diff --git a/src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs b/src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs index 855567b65..ad7dace68 100644 --- a/src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs +++ b/src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs @@ -11,7 +11,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; -using NodaTime; // ReSharper disable ConvertIfStatementToConditionalTernaryExpression // ReSharper disable InvertIf @@ -56,8 +55,6 @@ namespace Squidex.Infrastructure.CQRS.Events return; } - var startTime = SystemClock.Instance.GetCurrentInstant(); - eventStream.Connect("squidex", eventData => { var @event = ParseEvent(eventData); @@ -67,15 +64,13 @@ namespace Squidex.Infrastructure.CQRS.Events return; } - var isLive = @event.Headers.Timestamp() >= startTime; - - if (isLive) + if (canCatch) { - DispatchConsumers(catchConsumers.OfType().Union(liveConsumers), @event); + DispatchConsumers(catchConsumers, @event); } - else if (canCatch) + else { - DispatchConsumers(catchConsumers, @event); + DispatchConsumers(liveConsumers, @event); } logger.LogDebug("Event {0} handled", @event.Payload.GetType().Name); diff --git a/src/Squidex.Read/Apps/Services/Implementations/CachingAppProvider.cs b/src/Squidex.Read/Apps/Services/Implementations/CachingAppProvider.cs index a6319165d..ca617be3f 100644 --- a/src/Squidex.Read/Apps/Services/Implementations/CachingAppProvider.cs +++ b/src/Squidex.Read/Apps/Services/Implementations/CachingAppProvider.cs @@ -19,7 +19,7 @@ using Squidex.Read.Utils; namespace Squidex.Read.Apps.Services.Implementations { - public class CachingAppProvider : CachingProvider, IAppProvider, ICatchEventConsumer + public class CachingAppProvider : CachingProvider, IAppProvider, ICatchEventConsumer, ILiveEventConsumer { private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(30); private readonly IAppRepository repository; diff --git a/src/Squidex.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs b/src/Squidex.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs index 56712b5e0..010116f63 100644 --- a/src/Squidex.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs +++ b/src/Squidex.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs @@ -20,7 +20,7 @@ using Squidex.Events; namespace Squidex.Read.Schemas.Services.Implementations { - public class CachingSchemaProvider : CachingProvider, ISchemaProvider, ICatchEventConsumer + public class CachingSchemaProvider : CachingProvider, ISchemaProvider, ICatchEventConsumer, ILiveEventConsumer { private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(10); private readonly ISchemaRepository repository; diff --git a/src/Squidex/Config/Domain/ReadModule.cs b/src/Squidex/Config/Domain/ReadModule.cs index a7c59c642..8c153f368 100644 --- a/src/Squidex/Config/Domain/ReadModule.cs +++ b/src/Squidex/Config/Domain/ReadModule.cs @@ -33,11 +33,13 @@ namespace Squidex.Config.Domain { builder.RegisterType() .As() + .As() .As() .SingleInstance(); builder.RegisterType() .As() + .As() .As() .SingleInstance(); diff --git a/src/Squidex/app-config/helpers.js b/src/Squidex/app-config/helpers.js index fcf0f1160..30c3534da 100644 --- a/src/Squidex/app-config/helpers.js +++ b/src/Squidex/app-config/helpers.js @@ -13,14 +13,14 @@ exports.root = function () { }; exports.removeLoaders = function (config, extensions) { - var loaders = config.module.loaders; + var rules = config.module.rules; - for (var i = 0; i < loaders.length; i += 1) { - var loader = loaders[i]; + for (var i = 0; i < rules.length; i += 1) { + var rule = rules[i]; for (var j = 0; j < extensions.length; j += 1) { - if (loader.test.source.indexOf(extensions[j]) >= 0) { - loaders.splice(i, 1); + if (rule.test.source.indexOf(extensions[j]) >= 0) { + rules.splice(i, 1); i--; break; } diff --git a/src/Squidex/app-config/webpack.config.js b/src/Squidex/app-config/webpack.config.js index 2ced2004d..ce487334f 100644 --- a/src/Squidex/app-config/webpack.config.js +++ b/src/Squidex/app-config/webpack.config.js @@ -42,26 +42,44 @@ module.exports = { * * See: http://webpack.github.io/docs/configuration.html#module-loaders */ - loaders: [ + rules: [ { test: /\.ts$/, - loaders: ['awesome-typescript-loader', 'angular2-router-loader', 'angular2-template-loader', 'tslint-loader'] + use: [{ + loader: 'awesome-typescript-loader' + }, { + loader: 'angular2-router-loader' + }, { + loader: 'angular2-template-loader' + },{ + loader: 'tslint-loader' + }] }, { test: /\.html$/, - loader: 'raw-loader' + use: [{ + loader: 'raw-loader' + }] }, { test: /\.(woff|woff2|ttf|eot)(\?.*$|$)/, - loader: 'file-loader?name=assets/[name].[hash].[ext]' + use: [{ + loader: 'file-loader?name=assets/[name].[hash].[ext]' + }] }, { test: /\.(png|jpe?g|gif|svg|ico)(\?.*$|$)/, - loader: 'file-loader?name=assets/[name].[hash].[ext]' + use: [{ + loader: 'file-loader?name=assets/[name].[hash].[ext]' + }] }, { test: /\.css$/, - loader: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: 'css-loader?sourceMap' }) + use: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: 'css-loader?sourceMap' }) }, { test: /\.scss$/, - exclude: helpers.root('app', 'theme'), - loaders: ['raw-loader', 'sass-loader'] + use: [{ + loader: 'raw-loader' + }, { + loader: 'sass-loader' + }], + exclude: helpers.root('app', 'theme') } ] }, diff --git a/src/Squidex/app-config/webpack.run.dev.js b/src/Squidex/app-config/webpack.run.dev.js index 4b5e373d6..06ff4dfa0 100644 --- a/src/Squidex/app-config/webpack.run.dev.js +++ b/src/Squidex/app-config/webpack.run.dev.js @@ -37,11 +37,17 @@ module.exports = webpackMerge(runConfig, { * * See: http://webpack.github.io/docs/configuration.html#module-loaders */ - loaders: [ + rules: [ { test: /\.scss$/, - include: helpers.root('app', 'theme'), - loaders: ['style-loader', 'css-loader', 'sass-loader?sourceMap'] + use: [{ + loader: 'style-loader' + }, { + loader: 'css-loader' + }, { + loader: 'sass-loader?sourceMap', + }], + include: helpers.root('app', 'theme') } ] }, diff --git a/src/Squidex/app-config/webpack.test.coverage.js b/src/Squidex/app-config/webpack.test.coverage.js index e97306c30..9b5a60f49 100644 --- a/src/Squidex/app-config/webpack.test.coverage.js +++ b/src/Squidex/app-config/webpack.test.coverage.js @@ -4,20 +4,34 @@ var webpackMerge = require('webpack-merge'), helpers = require('./helpers'), testConfig = require('./webpack.test.js'); + // console.log(JSON.stringify(testConfig, null, '\t')); + helpers.removeLoaders(testConfig, ['ts']); module.exports = webpackMerge(testConfig, { module: { - loaders: [ + rules: [ { test: /\.ts$/, + use: [{ + loader: 'awesome-typescript-loader' + }], include: [/\.(e2e|spec)\.ts$/], - loaders: ['awesome-typescript-loader'] - }, - { + + }, { test: /\.ts$/, - exclude: [/\.(e2e|spec)\.ts$/], - loaders: ['istanbul-instrumenter-loader', helpers.root('app-config', 'fix-coverage-loader'), 'awesome-typescript-loader', 'angular2-router-loader', 'angular2-template-loader'] + use: [{ + loader: 'istanbul-instrumenter-loader' + }, { + loader: helpers.root('app-config', 'fix-coverage-loader') + }, { + loader: 'awesome-typescript-loader' + }, { + loader: 'angular2-router-loader' + }, { + loader: 'angular2-template-loader' + }], + exclude: [/\.(e2e|spec)\.ts$/] } ] } diff --git a/src/Squidex/app/framework/utils/immutable-array.spec.ts b/src/Squidex/app/framework/utils/immutable-array.spec.ts index 84f163af6..9b7edabaf 100644 --- a/src/Squidex/app/framework/utils/immutable-array.spec.ts +++ b/src/Squidex/app/framework/utils/immutable-array.spec.ts @@ -92,7 +92,7 @@ describe('ImmutableArray', () => { it('should replace all by predicate', () => { const array_1 = ImmutableArray.of([1, 2, 3, 4]); - const array_2 = array_1.replaceAll((i: number) => i % 2 === 0, i => i *2); + const array_2 = array_1.replaceAll((i: number) => i % 2 === 0, i => i * 2); expect(array_2.values).toEqual([1, 4, 3, 8]); }); @@ -113,7 +113,7 @@ describe('ImmutableArray', () => { it('should map items', () => { const array_1 = ImmutableArray.of([1, 2, 3, 4]); - const array_2 = array_1.map((i: number) => i *2); + const array_2 = array_1.map((i: number) => i * 2); expect(array_2.values).toEqual([2, 4, 6, 8]); }); diff --git a/src/Squidex/app/framework/utils/math-helper.spec.ts b/src/Squidex/app/framework/utils/math-helper.spec.ts index db2cbea9b..82bc9c74b 100644 --- a/src/Squidex/app/framework/utils/math-helper.spec.ts +++ b/src/Squidex/app/framework/utils/math-helper.spec.ts @@ -31,21 +31,21 @@ describe('MathHelper', () => { it('should convert to rad', () => { expect(MathHelper.toRad(0)).toBe(0); - expect(MathHelper.toRad(180)).toBe(Math.PI *1); - expect(MathHelper.toRad(360)).toBe(Math.PI *2); + expect(MathHelper.toRad(180)).toBe(Math.PI * 1); + expect(MathHelper.toRad(360)).toBe(Math.PI * 2); }); it('should convert to degree', () => { expect(MathHelper.toDegree(0)).toBe(0); - expect(MathHelper.toDegree(Math.PI *1)).toBe(180); - expect(MathHelper.toDegree(Math.PI *2)).toBe(360); + expect(MathHelper.toDegree(Math.PI * 1)).toBe(180); + expect(MathHelper.toDegree(Math.PI * 2)).toBe(360); }); it('should adjust invalid degrees', () => { - expect(MathHelper.toPositiveDegree(36.5 - (1 *360))).toBe(36.5); - expect(MathHelper.toPositiveDegree(36.5 - (2 *360))).toBe(36.5); - expect(MathHelper.toPositiveDegree(36.5 + (1 *360))).toBe(36.5); - expect(MathHelper.toPositiveDegree(36.5 + (2 *360))).toBe(36.5); + expect(MathHelper.toPositiveDegree(36.5 - (1 * 360))).toBe(36.5); + expect(MathHelper.toPositiveDegree(36.5 - (2 * 360))).toBe(36.5); + expect(MathHelper.toPositiveDegree(36.5 + (1 * 360))).toBe(36.5); + expect(MathHelper.toPositiveDegree(36.5 + (2 * 360))).toBe(36.5); }); it('should calculate simple sin', () => { diff --git a/tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs b/tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs index d2f493cc9..cff12c5c0 100644 --- a/tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs +++ b/tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs @@ -7,9 +7,9 @@ // ========================================================================== using System; +using System.Collections.Generic; using Microsoft.Extensions.Logging; using Moq; -using NodaTime; using Xunit; namespace Squidex.Infrastructure.CQRS.Events @@ -22,11 +22,13 @@ namespace Squidex.Infrastructure.CQRS.Events private sealed class MyLogger : ILogger { - public int LogCount { get; private set; } + public Dictionary LogCount { get; } = new Dictionary(); public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatterr) { - LogCount++; + var count = LogCount.GetOrDefault(logLevel); + + LogCount[logLevel] = count + 1; } public bool IsEnabled(LogLevel logLevel) @@ -46,47 +48,26 @@ namespace Squidex.Infrastructure.CQRS.Events private readonly Mock catchConsumer2 = new Mock(); private readonly Mock eventStream = new Mock(); private readonly Mock formatter = new Mock(new TypeNameRegistry(), null); - private readonly EventData eventDataPast = new EventData(); - private readonly EventData eventDataFuture = new EventData(); - private readonly Envelope eventPast = new Envelope(new MyEvent()); - private readonly Envelope eventFuture = new Envelope(new MyEvent()); + private readonly EventData eventData = new EventData(); + private readonly Envelope envelope = new Envelope(new MyEvent()); private readonly MyLogger logger = new MyLogger(); - private readonly EventReceiver sut; public EventReceiverTests() { - eventFuture.SetTimestamp(Instant.FromDateTimeUtc(DateTime.UtcNow.AddYears(1))); - - formatter.Setup(x => x.Parse(eventDataPast)).Returns(eventPast); - formatter.Setup(x => x.Parse(eventDataFuture)).Returns(eventFuture); + formatter.Setup(x => x.Parse(eventData)).Returns(envelope); eventStream.Setup(x => x.Connect("squidex", It.IsAny>())).Callback( new Action>((queue, callback) => { - callback(eventDataPast); - callback(eventDataFuture); + callback(eventData); })); - - sut = - new EventReceiver( - logger, - eventStream.Object, - new[] - { - liveConsumer1.Object, - liveConsumer2.Object - }, - new[] - { - catchConsumer1.Object, - catchConsumer2.Object - }, - formatter.Object); } [Fact] public void Should_only_connect_once() { + var sut = CreateSut(true); + sut.Subscribe(); sut.Subscribe(); @@ -94,69 +75,94 @@ namespace Squidex.Infrastructure.CQRS.Events } [Fact] - public void Should_invoke_consumers() + public void Should_invoke_live_consumers() { + var sut = CreateSut(false); + sut.Subscribe(); - catchConsumer1.Verify(x => x.On(eventPast), Times.Once()); - catchConsumer2.Verify(x => x.On(eventPast), Times.Once()); + catchConsumer1.Verify(x => x.On(It.IsAny>()), Times.Never()); + catchConsumer2.Verify(x => x.On(It.IsAny>()), Times.Never()); + + liveConsumer1.Verify(x => x.On(envelope), Times.Once()); + liveConsumer2.Verify(x => x.On(envelope), Times.Once()); - catchConsumer1.Verify(x => x.On(eventFuture), Times.Once()); - catchConsumer2.Verify(x => x.On(eventFuture), Times.Once()); + Assert.Equal(1, logger.LogCount.Count); + Assert.Equal(1, logger.LogCount[LogLevel.Debug]); + } - liveConsumer1.Verify(x => x.On(eventPast), Times.Never()); - liveConsumer2.Verify(x => x.On(eventPast), Times.Never()); + [Fact] + public void Should_invoke_catch_consumers() + { + var sut = CreateSut(true); + + sut.Subscribe(); - liveConsumer1.Verify(x => x.On(eventFuture), Times.Once()); - liveConsumer2.Verify(x => x.On(eventFuture), Times.Once()); + liveConsumer1.Verify(x => x.On(It.IsAny>()), Times.Never()); + liveConsumer2.Verify(x => x.On(It.IsAny>()), Times.Never()); - Assert.Equal(0, logger.LogCount); + catchConsumer1.Verify(x => x.On(envelope), Times.Once()); + catchConsumer2.Verify(x => x.On(envelope), Times.Once()); + + Assert.Equal(1, logger.LogCount.Count); + Assert.Equal(1, logger.LogCount[LogLevel.Debug]); } - + [Fact] public void Should_log_if_parsing_event_failed() { - formatter.Setup(x => x.Parse(eventDataPast)).Throws(new InvalidOperationException()); - - sut.Subscribe(); + formatter.Setup(x => x.Parse(eventData)).Throws(new InvalidOperationException()); - catchConsumer1.Verify(x => x.On(eventPast), Times.Never()); - catchConsumer2.Verify(x => x.On(eventPast), Times.Never()); + var sut = CreateSut(true); - catchConsumer1.Verify(x => x.On(eventFuture), Times.Once()); - catchConsumer2.Verify(x => x.On(eventFuture), Times.Once()); + sut.Subscribe(); - liveConsumer1.Verify(x => x.On(eventPast), Times.Never()); - liveConsumer2.Verify(x => x.On(eventPast), Times.Never()); + catchConsumer1.Verify(x => x.On(It.IsAny>()), Times.Never()); + catchConsumer2.Verify(x => x.On(It.IsAny>()), Times.Never()); - liveConsumer1.Verify(x => x.On(eventFuture), Times.Once()); - liveConsumer2.Verify(x => x.On(eventFuture), Times.Once()); + liveConsumer1.Verify(x => x.On(It.IsAny>()), Times.Never()); + liveConsumer2.Verify(x => x.On(It.IsAny>()), Times.Never()); - Assert.Equal(1, logger.LogCount); + Assert.Equal(1, logger.LogCount.Count); + Assert.Equal(1, logger.LogCount[LogLevel.Error]); } [Fact] public void Should_log_if_handling_failed() { - catchConsumer1.Setup(x => x.On(eventPast)).Throws(new InvalidOperationException()); + catchConsumer1.Setup(x => x.On(envelope)).Throws(new InvalidOperationException()); - liveConsumer1.Setup(x => x.On(eventFuture)).Throws(new InvalidOperationException()); + var sut = CreateSut(true); sut.Subscribe(); - catchConsumer1.Verify(x => x.On(eventPast), Times.Once()); - catchConsumer2.Verify(x => x.On(eventPast), Times.Once()); - - catchConsumer1.Verify(x => x.On(eventFuture), Times.Once()); - catchConsumer2.Verify(x => x.On(eventFuture), Times.Once()); + catchConsumer1.Verify(x => x.On(envelope), Times.Once()); + catchConsumer2.Verify(x => x.On(envelope), Times.Once()); - liveConsumer1.Verify(x => x.On(eventPast), Times.Never()); - liveConsumer2.Verify(x => x.On(eventPast), Times.Never()); + liveConsumer1.Verify(x => x.On(It.IsAny>()), Times.Never()); + liveConsumer2.Verify(x => x.On(It.IsAny>()), Times.Never()); - liveConsumer1.Verify(x => x.On(eventFuture), Times.Once()); - liveConsumer2.Verify(x => x.On(eventFuture), Times.Once()); + Assert.Equal(2, logger.LogCount.Count); + Assert.Equal(1, logger.LogCount[LogLevel.Debug]); + Assert.Equal(1, logger.LogCount[LogLevel.Error]); + } - Assert.Equal(2, logger.LogCount); + private EventReceiver CreateSut(bool canCatch) + { + return new EventReceiver( + logger, + eventStream.Object, + new[] + { + liveConsumer1.Object, + liveConsumer2.Object + }, + new[] + { + catchConsumer1.Object, + catchConsumer2.Object + }, + formatter.Object, canCatch); } } } diff --git a/tests/Squidex.Infrastructure.Tests/xunit.runner.json b/tests/Squidex.Infrastructure.Tests/xunit.runner.json deleted file mode 100644 index 6b3f1f87d..000000000 --- a/tests/Squidex.Infrastructure.Tests/xunit.runner.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "diagnosticMessages": false, - "methodDisplay": "classAndMethod", - "parallelizeTestCollections": true -}