Browse Source

Validation improved for app guards.

pull/303/head
Sebastian 8 years ago
parent
commit
6ba7652696
  1. 4
      NuGet.Config
  2. BIN
      libs/sharppwned.net/1.0.2-fix/sharppwned.net.1.0.2-fix.nupkg
  3. 1
      libs/sharppwned.net/1.0.2-fix/sharppwned.net.1.0.2-fix.nupkg.sha512
  4. 17
      libs/sharppwned.net/1.0.2-fix/sharppwned.net.nuspec
  5. 34
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardApp.cs
  6. 8
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppClients.cs
  7. 8
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppContributors.cs
  8. 14
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppLanguages.cs
  9. 2
      src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
  10. 4
      src/Squidex.Infrastructure/Validate.cs
  11. 27
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppClientsTests.cs
  12. 26
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppContributorsTests.cs
  13. 22
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppLanguagesTests.cs
  14. 21
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppTests.cs
  15. 54
      tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/ValidationAssert.cs

4
NuGet.Config

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="localfeed" value="libs" />
<add key="myget.org" value="https://dotnet.myget.org/F/orleans-ci/api/v3/index.json" protocolVersion="3" />
<add key="myget.org" value="https://dotnet.myget.org/F/orleans-ci/api/v3/index.json" protocolVersion="3" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="localfeed" value="libs" />
</packageSources>
</configuration>

BIN
libs/sharppwned.net/1.0.2-fix/sharppwned.net.1.0.2-fix.nupkg

Binary file not shown.

1
libs/sharppwned.net/1.0.2-fix/sharppwned.net.1.0.2-fix.nupkg.sha512

@ -0,0 +1 @@
44NJepeJdsgel9jiDTaWOXhCYM08/kGmW81dw8J31py1+4MJoOloWSUtk99fDbzM7X3/pdSNksJWb22liaDsVQ==

17
libs/sharppwned.net/1.0.2-fix/sharppwned.net.nuspec

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>SharpPwned.NET</id>
<version>1.0.2-fix</version>
<authors>SharpPwned.NET</authors>
<owners>SharpPwned.NET</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package Description</description>
<dependencies>
<group targetFramework=".NETStandard1.4">
<dependency id="NETStandard.Library" version="1.6.1" exclude="Build,Analyzers" />
<dependency id="Newtonsoft.Json" version="10.0.3" exclude="Build,Analyzers" />
</group>
</dependencies>
</metadata>
</package>

34
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardApp.cs

@ -22,14 +22,13 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
return Validate.It(() => "Cannot create app.", async error =>
{
if (await appProvider.GetAppAsync(command.Name) != null)
if (!command.Name.IsSlug())
{
error(new ValidationError($"An app with name '{command.Name}' already exists", nameof(command.Name)));
error(new ValidationError("Name must be a valid slug (lowercase characters, numbers and dashes).", nameof(command.Name)));
}
if (!command.Name.IsSlug())
else if (await appProvider.GetAppAsync(command.Name) != null)
{
error(new ValidationError("Name must be a valid slug.", nameof(command.Name)));
error(new ValidationError($"An app with name '{command.Name}' already exists.", nameof(command.Name)));
}
});
}
@ -42,21 +41,24 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
if (string.IsNullOrWhiteSpace(command.PlanId))
{
error(new ValidationError("PlanId is not defined.", nameof(command.PlanId)));
error(new ValidationError("Plan id is required.", nameof(command.PlanId)));
}
else if (appPlans.GetPlan(command.PlanId) == null)
else
{
error(new ValidationError("Plan id not available.", nameof(command.PlanId)));
}
if (appPlans.GetPlan(command.PlanId) == null)
{
error(new ValidationError($"Plan with id '{command.PlanId}' is not available.", nameof(command.PlanId)));
}
if (!string.IsNullOrWhiteSpace(command.PlanId) && plan != null && !plan.Owner.Equals(command.Actor))
{
error(new ValidationError("Plan can only be changed from current user."));
}
if (!string.IsNullOrWhiteSpace(command.PlanId) && plan != null && !plan.Owner.Equals(command.Actor))
{
error(new ValidationError("Plan can only changed from the user who configured the plan initially."));
}
if (string.Equals(command.PlanId, plan?.PlanId, StringComparison.OrdinalIgnoreCase))
{
error(new ValidationError("App has already this plan."));
if (string.Equals(command.PlanId, plan?.PlanId, StringComparison.OrdinalIgnoreCase))
{
error(new ValidationError("App has already this plan."));
}
}
});
}

8
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppClients.cs

@ -25,7 +25,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
}
else if (clients.ContainsKey(command.Id))
{
error(new ValidationError("Client id already added.", nameof(command.Id)));
error(new ValidationError("Client id already exists."));
}
});
}
@ -60,7 +60,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
if (string.IsNullOrWhiteSpace(command.Name) && command.Permission == null)
{
error(new ValidationError("Either name or permission is required.", nameof(command.Name), nameof(command.Permission)));
error(new ValidationError("Either name or permission must be defined.", nameof(command.Name), nameof(command.Permission)));
}
if (command.Permission.HasValue && !command.Permission.Value.IsEnumValue())
@ -72,12 +72,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
if (!string.IsNullOrWhiteSpace(command.Name) && string.Equals(client.Name, command.Name))
{
error(new ValidationError("Client already has this name.", nameof(command.Permission)));
error(new ValidationError("Client has already this name.", nameof(command.Name)));
}
if (command.Permission == client.Permission)
{
error(new ValidationError("Client already has this permission.", nameof(command.Permission)));
error(new ValidationError("Client has already this permission.", nameof(command.Permission)));
}
}
});

8
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppContributors.cs

@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
if (string.IsNullOrWhiteSpace(command.ContributorId))
{
error(new ValidationError("Contributor id not assigned.", nameof(command.ContributorId)));
error(new ValidationError("Contributor id is required.", nameof(command.ContributorId)));
}
else
{
@ -39,7 +39,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
if (user == null)
{
error(new ValidationError("Cannot find contributor id.", nameof(command.ContributorId)));
throw new DomainObjectNotFoundException(command.ContributorId, "Contributors", typeof(IAppEntity));
}
else
{
@ -73,14 +73,14 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
if (string.IsNullOrWhiteSpace(command.ContributorId))
{
error(new ValidationError("Contributor id not assigned.", nameof(command.ContributorId)));
error(new ValidationError("Contributor id is required.", nameof(command.ContributorId)));
}
var ownerIds = contributors.Where(x => x.Value == AppContributorPermission.Owner).Select(x => x.Key).ToList();
if (ownerIds.Count == 1 && ownerIds.Contains(command.ContributorId))
{
error(new ValidationError("Cannot remove the only owner.", nameof(command.ContributorId)));
error(new ValidationError("Cannot remove the only owner."));
}
});

14
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppLanguages.cs

@ -21,11 +21,11 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
if (command.Language == null)
{
error(new ValidationError("Language cannot be null.", nameof(command.Language)));
error(new ValidationError("Language code is required.", nameof(command.Language)));
}
else if (languages.Contains(command.Language))
{
error(new ValidationError("Language already added.", nameof(command.Language)));
error(new ValidationError("Language has already been added."));
}
});
}
@ -40,12 +40,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
if (command.Language == null)
{
error(new ValidationError("Language cannot be null.", nameof(command.Language)));
error(new ValidationError("Language code is required.", nameof(command.Language)));
}
if (languages.Master == languageConfig)
{
error(new ValidationError("Language config is master.", nameof(command.Language)));
error(new ValidationError("Master language cannot be removed."));
}
});
}
@ -60,12 +60,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
if (command.Language == null)
{
error(new ValidationError("Language cannot be null.", nameof(command.Language)));
error(new ValidationError("Language is required.", nameof(command.Language)));
}
if ((languages.Master == languageConfig || command.IsMaster) && command.IsOptional)
{
error(new ValidationError("Cannot make master language optional.", nameof(command.IsMaster)));
error(new ValidationError("Master language cannot be made optional.", nameof(command.IsMaster)));
}
if (command.Fallback != null)
@ -74,7 +74,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
if (!languages.Contains(fallback))
{
error(new ValidationError($"Config does not contain fallback language {fallback}.", nameof(command.Fallback)));
error(new ValidationError($"App does not have fallback language '{fallback}'.", nameof(command.Fallback)));
}
}
}

2
src/Squidex.Domain.Users/Squidex.Domain.Users.csproj

@ -14,7 +14,7 @@
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.0.2" />
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" />
<PackageReference Include="SharpPwned.NET" Version="1.0.2" />
<PackageReference Include="SharpPwned.NET" Version="1.0.2-fix" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />
<PackageReference Include="System.Linq.Queryable" Version="4.3.0" />
<PackageReference Include="System.Security.Principal.Windows" Version="4.4.1" />

4
src/Squidex.Infrastructure/Validate.cs

@ -14,7 +14,7 @@ namespace Squidex.Infrastructure
{
public static class Validate
{
public static void It(Func<string> message, Action<Action<ValidationError>> action)
public static void It(Func<string> message, Action<Action<ValidationError>> action, IReadOnlyDictionary<string, string> messages = null)
{
var errors = new List<ValidationError>();
@ -26,7 +26,7 @@ namespace Squidex.Infrastructure
}
}
public static async Task It(Func<string> message, Func<Action<ValidationError>, Task> action)
public static async Task It(Func<string> message, Func<Action<ValidationError>, Task> action, IReadOnlyDictionary<string, string> messages = null)
{
var errors = new List<ValidationError>();

27
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppClientsTests.cs

@ -7,6 +7,7 @@
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Infrastructure;
using Xunit;
@ -23,7 +24,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new AttachClient();
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients_0, command));
ValidationAssert.Throws(() => GuardAppClients.CanAttach(clients_0, command),
new ValidationError("Client id is required.", "Id"));
}
[Fact]
@ -33,7 +35,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("android", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients_1, command));
ValidationAssert.Throws(() => GuardAppClients.CanAttach(clients_1, command),
new ValidationError("Client id already exists.", "Id"));
}
[Fact]
@ -51,7 +54,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new RevokeClient();
Assert.Throws<ValidationException>(() => GuardAppClients.CanRevoke(clients_0, command));
ValidationAssert.Throws(() => GuardAppClients.CanRevoke(clients_0, command),
new ValidationError("Client id is required.", "Id"));
}
[Fact]
@ -75,9 +79,10 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
[Fact]
public void CanUpdate_should_throw_execption_if_client_id_is_null()
{
var command = new UpdateClient();
var command = new UpdateClient { Name = "iOS" };
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_0, command));
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_0, command),
new ValidationError("Client id is required.", "Id"));
}
[Fact]
@ -95,7 +100,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("ios", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command));
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command),
new ValidationError("Either name or permission must be defined.", "Name", "Permission"));
}
[Fact]
@ -105,7 +111,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("ios", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command));
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command),
new ValidationError("Permission is not valid.", "Permission"));
}
[Fact]
@ -115,7 +122,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("ios", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command));
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command),
new ValidationError("Client has already this name.", "Name"));
}
[Fact]
@ -125,7 +133,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("ios", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command));
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command),
new ValidationError("Client has already this permission.", "Permission"));
}
[Fact]

26
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppContributorsTests.cs

@ -10,6 +10,7 @@ using FakeItEasy;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Domain.Apps.Entities.Apps.Services;
using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Infrastructure;
using Squidex.Shared.Users;
using Xunit;
@ -53,7 +54,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new AssignContributor();
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan));
return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan),
new ValidationError("Contributor id is required.", "ContributorId"));
}
[Fact]
@ -61,7 +63,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new AssignContributor { ContributorId = "1", Permission = (AppContributorPermission)10 };
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan));
return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan),
new ValidationError("Permission is not valid.", "Permission"));
}
[Fact]
@ -71,7 +74,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_1, command, users, appPlan));
return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_1, command, users, appPlan),
new ValidationError("Contributor has already this permission.", "Permission"));
}
[Fact]
@ -79,15 +83,16 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new AssignContributor { ContributorId = "notfound", Permission = (AppContributorPermission)10 };
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan));
return Assert.ThrowsAsync<DomainObjectNotFoundException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan));
}
[Fact]
public Task CanAssign_should_throw_exception_if_user_is_actor()
{
var command = new AssignContributor { ContributorId = "3", Permission = (AppContributorPermission)10, Actor = new RefToken("user", "3") };
var command = new AssignContributor { ContributorId = "3", Permission = AppContributorPermission.Editor, Actor = new RefToken("user", "3") };
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan));
return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan),
new ValidationError("You cannot change your own permission."));
}
[Fact]
@ -101,7 +106,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor);
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_2, command, users, appPlan));
return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_2, command, users, appPlan),
new ValidationError("You have reached the maximum number of contributors for your plan."));
}
[Fact]
@ -151,7 +157,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new RemoveContributor();
Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors_0, command));
ValidationAssert.Throws(() => GuardAppContributors.CanRemove(contributors_0, command),
new ValidationError("Contributor id is required.", "ContributorId"));
}
[Fact]
@ -170,7 +177,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor);
Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors_2, command));
ValidationAssert.Throws(() => GuardAppContributors.CanRemove(contributors_2, command),
new ValidationError("Cannot remove the only owner."));
}
[Fact]

22
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppLanguagesTests.cs

@ -8,6 +8,7 @@
using System.Collections.Generic;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Infrastructure;
using Xunit;
@ -24,7 +25,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new AddLanguage();
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages_0, command));
ValidationAssert.Throws(() => GuardAppLanguages.CanAdd(languages_0, command),
new ValidationError("Language code is required.", "Language"));
}
[Fact]
@ -32,7 +34,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new AddLanguage { Language = Language.DE };
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages_0, command));
ValidationAssert.Throws(() => GuardAppLanguages.CanAdd(languages_0, command),
new ValidationError("Language has already been added."));
}
[Fact]
@ -48,7 +51,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new RemoveLanguage();
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages_0, command));
ValidationAssert.Throws(() => GuardAppLanguages.CanRemove(languages_0, command),
new ValidationError("Language code is required.", "Language"));
}
[Fact]
@ -64,7 +68,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new RemoveLanguage { Language = Language.DE };
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages_0, command));
ValidationAssert.Throws(() => GuardAppLanguages.CanRemove(languages_0, command),
new ValidationError("Master language cannot be removed."));
}
[Fact]
@ -84,7 +89,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages_1, command));
ValidationAssert.Throws(() => GuardAppLanguages.CanUpdate(languages_1, command),
new ValidationError("Language is required.", "Language"));
}
[Fact]
@ -94,7 +100,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages_1, command));
ValidationAssert.Throws(() => GuardAppLanguages.CanUpdate(languages_1, command),
new ValidationError("Master language cannot be made optional.", "IsMaster"));
}
[Fact]
@ -104,7 +111,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages_1, command));
ValidationAssert.Throws(() => GuardAppLanguages.CanUpdate(languages_1, command),
new ValidationError("App does not have fallback language 'Italian'.", "Fallback"));
}
[Fact]

21
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppTests.cs

@ -10,6 +10,7 @@ using FakeItEasy;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Domain.Apps.Entities.Apps.Services;
using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Infrastructure;
using Squidex.Shared.Users;
using Xunit;
@ -42,7 +43,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new CreateApp { Name = "new-app" };
return Assert.ThrowsAsync<ValidationException>(() => GuardApp.CanCreate(command, apps));
return ValidationAssert.ThrowsAsync(() => GuardApp.CanCreate(command, apps),
new ValidationError("An app with name 'new-app' already exists.", "Name"));
}
[Fact]
@ -50,7 +52,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
var command = new CreateApp { Name = "INVALID NAME" };
return Assert.ThrowsAsync<ValidationException>(() => GuardApp.CanCreate(command, apps));
return ValidationAssert.ThrowsAsync(() => GuardApp.CanCreate(command, apps),
new ValidationError("Name must be a valid slug (lowercase characters, numbers and dashes).", "Name"));
}
[Fact]
@ -62,13 +65,14 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
}
[Fact]
public void CanChangePlan_should_throw_exception_if_plan_id_null()
public void CanChangePlan_should_throw_exception_if_plan_id_is_null()
{
var command = new ChangePlan { Actor = new RefToken("user", "me") };
AppPlan plan = null;
Assert.Throws<ValidationException>(() => GuardApp.CanChangePlan(command, plan, appPlans));
ValidationAssert.Throws(() => GuardApp.CanChangePlan(command, plan, appPlans),
new ValidationError("Plan id is required.", "PlanId"));
}
[Fact]
@ -81,7 +85,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
AppPlan plan = null;
Assert.Throws<ValidationException>(() => GuardApp.CanChangePlan(command, plan, appPlans));
ValidationAssert.Throws(() => GuardApp.CanChangePlan(command, plan, appPlans),
new ValidationError("Plan with id 'free' is not available.", "PlanId"));
}
[Fact]
@ -91,7 +96,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var plan = new AppPlan(new RefToken("user", "other"), "premium");
Assert.Throws<ValidationException>(() => GuardApp.CanChangePlan(command, plan, appPlans));
ValidationAssert.Throws(() => GuardApp.CanChangePlan(command, plan, appPlans),
new ValidationError("Plan can only changed from the user who configured the plan initially."));
}
[Fact]
@ -101,7 +107,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var plan = new AppPlan(new RefToken("user", "me"), "free");
Assert.Throws<ValidationException>(() => GuardApp.CanChangePlan(command, plan, appPlans));
ValidationAssert.Throws(() => GuardApp.CanChangePlan(command, plan, appPlans),
new ValidationError("App has already this plan."));
}
[Fact]

54
tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/ValidationAssert.cs

@ -0,0 +1,54 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Xunit;
namespace Squidex.Domain.Apps.Entities.TestHelpers
{
public static class ValidationAssert
{
public static void Throws(Action action, params ValidationError[] errors)
{
try
{
action();
Assert.True(false, $"Expected {typeof(ValidationException)} but succeeded");
}
catch (ValidationException ex)
{
ex.Errors.ToArray().ShouldBeEquivalent(errors);
}
catch (Exception ex)
{
Assert.True(false, $"Excepted {typeof(ValidationException)}, but got {ex.GetType()}");
}
}
public static async Task ThrowsAsync(Func<Task> action, params ValidationError[] errors)
{
try
{
await action();
Assert.True(false, $"Expected {typeof(ValidationException)} but succeeded");
}
catch (ValidationException ex)
{
ex.Errors.ToArray().ShouldBeEquivalent(errors);
}
catch (Exception ex)
{
Assert.True(false, $"Excepted {typeof(ValidationException)}, but got {ex.GetType()}");
}
}
}
}
Loading…
Cancel
Save