From 12d74649af0ce60a5308e75215ae3fbca3ef0f04 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 16 Jun 2018 15:44:32 +0200 Subject: [PATCH] Better validation tests for rules. --- .../Rules/Guards/GuardRule.cs | 2 +- .../Rules/Guards/RuleActionValidator.cs | 18 ++++++------- .../Guards/Actions/AlgoliaActionTests.cs | 21 ++++++++++++--- .../Guards/Actions/AzureQueueActionTests.cs | 21 ++++++++++++--- .../Actions/ElasticSearchActionTests.cs | 27 ++++++++++++++++--- .../Rules/Guards/Actions/FastlyActionTests.cs | 15 +++++++++-- .../Rules/Guards/Actions/SlackActionTests.cs | 15 +++++++++-- .../Guards/Actions/WebhookActionTests.cs | 15 +++++++++-- .../Rules/Guards/GuardRuleTests.cs | 16 +++++++---- 9 files changed, 119 insertions(+), 31 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Rules/Guards/GuardRule.cs b/src/Squidex.Domain.Apps.Entities/Rules/Guards/GuardRule.cs index 77f1298df..181a502b0 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/Guards/GuardRule.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/Guards/GuardRule.cs @@ -34,7 +34,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards if (command.Action == null) { - error(new ValidationError("Trigger is required.", nameof(command.Action))); + error(new ValidationError("Action is required.", nameof(command.Action))); } else { diff --git a/src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs b/src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs index 1a0f522d8..6e2178bb3 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs @@ -31,12 +31,12 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards if (string.IsNullOrWhiteSpace(action.ApiKey)) { - errors.Add(new ValidationError("Api key is required.", nameof(action.ApiKey))); + errors.Add(new ValidationError("Api Key is required.", nameof(action.ApiKey))); } if (string.IsNullOrWhiteSpace(action.AppId)) { - errors.Add(new ValidationError("Application ID key is required.", nameof(action.AppId))); + errors.Add(new ValidationError("Application ID is required.", nameof(action.AppId))); } if (string.IsNullOrWhiteSpace(action.IndexName)) @@ -58,11 +58,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards if (string.IsNullOrWhiteSpace(action.Queue)) { - errors.Add(new ValidationError("Queue is required.", nameof(action.Queue))); + errors.Add(new ValidationError("Queue name is required.", nameof(action.Queue))); } else if (!Regex.IsMatch(action.Queue, "^[a-z][a-z0-9]{2,}(\\-[a-z0-9]+)*$")) { - errors.Add(new ValidationError("Queue must be valid azure queue name.", nameof(action.Queue))); + errors.Add(new ValidationError("Queue name must be valid azure queue name.", nameof(action.Queue))); } return Task.FromResult>(errors); @@ -79,12 +79,12 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards if (string.IsNullOrWhiteSpace(action.IndexType)) { - errors.Add(new ValidationError("TypeName is required.", nameof(action.IndexType))); + errors.Add(new ValidationError("Type name is required.", nameof(action.IndexType))); } if (string.IsNullOrWhiteSpace(action.IndexName)) { - errors.Add(new ValidationError("IndexName is required.", nameof(action.IndexName))); + errors.Add(new ValidationError("Index name is required.", nameof(action.IndexName))); } return Task.FromResult>(errors); @@ -96,7 +96,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards if (string.IsNullOrWhiteSpace(action.ApiKey)) { - errors.Add(new ValidationError("Api key is required.", nameof(action.ApiKey))); + errors.Add(new ValidationError("Api Key is required.", nameof(action.ApiKey))); } if (string.IsNullOrWhiteSpace(action.ServiceId)) @@ -113,7 +113,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards if (action.WebhookUrl == null || !action.WebhookUrl.IsAbsoluteUri) { - errors.Add(new ValidationError("Webhook Url is required and must be an absolute URL.", nameof(action.WebhookUrl))); + errors.Add(new ValidationError("Webhook URL is required and must be an absolute URL.", nameof(action.WebhookUrl))); } return Task.FromResult>(errors); @@ -125,7 +125,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards if (action.Url == null || !action.Url.IsAbsoluteUri) { - errors.Add(new ValidationError("Url is required and must be an absolute URL.", nameof(action.Url))); + errors.Add(new ValidationError("URL is required and must be an absolute URL.", nameof(action.Url))); } return Task.FromResult>(errors); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/AlgoliaActionTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/AlgoliaActionTests.cs index 87105bd9a..8b5c10ba5 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/AlgoliaActionTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/AlgoliaActionTests.cs @@ -5,8 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.Threading.Tasks; +using FluentAssertions; using Squidex.Domain.Apps.Core.Rules.Actions; +using Squidex.Infrastructure; using Xunit; namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions @@ -20,7 +23,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Application ID is required.", "AppId") + }); } [Fact] @@ -30,7 +37,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Api Key is required.", "ApiKey") + }); } [Fact] @@ -40,7 +51,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Index name is required.", "IndexName") + }); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/AzureQueueActionTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/AzureQueueActionTests.cs index 915104e0f..afa89bae3 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/AzureQueueActionTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/AzureQueueActionTests.cs @@ -5,8 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.Threading.Tasks; +using FluentAssertions; using Squidex.Domain.Apps.Core.Rules.Actions; +using Squidex.Infrastructure; using Xunit; namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions @@ -20,7 +23,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Connection string is required.", "ConnectionString") + }); } [Fact] @@ -30,7 +37,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Queue name is required.", "Queue") + }); } [Fact] @@ -40,7 +51,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Queue name must be valid azure queue name.", "Queue") + }); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/ElasticSearchActionTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/ElasticSearchActionTests.cs index 2bad9987c..024aa1a46 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/ElasticSearchActionTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/ElasticSearchActionTests.cs @@ -6,8 +6,11 @@ // ========================================================================== using System; +using System.Collections.Generic; using System.Threading.Tasks; +using FluentAssertions; using Squidex.Domain.Apps.Core.Rules.Actions; +using Squidex.Infrastructure; using Xunit; namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions @@ -21,7 +24,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Host is required and must be an absolute URL.", "Host") + }); } [Fact] @@ -31,7 +38,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Host is required and must be an absolute URL.", "Host") + }); } [Fact] @@ -41,7 +52,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Index name is required.", "IndexName") + }); } [Fact] @@ -51,7 +66,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Type name is required.", "IndexType") + }); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/FastlyActionTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/FastlyActionTests.cs index f744dcd45..aedc7c775 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/FastlyActionTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/FastlyActionTests.cs @@ -5,8 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.Threading.Tasks; +using FluentAssertions; using Squidex.Domain.Apps.Core.Rules.Actions; +using Squidex.Infrastructure; using Xunit; namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions @@ -20,7 +23,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Service ID is required.", "ServiceId") + }); } [Fact] @@ -30,7 +37,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Api Key is required.", "ApiKey") + }); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/SlackActionTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/SlackActionTests.cs index 84d3a2c0c..8077cc173 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/SlackActionTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/SlackActionTests.cs @@ -6,8 +6,11 @@ // ========================================================================== using System; +using System.Collections.Generic; using System.Threading.Tasks; +using FluentAssertions; using Squidex.Domain.Apps.Core.Rules.Actions; +using Squidex.Infrastructure; using Xunit; namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions @@ -21,7 +24,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Webhook URL is required and must be an absolute URL.", "WebhookUrl") + }); } [Fact] @@ -31,7 +38,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("Webhook URL is required and must be an absolute URL.", "WebhookUrl") + }); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/WebhookActionTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/WebhookActionTests.cs index 869dd2193..05b284292 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/WebhookActionTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Actions/WebhookActionTests.cs @@ -6,8 +6,11 @@ // ========================================================================== using System; +using System.Collections.Generic; using System.Threading.Tasks; +using FluentAssertions; using Squidex.Domain.Apps.Core.Rules.Actions; +using Squidex.Infrastructure; using Xunit; namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions @@ -21,7 +24,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("URL is required and must be an absolute URL.", "Url") + }); } [Fact] @@ -31,7 +38,11 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions var errors = await RuleActionValidator.ValidateAsync(action); - Assert.NotEmpty(errors); + errors.ShouldBeEquivalentTo( + new List + { + new ValidationError("URL is required and must be an absolute URL.", "Url") + }); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs index e225709e2..6a9996072 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs @@ -14,6 +14,7 @@ using Squidex.Domain.Apps.Core.Rules.Actions; using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Entities.Rules.Commands; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Xunit; @@ -46,7 +47,8 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards } }); - await Assert.ThrowsAsync(() => GuardRule.CanCreate(command, appProvider)); + await ValidationAssert.ThrowsAsync(() => GuardRule.CanCreate(command, appProvider), + new ValidationError("Trigger is required.", "Trigger")); } [Fact] @@ -61,7 +63,8 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards Action = null }); - await Assert.ThrowsAsync(() => GuardRule.CanCreate(command, appProvider)); + await ValidationAssert.ThrowsAsync(() => GuardRule.CanCreate(command, appProvider), + new ValidationError("Action is required.", "Action")); } [Fact] @@ -87,7 +90,8 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards { var command = new UpdateRule(); - await Assert.ThrowsAsync(() => GuardRule.CanUpdate(command, appId.Id, appProvider)); + await ValidationAssert.ThrowsAsync(() => GuardRule.CanUpdate(command, appId.Id, appProvider), + new ValidationError("Either trigger or action is required.", "Trigger", "Action")); } [Fact] @@ -115,7 +119,8 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards var rule_1 = rule_0.Enable(); - Assert.Throws(() => GuardRule.CanEnable(command, rule_1)); + ValidationAssert.Throws(() => GuardRule.CanEnable(command, rule_1), + new ValidationError("Rule is already enabled.")); ; } [Fact] @@ -135,7 +140,8 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards var rule_1 = rule_0.Disable(); - Assert.Throws(() => GuardRule.CanDisable(command, rule_1)); + ValidationAssert.Throws(() => GuardRule.CanDisable(command, rule_1), + new ValidationError("Rule is already disabled.")); } [Fact]