From 69abb768f50ac6ce677952148799190c5ccd7ad6 Mon Sep 17 00:00:00 2001 From: prtsie Date: Mon, 16 Sep 2024 15:19:16 +0300 Subject: [PATCH 01/22] Created project for tests --- SchengenVisaApi/SchengenVisaApi.sln | 6 +++++ SchengenVisaApi/VisaApiTests/GlobalUsings.cs | 1 + .../Repositories/GenericRepositoryTests.cs | 9 +++++++ .../VisaApiTests/VisaApiTests.csproj | 26 +++++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 SchengenVisaApi/VisaApiTests/GlobalUsings.cs create mode 100644 SchengenVisaApi/VisaApiTests/Repositories/GenericRepositoryTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/VisaApiTests.csproj diff --git a/SchengenVisaApi/SchengenVisaApi.sln b/SchengenVisaApi/SchengenVisaApi.sln index 522c115..b1149c9 100644 --- a/SchengenVisaApi/SchengenVisaApi.sln +++ b/SchengenVisaApi/SchengenVisaApi.sln @@ -12,6 +12,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisaApiClient", "VisaApiCli EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWebAssemblyVisaApiClient", "BlazorWebAssemblyVisaApiClient\BlazorWebAssemblyVisaApiClient.csproj", "{3DB49E3C-AAC3-452C-AEBE-F4F72D6134F8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisaApiTests", "VisaApiTests\VisaApiTests.csproj", "{4CB6FBC4-99CB-453D-8499-A498FAE9683D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -42,5 +44,9 @@ Global {3DB49E3C-AAC3-452C-AEBE-F4F72D6134F8}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DB49E3C-AAC3-452C-AEBE-F4F72D6134F8}.Release|Any CPU.ActiveCfg = Release|Any CPU {3DB49E3C-AAC3-452C-AEBE-F4F72D6134F8}.Release|Any CPU.Build.0 = Release|Any CPU + {4CB6FBC4-99CB-453D-8499-A498FAE9683D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CB6FBC4-99CB-453D-8499-A498FAE9683D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CB6FBC4-99CB-453D-8499-A498FAE9683D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CB6FBC4-99CB-453D-8499-A498FAE9683D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/SchengenVisaApi/VisaApiTests/GlobalUsings.cs b/SchengenVisaApi/VisaApiTests/GlobalUsings.cs new file mode 100644 index 0000000..c802f44 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; diff --git a/SchengenVisaApi/VisaApiTests/Repositories/GenericRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Repositories/GenericRepositoryTests.cs new file mode 100644 index 0000000..bee42d9 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Repositories/GenericRepositoryTests.cs @@ -0,0 +1,9 @@ +namespace VisaApi.Repositories; + +public class GenericRepositoryTests +{ + [Fact] + public void Test1() + { + } +} diff --git a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj new file mode 100644 index 0000000..9fadb7c --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj @@ -0,0 +1,26 @@ + + + + net8.0 + enable + enable + + false + true + VisaApi + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + From 6bad05f1674ceecb8ab757b0151c3aa3b62ea055 Mon Sep 17 00:00:00 2001 From: prtsie Date: Mon, 16 Sep 2024 19:08:24 +0300 Subject: [PATCH 02/22] moved folder --- .../{ => Database}/Repositories/GenericRepositoryTests.cs | 2 +- SchengenVisaApi/VisaApiTests/VisaApiTests.csproj | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) rename SchengenVisaApi/VisaApiTests/{ => Database}/Repositories/GenericRepositoryTests.cs (68%) diff --git a/SchengenVisaApi/VisaApiTests/Repositories/GenericRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/GenericRepositoryTests.cs similarity index 68% rename from SchengenVisaApi/VisaApiTests/Repositories/GenericRepositoryTests.cs rename to SchengenVisaApi/VisaApiTests/Database/Repositories/GenericRepositoryTests.cs index bee42d9..28e7ccf 100644 --- a/SchengenVisaApi/VisaApiTests/Repositories/GenericRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/GenericRepositoryTests.cs @@ -1,4 +1,4 @@ -namespace VisaApi.Repositories; +namespace VisaApi.Database.Repositories; public class GenericRepositoryTests { diff --git a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj index 9fadb7c..0e715ff 100644 --- a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj +++ b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj @@ -23,4 +23,8 @@ + + + + From 6d284ce0458072470358f8fe52e5926aa9e0c15e Mon Sep 17 00:00:00 2001 From: prtsie Date: Mon, 16 Sep 2024 19:18:25 +0300 Subject: [PATCH 03/22] removed redundant nuget --- SchengenVisaApi/VisaApiTests/VisaApiTests.csproj | 8 -------- 1 file changed, 8 deletions(-) diff --git a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj index 0e715ff..c22aa4e 100644 --- a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj +++ b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj @@ -17,14 +17,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - From e39b8851fc7ac6cd5076ced38dd75b2dc3266dde Mon Sep 17 00:00:00 2001 From: prtsie Date: Mon, 16 Sep 2024 19:19:08 +0300 Subject: [PATCH 04/22] added reference to api --- SchengenVisaApi/VisaApiTests/VisaApiTests.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj index c22aa4e..91e24fa 100644 --- a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj +++ b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj @@ -19,4 +19,8 @@ + + + + From 7f54782a962113d757b8b1d925eb73c18b1cd593 Mon Sep 17 00:00:00 2001 From: prtsie Date: Mon, 16 Sep 2024 20:58:09 +0300 Subject: [PATCH 05/22] tests for generic repository --- .../Database/InMemoryContextProvider.cs | 16 ++++ .../Generic/GenericRepositoryTests.cs | 85 +++++++++++++++++++ .../Generic/TestGenericRepository.cs | 7 ++ .../Repositories/GenericRepositoryTests.cs | 9 -- .../Services/TestDateTimeProvider.cs | 9 ++ .../VisaApiTests/VisaApiTests.csproj | 2 + 6 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs create mode 100644 SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/TestGenericRepository.cs delete mode 100644 SchengenVisaApi/VisaApiTests/Database/Repositories/GenericRepositoryTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Services/TestDateTimeProvider.cs diff --git a/SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs b/SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs new file mode 100644 index 0000000..4d33789 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using DbContext = Infrastructure.Database.DbContext; + +namespace VisaApi.Database +{ + public static class InMemoryContextProvider + { + private static DbContextOptions opts = new DbContextOptionsBuilder() + .UseInMemoryDatabase("VisaApiDB") + .ConfigureWarnings(b => b.Ignore(InMemoryEventId.TransactionIgnoredWarning)) + .Options; + + public static DbContext GetDbContext() => new(opts); + } +} diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs new file mode 100644 index 0000000..7b4690e --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs @@ -0,0 +1,85 @@ +using ApplicationLayer.GeneralExceptions; +using Domains.Users; +using FluentAssertions; +using Infrastructure.Database; +using Infrastructure.Database.Generic; + +namespace VisaApi.Database.Repositories.Generic; + +public class GenericRepositoryTests +{ + private static GenericRepository GetRepository(DbContext context) => new TestGenericRepository(context, context); + + /// Test for method that should return empty collection if nothing added + [Fact] + public async Task GetAllForEmptyShouldReturnEmpty() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + + var result = await repository.GetAllAsync(CancellationToken.None); + + result.Should().BeEmpty(); + } + + /// Test for method that should return collection with added entities + [Fact] + public async Task GetAllForNotEmptyShouldReturnEntities() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + User[] users = + [ + new() { Email = "nasrudin@mail.ru", Password = "12345", Role = Role.Admin }, + new() { Email = "bruh@mail.ru", Password = "123", Role = Role.Applicant } + ]; + foreach (var user in users) + { + await repository.AddAsync(user, CancellationToken.None); + } + + await context.SaveChangesAsync(); + + var result = await repository.GetAllAsync(CancellationToken.None); + + result.Should().OnlyContain(user => users.Contains(user)); + } + + /// Test for method that should return existing entity + [Fact] + public async Task GetByIdForExistingShouldReturnEntity() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = new User { Email = "nasrudin@mail.ru", Password = "12345", Role = Role.Admin }; + await repository.AddAsync(user, CancellationToken.None); + + await context.SaveChangesAsync(); + + var result = await repository.GetByIdAsync(user.Id, CancellationToken.None); + + result.Should().Be(user); + } + + /// Test for method that should throw exception for not found entity + [Fact] + public async Task GetByIdForNotExistingShouldThrow() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + + await context.SaveChangesAsync(); + + EntityNotFoundByIdException? result = null; + try + { + await repository.GetByIdAsync(Guid.NewGuid(), CancellationToken.None); + } + catch (Exception e) + { + result = e as EntityNotFoundByIdException; + } + + result.Should().NotBeNull(); + } +} diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/TestGenericRepository.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/TestGenericRepository.cs new file mode 100644 index 0000000..c89a2e0 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/TestGenericRepository.cs @@ -0,0 +1,7 @@ +using Domains.Users; +using Infrastructure.Database.Generic; + +namespace VisaApi.Database.Repositories.Generic +{ + public class TestGenericRepository(IGenericReader reader, IGenericWriter writer) : GenericRepository(reader, writer); +} diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/GenericRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/GenericRepositoryTests.cs deleted file mode 100644 index 28e7ccf..0000000 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/GenericRepositoryTests.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace VisaApi.Database.Repositories; - -public class GenericRepositoryTests -{ - [Fact] - public void Test1() - { - } -} diff --git a/SchengenVisaApi/VisaApiTests/Services/TestDateTimeProvider.cs b/SchengenVisaApi/VisaApiTests/Services/TestDateTimeProvider.cs new file mode 100644 index 0000000..8241e0b --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Services/TestDateTimeProvider.cs @@ -0,0 +1,9 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; + +namespace VisaApi.Services +{ + public class TestDateTimeProvider : IDateTimeProvider + { + public DateTime Now() => DateTime.Now; + } +} diff --git a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj index 91e24fa..0be6f2d 100644 --- a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj +++ b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj @@ -11,6 +11,8 @@ + + From 40c4d19990c450b3e4893893700343de913c89bf Mon Sep 17 00:00:00 2001 From: prtsie Date: Tue, 17 Sep 2024 16:56:30 +0300 Subject: [PATCH 06/22] started fakers --- .../VisaApiTests/Fakers/ApplicantFaker.cs | 64 +++++++++++++++++++ .../VisaApiTests/Fakers/UserFaker.cs | 15 +++++ .../VisaApiTests/VisaApiTests.csproj | 1 + 3 files changed, 80 insertions(+) create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/UserFaker.cs diff --git a/SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs new file mode 100644 index 0000000..12d2a73 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs @@ -0,0 +1,64 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using Bogus; +using Domains; +using Domains.ApplicantDomain; +using Domains.Users; + +namespace VisaApi.Fakers +{ + public sealed class ApplicantFaker : Faker + { + public ApplicantFaker(User user, IDateTimeProvider dateTimeProvider) + { + RuleFor(a => a.Citizenship, f => f.Address.Country()); + + RuleFor(a => a.Gender, f => f.Random.Enum()); + + RuleForType(typeof(Name), f + => new Name + { + FirstName = f.Name.LastName(), + Surname = f.Name.LastName(), + Patronymic = f.Name.FirstName() + }); + + RuleFor(a => a.BirthDate, + f => f.Date.Past(60, dateTimeProvider.Now())); + + RuleFor(a => a.Passport, f + => new Passport + { + Issuer = f.Company.CompanyName(), + Number = f.Random.String(ConfigurationConstraints.PasswordLength), + ExpirationDate = f.Date.Future(4, dateTimeProvider.Now()), + IssueDate = f.Date.Past(4, dateTimeProvider.Now()) + }); + + RuleFor(a => a.JobTitle, f => f.Name.JobTitle()); + + RuleFor(a => a.MaritalStatus, f => f.Random.Enum()); + + RuleFor(a => a.UserId, () => user.Id); + + RuleFor(a => a.CitizenshipByBirth, f => f.Address.Country()); + + RuleFor(a => a.CityOfBirth, f => f.Address.City()); + + RuleFor(a => a.IsNonResident, f => f.Random.Bool()); + + RuleFor(a => a.PlaceOfWork, f + => new PlaceOfWork + { + Address = new Address + { + Country = f.Address.Country(), + City = f.Address.City(), + Street = f.Address.StreetName(), + Building = f.Address.BuildingNumber() + }, + Name = f.Company.CompanyName(), + PhoneNum = f.Phone.PhoneNumber() + }); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/UserFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/UserFaker.cs new file mode 100644 index 0000000..7b9164f --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/UserFaker.cs @@ -0,0 +1,15 @@ +using Bogus; +using Domains.Users; + +namespace VisaApi.Fakers +{ + public sealed class UserFaker : Faker + { + public UserFaker() + { + RuleFor(u => u.Email, f => f.Internet.Email()); + + RuleFor(u => u.Password, f => f.Internet.Password()); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj index 0be6f2d..9511b31 100644 --- a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj +++ b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj @@ -11,6 +11,7 @@ + From d58255ed6fceebcab2dead9a5ba04547efcdf529 Mon Sep 17 00:00:00 2001 From: prtsie Date: Tue, 17 Sep 2024 20:49:43 +0300 Subject: [PATCH 07/22] finished ApplicantFaker.cs --- SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs index 12d2a73..dd68b6f 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs @@ -2,13 +2,12 @@ using ApplicationLayer.InfrastructureServicesInterfaces; using Bogus; using Domains; using Domains.ApplicantDomain; -using Domains.Users; namespace VisaApi.Fakers { public sealed class ApplicantFaker : Faker { - public ApplicantFaker(User user, IDateTimeProvider dateTimeProvider) + public ApplicantFaker(IDateTimeProvider dateTimeProvider) { RuleFor(a => a.Citizenship, f => f.Address.Country()); @@ -38,12 +37,12 @@ namespace VisaApi.Fakers RuleFor(a => a.MaritalStatus, f => f.Random.Enum()); - RuleFor(a => a.UserId, () => user.Id); - RuleFor(a => a.CitizenshipByBirth, f => f.Address.Country()); RuleFor(a => a.CityOfBirth, f => f.Address.City()); + RuleFor(a => a.CountryOfBirth, f => f.Address.Country()); + RuleFor(a => a.IsNonResident, f => f.Random.Bool()); RuleFor(a => a.PlaceOfWork, f From 6cff609168e0ef96bc2cc6dc34c71504777adbe8 Mon Sep 17 00:00:00 2001 From: prtsie Date: Tue, 17 Sep 2024 20:51:45 +0300 Subject: [PATCH 08/22] tests in ApplicantsRepositoryTests.cs for FindByUserId method --- .../Repositories/ApplicantsRepositoryTests.cs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs new file mode 100644 index 0000000..da47582 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs @@ -0,0 +1,55 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.Applicants.NeededServices; +using FluentAssertions; +using Infrastructure.Database; +using Infrastructure.Database.Applicants.Repositories; +using Infrastructure.Database.Applicants.Repositories.Exceptions; +using VisaApi.Fakers; +using VisaApi.Services; + +namespace VisaApi.Database.Repositories +{ + public class ApplicantsRepositoryTests + { + private static IApplicantsRepository GetRepository(DbContext context) + => new ApplicantsRepository(context, context); + + private static IDateTimeProvider GetDateTimeProvider() => new TestDateTimeProvider(); + + [Fact] + private async Task FindByUserIdForNotExistingShouldThrow() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + ApplicantNotFoundByUserIdException? result = null; + + try + { + await repository.FindByUserIdAsync(Guid.NewGuid(), CancellationToken.None); + } + catch (Exception e) + { + result = e as ApplicantNotFoundByUserIdException; + } + + result.Should().NotBeNull(); + } + + [Fact] + private async Task FindByUserIdForExistingShouldReturnApplicant() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = new UserFaker().Generate(); + var applicant = new ApplicantFaker(GetDateTimeProvider()).Generate(); + applicant.UserId = user.Id; + await context.AddAsync(user); + await repository.AddAsync(applicant, CancellationToken.None); + await context.SaveChangesAsync(); + + var result = await repository.FindByUserIdAsync(user.Id, CancellationToken.None); + + result.Should().BeEquivalentTo(applicant); + } + } +} From 34f76bb258554ce42c5847542118376b878e8dbb Mon Sep 17 00:00:00 2001 From: prtsie Date: Tue, 17 Sep 2024 22:23:16 +0300 Subject: [PATCH 09/22] tests for ApplicationsRepository --- .../Repositories/ApplicantsRepositoryTests.cs | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs index da47582..8444290 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs @@ -11,11 +11,18 @@ namespace VisaApi.Database.Repositories { public class ApplicantsRepositoryTests { + /// Returns + /// Database context + /// Repository private static IApplicantsRepository GetRepository(DbContext context) => new ApplicantsRepository(context, context); + /// Returns private static IDateTimeProvider GetDateTimeProvider() => new TestDateTimeProvider(); + /// + /// Test for method that should throw exception for not existing entity + /// [Fact] private async Task FindByUserIdForNotExistingShouldThrow() { @@ -35,6 +42,9 @@ namespace VisaApi.Database.Repositories result.Should().NotBeNull(); } + /// + /// Test for method that should return existing entity + /// [Fact] private async Task FindByUserIdForExistingShouldReturnApplicant() { @@ -51,5 +61,89 @@ namespace VisaApi.Database.Repositories result.Should().BeEquivalentTo(applicant); } + + /// + /// Test for method that should throw exception for not existing entity + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotExistingShouldThrow() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + ApplicantNotFoundByUserIdException? result = null; + + try + { + await repository.GetApplicantIdByUserId(Guid.NewGuid(), CancellationToken.None); + } + catch (Exception e) + { + result = e as ApplicantNotFoundByUserIdException; + } + + result.Should().NotBeNull(); + } + + /// + /// Test for method that should return existing entity's identifier + /// + [Fact] + private async Task GetApplicantIdByUserIdForExistingShouldReturnApplicant() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = new UserFaker().Generate(); + var applicant = new ApplicantFaker(GetDateTimeProvider()).Generate(); + applicant.UserId = user.Id; + await context.AddAsync(user); + await repository.AddAsync(applicant, CancellationToken.None); + await context.SaveChangesAsync(); + + var result = await repository.GetApplicantIdByUserId(user.Id, CancellationToken.None); + + result.Should().Be(applicant.Id); + } + + /// + /// Test for method that should throw exception for not existing entity + /// + [Fact] + private async Task IsApplicantNonResidentByUserIdForNotExistingShouldThrow() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + ApplicantNotFoundByUserIdException? result = null; + + try + { + await repository.IsApplicantNonResidentByUserId(Guid.NewGuid(), CancellationToken.None); + } + catch (Exception e) + { + result = e as ApplicantNotFoundByUserIdException; + } + + result.Should().NotBeNull(); + } + + /// + /// Test for method that should return existing entity's IsNonResident property + /// + [Fact] + private async Task IsApplicantNonResidentByUserIdForExistingShouldReturnApplicant() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = new UserFaker().Generate(); + var applicant = new ApplicantFaker(GetDateTimeProvider()).Generate(); + applicant.UserId = user.Id; + await context.AddAsync(user); + await repository.AddAsync(applicant, CancellationToken.None); + await context.SaveChangesAsync(); + + var result = await repository.IsApplicantNonResidentByUserId(user.Id, CancellationToken.None); + + result.Should().Be(applicant.IsNonResident); + } } } From 338915cb578472eb2a012a2da4b6740fcadbfe2c Mon Sep 17 00:00:00 2001 From: prtsie Date: Tue, 17 Sep 2024 22:23:30 +0300 Subject: [PATCH 10/22] comment in GenericRepositoryTests.cs --- .../Database/Repositories/Generic/GenericRepositoryTests.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs index 7b4690e..ca68f59 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs @@ -8,6 +8,9 @@ namespace VisaApi.Database.Repositories.Generic; public class GenericRepositoryTests { + /// Returns + /// Database context + /// Repository private static GenericRepository GetRepository(DbContext context) => new TestGenericRepository(context, context); /// Test for method that should return empty collection if nothing added From a78945c33b8c876b2c87ca224ff5dac36f911bce Mon Sep 17 00:00:00 2001 From: prtsie Date: Tue, 17 Sep 2024 22:25:14 +0300 Subject: [PATCH 11/22] moved files in separate folders --- .../VisaApiTests/Fakers/{ => Applicants}/ApplicantFaker.cs | 2 +- .../VisaApiTests/Fakers/{ => Common}/UserFaker.cs | 2 +- .../Fakers/VisaApplications/VisaApplicationFaker.cs | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) rename SchengenVisaApi/VisaApiTests/Fakers/{ => Applicants}/ApplicantFaker.cs (98%) rename SchengenVisaApi/VisaApiTests/Fakers/{ => Common}/UserFaker.cs (89%) create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs diff --git a/SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs similarity index 98% rename from SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs rename to SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs index dd68b6f..999ba29 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/ApplicantFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs @@ -3,7 +3,7 @@ using Bogus; using Domains; using Domains.ApplicantDomain; -namespace VisaApi.Fakers +namespace VisaApi.Fakers.Applicants { public sealed class ApplicantFaker : Faker { diff --git a/SchengenVisaApi/VisaApiTests/Fakers/UserFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs similarity index 89% rename from SchengenVisaApi/VisaApiTests/Fakers/UserFaker.cs rename to SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs index 7b9164f..a7ae1df 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/UserFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs @@ -1,7 +1,7 @@ using Bogus; using Domains.Users; -namespace VisaApi.Fakers +namespace VisaApi.Fakers.Common { public sealed class UserFaker : Faker { diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs new file mode 100644 index 0000000..c870b33 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs @@ -0,0 +1,7 @@ +namespace VisaApi.Fakers.VisaApplications +{ + public class VisaApplicationFaker + { + + } +} From 95610bc72aa035b93c36b05aa9348aca3bb4fde9 Mon Sep 17 00:00:00 2001 From: prtsie Date: Tue, 17 Sep 2024 22:25:35 +0300 Subject: [PATCH 12/22] fixed warning in ApplicantsRepositoryTests.cs --- .../Database/Repositories/ApplicantsRepositoryTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs index 8444290..02057a9 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs @@ -4,7 +4,8 @@ using FluentAssertions; using Infrastructure.Database; using Infrastructure.Database.Applicants.Repositories; using Infrastructure.Database.Applicants.Repositories.Exceptions; -using VisaApi.Fakers; +using VisaApi.Fakers.Applicants; +using VisaApi.Fakers.Common; using VisaApi.Services; namespace VisaApi.Database.Repositories From aa4ff9f18a7284f1ea5bcf9fadc339aa2f252c4f Mon Sep 17 00:00:00 2001 From: prtsie Date: Tue, 17 Sep 2024 22:26:36 +0300 Subject: [PATCH 13/22] comments for fakers --- .../VisaApiTests/Fakers/Applicants/ApplicantFaker.cs | 3 +++ SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs | 3 +++ .../Fakers/VisaApplications/VisaApplicationFaker.cs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs index 999ba29..d25e22d 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs @@ -5,6 +5,9 @@ using Domains.ApplicantDomain; namespace VisaApi.Fakers.Applicants { + /// + /// Generates applicants + /// public sealed class ApplicantFaker : Faker { public ApplicantFaker(IDateTimeProvider dateTimeProvider) diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs index a7ae1df..1e5f271 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs @@ -3,6 +3,9 @@ using Domains.Users; namespace VisaApi.Fakers.Common { + /// + /// Generates users + /// public sealed class UserFaker : Faker { public UserFaker() diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs index c870b33..38316f7 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs @@ -1,5 +1,8 @@ namespace VisaApi.Fakers.VisaApplications { + /// + /// Generates visa applications + /// public class VisaApplicationFaker { From 9d08a36c79461aef0f0dc03403bb21d967cc9333 Mon Sep 17 00:00:00 2001 From: prtsie Date: Wed, 18 Sep 2024 19:45:38 +0300 Subject: [PATCH 14/22] Repository tests --- SchengenVisaApi/VisaApiTests/Collections.cs | 7 + .../Database/InMemoryContextProvider.cs | 10 +- .../Repositories/ApplicantsRepositoryTests.cs | 15 +- .../Generic/GenericRepositoryTests.cs | 42 +-- .../Repositories/UsersRepositoryTests.cs | 92 ++++++ .../VisaApplicationsRepositoryTests.cs | 266 ++++++++++++++++++ .../Fakers/VisaApplications/PastVisaFaker.cs | 29 ++ .../Fakers/VisaApplications/PastVisitFaker.cs | 29 ++ .../PermissionToDestCountryFaker.cs | 20 ++ .../VisaApplications/ReentryPermitFaker.cs | 22 ++ .../VisaApplications/VisaApplicationFaker.cs | 59 +++- SchengenVisaApi/VisaApiTests/GlobalUsings.cs | 1 - 12 files changed, 563 insertions(+), 29 deletions(-) create mode 100644 SchengenVisaApi/VisaApiTests/Collections.cs create mode 100644 SchengenVisaApi/VisaApiTests/Database/Repositories/UsersRepositoryTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Database/Repositories/VisaApplicationsRepositoryTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs delete mode 100644 SchengenVisaApi/VisaApiTests/GlobalUsings.cs diff --git a/SchengenVisaApi/VisaApiTests/Collections.cs b/SchengenVisaApi/VisaApiTests/Collections.cs new file mode 100644 index 0000000..61c1979 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Collections.cs @@ -0,0 +1,7 @@ +namespace VisaApi +{ + public static class Collections + { + public const string ContextUsingTestCollection = "ContextUsingTestCollection"; + } +} diff --git a/SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs b/SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs index 4d33789..90e805a 100644 --- a/SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs +++ b/SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs @@ -11,6 +11,14 @@ namespace VisaApi.Database .ConfigureWarnings(b => b.Ignore(InMemoryEventId.TransactionIgnoredWarning)) .Options; - public static DbContext GetDbContext() => new(opts); + public static DbContext GetDbContext() + { + var result = new DbContext(opts); + + result.Database.EnsureDeleted(); + result.Database.EnsureCreated(); + + return result; + } } } diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs index 02057a9..c95a302 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs @@ -7,11 +7,16 @@ using Infrastructure.Database.Applicants.Repositories.Exceptions; using VisaApi.Fakers.Applicants; using VisaApi.Fakers.Common; using VisaApi.Services; +using Xunit; namespace VisaApi.Database.Repositories { + [Collection(Collections.ContextUsingTestCollection)] public class ApplicantsRepositoryTests { + private static UserFaker userFaker = new(); + private static ApplicantFaker applicantFaker = new(GetDateTimeProvider()); + /// Returns /// Database context /// Repository @@ -51,8 +56,8 @@ namespace VisaApi.Database.Repositories { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); - var user = new UserFaker().Generate(); - var applicant = new ApplicantFaker(GetDateTimeProvider()).Generate(); + var user = userFaker.Generate(); + var applicant = applicantFaker.Generate(); applicant.UserId = user.Id; await context.AddAsync(user); await repository.AddAsync(applicant, CancellationToken.None); @@ -93,8 +98,8 @@ namespace VisaApi.Database.Repositories { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); - var user = new UserFaker().Generate(); - var applicant = new ApplicantFaker(GetDateTimeProvider()).Generate(); + var user = userFaker.Generate(); + var applicant = applicantFaker.Generate(); applicant.UserId = user.Id; await context.AddAsync(user); await repository.AddAsync(applicant, CancellationToken.None); @@ -135,7 +140,7 @@ namespace VisaApi.Database.Repositories { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); - var user = new UserFaker().Generate(); + var user = userFaker.Generate(); var applicant = new ApplicantFaker(GetDateTimeProvider()).Generate(); applicant.UserId = user.Id; await context.AddAsync(user); diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs index ca68f59..b7da95d 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs @@ -3,9 +3,11 @@ using Domains.Users; using FluentAssertions; using Infrastructure.Database; using Infrastructure.Database.Generic; +using Xunit; namespace VisaApi.Database.Repositories.Generic; +[Collection(Collections.ContextUsingTestCollection)] public class GenericRepositoryTests { /// Returns @@ -15,21 +17,21 @@ public class GenericRepositoryTests /// Test for method that should return empty collection if nothing added [Fact] - public async Task GetAllForEmptyShouldReturnEmpty() + public void GetAllForEmptyShouldReturnEmpty() { - await using var context = InMemoryContextProvider.GetDbContext(); + using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); - var result = await repository.GetAllAsync(CancellationToken.None); + var result = repository.GetAllAsync(CancellationToken.None).Result; result.Should().BeEmpty(); } /// Test for method that should return collection with added entities [Fact] - public async Task GetAllForNotEmptyShouldReturnEntities() + public void GetAllForNotEmptyShouldReturnEntities() { - await using var context = InMemoryContextProvider.GetDbContext(); + using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); User[] users = [ @@ -38,49 +40,49 @@ public class GenericRepositoryTests ]; foreach (var user in users) { - await repository.AddAsync(user, CancellationToken.None); + repository.AddAsync(user, CancellationToken.None).Wait(); } - await context.SaveChangesAsync(); + context.SaveChanges(); - var result = await repository.GetAllAsync(CancellationToken.None); + var result = repository.GetAllAsync(CancellationToken.None).Result; - result.Should().OnlyContain(user => users.Contains(user)); + result.Should().Contain(users).And.HaveSameCount(users); } /// Test for method that should return existing entity [Fact] - public async Task GetByIdForExistingShouldReturnEntity() + public void GetByIdForExistingShouldReturnEntity() { - await using var context = InMemoryContextProvider.GetDbContext(); + using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = new User { Email = "nasrudin@mail.ru", Password = "12345", Role = Role.Admin }; - await repository.AddAsync(user, CancellationToken.None); + repository.AddAsync(user, CancellationToken.None).Wait(); - await context.SaveChangesAsync(); + context.SaveChanges(); - var result = await repository.GetByIdAsync(user.Id, CancellationToken.None); + var result = repository.GetByIdAsync(user.Id, CancellationToken.None).Result; result.Should().Be(user); } /// Test for method that should throw exception for not found entity [Fact] - public async Task GetByIdForNotExistingShouldThrow() + public void GetByIdForNotExistingShouldThrow() { - await using var context = InMemoryContextProvider.GetDbContext(); + using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); - await context.SaveChangesAsync(); + context.SaveChanges(); EntityNotFoundByIdException? result = null; try { - await repository.GetByIdAsync(Guid.NewGuid(), CancellationToken.None); + repository.GetByIdAsync(Guid.NewGuid(), CancellationToken.None).Wait(); } - catch (Exception e) + catch (AggregateException e) { - result = e as EntityNotFoundByIdException; + result = e.InnerException as EntityNotFoundByIdException; } result.Should().NotBeNull(); diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/UsersRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/UsersRepositoryTests.cs new file mode 100644 index 0000000..82ad536 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/UsersRepositoryTests.cs @@ -0,0 +1,92 @@ +using ApplicationLayer.Services.AuthServices.NeededServices; +using ApplicationLayer.Services.VisaApplications.NeededServices; +using Domains.Users; +using FluentAssertions; +using Infrastructure.Database; +using Infrastructure.Database.Users.Repositories; +using VisaApi.Fakers.Common; +using Xunit; + +namespace VisaApi.Database.Repositories +{ + [Collection(Collections.ContextUsingTestCollection)] + public class UsersRepositoryTests + { + private UserFaker userFaker = new(); + + /// Returns + /// Database context + /// Repository + private static IUsersRepository GetRepository(DbContext context) + => new UsersRepository(context, context); + + /// + /// Test for method that should return null for not existing email + /// + [Fact] + private async Task FindByEmailForNotExistingShouldReturnNull() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + + var result = await repository.FindByEmailAsync("email@email.ru", CancellationToken.None); + + result.Should().BeNull(); + } + + /// + /// Test for method that should return entity for existing email + /// + [Fact] + private async Task FindByEmailForExistingShouldReturnEntity() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = userFaker.Generate(); + await repository.AddAsync(user, CancellationToken.None); + await context.SaveChangesAsync(); + + var result = await repository.FindByEmailAsync(user.Email, CancellationToken.None); + + result.Should().Be(user); + } + + /// + /// Test for method that should return empty from empty db + /// + [Fact] + private async Task GetAllOfRoleForEmptyShouldReturnEmpty() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + + var result = await repository.GetAllOfRoleAsync(Role.ApprovingAuthority, CancellationToken.None); + + result.Should().BeEmpty(); + } + + /// + /// Test for method that should return entities from not empty db + /// + [Fact] + private async Task GetAllOfRoleForNotEmptyShouldReturnEntities() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var users = new List(); + for (var i = 0; i < 3; i++) + { + var user = userFaker.Generate(); + user.Role = Role.ApprovingAuthority; + users.Add(user); + await repository.AddAsync(user, CancellationToken.None); + } + + await context.SaveChangesAsync(); + + var result = await repository.GetAllOfRoleAsync(Role.ApprovingAuthority, CancellationToken.None); + + result.Should().Contain(users).And.HaveSameCount(users); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/VisaApplicationsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Database/Repositories/VisaApplicationsRepositoryTests.cs new file mode 100644 index 0000000..2709178 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Database/Repositories/VisaApplicationsRepositoryTests.cs @@ -0,0 +1,266 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.VisaApplications.NeededServices; +using Domains.VisaApplicationDomain; +using FluentAssertions; +using Infrastructure.Database; +using Infrastructure.Database.VisaApplications.Repositories; +using Infrastructure.Database.VisaApplications.Repositories.Exceptions; +using VisaApi.Fakers.Applicants; +using VisaApi.Fakers.Common; +using VisaApi.Fakers.VisaApplications; +using VisaApi.Services; +using Xunit; + +namespace VisaApi.Database.Repositories +{ + [Collection(Collections.ContextUsingTestCollection)] + public class VisaApplicationsRepositoryTests + { + private UserFaker userFaker = new(); + private ApplicantFaker applicantFaker = new(GetDateTimeProvider()); + private VisaApplicationFaker applicationFaker = new(GetDateTimeProvider()); + + /// Returns + /// Database context + /// Repository + private static IVisaApplicationsRepository GetRepository(DbContext context) + => new VisaApplicationsRepository(context, context); + + /// Returns + private static IDateTimeProvider GetDateTimeProvider() => new TestDateTimeProvider(); + + /// + /// Test for method that should return empty if no applications added + /// + [Fact] + private async Task GetOfApplicantForEmptyShouldReturnEmpty() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = userFaker.Generate(); + var applicant = applicantFaker.Generate(); + applicant.UserId = user.Id; + await context.AddAsync(user); + await context.AddAsync(applicant); + await context.SaveChangesAsync(); + + var result = await repository.GetOfApplicantAsync(applicant.Id, CancellationToken.None); + + result.Should().BeEmpty(); + } + + /// + /// Test for method that should return added entities + /// + [Fact] + private async Task GetOfApplicantForExistingShouldReturnEntities() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = userFaker.Generate(); + var applicant = applicantFaker.Generate(); + applicant.UserId = user.Id; + await context.AddAsync(user); + await context.AddAsync(applicant); + var applications = new List(); + for (var i = 0; i < 5; i++) + { + var application = applicationFaker.GenerateValid(applicant); + applications.Add(application); + await context.AddAsync(application); + } + + await context.SaveChangesAsync(); + + var result = await repository.GetOfApplicantAsync(applicant.Id, CancellationToken.None); + + result.Should().Contain(applications).And.HaveSameCount(applications); + } + + /// + /// Test for method that should throw exception for not existing entities + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotExistingShouldThrow() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + ApplicationNotFoundByApplicantAndApplicationIdException? result = null; + + await context.SaveChangesAsync(); + + try + { + await repository.GetByApplicantAndApplicationIdAsync(Guid.NewGuid(), Guid.NewGuid(), CancellationToken.None); + } + catch (Exception e) + { + result = e as ApplicationNotFoundByApplicantAndApplicationIdException; + } + + result.Should().NotBeNull(); + } + + /// + /// Test for method that should throw exception for not existing applicant + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotExistingApplicantShouldThrow() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = userFaker.Generate(); + var applicant = applicantFaker.Generate(); + applicant.UserId = user.Id; + var application = applicationFaker.GenerateValid(applicant); + await context.AddAsync(user); + await context.AddAsync(applicant); + await context.AddAsync(application); + ApplicationNotFoundByApplicantAndApplicationIdException? result = null; + + await context.SaveChangesAsync(); + + try + { + await repository.GetByApplicantAndApplicationIdAsync(Guid.NewGuid(), application.Id, CancellationToken.None); + } + catch (Exception e) + { + result = e as ApplicationNotFoundByApplicantAndApplicationIdException; + } + + result.Should().NotBeNull(); + } + + /// + /// Test for method that should throw exception for not existing application + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotExistingApplicationShouldThrow() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = userFaker.Generate(); + var applicant = applicantFaker.Generate(); + applicant.UserId = user.Id; + await context.AddAsync(user); + await context.AddAsync(applicant); + ApplicationNotFoundByApplicantAndApplicationIdException? result = null; + + await context.SaveChangesAsync(); + + try + { + await repository.GetByApplicantAndApplicationIdAsync(applicant.Id, Guid.NewGuid(), CancellationToken.None); + } + catch (Exception e) + { + result = e as ApplicationNotFoundByApplicantAndApplicationIdException; + } + + result.Should().NotBeNull(); + } + + /// + /// Test for method + /// that should throw exception for not accessible application + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotAccessibleApplicationShouldThrow() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = userFaker.Generate(); + var applicant = applicantFaker.Generate(); + applicant.UserId = user.Id; + var otherUser = userFaker.Generate(); + var otherApplicant = applicantFaker.Generate(); + otherApplicant.UserId = user.Id; + var notAccessibleApplication = applicationFaker.GenerateValid(otherApplicant); + await context.AddAsync(user); + await context.AddAsync(applicant); + await context.AddAsync(otherUser); + await context.AddAsync(otherApplicant); + await context.AddAsync(notAccessibleApplication); + ApplicationNotFoundByApplicantAndApplicationIdException? result = null; + + await context.SaveChangesAsync(); + + try + { + await repository.GetByApplicantAndApplicationIdAsync(applicant.Id, notAccessibleApplication.Id, CancellationToken.None); + } + catch (Exception e) + { + result = e as ApplicationNotFoundByApplicantAndApplicationIdException; + } + + result.Should().NotBeNull(); + } + + /// + /// Test for method + /// that should return application for valid identifiers + /// + [Fact] + private async Task GetApplicantIdByUserIdForValidIdsShouldReturnApplication() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = userFaker.Generate(); + var applicant = applicantFaker.Generate(); + applicant.UserId = user.Id; + var application = applicationFaker.GenerateValid(applicant); + await context.AddAsync(user); + await context.AddAsync(applicant); + await context.AddAsync(application); + + await context.SaveChangesAsync(); + + var result = await repository.GetByApplicantAndApplicationIdAsync(applicant.Id, application.Id, CancellationToken.None); + + result.Should().Be(application); + } + + /// + /// Test for method that should return empty from empty db + /// + [Fact] + private async Task GetPendingApplicationsForEmptyShouldReturnEmpty() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + + var result = await repository.GetPendingApplicationsAsync(CancellationToken.None); + + result.Should().BeEmpty(); + } + + /// + /// Test for method that should return pending applications from not empty db + /// + [Fact] + private async Task GetPendingApplicationsForExistingShouldReturnExistingPending() + { + await using var context = InMemoryContextProvider.GetDbContext(); + var repository = GetRepository(context); + var user = userFaker.Generate(); + var applicant = applicantFaker.Generate(); + applicant.UserId = user.Id; + var applicationPending = applicationFaker.GenerateValid(applicant); + applicationPending.Status = ApplicationStatus.Pending; + var applicationNotPending = applicationFaker.GenerateValid(applicant); + applicationNotPending.Status = ApplicationStatus.Approved; + await context.AddAsync(user); + await context.AddAsync(applicant); + await context.AddAsync(applicationPending); + await context.AddAsync(applicationNotPending); + + await context.SaveChangesAsync(); + + var result = await repository.GetPendingApplicationsAsync(CancellationToken.None); + + result.Should().Contain(applicationPending).And.HaveCount(1); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs new file mode 100644 index 0000000..3b827c2 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs @@ -0,0 +1,29 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using Bogus; +using Domains.VisaApplicationDomain; + +namespace VisaApi.Fakers.VisaApplications +{ + /// + /// Generates past visas + /// + public sealed class PastVisaFaker : Faker + { + private IDateTimeProvider dateTimeProvider; + + public PastVisaFaker(IDateTimeProvider dateTimeProvider) + { + this.dateTimeProvider = dateTimeProvider; + + RuleFor(pv => pv.Name, f => f.Random.Words()); + } + + public PastVisa GenerateValid() + { + var result = Generate(); + result.IssueDate = dateTimeProvider.Now().AddDays(Random.Shared.Next(11, 900)); + result.ExpirationDate = result.IssueDate.AddDays(Random.Shared.Next(1, 11)); + return result; + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs new file mode 100644 index 0000000..df32675 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs @@ -0,0 +1,29 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using Bogus; +using Domains.VisaApplicationDomain; + +namespace VisaApi.Fakers.VisaApplications +{ + /// + /// Generates past visas + /// + public sealed class PastVisitFaker : Faker + { + private IDateTimeProvider dateTimeProvider; + + public PastVisitFaker(IDateTimeProvider dateTimeProvider) + { + this.dateTimeProvider = dateTimeProvider; + + RuleFor(pv => pv.DestinationCountry, f => f.Address.Country()); + } + + public PastVisit GenerateValid() + { + var result = Generate(); + result.StartDate = dateTimeProvider.Now().AddDays(Random.Shared.Next(11, 900)); + result.EndDate = result.StartDate.AddDays(Random.Shared.Next(1, 11)); + return result; + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs new file mode 100644 index 0000000..f79b31c --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs @@ -0,0 +1,20 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using Bogus; +using Domains.VisaApplicationDomain; + +namespace VisaApi.Fakers.VisaApplications +{ + /// + /// Generates permissions to destination Country + /// + public sealed class PermissionToDestCountryFaker : Faker + { + public PermissionToDestCountryFaker(IDateTimeProvider dateTimeProvider) + { + RuleFor(p => p.Issuer, f => f.Company.CompanyName()); + + RuleFor(p => p.ExpirationDate, + f => f.Date.Future(4, dateTimeProvider.Now())); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs new file mode 100644 index 0000000..6ea3009 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs @@ -0,0 +1,22 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using Bogus; +using Domains; +using Domains.VisaApplicationDomain; + +namespace VisaApi.Fakers.VisaApplications +{ + /// + /// Generates re-entry permissions + /// + public sealed class ReentryPermitFaker : Faker + { + public ReentryPermitFaker(IDateTimeProvider dateTimeProvider) + { + RuleFor(p => p.Number, + f => f.Random.String(ConfigurationConstraints.ReentryPermitNumberLength)); + + RuleFor(p => p.ExpirationDate, + f => f.Date.Future(4, dateTimeProvider.Now())); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs index 38316f7..7514fa3 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs @@ -1,10 +1,65 @@ -namespace VisaApi.Fakers.VisaApplications +using ApplicationLayer.InfrastructureServicesInterfaces; +using Bogus; +using Domains; +using Domains.ApplicantDomain; +using Domains.VisaApplicationDomain; + +namespace VisaApi.Fakers.VisaApplications { /// /// Generates visa applications /// - public class VisaApplicationFaker + public sealed class VisaApplicationFaker : Faker { + private static ReentryPermitFaker reentryPermitFaker = null!; + private static PermissionToDestCountryFaker permissionToDestCountryFaker = null!; + public VisaApplicationFaker(IDateTimeProvider dateTimeProvider) + { + reentryPermitFaker = new(dateTimeProvider); + permissionToDestCountryFaker = new(dateTimeProvider); + var pastVisaFaker = new PastVisaFaker(dateTimeProvider); + var pastVisitFaker = new PastVisitFaker(dateTimeProvider); + + RuleFor(va => va.Status, f => f.Random.Enum()); + + RuleFor(va => va.DestinationCountry, f => f.Address.Country()); + + RuleFor(va => va.PastVisas, + f => f.PickRandom(pastVisaFaker.Generate(3), f.Random.Int(0, 3)).ToList()); + + RuleFor(va => va.PastVisits, + f => f.PickRandom(pastVisitFaker.Generate(3), f.Random.Int(0, 3)).ToList()); + + RuleFor(va => va.VisaCategory, f => f.Random.Enum()); + + RuleFor(va => va.ForGroup, f => f.Random.Bool()); + + RuleFor(va => va.RequestedNumberOfEntries, + f => f.Random.Enum()); + + RuleFor(va => va.RequestDate, dateTimeProvider.Now); + + RuleFor(va => va.ValidDaysRequested, + f => f.Random.Int(1, ConfigurationConstraints.MaxValidDays)); + } + + public VisaApplication GenerateValid(Applicant applicant) + { + var result = Generate(); + + result.ApplicantId = applicant.Id; + if (applicant.IsNonResident) + { + result.ReentryPermit = reentryPermitFaker.Generate(); + } + + if (result.VisaCategory is VisaCategory.Transit) + { + result.PermissionToDestCountry = permissionToDestCountryFaker.Generate(); + } + + return result; + } } } diff --git a/SchengenVisaApi/VisaApiTests/GlobalUsings.cs b/SchengenVisaApi/VisaApiTests/GlobalUsings.cs deleted file mode 100644 index c802f44..0000000 --- a/SchengenVisaApi/VisaApiTests/GlobalUsings.cs +++ /dev/null @@ -1 +0,0 @@ -global using Xunit; From dd3019492a6f31c34481cce886e70db38c5e02b8 Mon Sep 17 00:00:00 2001 From: prtsie Date: Wed, 18 Sep 2024 19:48:43 +0300 Subject: [PATCH 15/22] Changed file hierarchy for tests --- .../Infrastructure}/Database/InMemoryContextProvider.cs | 2 +- .../Database/Repositories/ApplicantsRepositoryTests.cs | 2 +- .../Database/Repositories/Generic/GenericRepositoryTests.cs | 2 +- .../Database/Repositories/Generic/TestGenericRepository.cs | 2 +- .../Database/Repositories/UsersRepositoryTests.cs | 2 +- .../Database/Repositories/VisaApplicationsRepositoryTests.cs | 2 +- SchengenVisaApi/VisaApiTests/VisaApiTests.csproj | 4 ++++ 7 files changed, 10 insertions(+), 6 deletions(-) rename SchengenVisaApi/VisaApiTests/{ => Tests/Infrastructure}/Database/InMemoryContextProvider.cs (93%) rename SchengenVisaApi/VisaApiTests/{ => Tests/Infrastructure}/Database/Repositories/ApplicantsRepositoryTests.cs (99%) rename SchengenVisaApi/VisaApiTests/{ => Tests/Infrastructure}/Database/Repositories/Generic/GenericRepositoryTests.cs (97%) rename SchengenVisaApi/VisaApiTests/{ => Tests/Infrastructure}/Database/Repositories/Generic/TestGenericRepository.cs (73%) rename SchengenVisaApi/VisaApiTests/{ => Tests/Infrastructure}/Database/Repositories/UsersRepositoryTests.cs (98%) rename SchengenVisaApi/VisaApiTests/{ => Tests/Infrastructure}/Database/Repositories/VisaApplicationsRepositoryTests.cs (99%) diff --git a/SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/InMemoryContextProvider.cs similarity index 93% rename from SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs rename to SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/InMemoryContextProvider.cs index 90e805a..ec81a0f 100644 --- a/SchengenVisaApi/VisaApiTests/Database/InMemoryContextProvider.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/InMemoryContextProvider.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using DbContext = Infrastructure.Database.DbContext; -namespace VisaApi.Database +namespace VisaApi.Tests.Infrastructure.Database { public static class InMemoryContextProvider { diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs similarity index 99% rename from SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs rename to SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs index c95a302..8cdd5a3 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/ApplicantsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs @@ -9,7 +9,7 @@ using VisaApi.Fakers.Common; using VisaApi.Services; using Xunit; -namespace VisaApi.Database.Repositories +namespace VisaApi.Tests.Infrastructure.Database.Repositories { [Collection(Collections.ContextUsingTestCollection)] public class ApplicantsRepositoryTests diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/GenericRepositoryTests.cs similarity index 97% rename from SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs rename to SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/GenericRepositoryTests.cs index b7da95d..035bfc7 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/GenericRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/GenericRepositoryTests.cs @@ -5,7 +5,7 @@ using Infrastructure.Database; using Infrastructure.Database.Generic; using Xunit; -namespace VisaApi.Database.Repositories.Generic; +namespace VisaApi.Tests.Infrastructure.Database.Repositories.Generic; [Collection(Collections.ContextUsingTestCollection)] public class GenericRepositoryTests diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/TestGenericRepository.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/TestGenericRepository.cs similarity index 73% rename from SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/TestGenericRepository.cs rename to SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/TestGenericRepository.cs index c89a2e0..94842b8 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/Generic/TestGenericRepository.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/TestGenericRepository.cs @@ -1,7 +1,7 @@ using Domains.Users; using Infrastructure.Database.Generic; -namespace VisaApi.Database.Repositories.Generic +namespace VisaApi.Tests.Infrastructure.Database.Repositories.Generic { public class TestGenericRepository(IGenericReader reader, IGenericWriter writer) : GenericRepository(reader, writer); } diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/UsersRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs similarity index 98% rename from SchengenVisaApi/VisaApiTests/Database/Repositories/UsersRepositoryTests.cs rename to SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs index 82ad536..834aa81 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/UsersRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs @@ -7,7 +7,7 @@ using Infrastructure.Database.Users.Repositories; using VisaApi.Fakers.Common; using Xunit; -namespace VisaApi.Database.Repositories +namespace VisaApi.Tests.Infrastructure.Database.Repositories { [Collection(Collections.ContextUsingTestCollection)] public class UsersRepositoryTests diff --git a/SchengenVisaApi/VisaApiTests/Database/Repositories/VisaApplicationsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs similarity index 99% rename from SchengenVisaApi/VisaApiTests/Database/Repositories/VisaApplicationsRepositoryTests.cs rename to SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs index 2709178..d18db91 100644 --- a/SchengenVisaApi/VisaApiTests/Database/Repositories/VisaApplicationsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs @@ -11,7 +11,7 @@ using VisaApi.Fakers.VisaApplications; using VisaApi.Services; using Xunit; -namespace VisaApi.Database.Repositories +namespace VisaApi.Tests.Infrastructure.Database.Repositories { [Collection(Collections.ContextUsingTestCollection)] public class VisaApplicationsRepositoryTests diff --git a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj index 9511b31..c58d98d 100644 --- a/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj +++ b/SchengenVisaApi/VisaApiTests/VisaApiTests.csproj @@ -26,4 +26,8 @@ + + + + From 23cdae8ff3a7b5116fd486e3b9dfdd7b936a9644 Mon Sep 17 00:00:00 2001 From: prtsie Date: Wed, 18 Sep 2024 19:50:14 +0300 Subject: [PATCH 16/22] made fakers in tests static and readonly --- .../Database/Repositories/ApplicantsRepositoryTests.cs | 4 ++-- .../Database/Repositories/UsersRepositoryTests.cs | 2 +- .../Repositories/VisaApplicationsRepositoryTests.cs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs index 8cdd5a3..23099a6 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs @@ -14,8 +14,8 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories [Collection(Collections.ContextUsingTestCollection)] public class ApplicantsRepositoryTests { - private static UserFaker userFaker = new(); - private static ApplicantFaker applicantFaker = new(GetDateTimeProvider()); + private readonly static UserFaker userFaker = new(); + private readonly static ApplicantFaker applicantFaker = new(GetDateTimeProvider()); /// Returns /// Database context diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs index 834aa81..3fc3e9a 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs @@ -12,7 +12,7 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories [Collection(Collections.ContextUsingTestCollection)] public class UsersRepositoryTests { - private UserFaker userFaker = new(); + private readonly static UserFaker userFaker = new(); /// Returns /// Database context diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs index d18db91..80de943 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs @@ -16,9 +16,9 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories [Collection(Collections.ContextUsingTestCollection)] public class VisaApplicationsRepositoryTests { - private UserFaker userFaker = new(); - private ApplicantFaker applicantFaker = new(GetDateTimeProvider()); - private VisaApplicationFaker applicationFaker = new(GetDateTimeProvider()); + private readonly static UserFaker userFaker = new(); + private readonly static ApplicantFaker applicantFaker = new(GetDateTimeProvider()); + private readonly static VisaApplicationFaker applicationFaker = new(GetDateTimeProvider()); /// Returns /// Database context From a2080d7e4e108f80eba3c93fddb1be29223e88b8 Mon Sep 17 00:00:00 2001 From: prtsie Date: Thu, 19 Sep 2024 17:28:51 +0300 Subject: [PATCH 17/22] Started validation tests --- .../ChangeUserAuthDataRequestValidator.cs | 3 ++ .../Fakers/Common/ChangeAuthDataFaker.cs | 15 ++++++++ .../ChangeUserAuthDataRequestFaker.cs | 16 ++++++++ .../Fakers/{Common => Users}/UserFaker.cs | 2 +- ...hangeUserAuthDataRequestValidationTests.cs | 37 +++++++++++++++++++ .../Repositories/ApplicantsRepositoryTests.cs | 2 +- .../Repositories/UsersRepositoryTests.cs | 2 +- .../VisaApplicationsRepositoryTests.cs | 2 +- 8 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/Common/ChangeAuthDataFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/Users/Requests/ChangeUserAuthDataRequestFaker.cs rename SchengenVisaApi/VisaApiTests/Fakers/{Common => Users}/UserFaker.cs (91%) create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs diff --git a/SchengenVisaApi/ApplicationLayer/Services/Users/Requests/Validation/ChangeUserAuthDataRequestValidator.cs b/SchengenVisaApi/ApplicationLayer/Services/Users/Requests/Validation/ChangeUserAuthDataRequestValidator.cs index e824e77..e858422 100644 --- a/SchengenVisaApi/ApplicationLayer/Services/Users/Requests/Validation/ChangeUserAuthDataRequestValidator.cs +++ b/SchengenVisaApi/ApplicationLayer/Services/Users/Requests/Validation/ChangeUserAuthDataRequestValidator.cs @@ -7,6 +7,9 @@ namespace ApplicationLayer.Services.Users.Requests.Validation { public ChangeUserAuthDataRequestValidator() { + RuleFor(r => r.UserId) + .NotEmpty(); + RuleFor(r => r.NewAuthData) .NotEmpty(); diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Common/ChangeAuthDataFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Common/ChangeAuthDataFaker.cs new file mode 100644 index 0000000..fa000f0 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/Common/ChangeAuthDataFaker.cs @@ -0,0 +1,15 @@ +using ApplicationLayer.Services.Users.Models; +using Bogus; + +namespace VisaApi.Fakers.Common +{ + public sealed class ChangeAuthDataFaker : Faker + { + public ChangeAuthDataFaker() + { + RuleFor(a => a.Email, f => f.Internet.Email()); + + RuleFor(a => a.Password, f => f.Internet.Password()); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Users/Requests/ChangeUserAuthDataRequestFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Users/Requests/ChangeUserAuthDataRequestFaker.cs new file mode 100644 index 0000000..dce8164 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/Users/Requests/ChangeUserAuthDataRequestFaker.cs @@ -0,0 +1,16 @@ +using ApplicationLayer.Services.Users.Requests; +using Bogus; +using VisaApi.Fakers.Common; + +namespace VisaApi.Fakers.Users.Requests +{ + public sealed class ChangeUserAuthDataRequestFaker : Faker + { + private static ChangeAuthDataFaker changeAuthDataFaker = new(); + + public ChangeUserAuthDataRequestFaker() + { + CustomInstantiator(_ => new(Guid.NewGuid(), changeAuthDataFaker.Generate())); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Users/UserFaker.cs similarity index 91% rename from SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs rename to SchengenVisaApi/VisaApiTests/Fakers/Users/UserFaker.cs index 1e5f271..11f7b40 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Common/UserFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Users/UserFaker.cs @@ -1,7 +1,7 @@ using Bogus; using Domains.Users; -namespace VisaApi.Fakers.Common +namespace VisaApi.Fakers.Users { /// /// Generates users diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs new file mode 100644 index 0000000..59ad092 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs @@ -0,0 +1,37 @@ +using ApplicationLayer.Services.Users.Requests; +using ApplicationLayer.Services.Users.Requests.Validation; +using FluentAssertions; +using FluentValidation; +using VisaApi.Fakers.Users.Requests; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.Users +{ + public class ChangeUserAuthDataRequestValidationTests + { + private readonly static IValidator validator = new ChangeUserAuthDataRequestValidator(); + private readonly static ChangeUserAuthDataRequestFaker faker = new(); + + /// + /// Test for validator that should return validation error for empty auth data + /// + [Fact] + private async Task ValidateForEmptyAuthDataShouldReturnError() + { + var request = faker.Generate(); + request.NewAuthData = null!; + NullReferenceException? result = null; + + try + { + await validator.ValidateAsync(request); + } + catch (Exception e) + { + result = e as NullReferenceException; + } + + result.Should().NotBeNull(); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs index 23099a6..e5eb0b2 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs @@ -5,7 +5,7 @@ using Infrastructure.Database; using Infrastructure.Database.Applicants.Repositories; using Infrastructure.Database.Applicants.Repositories.Exceptions; using VisaApi.Fakers.Applicants; -using VisaApi.Fakers.Common; +using VisaApi.Fakers.Users; using VisaApi.Services; using Xunit; diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs index 3fc3e9a..50227d7 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs @@ -4,7 +4,7 @@ using Domains.Users; using FluentAssertions; using Infrastructure.Database; using Infrastructure.Database.Users.Repositories; -using VisaApi.Fakers.Common; +using VisaApi.Fakers.Users; using Xunit; namespace VisaApi.Tests.Infrastructure.Database.Repositories diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs index 80de943..b034dd9 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs @@ -6,7 +6,7 @@ using Infrastructure.Database; using Infrastructure.Database.VisaApplications.Repositories; using Infrastructure.Database.VisaApplications.Repositories.Exceptions; using VisaApi.Fakers.Applicants; -using VisaApi.Fakers.Common; +using VisaApi.Fakers.Users; using VisaApi.Fakers.VisaApplications; using VisaApi.Services; using Xunit; From 7d5d3501878f4aae02aee79dd45b3fe9f36fe9c0 Mon Sep 17 00:00:00 2001 From: prtsie Date: Thu, 19 Sep 2024 20:44:36 +0300 Subject: [PATCH 18/22] Error fix in ChangeUserAuthDataRequestValidationTests.cs --- .../ChangeUserAuthDataRequestValidationTests.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs index 59ad092..2b9ea74 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs @@ -13,10 +13,10 @@ namespace VisaApi.Tests.Application.Validation.Users private readonly static ChangeUserAuthDataRequestFaker faker = new(); /// - /// Test for validator that should return validation error for empty auth data + /// Test for validator that should throw exception for empty auth data /// [Fact] - private async Task ValidateForEmptyAuthDataShouldReturnError() + private async Task ValidateForEmptyAuthDataShouldThrow() { var request = faker.Generate(); request.NewAuthData = null!; @@ -33,5 +33,17 @@ namespace VisaApi.Tests.Application.Validation.Users result.Should().NotBeNull(); } + + /// + /// Test for validator that should no errors for valid entity + /// + [Fact] + private async Task ValidateForValidShouldReturnNoErrors() + { + var request = faker.Generate(); + var result = await validator.ValidateAsync(request); + + result.IsValid.Should().BeTrue(); + } } } From 958c69df4c61555d4f425422e700a80682687c17 Mon Sep 17 00:00:00 2001 From: prtsie Date: Thu, 19 Sep 2024 20:44:57 +0300 Subject: [PATCH 19/22] Tests --- .../Applicants/Requests/NameModelFaker.cs | 17 ++ .../VisaApiTests/Fakers/Auth/AuthDataFaker.cs | 15 ++ .../Fakers/Auth/RegisterRequestFaker.cs | 15 ++ .../Applicants/NameValidatorTests.cs | 171 ++++++++++++++++++ .../Validation/Auth/AuthDataValidatorTests.cs | 114 ++++++++++++ .../Auth/RegisterRequestValidatorTests.cs | 94 ++++++++++ 6 files changed, 426 insertions(+) create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/NameModelFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/Auth/AuthDataFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/Auth/RegisterRequestFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameValidatorTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/AuthDataValidatorTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/NameModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/NameModelFaker.cs new file mode 100644 index 0000000..31d476d --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/NameModelFaker.cs @@ -0,0 +1,17 @@ +using ApplicationLayer.Services.Applicants.Models; +using Bogus; + +namespace VisaApi.Fakers.Applicants.Requests +{ + public sealed class NameModelFaker : Faker + { + public NameModelFaker() + { + RuleFor(m => m.FirstName, f => f.Name.FirstName()); + + RuleFor(m => m.Surname, f => f.Name.LastName()); + + RuleFor(m => m.Patronymic, f => f.Name.FirstName()); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Auth/AuthDataFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Auth/AuthDataFaker.cs new file mode 100644 index 0000000..2309f79 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/Auth/AuthDataFaker.cs @@ -0,0 +1,15 @@ +using ApplicationLayer.Services.AuthServices.Common; +using Bogus; + +namespace VisaApi.Fakers.Auth +{ + public sealed class AuthDataFaker : Faker + { + public AuthDataFaker() + { + RuleFor(a => a.Email, f => f.Internet.Email()); + + RuleFor(a => a.Password, f => f.Internet.Password()); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Auth/RegisterRequestFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Auth/RegisterRequestFaker.cs new file mode 100644 index 0000000..2835c35 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/Auth/RegisterRequestFaker.cs @@ -0,0 +1,15 @@ +using ApplicationLayer.Services.AuthServices.Requests; +using Bogus; + +namespace VisaApi.Fakers.Auth +{ + public sealed class RegisterRequestFaker : Faker + { + private static AuthDataFaker authDataFaker = new(); + + public RegisterRequestFaker() + { + RuleFor(r => r.AuthData, () => authDataFaker.Generate()); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameValidatorTests.cs new file mode 100644 index 0000000..2f91c47 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameValidatorTests.cs @@ -0,0 +1,171 @@ +using System.Text; +using ApplicationLayer.Services.Applicants.Models; +using ApplicationLayer.Services.Applicants.Models.Validation; +using Domains; +using FluentAssertions; +using FluentValidation; +using VisaApi.Fakers.Applicants.Requests; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.Applicants +{ + public class NameValidatorTests + { + private static IValidator validator = new NameModelValidator(); + private static NameModelFaker faker = new(); + + /// + /// Test for validator that should throw for empty first name + /// + [Fact] + private async Task ValidateForEmptyFirstNameShouldThrow() + { + var name = faker.Generate(); + name.FirstName = null!; + + var result = await validator.ValidateAsync(name); + + result.Errors.Where(error => error.PropertyName == nameof(name.FirstName)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should throw for empty surname + /// + [Fact] + private async Task ValidateForEmptySurnameShouldThrow() + { + var name = faker.Generate(); + name.Surname = null!; + + var result = await validator.ValidateAsync(name); + + result.Errors.Where(error => error.PropertyName == nameof(name.Surname)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return no errors for empty patronymic + /// + [Fact] + private async Task ValidateForEmptyPatronymicShouldReturnNoErrors() + { + var name = faker.Generate(); + name.Patronymic = null; + + var result = await validator.ValidateAsync(name); + + result.Errors.Where(error => error.PropertyName == nameof(name.Patronymic)) + .Should().BeEmpty(); + } + + /// + /// Test for validator that should return error for too long first name + /// + [Fact] + private async Task ValidateForLongFirstNameShouldReturnError() + { + var name = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('h', ConfigurationConstraints.NameLength + 1); + name.FirstName = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(name); + + result.Errors.Where(error => error.PropertyName == nameof(name.FirstName)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long surname + /// + [Fact] + private async Task ValidateForLongSurnameShouldReturnError() + { + var name = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('h', ConfigurationConstraints.NameLength + 1); + name.Surname = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(name); + + result.Errors.Where(error => error.PropertyName == nameof(name.Surname)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long patronymic + /// + [Fact] + private async Task ValidateForLongPatronymicShouldReturnError() + { + var name = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('h', ConfigurationConstraints.NameLength + 1); + name.Patronymic = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(name); + + result.Errors.Where(error => error.PropertyName == nameof(name.Patronymic)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid firstname + /// + [Fact] + private async Task ValidateForNotValidFirstNameShouldReturnError() + { + var name = faker.Generate(); + name.FirstName = "&&7!**|"; + + var result = await validator.ValidateAsync(name); + + result.Errors.Where(error => error.PropertyName == nameof(name.FirstName)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid surname + /// + [Fact] + private async Task ValidateForNotValidSurnameShouldReturnError() + { + var name = faker.Generate(); + name.Surname = "&&7!**|"; + + var result = await validator.ValidateAsync(name); + + result.Errors.Where(error => error.PropertyName == nameof(name.Surname)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid patronymic + /// + [Fact] + private async Task ValidateForNotValidPatronymicShouldReturnError() + { + var name = faker.Generate(); + name.Patronymic = "&&7!**|"; + + var result = await validator.ValidateAsync(name); + + result.Errors.Where(error => error.PropertyName == nameof(name.Patronymic)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return no errors for valid name + /// + [Fact] + private async Task ValidateForValidNameShouldReturnNoErrors() + { + var name = faker.Generate(); + + var result = await validator.ValidateAsync(name); + + result.Errors.Should().BeEmpty(); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/AuthDataValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/AuthDataValidatorTests.cs new file mode 100644 index 0000000..0356f0a --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/AuthDataValidatorTests.cs @@ -0,0 +1,114 @@ +using System.Text; +using ApplicationLayer.Services.AuthServices.Common; +using ApplicationLayer.Services.AuthServices.Requests.Validation; +using Domains; +using FluentAssertions; +using FluentValidation; +using VisaApi.Fakers.Auth; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.Auth +{ + public class AuthDataValidatorTests + { + private readonly static IValidator validator = new AuthDataValidator(); + private readonly static AuthDataFaker faker = new(); + + /// + /// Test for validator that should return validation error for invalid email + /// + [Fact] + private async Task ValidateForInvalidEmailShouldReturnError() + { + var authData = faker.Generate(); + authData.Email = "alsdas'dsa"; + + var result = await validator.ValidateAsync(authData); + + result.Errors.Should() + .HaveCount(1) + .And.Contain(error => error.PropertyName == nameof(authData.Email)); + } + + /// + /// Test for validator that should return validation error for too long email + /// + [Fact] + private async Task ValidateForLongEmailShouldReturnError() + { + var authData = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('d', ConfigurationConstraints.EmailLength); + stringBuilder.Append("@mail.ru"); + authData.Email = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(authData); + + result.Errors.Should() + .HaveCount(1) + .And.Contain(error => error.PropertyName == nameof(authData.Email)); + } + + /// + /// Test for validator that should return no errors for valid email + /// + [Fact] + private async Task ValidateForValidEmailShouldReturnNoError() + { + var authData = faker.Generate(); + + var result = await validator.ValidateAsync(authData); + + result.Errors.Where(error => error.PropertyName == nameof(authData.Email)) + .Should().BeEmpty(); + } + + /// + /// Test for validator that should return validation error for empty password + /// + [Fact] + private async Task ValidateForEmptyPasswordShouldReturnError() + { + var authData = faker.Generate(); + authData.Password = string.Empty; + + var result = await validator.ValidateAsync(authData); + + result.Errors.Should() + .HaveCount(1) + .And.Contain(error => error.PropertyName == nameof(authData.Password)); + } + + /// + /// Test for validator that should return validation error for too long password + /// + [Fact] + private async Task ValidateForLongPasswordShouldReturnError() + { + var authData = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('d', ConfigurationConstraints.PasswordLength + 1); + authData.Password = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(authData); + + result.Errors.Should() + .HaveCount(1) + .And.Contain(error => error.PropertyName == nameof(authData.Password)); + } + + /// + /// Test for validator that should return no errors for valid password + /// + [Fact] + private async Task ValidateForValidPasswordShouldReturnNoError() + { + var authData = faker.Generate(); + + var result = await validator.ValidateAsync(authData); + + result.Errors.Where(error => error.PropertyName == nameof(authData.Password)) + .Should().BeEmpty(); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs new file mode 100644 index 0000000..eb3eae1 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs @@ -0,0 +1,94 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.AuthServices.Common; +using ApplicationLayer.Services.AuthServices.Requests; +using ApplicationLayer.Services.AuthServices.Requests.Validation; +using FluentAssertions; +using FluentValidation; +using Infrastructure.Database; +using Infrastructure.Database.Users.Repositories; +using VisaApi.Fakers.Auth; +using VisaApi.Fakers.Users; +using VisaApi.Tests.Infrastructure.Database; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.Auth +{ + [Collection(Collections.ContextUsingTestCollection)] + public class RegisterRequestValidatorTests + { + private readonly static IValidator authDataValidator = new AuthDataValidator(); + private readonly static RegisterRequestFaker requestFaker = new(); + private readonly static UserFaker userFaker = new(); + + /// + /// Creates validator from context + /// + /// db context + /// RegisterRequest validator + private static IValidator GetValidator(DbContext context) + { + var repository = new UsersRepository(context, context); + return new RegisterRequestValidator(repository, authDataValidator); + } + + /// + /// Test for validator that should throw for empty auth data + /// + [Fact] + private async Task ValidateForEmptyAuthDataShouldThrow() + { + var context = InMemoryContextProvider.GetDbContext(); + var validator = GetValidator(context); + var request = requestFaker.Generate(); + request.AuthData = null!; + NullReferenceException? result = null; + + try + { + await validator.ValidateAsync(request); + } + catch (Exception e) + { + result = e as NullReferenceException; + } + + result.Should().NotBeNull(); + } + + /// + /// Test for validator that should return error for used email + /// + [Fact] + private async Task ValidateForUsedEmailShouldReturnError() + { + var context = InMemoryContextProvider.GetDbContext(); + var validator = GetValidator(context); + var user = userFaker.Generate(); + await context.AddAsync(user); + await context.SaveChangesAsync(); + var request = requestFaker.Generate(); + request.AuthData.Email = user.Email; + + var result = await validator.ValidateAsync(request); + + result.Errors.Should() + .Contain(error => error.PropertyName == nameof(request.AuthData)) + .And.HaveCount(1); + } + + /// + /// Test for validator that should return o errors for valid requests + /// + [Fact] + private async Task ValidateForValidRequestShouldReturnNoErrors() + { + var context = InMemoryContextProvider.GetDbContext(); + var validator = GetValidator(context); + var request = requestFaker.Generate(); + + var result = await validator.ValidateAsync(request); + + result.Errors.Should().BeEmpty(); + } + } +} From 1625764e0a9f98fe7815610058a7536e84e5c4c8 Mon Sep 17 00:00:00 2001 From: prtsie Date: Sun, 22 Sep 2024 17:19:58 +0300 Subject: [PATCH 20/22] tests --- SchengenVisaApi/ApplicationLayer/Constants.cs | 2 +- .../Validation/PlaceOfWorkModelValidator.cs | 2 +- .../Constants.cs | 2 +- .../Fakers/Applicants/ApplicantFaker.cs | 2 +- .../Applicants/Requests/PassportModelFaker.cs | 24 ++ .../Requests/PlaceOfWorkModelFaker.cs | 25 ++ .../VisaApplications/ReentryPermitFaker.cs | 2 +- ...torTests.cs => NameModelValidatorTests.cs} | 2 +- .../Applicants/PassportModelValidatorTests.cs | 175 +++++++++ .../PlaceOfWorkModelValidatorTests.cs | 354 ++++++++++++++++++ 10 files changed, 584 insertions(+), 6 deletions(-) create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PassportModelFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs rename SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/{NameValidatorTests.cs => NameModelValidatorTests.cs} (99%) create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PassportModelValidatorTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PlaceOfWorkModelValidatorTests.cs diff --git a/SchengenVisaApi/ApplicationLayer/Constants.cs b/SchengenVisaApi/ApplicationLayer/Constants.cs index 2cf42e8..c6b3e62 100644 --- a/SchengenVisaApi/ApplicationLayer/Constants.cs +++ b/SchengenVisaApi/ApplicationLayer/Constants.cs @@ -6,7 +6,7 @@ namespace ApplicationLayer { public readonly static Regex EnglishWordRegex = new("^[a-zA-Z]*$"); - public readonly static Regex EnglishPhraseRegex = new(@"^[a-zA-Z№0-9?><;,{}[\]\-_+=!@#$%\^&*|']*$"); + public readonly static Regex EnglishPhraseRegex = new(@"^[a-zA-Z №0-9;,\-_+=#*']*$"); public readonly static Regex PhoneNumRegex = new(@"^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"); } diff --git a/SchengenVisaApi/ApplicationLayer/Services/Applicants/Models/Validation/PlaceOfWorkModelValidator.cs b/SchengenVisaApi/ApplicationLayer/Services/Applicants/Models/Validation/PlaceOfWorkModelValidator.cs index dc5449b..b1f30aa 100644 --- a/SchengenVisaApi/ApplicationLayer/Services/Applicants/Models/Validation/PlaceOfWorkModelValidator.cs +++ b/SchengenVisaApi/ApplicationLayer/Services/Applicants/Models/Validation/PlaceOfWorkModelValidator.cs @@ -60,7 +60,7 @@ public class PlaceOfWorkModelValidator : AbstractValidator .WithMessage("Building of place of work can not be empty") .Matches(Constants.EnglishPhraseRegex) .WithMessage("Place of work building field can contain only english letters, digits and special symbols") - .MaximumLength(ConfigurationConstraints.CountryNameLength) + .MaximumLength(ConfigurationConstraints.BuildingNumberLength) .WithMessage($"Building of place of work length must be less than {ConfigurationConstraints.BuildingNumberLength}"); } } diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Constants.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Constants.cs index 9131708..907fa52 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Constants.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Constants.cs @@ -7,7 +7,7 @@ namespace BlazorWebAssemblyVisaApiClient { public readonly static Regex EnglishWordRegex = new("^[a-zA-Z]*$"); - public readonly static Regex EnglishPhraseRegex = new(@"^[a-zA-Z№0-9?><;,{}[\]\-_+=!@#$%\^&*|']*$"); + public readonly static Regex EnglishPhraseRegex = new(@"^[a-z A-Z№0-9?><;,{}[\]\-_+=!@#$%\^&*|']*$"); public readonly static Regex PhoneNumRegex = new(@"^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"); diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs index d25e22d..ddb8503 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs @@ -31,7 +31,7 @@ namespace VisaApi.Fakers.Applicants => new Passport { Issuer = f.Company.CompanyName(), - Number = f.Random.String(ConfigurationConstraints.PasswordLength), + Number = f.Random.String(ConfigurationConstraints.PasswordLength, 'a', 'z'), ExpirationDate = f.Date.Future(4, dateTimeProvider.Now()), IssueDate = f.Date.Past(4, dateTimeProvider.Now()) }); diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PassportModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PassportModelFaker.cs new file mode 100644 index 0000000..c923a9c --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PassportModelFaker.cs @@ -0,0 +1,24 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.Applicants.Models; +using Bogus; +using Domains; + +namespace VisaApi.Fakers.Applicants.Requests +{ + public sealed class PassportModelFaker : Faker + { + public PassportModelFaker(IDateTimeProvider dateTimeProvider) + { + RuleFor(m => m.Issuer, f => f.Company.CompanyName()); + + RuleFor(m => m.Number, + f => f.Random.String(ConfigurationConstraints.PassportNumberLength, 'a', 'z')); + + RuleFor(m => m.ExpirationDate, + f => f.Date.Future(4, dateTimeProvider.Now())); + + RuleFor(m => m.IssueDate, + f => f.Date.Past(4, dateTimeProvider.Now())); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs new file mode 100644 index 0000000..d4df87a --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs @@ -0,0 +1,25 @@ +using ApplicationLayer.Services.Applicants.Models; +using Bogus; +using Domains.ApplicantDomain; + +namespace VisaApi.Fakers.Applicants.Requests +{ + public sealed class PlaceOfWorkModelFaker : Faker + { + public PlaceOfWorkModelFaker() + { + RuleFor(m => m.Name, f => f.Company.CompanyName()); + + RuleFor(m => m.PhoneNum, f => f.Phone.PhoneNumber("###########")); + + RuleFor(m => m.Address, + f => new AddressModel + { + Country = f.Address.Country(), + City = f.Address.City(), + Street = f.Address.StreetName(), + Building = f.Address.BuildingNumber() + }); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs index 6ea3009..f4a3c96 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs @@ -13,7 +13,7 @@ namespace VisaApi.Fakers.VisaApplications public ReentryPermitFaker(IDateTimeProvider dateTimeProvider) { RuleFor(p => p.Number, - f => f.Random.String(ConfigurationConstraints.ReentryPermitNumberLength)); + f => f.Random.String(ConfigurationConstraints.ReentryPermitNumberLength, 'a', 'z')); RuleFor(p => p.ExpirationDate, f => f.Date.Future(4, dateTimeProvider.Now())); diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameModelValidatorTests.cs similarity index 99% rename from SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameValidatorTests.cs rename to SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameModelValidatorTests.cs index 2f91c47..ec552e4 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameValidatorTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameModelValidatorTests.cs @@ -9,7 +9,7 @@ using Xunit; namespace VisaApi.Tests.Application.Validation.Applicants { - public class NameValidatorTests + public class NameModelValidatorTests { private static IValidator validator = new NameModelValidator(); private static NameModelFaker faker = new(); diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PassportModelValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PassportModelValidatorTests.cs new file mode 100644 index 0000000..e398186 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PassportModelValidatorTests.cs @@ -0,0 +1,175 @@ +using System.Text; +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.Applicants.Models; +using ApplicationLayer.Services.Applicants.Models.Validation; +using Domains; +using FluentAssertions; +using FluentValidation; +using VisaApi.Fakers.Applicants.Requests; +using VisaApi.Services; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.Applicants +{ + public class PassportModelValidatorTests + { + private static IDateTimeProvider dateTimeProvider = new TestDateTimeProvider(); + private static IValidator validator = new PassportModelValidator(dateTimeProvider); + private static PassportModelFaker faker = new(dateTimeProvider); + + /// + /// Test for validator that should return error for empty number + /// + [Fact] + private async Task ValidateForEmptyNumberShouldReturnError() + { + var model = faker.Generate(); + model.Number = string.Empty; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Number)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long number + /// + [Fact] + private async Task ValidateForLongNumberShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('d', ConfigurationConstraints.PassportNumberLength + 1); + model.Number = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Number)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid number + /// + [Fact] + private async Task ValidateForNotValidNumberShouldReturnError() + { + var model = faker.Generate(); + model.Number = "&?%$24asd\\]|"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Number)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty issuer + /// + [Fact] + private async Task ValidateForEmptyIssuerShouldReturnError() + { + var model = faker.Generate(); + model.Issuer = string.Empty; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long issuer + /// + [Fact] + private async Task ValidateForLongIssuerShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('d', ConfigurationConstraints.IssuerNameLength + 1); + model.Issuer = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid issuer + /// + [Fact] + private async Task ValidateForNotValidIssuerShouldReturnError() + { + var model = faker.Generate(); + model.Issuer = "&?%$24asd\\]|"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for expired passport + /// + [Fact] + private async Task ValidateForExpiredPassportShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = dateTimeProvider.Now().AddDays(-10); + model.IssueDate = model.ExpirationDate.AddDays(-10); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.ExpirationDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for passport from future + /// + [Fact] + private async Task ValidateForPassportFromFutureShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = dateTimeProvider.Now().AddDays(10); + model.IssueDate = model.ExpirationDate.AddDays(-3); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.IssueDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for passport that expired before issue + /// + [Fact] + private async Task ValidateForPassportExpiredBeforeIssueShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = dateTimeProvider.Now().AddDays(10); + model.IssueDate = model.ExpirationDate.AddDays(3); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.IssueDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return no errors for valid passport + /// + [Fact] + private async Task ValidateForValidPassportShouldReturnNoErrors() + { + var model = faker.Generate(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Should().BeEmpty(); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PlaceOfWorkModelValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PlaceOfWorkModelValidatorTests.cs new file mode 100644 index 0000000..aa15179 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PlaceOfWorkModelValidatorTests.cs @@ -0,0 +1,354 @@ +using System.Text; +using ApplicationLayer.Services.Applicants.Models; +using ApplicationLayer.Services.Applicants.Models.Validation; +using Domains; +using FluentAssertions; +using FluentValidation; +using VisaApi.Fakers.Applicants.Requests; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.Applicants +{ + public class PlaceOfWorkModelValidatorTests + { + private static IValidator validator = new PlaceOfWorkModelValidator(); + private static PlaceOfWorkModelFaker faker = new(); + + /// + /// Test for validator that should return error for empty phone num + /// + [Fact] + private async Task ValidateForEmptyPhoneNumShouldReturnError() + { + var model = faker.Generate(); + model.PhoneNum = string.Empty; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) + .Should().NotBeEmpty(); + } + + /// + /// Test for validator that should return error for long phone num + /// + [Fact] + private async Task ValidateForLongPhoneNumShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('8', ConfigurationConstraints.PhoneNumberLength + 1); + model.PhoneNum = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) + .Should().NotBeEmpty(); + } + + /// + /// Test for validator that should return error for short phone num + /// + [Fact] + private async Task ValidateForShortPhoneNumShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('8', ConfigurationConstraints.PhoneNumberMinLength - 1); + model.PhoneNum = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) + .Should() + .HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid phone num + /// + [Fact] + private async Task ValidateForNotValidPhoneNumShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.PhoneNumberMinLength); + model.PhoneNum = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) + .Should() + .HaveCount(1); + } + + /// + /// Test for validator that should throw exception for null address + /// + [Fact] + private async Task ValidateForEmptyAddressShouldThrow() + { + var model = faker.Generate(); + model.Address = null!; + NullReferenceException? result = null; + + try + { + await validator.ValidateAsync(model); + } + catch (Exception e) + { + result = e as NullReferenceException; + } + + result.Should().NotBeNull(); + } + + /// + /// Test for validator that should return error for empty Country + /// + [Fact] + private async Task ValidateForEmptyCountryShouldReturnError() + { + var model = faker.Generate(); + model.Address.Country = ""; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.Country") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long Country + /// + [Fact] + private async Task ValidateForLongCountryShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.CountryNameLength + 1); + model.Address.Country = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.Country") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid Country + /// + [Fact] + private async Task ValidateForNotValidCountryShouldReturnError() + { + var model = faker.Generate(); + model.Address.Country = "|&%"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.Country") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty City + /// + [Fact] + private async Task ValidateForEmptyCityShouldReturnError() + { + var model = faker.Generate(); + model.Address.City = ""; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.City") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long city + /// + [Fact] + private async Task ValidateForLongCityShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.CityNameLength + 1); + model.Address.City = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.City") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid city + /// + [Fact] + private async Task ValidateForNotValidCityShouldReturnError() + { + var model = faker.Generate(); + model.Address.City = "|&%"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.City") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty street + /// + [Fact] + private async Task ValidateForEmptyStreetShouldReturnError() + { + var model = faker.Generate(); + model.Address.Street = ""; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.Street") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long street + /// + [Fact] + private async Task ValidateForLongStreetShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.StreetNameLength + 1); + model.Address.Street = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.Street") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid street + /// + [Fact] + private async Task ValidateForNotValidStreetShouldReturnError() + { + var model = faker.Generate(); + model.Address.Street = "|&%"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.Street") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty building /// + [Fact] + private async Task ValidateForEmptyBuildingShouldReturnError() + { + var model = faker.Generate(); + model.Address.Building = ""; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.Building") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long building + /// + [Fact] + private async Task ValidateForLongBuildingShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.BuildingNumberLength + 1); + model.Address.Building = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.Building") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid building + /// + [Fact] + private async Task ValidateForNotValidBuildingShouldReturnError() + { + var model = faker.Generate(); + model.Address.Building = "|&%"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == "Address.Building") + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty name + /// + [Fact] + private async Task ValidateForEmptyNameShouldReturnError() + { + var model = faker.Generate(); + model.Name = ""; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Name)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long name + /// + [Fact] + private async Task ValidateForTooLongNameShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('g', ConfigurationConstraints.PlaceOfWorkNameLength + 1); + model.Name = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Name)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid name + /// + [Fact] + private async Task ValidateForNotValidNameShouldReturnError() + { + var model = faker.Generate(); + model.Name = "@$%&|"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Name)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return no errors for valid model + /// + [Fact] + private async Task ValidateForValidShouldReturnNoErrors() + { + var model = faker.Generate(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Should().BeEmpty(); + } + } +} From a80076e2e6be612df0fecb2d9412c507ce3470b6 Mon Sep 17 00:00:00 2001 From: prtsie Date: Sun, 22 Sep 2024 17:34:29 +0300 Subject: [PATCH 21/22] refactor (readonly for static objects in tests and file-scoped namespaces --- SchengenVisaApi/ApplicationLayer/Constants.cs | 15 +- .../Services/AuthServices/Common/AuthToken.cs | 11 +- .../Services/Users/Models/ChangeAuthData.cs | 23 +- .../Services/Users/Models/UserModel.cs | 23 +- .../ChangeUserAuthDataRequestValidator.cs | 31 +- .../Exceptions/BlazorClientException.cs | 7 +- .../Common/Exceptions/NotLoggedInException.cs | 7 +- .../Constants.cs | 23 +- .../RegisterApplicantRequestProfile.cs | 11 +- .../VisaApplicationCreateRequestProfile.cs | 11 +- .../Infrastructure/Helpers/EnumExtensions.cs | 11 +- .../Helpers/ValidationResultExtensions.cs | 19 +- .../DateTimeProvider/DateTimeProvider.cs | 15 +- .../DateTimeProvider/IDateTimeProvider.cs | 15 +- .../Exceptions/UnknownRoleException.cs | 7 +- .../UserDataProvider/IUserDataProvider.cs | 17 +- .../UserDataProvider/UserDataProvider.cs | 27 +- .../Applicants/Models/PlaceOfWorkModel.cs | 29 +- .../Models/RegisterApplicantRequestModel.cs | 95 ++- .../Applicants/Models/RegisterRequestModel.cs | 17 +- .../ChangeUserAuthDataRequestValidator.cs | 11 +- .../VisaApplicationCreateRequestModel.cs | 51 +- SchengenVisaApi/VisaApiClient/ClientBase.cs | 29 +- SchengenVisaApi/VisaApiTests/Collections.cs | 11 +- .../Fakers/Applicants/ApplicantFaker.cs | 17 +- .../Applicants/Requests/NameModelFaker.cs | 11 +- .../Applicants/Requests/PassportModelFaker.cs | 11 +- .../Requests/PlaceOfWorkModelFaker.cs | 11 +- .../VisaApiTests/Fakers/Auth/AuthDataFaker.cs | 11 +- .../Fakers/Auth/RegisterRequestFaker.cs | 17 +- .../Fakers/Common/ChangeAuthDataFaker.cs | 11 +- .../ChangeUserAuthDataRequestFaker.cs | 17 +- .../VisaApiTests/Fakers/Users/UserFaker.cs | 17 +- .../Fakers/VisaApplications/PastVisaFaker.cs | 27 +- .../Fakers/VisaApplications/PastVisitFaker.cs | 27 +- .../PermissionToDestCountryFaker.cs | 17 +- .../VisaApplications/ReentryPermitFaker.cs | 17 +- .../VisaApplications/VisaApplicationFaker.cs | 29 +- .../Services/TestDateTimeProvider.cs | 11 +- .../Applicants/NameModelValidatorTests.cs | 257 ++++---- .../Applicants/PassportModelValidatorTests.cs | 261 ++++---- .../PlaceOfWorkModelValidatorTests.cs | 577 +++++++++--------- .../Validation/Auth/AuthDataValidatorTests.cs | 87 ++- .../Auth/RegisterRequestValidatorTests.cs | 69 ++- ...hangeUserAuthDataRequestValidationTests.cs | 69 ++- .../Database/InMemoryContextProvider.cs | 23 +- .../Repositories/ApplicantsRepositoryTests.cs | 105 ++-- .../Generic/TestGenericRepository.cs | 7 +- .../Repositories/UsersRepositoryTests.cs | 73 ++- .../VisaApplicationsRepositoryTests.cs | 147 +++-- 50 files changed, 1196 insertions(+), 1246 deletions(-) diff --git a/SchengenVisaApi/ApplicationLayer/Constants.cs b/SchengenVisaApi/ApplicationLayer/Constants.cs index c6b3e62..aa8dc09 100644 --- a/SchengenVisaApi/ApplicationLayer/Constants.cs +++ b/SchengenVisaApi/ApplicationLayer/Constants.cs @@ -1,13 +1,12 @@ using System.Text.RegularExpressions; -namespace ApplicationLayer +namespace ApplicationLayer; + +public static class Constants { - public static class Constants - { - public readonly static Regex EnglishWordRegex = new("^[a-zA-Z]*$"); + public readonly static Regex EnglishWordRegex = new("^[a-zA-Z]*$"); - public readonly static Regex EnglishPhraseRegex = new(@"^[a-zA-Z №0-9;,\-_+=#*']*$"); + public readonly static Regex EnglishPhraseRegex = new(@"^[a-zA-Z №0-9;,\-_+=#*']*$"); - public readonly static Regex PhoneNumRegex = new(@"^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"); - } -} + public readonly static Regex PhoneNumRegex = new(@"^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"); +} \ No newline at end of file diff --git a/SchengenVisaApi/ApplicationLayer/Services/AuthServices/Common/AuthToken.cs b/SchengenVisaApi/ApplicationLayer/Services/AuthServices/Common/AuthToken.cs index 7c152ad..e1f661b 100644 --- a/SchengenVisaApi/ApplicationLayer/Services/AuthServices/Common/AuthToken.cs +++ b/SchengenVisaApi/ApplicationLayer/Services/AuthServices/Common/AuthToken.cs @@ -1,9 +1,8 @@ using System.ComponentModel.DataAnnotations; -namespace ApplicationLayer.Services.AuthServices.Common +namespace ApplicationLayer.Services.AuthServices.Common; + +public class AuthToken { - public class AuthToken - { - [Required] public string Token { get; set; } = null!; - } -} + [Required] public string Token { get; set; } = null!; +} \ No newline at end of file diff --git a/SchengenVisaApi/ApplicationLayer/Services/Users/Models/ChangeAuthData.cs b/SchengenVisaApi/ApplicationLayer/Services/Users/Models/ChangeAuthData.cs index b0ac255..e95f137 100644 --- a/SchengenVisaApi/ApplicationLayer/Services/Users/Models/ChangeAuthData.cs +++ b/SchengenVisaApi/ApplicationLayer/Services/Users/Models/ChangeAuthData.cs @@ -1,16 +1,15 @@ using System.ComponentModel.DataAnnotations; using Domains; -namespace ApplicationLayer.Services.Users.Models -{ - /// Auth data with nullable password for making change auth data requests - public class ChangeAuthData - { - [Required] - [MaxLength(ConfigurationConstraints.EmailLength)] - public string Email { get; set; } = null!; +namespace ApplicationLayer.Services.Users.Models; - [MaxLength(ConfigurationConstraints.PasswordLength)] - public string? Password { get; set; } - } -} +/// Auth data with nullable password for making change auth data requests +public class ChangeAuthData +{ + [Required] + [MaxLength(ConfigurationConstraints.EmailLength)] + public string Email { get; set; } = null!; + + [MaxLength(ConfigurationConstraints.PasswordLength)] + public string? Password { get; set; } +} \ No newline at end of file diff --git a/SchengenVisaApi/ApplicationLayer/Services/Users/Models/UserModel.cs b/SchengenVisaApi/ApplicationLayer/Services/Users/Models/UserModel.cs index 36f87b1..3127236 100644 --- a/SchengenVisaApi/ApplicationLayer/Services/Users/Models/UserModel.cs +++ b/SchengenVisaApi/ApplicationLayer/Services/Users/Models/UserModel.cs @@ -1,16 +1,15 @@ using System.ComponentModel.DataAnnotations; using Domains; -namespace ApplicationLayer.Services.Users.Models -{ - public class UserModel - { - /// Unique Identifier of user - [Required] - public Guid Id { get; private set; } = Guid.NewGuid(); +namespace ApplicationLayer.Services.Users.Models; - [Required] - [MaxLength(ConfigurationConstraints.EmailLength)] - public string Email { get; set; } = null!; - } -} +public class UserModel +{ + /// Unique Identifier of user + [Required] + public Guid Id { get; private set; } = Guid.NewGuid(); + + [Required] + [MaxLength(ConfigurationConstraints.EmailLength)] + public string Email { get; set; } = null!; +} \ No newline at end of file diff --git a/SchengenVisaApi/ApplicationLayer/Services/Users/Requests/Validation/ChangeUserAuthDataRequestValidator.cs b/SchengenVisaApi/ApplicationLayer/Services/Users/Requests/Validation/ChangeUserAuthDataRequestValidator.cs index e858422..bb44b86 100644 --- a/SchengenVisaApi/ApplicationLayer/Services/Users/Requests/Validation/ChangeUserAuthDataRequestValidator.cs +++ b/SchengenVisaApi/ApplicationLayer/Services/Users/Requests/Validation/ChangeUserAuthDataRequestValidator.cs @@ -1,24 +1,23 @@ using Domains; using FluentValidation; -namespace ApplicationLayer.Services.Users.Requests.Validation +namespace ApplicationLayer.Services.Users.Requests.Validation; + +public class ChangeUserAuthDataRequestValidator : AbstractValidator { - public class ChangeUserAuthDataRequestValidator : AbstractValidator + public ChangeUserAuthDataRequestValidator() { - public ChangeUserAuthDataRequestValidator() - { - RuleFor(r => r.UserId) - .NotEmpty(); + RuleFor(r => r.UserId) + .NotEmpty(); - RuleFor(r => r.NewAuthData) - .NotEmpty(); + RuleFor(r => r.NewAuthData) + .NotEmpty(); - RuleFor(r => r.NewAuthData.Email) - .NotEmpty() - .EmailAddress() - .WithMessage("Email should be valid") - .MaximumLength(ConfigurationConstraints.EmailLength) - .WithMessage($"Email address length must be less than {ConfigurationConstraints.EmailLength}"); - } + RuleFor(r => r.NewAuthData.Email) + .NotEmpty() + .EmailAddress() + .WithMessage("Email should be valid") + .MaximumLength(ConfigurationConstraints.EmailLength) + .WithMessage($"Email address length must be less than {ConfigurationConstraints.EmailLength}"); } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Common/Exceptions/BlazorClientException.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Common/Exceptions/BlazorClientException.cs index 7603cb9..d40c912 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Common/Exceptions/BlazorClientException.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Common/Exceptions/BlazorClientException.cs @@ -1,4 +1,3 @@ -namespace BlazorWebAssemblyVisaApiClient.Common.Exceptions -{ - public class BlazorClientException(string message) : Exception(message); -} +namespace BlazorWebAssemblyVisaApiClient.Common.Exceptions; + +public class BlazorClientException(string message) : Exception(message); \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Common/Exceptions/NotLoggedInException.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Common/Exceptions/NotLoggedInException.cs index 130a6ec..adb6001 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Common/Exceptions/NotLoggedInException.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Common/Exceptions/NotLoggedInException.cs @@ -1,4 +1,3 @@ -namespace BlazorWebAssemblyVisaApiClient.Common.Exceptions -{ - public class NotLoggedInException() : BlazorClientException("User is not logged in."); -} +namespace BlazorWebAssemblyVisaApiClient.Common.Exceptions; + +public class NotLoggedInException() : BlazorClientException("User is not logged in."); \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Constants.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Constants.cs index 907fa52..09676d9 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Constants.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Constants.cs @@ -1,20 +1,19 @@ using System.Text.RegularExpressions; using Microsoft.AspNetCore.Components; -namespace BlazorWebAssemblyVisaApiClient +namespace BlazorWebAssemblyVisaApiClient; + +public static class Constants { - public static class Constants - { - public readonly static Regex EnglishWordRegex = new("^[a-zA-Z]*$"); + public readonly static Regex EnglishWordRegex = new("^[a-zA-Z]*$"); - public readonly static Regex EnglishPhraseRegex = new(@"^[a-z A-Z№0-9?><;,{}[\]\-_+=!@#$%\^&*|']*$"); + public readonly static Regex EnglishPhraseRegex = new(@"^[a-z A-Z№0-9?><;,{}[\]\-_+=!@#$%\^&*|']*$"); - public readonly static Regex PhoneNumRegex = new(@"^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"); + public readonly static Regex PhoneNumRegex = new(@"^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"); - public readonly static MarkupString RequiredFieldMarkup = (MarkupString)"*"; + public readonly static MarkupString RequiredFieldMarkup = (MarkupString)"*"; - public const string ApplicantRole = "Applicant"; - public const string ApprovingAuthorityRole = "ApprovingAuthority"; - public const string AdminRole = "Admin"; - } -} + public const string ApplicantRole = "Applicant"; + public const string ApprovingAuthorityRole = "ApprovingAuthority"; + public const string AdminRole = "Admin"; +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/RegisterApplicantRequestProfile.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/RegisterApplicantRequestProfile.cs index e1c7d61..c395d1b 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/RegisterApplicantRequestProfile.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/RegisterApplicantRequestProfile.cs @@ -3,17 +3,16 @@ using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models; using VisaApiClient; using PlaceOfWorkModel = BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models.PlaceOfWorkModel; -namespace BlazorWebAssemblyVisaApiClient.Infrastructure.AutoMapper.Profiles +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.AutoMapper.Profiles; + +public class RegisterApplicantRequestProfile : Profile { - public class RegisterApplicantRequestProfile : Profile + public RegisterApplicantRequestProfile() { - public RegisterApplicantRequestProfile() - { CreateMap(MemberList.Destination); CreateMap(MemberList.Destination); CreateMap(MemberList.Destination); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/VisaApplicationCreateRequestProfile.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/VisaApplicationCreateRequestProfile.cs index 2bf617e..e2aa737 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/VisaApplicationCreateRequestProfile.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/VisaApplicationCreateRequestProfile.cs @@ -2,13 +2,12 @@ using BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Models; using VisaApiClient; -namespace BlazorWebAssemblyVisaApiClient.Infrastructure.AutoMapper.Profiles +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.AutoMapper.Profiles; + +public class VisaApplicationCreateRequestProfile : Profile { - public class VisaApplicationCreateRequestProfile : Profile + public VisaApplicationCreateRequestProfile() { - public VisaApplicationCreateRequestProfile() - { CreateMap(MemberList.Destination); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Helpers/EnumExtensions.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Helpers/EnumExtensions.cs index d49ba1b..c46deb6 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Helpers/EnumExtensions.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Helpers/EnumExtensions.cs @@ -1,11 +1,11 @@ using System.ComponentModel.DataAnnotations; -namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers; + +public static class EnumExtensions { - public static class EnumExtensions + public static string GetDisplayName(this Enum value) { - public static string GetDisplayName(this Enum value) - { var enumMembers = value.GetType().GetMembers(); var member = enumMembers.First(info => info.Name == value.ToString()); var displayAttribute = (DisplayAttribute?)member @@ -14,5 +14,4 @@ namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers var displayName = displayAttribute?.Name ?? value.ToString(); return displayName; } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Helpers/ValidationResultExtensions.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Helpers/ValidationResultExtensions.cs index d77c8a5..fbf2f27 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Helpers/ValidationResultExtensions.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Helpers/ValidationResultExtensions.cs @@ -1,15 +1,15 @@ using System.Text; using FluentValidation.Results; -namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers -{ - public static class ValidationResultExtensions - { - public static string ToErrorsString(this ValidationResult validationResult) - => ErrorsToString(validationResult.Errors.Select(e => e.ErrorMessage)); +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers; - private static string ErrorsToString(IEnumerable errors) - { +public static class ValidationResultExtensions +{ + public static string ToErrorsString(this ValidationResult validationResult) + => ErrorsToString(validationResult.Errors.Select(e => e.ErrorMessage)); + + private static string ErrorsToString(IEnumerable errors) + { var stringBuilder = new StringBuilder(); foreach (var error in errors) { @@ -18,5 +18,4 @@ namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers return stringBuilder.ToString(); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider/DateTimeProvider.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider/DateTimeProvider.cs index 21952f4..8b94ddb 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider/DateTimeProvider.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider/DateTimeProvider.cs @@ -1,9 +1,8 @@ -namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider -{ - public class DateTimeProvider : IDateTimeProvider - { - public DateTime Now() => DateTime.Now; +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; - public string FormattedNow() => Now().ToString("yyyy-MM-dd"); - } -} +public class DateTimeProvider : IDateTimeProvider +{ + public DateTime Now() => DateTime.Now; + + public string FormattedNow() => Now().ToString("yyyy-MM-dd"); +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider/IDateTimeProvider.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider/IDateTimeProvider.cs index bcdcccd..b85ec3d 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider/IDateTimeProvider.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider/IDateTimeProvider.cs @@ -1,9 +1,8 @@ -namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider -{ - public interface IDateTimeProvider - { - DateTime Now(); +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; - string FormattedNow(); - } -} +public interface IDateTimeProvider +{ + DateTime Now(); + + string FormattedNow(); +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/Exceptions/UnknownRoleException.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/Exceptions/UnknownRoleException.cs index 7ece731..f28aea9 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/Exceptions/UnknownRoleException.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/Exceptions/UnknownRoleException.cs @@ -1,6 +1,5 @@ using BlazorWebAssemblyVisaApiClient.Common.Exceptions; -namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider.Exceptions -{ - public class UnknownRoleException() : BlazorClientException("Unknown user role"); -} +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider.Exceptions; + +public class UnknownRoleException() : BlazorClientException("Unknown user role"); \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/IUserDataProvider.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/IUserDataProvider.cs index f72ad20..165ce84 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/IUserDataProvider.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/IUserDataProvider.cs @@ -1,15 +1,14 @@ using VisaApiClient; -namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider; + +public interface IUserDataProvider { - public interface IUserDataProvider - { - public string? CurrentRole { get; } + public string? CurrentRole { get; } - public Action? OnRoleChanged { get; set; } + public Action? OnRoleChanged { get; set; } - public Task GetApplicant(); + public Task GetApplicant(); - public void UpdateCurrentRole(); - } -} + public void UpdateCurrentRole(); +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/UserDataProvider.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/UserDataProvider.cs index dff20c7..7f1bf25 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/UserDataProvider.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/UserDataProvider/UserDataProvider.cs @@ -3,23 +3,23 @@ using System.Security.Claims; using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider.Exceptions; using VisaApiClient; -namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider; + +public class UserDataProvider(Client client) : IUserDataProvider { - public class UserDataProvider(Client client) : IUserDataProvider + private readonly static JwtSecurityTokenHandler tokenHandler = new(); + + public string? CurrentRole { get; private set; } + + public Action? OnRoleChanged { get; set; } + + public async Task GetApplicant() { - private readonly static JwtSecurityTokenHandler tokenHandler = new(); - - public string? CurrentRole { get; private set; } - - public Action? OnRoleChanged { get; set; } - - public async Task GetApplicant() - { return await client.GetApplicantAsync(); } - public void UpdateCurrentRole() - { + public void UpdateCurrentRole() + { var role = CurrentRole; if (client.AuthToken is null) @@ -49,5 +49,4 @@ namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvide OnRoleChanged?.Invoke(); } } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/PlaceOfWorkModel.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/PlaceOfWorkModel.cs index cd6d703..fa1215e 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/PlaceOfWorkModel.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/PlaceOfWorkModel.cs @@ -1,21 +1,20 @@ using System.ComponentModel.DataAnnotations; using VisaApiClient; -namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models +namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models; + +/// Model of place of work with attributes required for validation to work +public class PlaceOfWorkModel { - /// Model of place of work with attributes required for validation to work - public class PlaceOfWorkModel - { - [Required] - [StringLength(ConfigurationConstraints.PlaceOfWorkNameLength, MinimumLength = 1)] - public string Name { get; set; } = default!; + [Required] + [StringLength(ConfigurationConstraints.PlaceOfWorkNameLength, MinimumLength = 1)] + public string Name { get; set; } = default!; - [Required] - [ValidateComplexType] - public AddressModel Address { get; set; } = new AddressModel(); + [Required] + [ValidateComplexType] + public AddressModel Address { get; set; } = new AddressModel(); - [Required] - [StringLength(ConfigurationConstraints.PhoneNumberLength, MinimumLength = ConfigurationConstraints.PhoneNumberMinLength)] - public string PhoneNum { get; set; } = default!; - } -} + [Required] + [StringLength(ConfigurationConstraints.PhoneNumberLength, MinimumLength = ConfigurationConstraints.PhoneNumberMinLength)] + public string PhoneNum { get; set; } = default!; +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/RegisterApplicantRequestModel.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/RegisterApplicantRequestModel.cs index d544d66..0056bbd 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/RegisterApplicantRequestModel.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/RegisterApplicantRequestModel.cs @@ -3,66 +3,65 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; using VisaApiClient; -namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models +namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models; + +/// Model of request with attributes required for validation to work +public class RegisterApplicantRequestModel { - /// Model of request with attributes required for validation to work - public class RegisterApplicantRequestModel - { - [Required] - [ValidateComplexType] - public RegisterRequestModel RegisterRequest { get; set; } = new(); + [Required] + [ValidateComplexType] + public RegisterRequestModel RegisterRequest { get; set; } = new(); - [Required] - [ValidateComplexType] - public NameModel ApplicantName { get; set; } = new(); + [Required] + [ValidateComplexType] + public NameModel ApplicantName { get; set; } = new(); - [Required] - [ValidateComplexType] - public PassportModel Passport { get; set; } = new(); + [Required] + [ValidateComplexType] + public PassportModel Passport { get; set; } = new(); - [Required(AllowEmptyStrings = true)] - public DateTimeOffset BirthDate { get; set; } + [Required(AllowEmptyStrings = true)] + public DateTimeOffset BirthDate { get; set; } - [Required] - [StringLength(70, MinimumLength = 1)] - public string CityOfBirth { get; set; } = default!; + [Required] + [StringLength(70, MinimumLength = 1)] + public string CityOfBirth { get; set; } = default!; - [Required] - [StringLength(70, MinimumLength = 1)] - public string CountryOfBirth { get; set; } = default!; + [Required] + [StringLength(70, MinimumLength = 1)] + public string CountryOfBirth { get; set; } = default!; - [Required] - [StringLength(30, MinimumLength = 1)] - public string Citizenship { get; set; } = default!; + [Required] + [StringLength(30, MinimumLength = 1)] + public string Citizenship { get; set; } = default!; - [Required] - [StringLength(30, MinimumLength = 1)] - public string CitizenshipByBirth { get; set; } = default!; + [Required] + [StringLength(30, MinimumLength = 1)] + public string CitizenshipByBirth { get; set; } = default!; - [Required(AllowEmptyStrings = true)] - [JsonConverter(typeof(StringEnumConverter))] - public Gender Gender { get; set; } + [Required(AllowEmptyStrings = true)] + [JsonConverter(typeof(StringEnumConverter))] + public Gender Gender { get; set; } - [Required(AllowEmptyStrings = true)] - [JsonConverter(typeof(StringEnumConverter))] - public MaritalStatus MaritalStatus { get; set; } + [Required(AllowEmptyStrings = true)] + [JsonConverter(typeof(StringEnumConverter))] + public MaritalStatus MaritalStatus { get; set; } - [Required] - [ValidateComplexType] - public NameModel FatherName { get; set; } = new(); + [Required] + [ValidateComplexType] + public NameModel FatherName { get; set; } = new(); - [Required] - [ValidateComplexType] - public NameModel MotherName { get; set; } = new(); + [Required] + [ValidateComplexType] + public NameModel MotherName { get; set; } = new(); - [Required] - [StringLength(50, MinimumLength = 1)] - public string JobTitle { get; set; } = default!; + [Required] + [StringLength(50, MinimumLength = 1)] + public string JobTitle { get; set; } = default!; - [Required] - [ValidateComplexType] - public PlaceOfWorkModel PlaceOfWork { get; set; } = new(); + [Required] + [ValidateComplexType] + public PlaceOfWorkModel PlaceOfWork { get; set; } = new(); - public bool IsNonResident { get; set; } - } -} + public bool IsNonResident { get; set; } +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/RegisterRequestModel.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/RegisterRequestModel.cs index a53b582..ce54f8d 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/RegisterRequestModel.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Applicants/Models/RegisterRequestModel.cs @@ -1,13 +1,12 @@ using System.ComponentModel.DataAnnotations; using VisaApiClient; -namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models +namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models; + +/// Model of request with attributes required for validation to work +public class RegisterRequestModel { - /// Model of request with attributes required for validation to work - public class RegisterRequestModel - { - [Required] - [ValidateComplexType] - public AuthData AuthData { get; set; } = new AuthData(); - } -} + [Required] + [ValidateComplexType] + public AuthData AuthData { get; set; } = new AuthData(); +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Auth/ChangeUserAuthDataRequestValidator.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Auth/ChangeUserAuthDataRequestValidator.cs index ffb45ae..37462dc 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Auth/ChangeUserAuthDataRequestValidator.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/Auth/ChangeUserAuthDataRequestValidator.cs @@ -1,12 +1,12 @@ using FluentValidation; using VisaApiClient; -namespace BlazorWebAssemblyVisaApiClient.Validation.Auth +namespace BlazorWebAssemblyVisaApiClient.Validation.Auth; + +public class ChangeUserAuthDataRequestValidator : AbstractValidator { - public class ChangeUserAuthDataRequestValidator : AbstractValidator + public ChangeUserAuthDataRequestValidator() { - public ChangeUserAuthDataRequestValidator() - { RuleFor(r => r.NewAuthData) .NotEmpty(); @@ -17,5 +17,4 @@ namespace BlazorWebAssemblyVisaApiClient.Validation.Auth .MaximumLength(ConfigurationConstraints.EmailLength) .WithMessage($"Email address length must be less than {ConfigurationConstraints.EmailLength}"); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/VisaApplications/Models/VisaApplicationCreateRequestModel.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/VisaApplications/Models/VisaApplicationCreateRequestModel.cs index a15a453..8526dbd 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/VisaApplications/Models/VisaApplicationCreateRequestModel.cs +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Validation/VisaApplications/Models/VisaApplicationCreateRequestModel.cs @@ -1,38 +1,37 @@ using System.ComponentModel.DataAnnotations; using VisaApiClient; -namespace BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Models +namespace BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Models; + +/// Model for request for data annotations validation to work +public class VisaApplicationCreateRequestModel { - /// Model for request for data annotations validation to work - public class VisaApplicationCreateRequestModel - { - [ValidateComplexType] - public ReentryPermitModel? ReentryPermit { get; set; } = default!; + [ValidateComplexType] + public ReentryPermitModel? ReentryPermit { get; set; } = default!; - [Required] - [MaxLength(ConfigurationConstraints.CountryNameLength)] - public string DestinationCountry { get; set; } = default!; + [Required] + [MaxLength(ConfigurationConstraints.CountryNameLength)] + public string DestinationCountry { get; set; } = default!; - [Required] - public VisaCategory VisaCategory { get; set; } + [Required] + public VisaCategory VisaCategory { get; set; } - [Required] - public bool IsForGroup { get; set; } + [Required] + public bool IsForGroup { get; set; } - [Required] - public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; } + [Required] + public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; } - [Required] - [Range(0, ConfigurationConstraints.MaxValidDays)] - public int ValidDaysRequested { get; set; } + [Required] + [Range(0, ConfigurationConstraints.MaxValidDays)] + public int ValidDaysRequested { get; set; } - [ValidateComplexType] - public List PastVisas { get; set; } = []; + [ValidateComplexType] + public List PastVisas { get; set; } = []; - [ValidateComplexType] - public PermissionToDestCountryModel? PermissionToDestCountry { get; set; } = default!; + [ValidateComplexType] + public PermissionToDestCountryModel? PermissionToDestCountry { get; set; } = default!; - [ValidateComplexType] - public List PastVisits { get; set; } = []; - } -} + [ValidateComplexType] + public List PastVisits { get; set; } = []; +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiClient/ClientBase.cs b/SchengenVisaApi/VisaApiClient/ClientBase.cs index b4150b8..94e19a4 100644 --- a/SchengenVisaApi/VisaApiClient/ClientBase.cs +++ b/SchengenVisaApi/VisaApiClient/ClientBase.cs @@ -1,13 +1,13 @@ using System.Text; -namespace VisaApiClient -{ - public class ClientBase - { - public AuthToken? AuthToken { get; set; } +namespace VisaApiClient; - protected Task CreateHttpRequestMessageAsync(CancellationToken cancellationToken) - { +public class ClientBase +{ + public AuthToken? AuthToken { get; set; } + + protected Task CreateHttpRequestMessageAsync(CancellationToken cancellationToken) + { var msg = new HttpRequestMessage(); msg.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", AuthToken?.Token); @@ -16,15 +16,14 @@ namespace VisaApiClient } - protected async Task PrepareRequestAsync(HttpClient client, HttpRequestMessage request, string url, CancellationToken cancellationToken) - => await Task.CompletedTask; + protected async Task PrepareRequestAsync(HttpClient client, HttpRequestMessage request, string url, CancellationToken cancellationToken) + => await Task.CompletedTask; - protected async Task PrepareRequestAsync(HttpClient client, HttpRequestMessage request, StringBuilder urlBuilder, CancellationToken cancellationToken) - { + protected async Task PrepareRequestAsync(HttpClient client, HttpRequestMessage request, StringBuilder urlBuilder, CancellationToken cancellationToken) + { await Task.CompletedTask; } - protected async Task ProcessResponseAsync(HttpClient client, HttpResponseMessage response, CancellationToken cancellationToken) - => await Task.CompletedTask; - } -} + protected async Task ProcessResponseAsync(HttpClient client, HttpResponseMessage response, CancellationToken cancellationToken) + => await Task.CompletedTask; +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Collections.cs b/SchengenVisaApi/VisaApiTests/Collections.cs index 61c1979..ffa17ec 100644 --- a/SchengenVisaApi/VisaApiTests/Collections.cs +++ b/SchengenVisaApi/VisaApiTests/Collections.cs @@ -1,7 +1,6 @@ -namespace VisaApi +namespace VisaApi; + +public static class Collections { - public static class Collections - { - public const string ContextUsingTestCollection = "ContextUsingTestCollection"; - } -} + public const string ContextUsingTestCollection = "ContextUsingTestCollection"; +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs index ddb8503..55c45da 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/ApplicantFaker.cs @@ -3,15 +3,15 @@ using Bogus; using Domains; using Domains.ApplicantDomain; -namespace VisaApi.Fakers.Applicants +namespace VisaApi.Fakers.Applicants; + +/// +/// Generates applicants +/// +public sealed class ApplicantFaker : Faker { - /// - /// Generates applicants - /// - public sealed class ApplicantFaker : Faker + public ApplicantFaker(IDateTimeProvider dateTimeProvider) { - public ApplicantFaker(IDateTimeProvider dateTimeProvider) - { RuleFor(a => a.Citizenship, f => f.Address.Country()); RuleFor(a => a.Gender, f => f.Random.Enum()); @@ -62,5 +62,4 @@ namespace VisaApi.Fakers.Applicants PhoneNum = f.Phone.PhoneNumber() }); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/NameModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/NameModelFaker.cs index 31d476d..bc2209c 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/NameModelFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/NameModelFaker.cs @@ -1,17 +1,16 @@ using ApplicationLayer.Services.Applicants.Models; using Bogus; -namespace VisaApi.Fakers.Applicants.Requests +namespace VisaApi.Fakers.Applicants.Requests; + +public sealed class NameModelFaker : Faker { - public sealed class NameModelFaker : Faker + public NameModelFaker() { - public NameModelFaker() - { RuleFor(m => m.FirstName, f => f.Name.FirstName()); RuleFor(m => m.Surname, f => f.Name.LastName()); RuleFor(m => m.Patronymic, f => f.Name.FirstName()); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PassportModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PassportModelFaker.cs index c923a9c..0917c60 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PassportModelFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PassportModelFaker.cs @@ -3,12 +3,12 @@ using ApplicationLayer.Services.Applicants.Models; using Bogus; using Domains; -namespace VisaApi.Fakers.Applicants.Requests +namespace VisaApi.Fakers.Applicants.Requests; + +public sealed class PassportModelFaker : Faker { - public sealed class PassportModelFaker : Faker + public PassportModelFaker(IDateTimeProvider dateTimeProvider) { - public PassportModelFaker(IDateTimeProvider dateTimeProvider) - { RuleFor(m => m.Issuer, f => f.Company.CompanyName()); RuleFor(m => m.Number, @@ -20,5 +20,4 @@ namespace VisaApi.Fakers.Applicants.Requests RuleFor(m => m.IssueDate, f => f.Date.Past(4, dateTimeProvider.Now())); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs index d4df87a..eab2af5 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs @@ -2,12 +2,12 @@ using ApplicationLayer.Services.Applicants.Models; using Bogus; using Domains.ApplicantDomain; -namespace VisaApi.Fakers.Applicants.Requests +namespace VisaApi.Fakers.Applicants.Requests; + +public sealed class PlaceOfWorkModelFaker : Faker { - public sealed class PlaceOfWorkModelFaker : Faker + public PlaceOfWorkModelFaker() { - public PlaceOfWorkModelFaker() - { RuleFor(m => m.Name, f => f.Company.CompanyName()); RuleFor(m => m.PhoneNum, f => f.Phone.PhoneNumber("###########")); @@ -21,5 +21,4 @@ namespace VisaApi.Fakers.Applicants.Requests Building = f.Address.BuildingNumber() }); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Auth/AuthDataFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Auth/AuthDataFaker.cs index 2309f79..3833b0e 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Auth/AuthDataFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Auth/AuthDataFaker.cs @@ -1,15 +1,14 @@ using ApplicationLayer.Services.AuthServices.Common; using Bogus; -namespace VisaApi.Fakers.Auth +namespace VisaApi.Fakers.Auth; + +public sealed class AuthDataFaker : Faker { - public sealed class AuthDataFaker : Faker + public AuthDataFaker() { - public AuthDataFaker() - { RuleFor(a => a.Email, f => f.Internet.Email()); RuleFor(a => a.Password, f => f.Internet.Password()); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Auth/RegisterRequestFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Auth/RegisterRequestFaker.cs index 2835c35..eb57366 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Auth/RegisterRequestFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Auth/RegisterRequestFaker.cs @@ -1,15 +1,14 @@ using ApplicationLayer.Services.AuthServices.Requests; using Bogus; -namespace VisaApi.Fakers.Auth -{ - public sealed class RegisterRequestFaker : Faker - { - private static AuthDataFaker authDataFaker = new(); +namespace VisaApi.Fakers.Auth; - public RegisterRequestFaker() - { +public sealed class RegisterRequestFaker : Faker +{ + private static AuthDataFaker authDataFaker = new(); + + public RegisterRequestFaker() + { RuleFor(r => r.AuthData, () => authDataFaker.Generate()); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Common/ChangeAuthDataFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Common/ChangeAuthDataFaker.cs index fa000f0..d51b35f 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Common/ChangeAuthDataFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Common/ChangeAuthDataFaker.cs @@ -1,15 +1,14 @@ using ApplicationLayer.Services.Users.Models; using Bogus; -namespace VisaApi.Fakers.Common +namespace VisaApi.Fakers.Common; + +public sealed class ChangeAuthDataFaker : Faker { - public sealed class ChangeAuthDataFaker : Faker + public ChangeAuthDataFaker() { - public ChangeAuthDataFaker() - { RuleFor(a => a.Email, f => f.Internet.Email()); RuleFor(a => a.Password, f => f.Internet.Password()); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Users/Requests/ChangeUserAuthDataRequestFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Users/Requests/ChangeUserAuthDataRequestFaker.cs index dce8164..47b283d 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Users/Requests/ChangeUserAuthDataRequestFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Users/Requests/ChangeUserAuthDataRequestFaker.cs @@ -2,15 +2,14 @@ using Bogus; using VisaApi.Fakers.Common; -namespace VisaApi.Fakers.Users.Requests -{ - public sealed class ChangeUserAuthDataRequestFaker : Faker - { - private static ChangeAuthDataFaker changeAuthDataFaker = new(); +namespace VisaApi.Fakers.Users.Requests; - public ChangeUserAuthDataRequestFaker() - { +public sealed class ChangeUserAuthDataRequestFaker : Faker +{ + private static ChangeAuthDataFaker changeAuthDataFaker = new(); + + public ChangeUserAuthDataRequestFaker() + { CustomInstantiator(_ => new(Guid.NewGuid(), changeAuthDataFaker.Generate())); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Users/UserFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Users/UserFaker.cs index 11f7b40..73f485c 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Users/UserFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Users/UserFaker.cs @@ -1,18 +1,17 @@ using Bogus; using Domains.Users; -namespace VisaApi.Fakers.Users +namespace VisaApi.Fakers.Users; + +/// +/// Generates users +/// +public sealed class UserFaker : Faker { - /// - /// Generates users - /// - public sealed class UserFaker : Faker + public UserFaker() { - public UserFaker() - { RuleFor(u => u.Email, f => f.Internet.Email()); RuleFor(u => u.Password, f => f.Internet.Password()); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs index 3b827c2..f853eb3 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs @@ -2,28 +2,27 @@ using Bogus; using Domains.VisaApplicationDomain; -namespace VisaApi.Fakers.VisaApplications -{ - /// - /// Generates past visas - /// - public sealed class PastVisaFaker : Faker - { - private IDateTimeProvider dateTimeProvider; +namespace VisaApi.Fakers.VisaApplications; - public PastVisaFaker(IDateTimeProvider dateTimeProvider) - { +/// +/// Generates past visas +/// +public sealed class PastVisaFaker : Faker +{ + private IDateTimeProvider dateTimeProvider; + + public PastVisaFaker(IDateTimeProvider dateTimeProvider) + { this.dateTimeProvider = dateTimeProvider; RuleFor(pv => pv.Name, f => f.Random.Words()); } - public PastVisa GenerateValid() - { + public PastVisa GenerateValid() + { var result = Generate(); result.IssueDate = dateTimeProvider.Now().AddDays(Random.Shared.Next(11, 900)); result.ExpirationDate = result.IssueDate.AddDays(Random.Shared.Next(1, 11)); return result; } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs index df32675..183f1ba 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs @@ -2,28 +2,27 @@ using Bogus; using Domains.VisaApplicationDomain; -namespace VisaApi.Fakers.VisaApplications -{ - /// - /// Generates past visas - /// - public sealed class PastVisitFaker : Faker - { - private IDateTimeProvider dateTimeProvider; +namespace VisaApi.Fakers.VisaApplications; - public PastVisitFaker(IDateTimeProvider dateTimeProvider) - { +/// +/// Generates past visas +/// +public sealed class PastVisitFaker : Faker +{ + private IDateTimeProvider dateTimeProvider; + + public PastVisitFaker(IDateTimeProvider dateTimeProvider) + { this.dateTimeProvider = dateTimeProvider; RuleFor(pv => pv.DestinationCountry, f => f.Address.Country()); } - public PastVisit GenerateValid() - { + public PastVisit GenerateValid() + { var result = Generate(); result.StartDate = dateTimeProvider.Now().AddDays(Random.Shared.Next(11, 900)); result.EndDate = result.StartDate.AddDays(Random.Shared.Next(1, 11)); return result; } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs index f79b31c..73bb3f6 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs @@ -2,19 +2,18 @@ using Bogus; using Domains.VisaApplicationDomain; -namespace VisaApi.Fakers.VisaApplications +namespace VisaApi.Fakers.VisaApplications; + +/// +/// Generates permissions to destination Country +/// +public sealed class PermissionToDestCountryFaker : Faker { - /// - /// Generates permissions to destination Country - /// - public sealed class PermissionToDestCountryFaker : Faker + public PermissionToDestCountryFaker(IDateTimeProvider dateTimeProvider) { - public PermissionToDestCountryFaker(IDateTimeProvider dateTimeProvider) - { RuleFor(p => p.Issuer, f => f.Company.CompanyName()); RuleFor(p => p.ExpirationDate, f => f.Date.Future(4, dateTimeProvider.Now())); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs index f4a3c96..ffd7fec 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/ReentryPermitFaker.cs @@ -3,20 +3,19 @@ using Bogus; using Domains; using Domains.VisaApplicationDomain; -namespace VisaApi.Fakers.VisaApplications +namespace VisaApi.Fakers.VisaApplications; + +/// +/// Generates re-entry permissions +/// +public sealed class ReentryPermitFaker : Faker { - /// - /// Generates re-entry permissions - /// - public sealed class ReentryPermitFaker : Faker + public ReentryPermitFaker(IDateTimeProvider dateTimeProvider) { - public ReentryPermitFaker(IDateTimeProvider dateTimeProvider) - { RuleFor(p => p.Number, f => f.Random.String(ConfigurationConstraints.ReentryPermitNumberLength, 'a', 'z')); RuleFor(p => p.ExpirationDate, f => f.Date.Future(4, dateTimeProvider.Now())); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs index 7514fa3..ab931b1 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/VisaApplicationFaker.cs @@ -4,18 +4,18 @@ using Domains; using Domains.ApplicantDomain; using Domains.VisaApplicationDomain; -namespace VisaApi.Fakers.VisaApplications -{ - /// - /// Generates visa applications - /// - public sealed class VisaApplicationFaker : Faker - { - private static ReentryPermitFaker reentryPermitFaker = null!; - private static PermissionToDestCountryFaker permissionToDestCountryFaker = null!; +namespace VisaApi.Fakers.VisaApplications; - public VisaApplicationFaker(IDateTimeProvider dateTimeProvider) - { +/// +/// Generates visa applications +/// +public sealed class VisaApplicationFaker : Faker +{ + private static ReentryPermitFaker reentryPermitFaker = null!; + private static PermissionToDestCountryFaker permissionToDestCountryFaker = null!; + + public VisaApplicationFaker(IDateTimeProvider dateTimeProvider) + { reentryPermitFaker = new(dateTimeProvider); permissionToDestCountryFaker = new(dateTimeProvider); var pastVisaFaker = new PastVisaFaker(dateTimeProvider); @@ -44,8 +44,8 @@ namespace VisaApi.Fakers.VisaApplications f => f.Random.Int(1, ConfigurationConstraints.MaxValidDays)); } - public VisaApplication GenerateValid(Applicant applicant) - { + public VisaApplication GenerateValid(Applicant applicant) + { var result = Generate(); result.ApplicantId = applicant.Id; @@ -61,5 +61,4 @@ namespace VisaApi.Fakers.VisaApplications return result; } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Services/TestDateTimeProvider.cs b/SchengenVisaApi/VisaApiTests/Services/TestDateTimeProvider.cs index 8241e0b..d8eefce 100644 --- a/SchengenVisaApi/VisaApiTests/Services/TestDateTimeProvider.cs +++ b/SchengenVisaApi/VisaApiTests/Services/TestDateTimeProvider.cs @@ -1,9 +1,8 @@ using ApplicationLayer.InfrastructureServicesInterfaces; -namespace VisaApi.Services +namespace VisaApi.Services; + +public class TestDateTimeProvider : IDateTimeProvider { - public class TestDateTimeProvider : IDateTimeProvider - { - public DateTime Now() => DateTime.Now; - } -} + public DateTime Now() => DateTime.Now; +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameModelValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameModelValidatorTests.cs index ec552e4..f7c72fb 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameModelValidatorTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/NameModelValidatorTests.cs @@ -7,165 +7,164 @@ using FluentValidation; using VisaApi.Fakers.Applicants.Requests; using Xunit; -namespace VisaApi.Tests.Application.Validation.Applicants +namespace VisaApi.Tests.Application.Validation.Applicants; + +public class NameModelValidatorTests { - public class NameModelValidatorTests + private readonly static IValidator validator = new NameModelValidator(); + private readonly static NameModelFaker faker = new(); + + /// + /// Test for validator that should throw for empty first name + /// + [Fact] + private async Task ValidateForEmptyFirstNameShouldThrow() { - private static IValidator validator = new NameModelValidator(); - private static NameModelFaker faker = new(); + var name = faker.Generate(); + name.FirstName = null!; - /// - /// Test for validator that should throw for empty first name - /// - [Fact] - private async Task ValidateForEmptyFirstNameShouldThrow() - { - var name = faker.Generate(); - name.FirstName = null!; + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); + result.Errors.Where(error => error.PropertyName == nameof(name.FirstName)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(name.FirstName)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should throw for empty surname + /// + [Fact] + private async Task ValidateForEmptySurnameShouldThrow() + { + var name = faker.Generate(); + name.Surname = null!; - /// - /// Test for validator that should throw for empty surname - /// - [Fact] - private async Task ValidateForEmptySurnameShouldThrow() - { - var name = faker.Generate(); - name.Surname = null!; + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); + result.Errors.Where(error => error.PropertyName == nameof(name.Surname)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(name.Surname)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return no errors for empty patronymic + /// + [Fact] + private async Task ValidateForEmptyPatronymicShouldReturnNoErrors() + { + var name = faker.Generate(); + name.Patronymic = null; - /// - /// Test for validator that should return no errors for empty patronymic - /// - [Fact] - private async Task ValidateForEmptyPatronymicShouldReturnNoErrors() - { - var name = faker.Generate(); - name.Patronymic = null; + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); + result.Errors.Where(error => error.PropertyName == nameof(name.Patronymic)) + .Should().BeEmpty(); + } - result.Errors.Where(error => error.PropertyName == nameof(name.Patronymic)) - .Should().BeEmpty(); - } + /// + /// Test for validator that should return error for too long first name + /// + [Fact] + private async Task ValidateForLongFirstNameShouldReturnError() + { + var name = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('h', ConfigurationConstraints.NameLength + 1); + name.FirstName = stringBuilder.ToString(); - /// - /// Test for validator that should return error for too long first name - /// - [Fact] - private async Task ValidateForLongFirstNameShouldReturnError() - { - var name = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('h', ConfigurationConstraints.NameLength + 1); - name.FirstName = stringBuilder.ToString(); + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); + result.Errors.Where(error => error.PropertyName == nameof(name.FirstName)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(name.FirstName)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for too long surname + /// + [Fact] + private async Task ValidateForLongSurnameShouldReturnError() + { + var name = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('h', ConfigurationConstraints.NameLength + 1); + name.Surname = stringBuilder.ToString(); - /// - /// Test for validator that should return error for too long surname - /// - [Fact] - private async Task ValidateForLongSurnameShouldReturnError() - { - var name = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('h', ConfigurationConstraints.NameLength + 1); - name.Surname = stringBuilder.ToString(); + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); + result.Errors.Where(error => error.PropertyName == nameof(name.Surname)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(name.Surname)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for too long patronymic + /// + [Fact] + private async Task ValidateForLongPatronymicShouldReturnError() + { + var name = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('h', ConfigurationConstraints.NameLength + 1); + name.Patronymic = stringBuilder.ToString(); - /// - /// Test for validator that should return error for too long patronymic - /// - [Fact] - private async Task ValidateForLongPatronymicShouldReturnError() - { - var name = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('h', ConfigurationConstraints.NameLength + 1); - name.Patronymic = stringBuilder.ToString(); + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); + result.Errors.Where(error => error.PropertyName == nameof(name.Patronymic)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(name.Patronymic)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for not valid firstname + /// + [Fact] + private async Task ValidateForNotValidFirstNameShouldReturnError() + { + var name = faker.Generate(); + name.FirstName = "&&7!**|"; - /// - /// Test for validator that should return error for not valid firstname - /// - [Fact] - private async Task ValidateForNotValidFirstNameShouldReturnError() - { - var name = faker.Generate(); - name.FirstName = "&&7!**|"; + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); + result.Errors.Where(error => error.PropertyName == nameof(name.FirstName)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(name.FirstName)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for not valid surname + /// + [Fact] + private async Task ValidateForNotValidSurnameShouldReturnError() + { + var name = faker.Generate(); + name.Surname = "&&7!**|"; - /// - /// Test for validator that should return error for not valid surname - /// - [Fact] - private async Task ValidateForNotValidSurnameShouldReturnError() - { - var name = faker.Generate(); - name.Surname = "&&7!**|"; + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); + result.Errors.Where(error => error.PropertyName == nameof(name.Surname)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(name.Surname)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for not valid patronymic + /// + [Fact] + private async Task ValidateForNotValidPatronymicShouldReturnError() + { + var name = faker.Generate(); + name.Patronymic = "&&7!**|"; - /// - /// Test for validator that should return error for not valid patronymic - /// - [Fact] - private async Task ValidateForNotValidPatronymicShouldReturnError() - { - var name = faker.Generate(); - name.Patronymic = "&&7!**|"; + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); + result.Errors.Where(error => error.PropertyName == nameof(name.Patronymic)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(name.Patronymic)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return no errors for valid name + /// + [Fact] + private async Task ValidateForValidNameShouldReturnNoErrors() + { + var name = faker.Generate(); - /// - /// Test for validator that should return no errors for valid name - /// - [Fact] - private async Task ValidateForValidNameShouldReturnNoErrors() - { - var name = faker.Generate(); + var result = await validator.ValidateAsync(name); - var result = await validator.ValidateAsync(name); - - result.Errors.Should().BeEmpty(); - } + result.Errors.Should().BeEmpty(); } } diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PassportModelValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PassportModelValidatorTests.cs index e398186..f1179d4 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PassportModelValidatorTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PassportModelValidatorTests.cs @@ -9,167 +9,166 @@ using VisaApi.Fakers.Applicants.Requests; using VisaApi.Services; using Xunit; -namespace VisaApi.Tests.Application.Validation.Applicants +namespace VisaApi.Tests.Application.Validation.Applicants; + +public class PassportModelValidatorTests { - public class PassportModelValidatorTests + private readonly static IDateTimeProvider dateTimeProvider = new TestDateTimeProvider(); + private readonly static IValidator validator = new PassportModelValidator(dateTimeProvider); + private readonly static PassportModelFaker faker = new(dateTimeProvider); + + /// + /// Test for validator that should return error for empty number + /// + [Fact] + private async Task ValidateForEmptyNumberShouldReturnError() { - private static IDateTimeProvider dateTimeProvider = new TestDateTimeProvider(); - private static IValidator validator = new PassportModelValidator(dateTimeProvider); - private static PassportModelFaker faker = new(dateTimeProvider); + var model = faker.Generate(); + model.Number = string.Empty; - /// - /// Test for validator that should return error for empty number - /// - [Fact] - private async Task ValidateForEmptyNumberShouldReturnError() - { - var model = faker.Generate(); - model.Number = string.Empty; + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); + result.Errors.Where(error => error.PropertyName == nameof(model.Number)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(model.Number)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for too long number + /// + [Fact] + private async Task ValidateForLongNumberShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('d', ConfigurationConstraints.PassportNumberLength + 1); + model.Number = stringBuilder.ToString(); - /// - /// Test for validator that should return error for too long number - /// - [Fact] - private async Task ValidateForLongNumberShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('d', ConfigurationConstraints.PassportNumberLength + 1); - model.Number = stringBuilder.ToString(); + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); + result.Errors.Where(error => error.PropertyName == nameof(model.Number)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(model.Number)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for not valid number + /// + [Fact] + private async Task ValidateForNotValidNumberShouldReturnError() + { + var model = faker.Generate(); + model.Number = "&?%$24asd\\]|"; - /// - /// Test for validator that should return error for not valid number - /// - [Fact] - private async Task ValidateForNotValidNumberShouldReturnError() - { - var model = faker.Generate(); - model.Number = "&?%$24asd\\]|"; + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); + result.Errors.Where(error => error.PropertyName == nameof(model.Number)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(model.Number)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for empty issuer + /// + [Fact] + private async Task ValidateForEmptyIssuerShouldReturnError() + { + var model = faker.Generate(); + model.Issuer = string.Empty; - /// - /// Test for validator that should return error for empty issuer - /// - [Fact] - private async Task ValidateForEmptyIssuerShouldReturnError() - { - var model = faker.Generate(); - model.Issuer = string.Empty; + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); + result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for too long issuer + /// + [Fact] + private async Task ValidateForLongIssuerShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('d', ConfigurationConstraints.IssuerNameLength + 1); + model.Issuer = stringBuilder.ToString(); - /// - /// Test for validator that should return error for too long issuer - /// - [Fact] - private async Task ValidateForLongIssuerShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('d', ConfigurationConstraints.IssuerNameLength + 1); - model.Issuer = stringBuilder.ToString(); + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); + result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for not valid issuer + /// + [Fact] + private async Task ValidateForNotValidIssuerShouldReturnError() + { + var model = faker.Generate(); + model.Issuer = "&?%$24asd\\]|"; - /// - /// Test for validator that should return error for not valid issuer - /// - [Fact] - private async Task ValidateForNotValidIssuerShouldReturnError() - { - var model = faker.Generate(); - model.Issuer = "&?%$24asd\\]|"; + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); + result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for expired passport + /// + [Fact] + private async Task ValidateForExpiredPassportShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = dateTimeProvider.Now().AddDays(-10); + model.IssueDate = model.ExpirationDate.AddDays(-10); - /// - /// Test for validator that should return error for expired passport - /// - [Fact] - private async Task ValidateForExpiredPassportShouldReturnError() - { - var model = faker.Generate(); - model.ExpirationDate = dateTimeProvider.Now().AddDays(-10); - model.IssueDate = model.ExpirationDate.AddDays(-10); + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); + result.Errors.Where(error => error.PropertyName == nameof(model.ExpirationDate)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(model.ExpirationDate)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for passport from future + /// + [Fact] + private async Task ValidateForPassportFromFutureShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = dateTimeProvider.Now().AddDays(10); + model.IssueDate = model.ExpirationDate.AddDays(-3); - /// - /// Test for validator that should return error for passport from future - /// - [Fact] - private async Task ValidateForPassportFromFutureShouldReturnError() - { - var model = faker.Generate(); - model.ExpirationDate = dateTimeProvider.Now().AddDays(10); - model.IssueDate = model.ExpirationDate.AddDays(-3); + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); + result.Errors.Where(error => error.PropertyName == nameof(model.IssueDate)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(model.IssueDate)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return error for passport that expired before issue + /// + [Fact] + private async Task ValidateForPassportExpiredBeforeIssueShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = dateTimeProvider.Now().AddDays(10); + model.IssueDate = model.ExpirationDate.AddDays(3); - /// - /// Test for validator that should return error for passport that expired before issue - /// - [Fact] - private async Task ValidateForPassportExpiredBeforeIssueShouldReturnError() - { - var model = faker.Generate(); - model.ExpirationDate = dateTimeProvider.Now().AddDays(10); - model.IssueDate = model.ExpirationDate.AddDays(3); + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); + result.Errors.Where(error => error.PropertyName == nameof(model.IssueDate)) + .Should().HaveCount(1); + } - result.Errors.Where(error => error.PropertyName == nameof(model.IssueDate)) - .Should().HaveCount(1); - } + /// + /// Test for validator that should return no errors for valid passport + /// + [Fact] + private async Task ValidateForValidPassportShouldReturnNoErrors() + { + var model = faker.Generate(); - /// - /// Test for validator that should return no errors for valid passport - /// - [Fact] - private async Task ValidateForValidPassportShouldReturnNoErrors() - { - var model = faker.Generate(); + var result = await validator.ValidateAsync(model); - var result = await validator.ValidateAsync(model); - - result.Errors.Should().BeEmpty(); - } + result.Errors.Should().BeEmpty(); } } diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PlaceOfWorkModelValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PlaceOfWorkModelValidatorTests.cs index aa15179..aebd5fd 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PlaceOfWorkModelValidatorTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Applicants/PlaceOfWorkModelValidatorTests.cs @@ -7,348 +7,347 @@ using FluentValidation; using VisaApi.Fakers.Applicants.Requests; using Xunit; -namespace VisaApi.Tests.Application.Validation.Applicants +namespace VisaApi.Tests.Application.Validation.Applicants; + +public class PlaceOfWorkModelValidatorTests { - public class PlaceOfWorkModelValidatorTests + private readonly static IValidator validator = new PlaceOfWorkModelValidator(); + private readonly static PlaceOfWorkModelFaker faker = new(); + + /// + /// Test for validator that should return error for empty phone num + /// + [Fact] + private async Task ValidateForEmptyPhoneNumShouldReturnError() { - private static IValidator validator = new PlaceOfWorkModelValidator(); - private static PlaceOfWorkModelFaker faker = new(); + var model = faker.Generate(); + model.PhoneNum = string.Empty; - /// - /// Test for validator that should return error for empty phone num - /// - [Fact] - private async Task ValidateForEmptyPhoneNumShouldReturnError() + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) + .Should().NotBeEmpty(); + } + + /// + /// Test for validator that should return error for long phone num + /// + [Fact] + private async Task ValidateForLongPhoneNumShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('8', ConfigurationConstraints.PhoneNumberLength + 1); + model.PhoneNum = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) + .Should().NotBeEmpty(); + } + + /// + /// Test for validator that should return error for short phone num + /// + [Fact] + private async Task ValidateForShortPhoneNumShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('8', ConfigurationConstraints.PhoneNumberMinLength - 1); + model.PhoneNum = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) + .Should() + .HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid phone num + /// + [Fact] + private async Task ValidateForNotValidPhoneNumShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.PhoneNumberMinLength); + model.PhoneNum = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) + .Should() + .HaveCount(1); + } + + /// + /// Test for validator that should throw exception for null address + /// + [Fact] + private async Task ValidateForEmptyAddressShouldThrow() + { + var model = faker.Generate(); + model.Address = null!; + NullReferenceException? result = null; + + try { - var model = faker.Generate(); - model.PhoneNum = string.Empty; - - var result = await validator.ValidateAsync(model); - - result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) - .Should().NotBeEmpty(); + await validator.ValidateAsync(model); + } + catch (Exception e) + { + result = e as NullReferenceException; } - /// - /// Test for validator that should return error for long phone num - /// - [Fact] - private async Task ValidateForLongPhoneNumShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('8', ConfigurationConstraints.PhoneNumberLength + 1); - model.PhoneNum = stringBuilder.ToString(); + result.Should().NotBeNull(); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for empty Country + /// + [Fact] + private async Task ValidateForEmptyCountryShouldReturnError() + { + var model = faker.Generate(); + model.Address.Country = ""; - result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) - .Should().NotBeEmpty(); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for short phone num - /// - [Fact] - private async Task ValidateForShortPhoneNumShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('8', ConfigurationConstraints.PhoneNumberMinLength - 1); - model.PhoneNum = stringBuilder.ToString(); + result.Errors.Where(error => error.PropertyName == "Address.Country") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for too long Country + /// + [Fact] + private async Task ValidateForLongCountryShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.CountryNameLength + 1); + model.Address.Country = stringBuilder.ToString(); - result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) - .Should() - .HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for not valid phone num - /// - [Fact] - private async Task ValidateForNotValidPhoneNumShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('a', ConfigurationConstraints.PhoneNumberMinLength); - model.PhoneNum = stringBuilder.ToString(); + result.Errors.Where(error => error.PropertyName == "Address.Country") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for not valid Country + /// + [Fact] + private async Task ValidateForNotValidCountryShouldReturnError() + { + var model = faker.Generate(); + model.Address.Country = "|&%"; - result.Errors.Where(error => error.PropertyName == nameof(model.PhoneNum)) - .Should() - .HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should throw exception for null address - /// - [Fact] - private async Task ValidateForEmptyAddressShouldThrow() - { - var model = faker.Generate(); - model.Address = null!; - NullReferenceException? result = null; + result.Errors.Where(error => error.PropertyName == "Address.Country") + .Should().HaveCount(1); + } - try - { - await validator.ValidateAsync(model); - } - catch (Exception e) - { - result = e as NullReferenceException; - } + /// + /// Test for validator that should return error for empty City + /// + [Fact] + private async Task ValidateForEmptyCityShouldReturnError() + { + var model = faker.Generate(); + model.Address.City = ""; - result.Should().NotBeNull(); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for empty Country - /// - [Fact] - private async Task ValidateForEmptyCountryShouldReturnError() - { - var model = faker.Generate(); - model.Address.Country = ""; + result.Errors.Where(error => error.PropertyName == "Address.City") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for too long city + /// + [Fact] + private async Task ValidateForLongCityShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.CityNameLength + 1); + model.Address.City = stringBuilder.ToString(); - result.Errors.Where(error => error.PropertyName == "Address.Country") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for too long Country - /// - [Fact] - private async Task ValidateForLongCountryShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('a', ConfigurationConstraints.CountryNameLength + 1); - model.Address.Country = stringBuilder.ToString(); + result.Errors.Where(error => error.PropertyName == "Address.City") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for not valid city + /// + [Fact] + private async Task ValidateForNotValidCityShouldReturnError() + { + var model = faker.Generate(); + model.Address.City = "|&%"; - result.Errors.Where(error => error.PropertyName == "Address.Country") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for not valid Country - /// - [Fact] - private async Task ValidateForNotValidCountryShouldReturnError() - { - var model = faker.Generate(); - model.Address.Country = "|&%"; + result.Errors.Where(error => error.PropertyName == "Address.City") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for empty street + /// + [Fact] + private async Task ValidateForEmptyStreetShouldReturnError() + { + var model = faker.Generate(); + model.Address.Street = ""; - result.Errors.Where(error => error.PropertyName == "Address.Country") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for empty City - /// - [Fact] - private async Task ValidateForEmptyCityShouldReturnError() - { - var model = faker.Generate(); - model.Address.City = ""; + result.Errors.Where(error => error.PropertyName == "Address.Street") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for too long street + /// + [Fact] + private async Task ValidateForLongStreetShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.StreetNameLength + 1); + model.Address.Street = stringBuilder.ToString(); - result.Errors.Where(error => error.PropertyName == "Address.City") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for too long city - /// - [Fact] - private async Task ValidateForLongCityShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('a', ConfigurationConstraints.CityNameLength + 1); - model.Address.City = stringBuilder.ToString(); + result.Errors.Where(error => error.PropertyName == "Address.Street") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for not valid street + /// + [Fact] + private async Task ValidateForNotValidStreetShouldReturnError() + { + var model = faker.Generate(); + model.Address.Street = "|&%"; - result.Errors.Where(error => error.PropertyName == "Address.City") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for not valid city - /// - [Fact] - private async Task ValidateForNotValidCityShouldReturnError() - { - var model = faker.Generate(); - model.Address.City = "|&%"; + result.Errors.Where(error => error.PropertyName == "Address.Street") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for empty building /// + [Fact] + private async Task ValidateForEmptyBuildingShouldReturnError() + { + var model = faker.Generate(); + model.Address.Building = ""; - result.Errors.Where(error => error.PropertyName == "Address.City") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for empty street - /// - [Fact] - private async Task ValidateForEmptyStreetShouldReturnError() - { - var model = faker.Generate(); - model.Address.Street = ""; + result.Errors.Where(error => error.PropertyName == "Address.Building") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for too long building + /// + [Fact] + private async Task ValidateForLongBuildingShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('a', ConfigurationConstraints.BuildingNumberLength + 1); + model.Address.Building = stringBuilder.ToString(); - result.Errors.Where(error => error.PropertyName == "Address.Street") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for too long street - /// - [Fact] - private async Task ValidateForLongStreetShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('a', ConfigurationConstraints.StreetNameLength + 1); - model.Address.Street = stringBuilder.ToString(); + result.Errors.Where(error => error.PropertyName == "Address.Building") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for not valid building + /// + [Fact] + private async Task ValidateForNotValidBuildingShouldReturnError() + { + var model = faker.Generate(); + model.Address.Building = "|&%"; - result.Errors.Where(error => error.PropertyName == "Address.Street") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for not valid street - /// - [Fact] - private async Task ValidateForNotValidStreetShouldReturnError() - { - var model = faker.Generate(); - model.Address.Street = "|&%"; + result.Errors.Where(error => error.PropertyName == "Address.Building") + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for empty name + /// + [Fact] + private async Task ValidateForEmptyNameShouldReturnError() + { + var model = faker.Generate(); + model.Name = ""; - result.Errors.Where(error => error.PropertyName == "Address.Street") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for empty building /// - [Fact] - private async Task ValidateForEmptyBuildingShouldReturnError() - { - var model = faker.Generate(); - model.Address.Building = ""; + result.Errors.Where(error => error.PropertyName == nameof(model.Name)) + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for too long name + /// + [Fact] + private async Task ValidateForTooLongNameShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('g', ConfigurationConstraints.PlaceOfWorkNameLength + 1); + model.Name = stringBuilder.ToString(); - result.Errors.Where(error => error.PropertyName == "Address.Building") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for too long building - /// - [Fact] - private async Task ValidateForLongBuildingShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('a', ConfigurationConstraints.BuildingNumberLength + 1); - model.Address.Building = stringBuilder.ToString(); + result.Errors.Where(error => error.PropertyName == nameof(model.Name)) + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return error for not valid name + /// + [Fact] + private async Task ValidateForNotValidNameShouldReturnError() + { + var model = faker.Generate(); + model.Name = "@$%&|"; - result.Errors.Where(error => error.PropertyName == "Address.Building") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for not valid building - /// - [Fact] - private async Task ValidateForNotValidBuildingShouldReturnError() - { - var model = faker.Generate(); - model.Address.Building = "|&%"; + result.Errors.Where(error => error.PropertyName == nameof(model.Name)) + .Should().HaveCount(1); + } - var result = await validator.ValidateAsync(model); + /// + /// Test for validator that should return no errors for valid model + /// + [Fact] + private async Task ValidateForValidShouldReturnNoErrors() + { + var model = faker.Generate(); - result.Errors.Where(error => error.PropertyName == "Address.Building") - .Should().HaveCount(1); - } + var result = await validator.ValidateAsync(model); - /// - /// Test for validator that should return error for empty name - /// - [Fact] - private async Task ValidateForEmptyNameShouldReturnError() - { - var model = faker.Generate(); - model.Name = ""; - - var result = await validator.ValidateAsync(model); - - result.Errors.Where(error => error.PropertyName == nameof(model.Name)) - .Should().HaveCount(1); - } - - /// - /// Test for validator that should return error for too long name - /// - [Fact] - private async Task ValidateForTooLongNameShouldReturnError() - { - var model = faker.Generate(); - var stringBuilder = new StringBuilder(); - stringBuilder.Append('g', ConfigurationConstraints.PlaceOfWorkNameLength + 1); - model.Name = stringBuilder.ToString(); - - var result = await validator.ValidateAsync(model); - - result.Errors.Where(error => error.PropertyName == nameof(model.Name)) - .Should().HaveCount(1); - } - - /// - /// Test for validator that should return error for not valid name - /// - [Fact] - private async Task ValidateForNotValidNameShouldReturnError() - { - var model = faker.Generate(); - model.Name = "@$%&|"; - - var result = await validator.ValidateAsync(model); - - result.Errors.Where(error => error.PropertyName == nameof(model.Name)) - .Should().HaveCount(1); - } - - /// - /// Test for validator that should return no errors for valid model - /// - [Fact] - private async Task ValidateForValidShouldReturnNoErrors() - { - var model = faker.Generate(); - - var result = await validator.ValidateAsync(model); - - result.Errors.Should().BeEmpty(); - } + result.Errors.Should().BeEmpty(); } } diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/AuthDataValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/AuthDataValidatorTests.cs index 0356f0a..d0c0725 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/AuthDataValidatorTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/AuthDataValidatorTests.cs @@ -7,19 +7,19 @@ using FluentValidation; using VisaApi.Fakers.Auth; using Xunit; -namespace VisaApi.Tests.Application.Validation.Auth -{ - public class AuthDataValidatorTests - { - private readonly static IValidator validator = new AuthDataValidator(); - private readonly static AuthDataFaker faker = new(); +namespace VisaApi.Tests.Application.Validation.Auth; - /// - /// Test for validator that should return validation error for invalid email - /// - [Fact] - private async Task ValidateForInvalidEmailShouldReturnError() - { +public class AuthDataValidatorTests +{ + private readonly static IValidator validator = new AuthDataValidator(); + private readonly static AuthDataFaker faker = new(); + + /// + /// Test for validator that should return validation error for invalid email + /// + [Fact] + private async Task ValidateForInvalidEmailShouldReturnError() + { var authData = faker.Generate(); authData.Email = "alsdas'dsa"; @@ -30,12 +30,12 @@ namespace VisaApi.Tests.Application.Validation.Auth .And.Contain(error => error.PropertyName == nameof(authData.Email)); } - /// - /// Test for validator that should return validation error for too long email - /// - [Fact] - private async Task ValidateForLongEmailShouldReturnError() - { + /// + /// Test for validator that should return validation error for too long email + /// + [Fact] + private async Task ValidateForLongEmailShouldReturnError() + { var authData = faker.Generate(); var stringBuilder = new StringBuilder(); stringBuilder.Append('d', ConfigurationConstraints.EmailLength); @@ -49,12 +49,12 @@ namespace VisaApi.Tests.Application.Validation.Auth .And.Contain(error => error.PropertyName == nameof(authData.Email)); } - /// - /// Test for validator that should return no errors for valid email - /// - [Fact] - private async Task ValidateForValidEmailShouldReturnNoError() - { + /// + /// Test for validator that should return no errors for valid email + /// + [Fact] + private async Task ValidateForValidEmailShouldReturnNoError() + { var authData = faker.Generate(); var result = await validator.ValidateAsync(authData); @@ -63,12 +63,12 @@ namespace VisaApi.Tests.Application.Validation.Auth .Should().BeEmpty(); } - /// - /// Test for validator that should return validation error for empty password - /// - [Fact] - private async Task ValidateForEmptyPasswordShouldReturnError() - { + /// + /// Test for validator that should return validation error for empty password + /// + [Fact] + private async Task ValidateForEmptyPasswordShouldReturnError() + { var authData = faker.Generate(); authData.Password = string.Empty; @@ -79,12 +79,12 @@ namespace VisaApi.Tests.Application.Validation.Auth .And.Contain(error => error.PropertyName == nameof(authData.Password)); } - /// - /// Test for validator that should return validation error for too long password - /// - [Fact] - private async Task ValidateForLongPasswordShouldReturnError() - { + /// + /// Test for validator that should return validation error for too long password + /// + [Fact] + private async Task ValidateForLongPasswordShouldReturnError() + { var authData = faker.Generate(); var stringBuilder = new StringBuilder(); stringBuilder.Append('d', ConfigurationConstraints.PasswordLength + 1); @@ -97,12 +97,12 @@ namespace VisaApi.Tests.Application.Validation.Auth .And.Contain(error => error.PropertyName == nameof(authData.Password)); } - /// - /// Test for validator that should return no errors for valid password - /// - [Fact] - private async Task ValidateForValidPasswordShouldReturnNoError() - { + /// + /// Test for validator that should return no errors for valid password + /// + [Fact] + private async Task ValidateForValidPasswordShouldReturnNoError() + { var authData = faker.Generate(); var result = await validator.ValidateAsync(authData); @@ -110,5 +110,4 @@ namespace VisaApi.Tests.Application.Validation.Auth result.Errors.Where(error => error.PropertyName == nameof(authData.Password)) .Should().BeEmpty(); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs index eb3eae1..74eb02f 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs @@ -11,32 +11,32 @@ using VisaApi.Fakers.Users; using VisaApi.Tests.Infrastructure.Database; using Xunit; -namespace VisaApi.Tests.Application.Validation.Auth -{ - [Collection(Collections.ContextUsingTestCollection)] - public class RegisterRequestValidatorTests - { - private readonly static IValidator authDataValidator = new AuthDataValidator(); - private readonly static RegisterRequestFaker requestFaker = new(); - private readonly static UserFaker userFaker = new(); +namespace VisaApi.Tests.Application.Validation.Auth; - /// - /// Creates validator from context - /// - /// db context - /// RegisterRequest validator - private static IValidator GetValidator(DbContext context) - { +[Collection(Collections.ContextUsingTestCollection)] +public class RegisterRequestValidatorTests +{ + private readonly static IValidator authDataValidator = new AuthDataValidator(); + private readonly static RegisterRequestFaker requestFaker = new(); + private readonly static UserFaker userFaker = new(); + + /// + /// Creates validator from context + /// + /// db context + /// RegisterRequest validator + private static IValidator GetValidator(DbContext context) + { var repository = new UsersRepository(context, context); return new RegisterRequestValidator(repository, authDataValidator); } - /// - /// Test for validator that should throw for empty auth data - /// - [Fact] - private async Task ValidateForEmptyAuthDataShouldThrow() - { + /// + /// Test for validator that should throw for empty auth data + /// + [Fact] + private async Task ValidateForEmptyAuthDataShouldThrow() + { var context = InMemoryContextProvider.GetDbContext(); var validator = GetValidator(context); var request = requestFaker.Generate(); @@ -55,12 +55,12 @@ namespace VisaApi.Tests.Application.Validation.Auth result.Should().NotBeNull(); } - /// - /// Test for validator that should return error for used email - /// - [Fact] - private async Task ValidateForUsedEmailShouldReturnError() - { + /// + /// Test for validator that should return error for used email + /// + [Fact] + private async Task ValidateForUsedEmailShouldReturnError() + { var context = InMemoryContextProvider.GetDbContext(); var validator = GetValidator(context); var user = userFaker.Generate(); @@ -76,12 +76,12 @@ namespace VisaApi.Tests.Application.Validation.Auth .And.HaveCount(1); } - /// - /// Test for validator that should return o errors for valid requests - /// - [Fact] - private async Task ValidateForValidRequestShouldReturnNoErrors() - { + /// + /// Test for validator that should return o errors for valid requests + /// + [Fact] + private async Task ValidateForValidRequestShouldReturnNoErrors() + { var context = InMemoryContextProvider.GetDbContext(); var validator = GetValidator(context); var request = requestFaker.Generate(); @@ -90,5 +90,4 @@ namespace VisaApi.Tests.Application.Validation.Auth result.Errors.Should().BeEmpty(); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs index 2b9ea74..0e1211b 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Users/ChangeUserAuthDataRequestValidationTests.cs @@ -5,45 +5,44 @@ using FluentValidation; using VisaApi.Fakers.Users.Requests; using Xunit; -namespace VisaApi.Tests.Application.Validation.Users +namespace VisaApi.Tests.Application.Validation.Users; + +public class ChangeUserAuthDataRequestValidationTests { - public class ChangeUserAuthDataRequestValidationTests + private readonly static IValidator validator = new ChangeUserAuthDataRequestValidator(); + private readonly static ChangeUserAuthDataRequestFaker faker = new(); + + /// + /// Test for validator that should throw exception for empty auth data + /// + [Fact] + private async Task ValidateForEmptyAuthDataShouldThrow() { - private readonly static IValidator validator = new ChangeUserAuthDataRequestValidator(); - private readonly static ChangeUserAuthDataRequestFaker faker = new(); + var request = faker.Generate(); + request.NewAuthData = null!; + NullReferenceException? result = null; - /// - /// Test for validator that should throw exception for empty auth data - /// - [Fact] - private async Task ValidateForEmptyAuthDataShouldThrow() + try { - var request = faker.Generate(); - request.NewAuthData = null!; - NullReferenceException? result = null; - - try - { - await validator.ValidateAsync(request); - } - catch (Exception e) - { - result = e as NullReferenceException; - } - - result.Should().NotBeNull(); + await validator.ValidateAsync(request); + } + catch (Exception e) + { + result = e as NullReferenceException; } - /// - /// Test for validator that should no errors for valid entity - /// - [Fact] - private async Task ValidateForValidShouldReturnNoErrors() - { - var request = faker.Generate(); - var result = await validator.ValidateAsync(request); - - result.IsValid.Should().BeTrue(); - } + result.Should().NotBeNull(); } -} + + /// + /// Test for validator that should no errors for valid entity + /// + [Fact] + private async Task ValidateForValidShouldReturnNoErrors() + { + var request = faker.Generate(); + var result = await validator.ValidateAsync(request); + + result.IsValid.Should().BeTrue(); + } +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/InMemoryContextProvider.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/InMemoryContextProvider.cs index ec81a0f..72953a3 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/InMemoryContextProvider.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/InMemoryContextProvider.cs @@ -2,17 +2,17 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using DbContext = Infrastructure.Database.DbContext; -namespace VisaApi.Tests.Infrastructure.Database -{ - public static class InMemoryContextProvider - { - private static DbContextOptions opts = new DbContextOptionsBuilder() - .UseInMemoryDatabase("VisaApiDB") - .ConfigureWarnings(b => b.Ignore(InMemoryEventId.TransactionIgnoredWarning)) - .Options; +namespace VisaApi.Tests.Infrastructure.Database; - public static DbContext GetDbContext() - { +public static class InMemoryContextProvider +{ + private static DbContextOptions opts = new DbContextOptionsBuilder() + .UseInMemoryDatabase("VisaApiDB") + .ConfigureWarnings(b => b.Ignore(InMemoryEventId.TransactionIgnoredWarning)) + .Options; + + public static DbContext GetDbContext() + { var result = new DbContext(opts); result.Database.EnsureDeleted(); @@ -20,5 +20,4 @@ namespace VisaApi.Tests.Infrastructure.Database return result; } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs index e5eb0b2..64035c0 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/ApplicantsRepositoryTests.cs @@ -9,29 +9,29 @@ using VisaApi.Fakers.Users; using VisaApi.Services; using Xunit; -namespace VisaApi.Tests.Infrastructure.Database.Repositories +namespace VisaApi.Tests.Infrastructure.Database.Repositories; + +[Collection(Collections.ContextUsingTestCollection)] +public class ApplicantsRepositoryTests { - [Collection(Collections.ContextUsingTestCollection)] - public class ApplicantsRepositoryTests + private readonly static UserFaker userFaker = new(); + private readonly static ApplicantFaker applicantFaker = new(GetDateTimeProvider()); + + /// Returns + /// Database context + /// Repository + private static IApplicantsRepository GetRepository(DbContext context) + => new ApplicantsRepository(context, context); + + /// Returns + private static IDateTimeProvider GetDateTimeProvider() => new TestDateTimeProvider(); + + /// + /// Test for method that should throw exception for not existing entity + /// + [Fact] + private async Task FindByUserIdForNotExistingShouldThrow() { - private readonly static UserFaker userFaker = new(); - private readonly static ApplicantFaker applicantFaker = new(GetDateTimeProvider()); - - /// Returns - /// Database context - /// Repository - private static IApplicantsRepository GetRepository(DbContext context) - => new ApplicantsRepository(context, context); - - /// Returns - private static IDateTimeProvider GetDateTimeProvider() => new TestDateTimeProvider(); - - /// - /// Test for method that should throw exception for not existing entity - /// - [Fact] - private async Task FindByUserIdForNotExistingShouldThrow() - { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); ApplicantNotFoundByUserIdException? result = null; @@ -48,12 +48,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().NotBeNull(); } - /// - /// Test for method that should return existing entity - /// - [Fact] - private async Task FindByUserIdForExistingShouldReturnApplicant() - { + /// + /// Test for method that should return existing entity + /// + [Fact] + private async Task FindByUserIdForExistingShouldReturnApplicant() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -68,12 +68,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().BeEquivalentTo(applicant); } - /// - /// Test for method that should throw exception for not existing entity - /// - [Fact] - private async Task GetApplicantIdByUserIdForNotExistingShouldThrow() - { + /// + /// Test for method that should throw exception for not existing entity + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotExistingShouldThrow() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); ApplicantNotFoundByUserIdException? result = null; @@ -90,12 +90,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().NotBeNull(); } - /// - /// Test for method that should return existing entity's identifier - /// - [Fact] - private async Task GetApplicantIdByUserIdForExistingShouldReturnApplicant() - { + /// + /// Test for method that should return existing entity's identifier + /// + [Fact] + private async Task GetApplicantIdByUserIdForExistingShouldReturnApplicant() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -110,12 +110,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().Be(applicant.Id); } - /// - /// Test for method that should throw exception for not existing entity - /// - [Fact] - private async Task IsApplicantNonResidentByUserIdForNotExistingShouldThrow() - { + /// + /// Test for method that should throw exception for not existing entity + /// + [Fact] + private async Task IsApplicantNonResidentByUserIdForNotExistingShouldThrow() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); ApplicantNotFoundByUserIdException? result = null; @@ -132,12 +132,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().NotBeNull(); } - /// - /// Test for method that should return existing entity's IsNonResident property - /// - [Fact] - private async Task IsApplicantNonResidentByUserIdForExistingShouldReturnApplicant() - { + /// + /// Test for method that should return existing entity's IsNonResident property + /// + [Fact] + private async Task IsApplicantNonResidentByUserIdForExistingShouldReturnApplicant() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -151,5 +151,4 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().Be(applicant.IsNonResident); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/TestGenericRepository.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/TestGenericRepository.cs index 94842b8..06cfe24 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/TestGenericRepository.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/Generic/TestGenericRepository.cs @@ -1,7 +1,6 @@ using Domains.Users; using Infrastructure.Database.Generic; -namespace VisaApi.Tests.Infrastructure.Database.Repositories.Generic -{ - public class TestGenericRepository(IGenericReader reader, IGenericWriter writer) : GenericRepository(reader, writer); -} +namespace VisaApi.Tests.Infrastructure.Database.Repositories.Generic; + +public class TestGenericRepository(IGenericReader reader, IGenericWriter writer) : GenericRepository(reader, writer); \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs index 50227d7..f41c8cd 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/UsersRepositoryTests.cs @@ -7,25 +7,25 @@ using Infrastructure.Database.Users.Repositories; using VisaApi.Fakers.Users; using Xunit; -namespace VisaApi.Tests.Infrastructure.Database.Repositories +namespace VisaApi.Tests.Infrastructure.Database.Repositories; + +[Collection(Collections.ContextUsingTestCollection)] +public class UsersRepositoryTests { - [Collection(Collections.ContextUsingTestCollection)] - public class UsersRepositoryTests + private readonly static UserFaker userFaker = new(); + + /// Returns + /// Database context + /// Repository + private static IUsersRepository GetRepository(DbContext context) + => new UsersRepository(context, context); + + /// + /// Test for method that should return null for not existing email + /// + [Fact] + private async Task FindByEmailForNotExistingShouldReturnNull() { - private readonly static UserFaker userFaker = new(); - - /// Returns - /// Database context - /// Repository - private static IUsersRepository GetRepository(DbContext context) - => new UsersRepository(context, context); - - /// - /// Test for method that should return null for not existing email - /// - [Fact] - private async Task FindByEmailForNotExistingShouldReturnNull() - { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); @@ -34,12 +34,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().BeNull(); } - /// - /// Test for method that should return entity for existing email - /// - [Fact] - private async Task FindByEmailForExistingShouldReturnEntity() - { + /// + /// Test for method that should return entity for existing email + /// + [Fact] + private async Task FindByEmailForExistingShouldReturnEntity() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -51,12 +51,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().Be(user); } - /// - /// Test for method that should return empty from empty db - /// - [Fact] - private async Task GetAllOfRoleForEmptyShouldReturnEmpty() - { + /// + /// Test for method that should return empty from empty db + /// + [Fact] + private async Task GetAllOfRoleForEmptyShouldReturnEmpty() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); @@ -65,12 +65,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().BeEmpty(); } - /// - /// Test for method that should return entities from not empty db - /// - [Fact] - private async Task GetAllOfRoleForNotEmptyShouldReturnEntities() - { + /// + /// Test for method that should return entities from not empty db + /// + [Fact] + private async Task GetAllOfRoleForNotEmptyShouldReturnEntities() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var users = new List(); @@ -88,5 +88,4 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().Contain(users).And.HaveSameCount(users); } - } -} +} \ No newline at end of file diff --git a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs index b034dd9..0abe709 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Infrastructure/Database/Repositories/VisaApplicationsRepositoryTests.cs @@ -11,30 +11,30 @@ using VisaApi.Fakers.VisaApplications; using VisaApi.Services; using Xunit; -namespace VisaApi.Tests.Infrastructure.Database.Repositories +namespace VisaApi.Tests.Infrastructure.Database.Repositories; + +[Collection(Collections.ContextUsingTestCollection)] +public class VisaApplicationsRepositoryTests { - [Collection(Collections.ContextUsingTestCollection)] - public class VisaApplicationsRepositoryTests + private readonly static UserFaker userFaker = new(); + private readonly static ApplicantFaker applicantFaker = new(GetDateTimeProvider()); + private readonly static VisaApplicationFaker applicationFaker = new(GetDateTimeProvider()); + + /// Returns + /// Database context + /// Repository + private static IVisaApplicationsRepository GetRepository(DbContext context) + => new VisaApplicationsRepository(context, context); + + /// Returns + private static IDateTimeProvider GetDateTimeProvider() => new TestDateTimeProvider(); + + /// + /// Test for method that should return empty if no applications added + /// + [Fact] + private async Task GetOfApplicantForEmptyShouldReturnEmpty() { - private readonly static UserFaker userFaker = new(); - private readonly static ApplicantFaker applicantFaker = new(GetDateTimeProvider()); - private readonly static VisaApplicationFaker applicationFaker = new(GetDateTimeProvider()); - - /// Returns - /// Database context - /// Repository - private static IVisaApplicationsRepository GetRepository(DbContext context) - => new VisaApplicationsRepository(context, context); - - /// Returns - private static IDateTimeProvider GetDateTimeProvider() => new TestDateTimeProvider(); - - /// - /// Test for method that should return empty if no applications added - /// - [Fact] - private async Task GetOfApplicantForEmptyShouldReturnEmpty() - { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -49,12 +49,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().BeEmpty(); } - /// - /// Test for method that should return added entities - /// - [Fact] - private async Task GetOfApplicantForExistingShouldReturnEntities() - { + /// + /// Test for method that should return added entities + /// + [Fact] + private async Task GetOfApplicantForExistingShouldReturnEntities() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -77,12 +77,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().Contain(applications).And.HaveSameCount(applications); } - /// - /// Test for method that should throw exception for not existing entities - /// - [Fact] - private async Task GetApplicantIdByUserIdForNotExistingShouldThrow() - { + /// + /// Test for method that should throw exception for not existing entities + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotExistingShouldThrow() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); ApplicationNotFoundByApplicantAndApplicationIdException? result = null; @@ -101,12 +101,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().NotBeNull(); } - /// - /// Test for method that should throw exception for not existing applicant - /// - [Fact] - private async Task GetApplicantIdByUserIdForNotExistingApplicantShouldThrow() - { + /// + /// Test for method that should throw exception for not existing applicant + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotExistingApplicantShouldThrow() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -132,12 +132,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().NotBeNull(); } - /// - /// Test for method that should throw exception for not existing application - /// - [Fact] - private async Task GetApplicantIdByUserIdForNotExistingApplicationShouldThrow() - { + /// + /// Test for method that should throw exception for not existing application + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotExistingApplicationShouldThrow() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -161,13 +161,13 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().NotBeNull(); } - /// - /// Test for method - /// that should throw exception for not accessible application - /// - [Fact] - private async Task GetApplicantIdByUserIdForNotAccessibleApplicationShouldThrow() - { + /// + /// Test for method + /// that should throw exception for not accessible application + /// + [Fact] + private async Task GetApplicantIdByUserIdForNotAccessibleApplicationShouldThrow() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -198,13 +198,13 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().NotBeNull(); } - /// - /// Test for method - /// that should return application for valid identifiers - /// - [Fact] - private async Task GetApplicantIdByUserIdForValidIdsShouldReturnApplication() - { + /// + /// Test for method + /// that should return application for valid identifiers + /// + [Fact] + private async Task GetApplicantIdByUserIdForValidIdsShouldReturnApplication() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -222,12 +222,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().Be(application); } - /// - /// Test for method that should return empty from empty db - /// - [Fact] - private async Task GetPendingApplicationsForEmptyShouldReturnEmpty() - { + /// + /// Test for method that should return empty from empty db + /// + [Fact] + private async Task GetPendingApplicationsForEmptyShouldReturnEmpty() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); @@ -236,12 +236,12 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().BeEmpty(); } - /// - /// Test for method that should return pending applications from not empty db - /// - [Fact] - private async Task GetPendingApplicationsForExistingShouldReturnExistingPending() - { + /// + /// Test for method that should return pending applications from not empty db + /// + [Fact] + private async Task GetPendingApplicationsForExistingShouldReturnExistingPending() + { await using var context = InMemoryContextProvider.GetDbContext(); var repository = GetRepository(context); var user = userFaker.Generate(); @@ -262,5 +262,4 @@ namespace VisaApi.Tests.Infrastructure.Database.Repositories result.Should().Contain(applicationPending).And.HaveCount(1); } - } -} +} \ No newline at end of file From 078e20d80e25348ba064a8259c75b9ca218fedc2 Mon Sep 17 00:00:00 2001 From: prtsie Date: Sun, 22 Sep 2024 19:54:03 +0300 Subject: [PATCH 22/22] tests --- .../Requests/PlaceOfWorkModelFaker.cs | 1 - .../Fakers/VisaApplications/PastVisaFaker.cs | 4 +- .../Fakers/VisaApplications/PastVisitFaker.cs | 4 +- .../PermissionToDestCountryFaker.cs | 10 +- .../Requests/PastVisaModelFaker.cs | 28 ++++ .../Requests/PastVisitModelFaker.cs | 28 ++++ .../PermissionToDestCountryModelFaker.cs | 17 +++ .../Requests/ReentryPermitModelFaker.cs | 21 +++ .../Auth/RegisterRequestValidatorTests.cs | 1 - .../PastVisaModelValidatorTests.cs | 140 +++++++++++++++++ .../PastVisitModelValidatorTests.cs | 142 ++++++++++++++++++ ...missionToDestCountryModelValidatorTests.cs | 110 ++++++++++++++ .../ReentryPermitModelValidatorTests.cs | 110 ++++++++++++++ 13 files changed, 605 insertions(+), 11 deletions(-) create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PastVisaModelFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PastVisitModelFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PermissionToDestCountryModelFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/ReentryPermitModelFaker.cs create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PastVisaModelValidatorTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PastVisitModelValidatorTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PermissionToDestCountryModelValidatorTests.cs create mode 100644 SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/ReentryPermitModelValidatorTests.cs diff --git a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs index eab2af5..1b42aab 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/Applicants/Requests/PlaceOfWorkModelFaker.cs @@ -1,6 +1,5 @@ using ApplicationLayer.Services.Applicants.Models; using Bogus; -using Domains.ApplicantDomain; namespace VisaApi.Fakers.Applicants.Requests; diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs index f853eb3..1ac6c60 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisaFaker.cs @@ -21,8 +21,8 @@ public sealed class PastVisaFaker : Faker public PastVisa GenerateValid() { var result = Generate(); - result.IssueDate = dateTimeProvider.Now().AddDays(Random.Shared.Next(11, 900)); + result.IssueDate = dateTimeProvider.Now().AddDays(-Random.Shared.Next(11, 900)); result.ExpirationDate = result.IssueDate.AddDays(Random.Shared.Next(1, 11)); return result; } -} \ No newline at end of file +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs index 183f1ba..96183c2 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PastVisitFaker.cs @@ -21,8 +21,8 @@ public sealed class PastVisitFaker : Faker public PastVisit GenerateValid() { var result = Generate(); - result.StartDate = dateTimeProvider.Now().AddDays(Random.Shared.Next(11, 900)); + result.StartDate = dateTimeProvider.Now().AddDays(-Random.Shared.Next(11, 900)); result.EndDate = result.StartDate.AddDays(Random.Shared.Next(1, 11)); return result; } -} \ No newline at end of file +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs index 73bb3f6..8ca6846 100644 --- a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/PermissionToDestCountryFaker.cs @@ -11,9 +11,9 @@ public sealed class PermissionToDestCountryFaker : Faker p.Issuer, f => f.Company.CompanyName()); + RuleFor(p => p.Issuer, f => f.Company.CompanyName()); - RuleFor(p => p.ExpirationDate, - f => f.Date.Future(4, dateTimeProvider.Now())); - } -} \ No newline at end of file + RuleFor(p => p.ExpirationDate, + f => f.Date.Future(4, dateTimeProvider.Now())); + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PastVisaModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PastVisaModelFaker.cs new file mode 100644 index 0000000..1b9ff0d --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PastVisaModelFaker.cs @@ -0,0 +1,28 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.VisaApplications.Models; +using Bogus; + +namespace VisaApi.Fakers.VisaApplications.Requests; + +/// +/// Generates past visas +/// +public sealed class PastVisaModelFaker : Faker +{ + private IDateTimeProvider dateTimeProvider; + + public PastVisaModelFaker(IDateTimeProvider dateTimeProvider) + { + this.dateTimeProvider = dateTimeProvider; + + RuleFor(pv => pv.Name, f => f.Random.Words()); + } + + public PastVisaModel GenerateValid() + { + var result = Generate(); + result.IssueDate = dateTimeProvider.Now().AddDays(-Random.Shared.Next(11, 900)); + result.ExpirationDate = result.IssueDate.AddDays(Random.Shared.Next(1, 11)); + return result; + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PastVisitModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PastVisitModelFaker.cs new file mode 100644 index 0000000..e975d08 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PastVisitModelFaker.cs @@ -0,0 +1,28 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.VisaApplications.Models; +using Bogus; + +namespace VisaApi.Fakers.VisaApplications.Requests; + +/// +/// Generates past visas +/// +public sealed class PastVisitModelFaker : Faker +{ + private IDateTimeProvider dateTimeProvider; + + public PastVisitModelFaker(IDateTimeProvider dateTimeProvider) + { + this.dateTimeProvider = dateTimeProvider; + + RuleFor(pv => pv.DestinationCountry, f => f.Address.Country()); + } + + public PastVisitModel GenerateValid() + { + var result = Generate(); + result.StartDate = dateTimeProvider.Now().AddDays(-Random.Shared.Next(11, 900)); + result.EndDate = result.StartDate.AddDays(Random.Shared.Next(1, 11)); + return result; + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PermissionToDestCountryModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PermissionToDestCountryModelFaker.cs new file mode 100644 index 0000000..719bb49 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/PermissionToDestCountryModelFaker.cs @@ -0,0 +1,17 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.VisaApplications.Models; +using Bogus; + +namespace VisaApi.Fakers.VisaApplications.Requests +{ + public sealed class PermissionToDestCountryModelFaker : Faker + { + public PermissionToDestCountryModelFaker(IDateTimeProvider dateTimeProvider) + { + RuleFor(p => p.Issuer, f => f.Company.CompanyName()); + + RuleFor(p => p.ExpirationDate, + f => f.Date.Future(4, dateTimeProvider.Now())); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/ReentryPermitModelFaker.cs b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/ReentryPermitModelFaker.cs new file mode 100644 index 0000000..4efcd47 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Fakers/VisaApplications/Requests/ReentryPermitModelFaker.cs @@ -0,0 +1,21 @@ +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.VisaApplications.Models; +using Bogus; +using Domains; + +namespace VisaApi.Fakers.VisaApplications.Requests; + +/// +/// Generates re-entry permissions +/// +public sealed class ReentryPermitModelFaker : Faker +{ + public ReentryPermitModelFaker(IDateTimeProvider dateTimeProvider) + { + RuleFor(p => p.Number, + f => f.Random.String(ConfigurationConstraints.ReentryPermitNumberLength, 'a', 'z')); + + RuleFor(p => p.ExpirationDate, + f => f.Date.Future(4, dateTimeProvider.Now())); + } +} diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs index 74eb02f..5165e3c 100644 --- a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/Auth/RegisterRequestValidatorTests.cs @@ -1,4 +1,3 @@ -using ApplicationLayer.InfrastructureServicesInterfaces; using ApplicationLayer.Services.AuthServices.Common; using ApplicationLayer.Services.AuthServices.Requests; using ApplicationLayer.Services.AuthServices.Requests.Validation; diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PastVisaModelValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PastVisaModelValidatorTests.cs new file mode 100644 index 0000000..a40a3f2 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PastVisaModelValidatorTests.cs @@ -0,0 +1,140 @@ +using System.Text; +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.VisaApplications.Models; +using ApplicationLayer.Services.VisaApplications.Models.Validation; +using Domains; +using FluentAssertions; +using FluentValidation; +using VisaApi.Fakers.VisaApplications.Requests; +using VisaApi.Services; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.VisaApplications +{ + public class PastVisaModelValidatorTests + { + private readonly static IDateTimeProvider dateTimeProvider = new TestDateTimeProvider(); + private readonly static IValidator validator = new PastVisaModelValidator(dateTimeProvider); + private readonly static PastVisaModelFaker faker = new(dateTimeProvider); + + /// + /// Test for validator that should return error for empty expiration date + /// + [Fact] + private async Task ValidateForEmptyExpirationDateShouldReturnError() + { + var model = faker.GenerateValid(); + model.ExpirationDate = new(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.ExpirationDate)) + .Should().HaveCount(2); //expected error + error because of expiration date less than issue date + } + + /// + /// Test for validator that should return error for expiration date less than issue date + /// + [Fact] + private async Task ValidateForExpirationDateLessThanIssueDateShouldReturnError() + { + var model = faker.GenerateValid(); + model.ExpirationDate = model.IssueDate.AddDays(-4); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.ExpirationDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty issue date + /// + [Fact] + private async Task ValidateForEmptyIssueDateShouldReturnError() + { + var model = faker.GenerateValid(); + model.IssueDate = new(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.IssueDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for issue date greater than current date + /// + [Fact] + private async Task ValidateForIssueDateGreaterThanCurrentDateShouldReturnError() + { + var model = faker.GenerateValid(); + model.IssueDate = dateTimeProvider.Now().AddDays(4); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.IssueDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty name + /// + [Fact] + private async Task ValidateForEmptyNameShouldReturnError() + { + var model = faker.GenerateValid(); + model.Name = string.Empty; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Name)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long name + /// + [Fact] + private async Task ValidateForTooLongNameShouldReturnError() + { + var model = faker.GenerateValid(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('d', ConfigurationConstraints.VisaNameLength + 1); + model.Name = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Name)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid name + /// + [Fact] + private async Task ValidateForNotValidNameShouldReturnError() + { + var model = faker.GenerateValid(); + model.Name = "|}{%^&"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Name)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return no errors for valid model + /// + [Fact] + private async Task ValidateForValidShouldReturnNoErrors() + { + var model = faker.GenerateValid(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Should().BeEmpty(); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PastVisitModelValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PastVisitModelValidatorTests.cs new file mode 100644 index 0000000..d04cbf1 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PastVisitModelValidatorTests.cs @@ -0,0 +1,142 @@ +using System.Text; +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.VisaApplications.Models; +using ApplicationLayer.Services.VisaApplications.Models.Validation; +using Domains; +using FluentAssertions; +using FluentValidation; +using VisaApi.Fakers.VisaApplications.Requests; +using VisaApi.Services; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.VisaApplications +{ + public class PastVisitModelValidatorTests + { + private readonly static IDateTimeProvider dateTimeProvider = new TestDateTimeProvider(); + private readonly static IValidator validator = new PastVisitModelValidator(dateTimeProvider); + private readonly static PastVisitModelFaker faker = new(dateTimeProvider); + + /// + /// Test for validator that should return error for empty start date + /// + [Fact] + private async Task ValidateForEmptyStartDateShouldReturnError() + { + var model = faker.GenerateValid(); + model.StartDate = new(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.StartDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for start date greater than end date + /// + [Fact] + private async Task ValidateForStartDateGreaterThanEndDateShouldReturnError() + { + var model = faker.GenerateValid(); + model.EndDate = dateTimeProvider.Now().AddDays(-10); + model.StartDate = model.EndDate.AddDays(4); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.StartDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty end date + /// + [Fact] + private async Task ValidateForEmptyEndDateShouldReturnError() + { + var model = faker.GenerateValid(); + model.EndDate = new(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.EndDate)) + .Should().HaveCount(1); //expected error + error because of end date less than start date + } + + /// + /// Test for validator that should return error for start date greater than current date + /// + [Fact] + private async Task ValidateForStartDateGreaterThanCurrentDateShouldReturnError() + { + var model = faker.GenerateValid(); + model.StartDate = dateTimeProvider.Now().AddDays(4); + model.EndDate = model.StartDate.AddDays(4); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.StartDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty destination Country + /// + [Fact] + private async Task ValidateForEmptyDestinationCountryShouldReturnError() + { + var model = faker.GenerateValid(); + model.DestinationCountry = string.Empty; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.DestinationCountry)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long destination Country + /// + [Fact] + private async Task ValidateForTooLongDestinationCountryShouldReturnError() + { + var model = faker.GenerateValid(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('d', ConfigurationConstraints.CountryNameLength + 1); + model.DestinationCountry = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.DestinationCountry)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid destination Country + /// + [Fact] + private async Task ValidateForNotValidDestinationCountryShouldReturnError() + { + var model = faker.GenerateValid(); + model.DestinationCountry = "|}{%^&"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.DestinationCountry)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return no errors for valid model + /// + [Fact] + private async Task ValidateForValidShouldReturnNoErrors() + { + var model = faker.GenerateValid(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Should().BeEmpty(); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PermissionToDestCountryModelValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PermissionToDestCountryModelValidatorTests.cs new file mode 100644 index 0000000..37a55a2 --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/PermissionToDestCountryModelValidatorTests.cs @@ -0,0 +1,110 @@ +using System.Text; +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.VisaApplications.Models; +using ApplicationLayer.Services.VisaApplications.Models.Validation; +using Domains; +using FluentAssertions; +using FluentValidation; +using VisaApi.Fakers.VisaApplications.Requests; +using VisaApi.Services; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.VisaApplications +{ + public class PermissionToDestCountryModelValidatorTests + { + private readonly static IDateTimeProvider dateTimeProvider = new TestDateTimeProvider(); + private readonly static IValidator validator = new PermissionToDestCountryModelValidator(dateTimeProvider); + private readonly static PermissionToDestCountryModelFaker faker = new(dateTimeProvider); + + /// + /// Test for validator that should return error for empty expiration date + /// + [Fact] + private async Task ValidateForEmptyExpirationDateShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = new(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.ExpirationDate)) + .Should().HaveCount(2); //expected error + error because of expired + } + + /// + /// Test for validator that should return error for expiration date less than current date + /// + [Fact] + private async Task ValidateForExpirationDateLessThanCurrentDateShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = dateTimeProvider.Now().AddDays(-1); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.ExpirationDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty issuer + /// + [Fact] + private async Task ValidateForEmptyIssuerShouldReturnError() + { + var model = faker.Generate(); + model.Issuer = string.Empty; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid issuer + /// + [Fact] + private async Task ValidateForNotValidIssuerShouldReturnError() + { + var model = faker.Generate(); + model.Issuer = "}{)(*&*^%#!#!:"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long issuer + /// + [Fact] + private async Task ValidateForTooLongIssuerShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('g', ConfigurationConstraints.IssuerNameLength + 1); + model.Issuer = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Issuer)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return no errors for valid model + /// + [Fact] + private async Task ValidateForValidShouldReturnNoErrors() + { + var model = faker.Generate(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Should().BeEmpty(); + } + } +} diff --git a/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/ReentryPermitModelValidatorTests.cs b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/ReentryPermitModelValidatorTests.cs new file mode 100644 index 0000000..b4613cb --- /dev/null +++ b/SchengenVisaApi/VisaApiTests/Tests/Application/Validation/VisaApplications/ReentryPermitModelValidatorTests.cs @@ -0,0 +1,110 @@ +using System.Text; +using ApplicationLayer.InfrastructureServicesInterfaces; +using ApplicationLayer.Services.VisaApplications.Models; +using ApplicationLayer.Services.VisaApplications.Models.Validation; +using Domains; +using FluentAssertions; +using FluentValidation; +using VisaApi.Fakers.VisaApplications.Requests; +using VisaApi.Services; +using Xunit; + +namespace VisaApi.Tests.Application.Validation.VisaApplications +{ + public class ReentryPermitModelValidatorTests + { + private readonly static IDateTimeProvider dateTimeProvider = new TestDateTimeProvider(); + private readonly static IValidator validator = new ReentryPermitModelValidator(dateTimeProvider); + private readonly static ReentryPermitModelFaker faker = new(dateTimeProvider); + + /// + /// Test for validator that should return error for empty expiration date + /// + [Fact] + private async Task ValidateForEmptyExpirationDateShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = new(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.ExpirationDate)) + .Should().HaveCount(2); //expected error + error because of expired + } + + /// + /// Test for validator that should return error for expiration date less than current date + /// + [Fact] + private async Task ValidateForExpirationDateLessThanCurrentDateShouldReturnError() + { + var model = faker.Generate(); + model.ExpirationDate = dateTimeProvider.Now().AddDays(-1); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.ExpirationDate)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for empty number + /// + [Fact] + private async Task ValidateForEmptyNumberShouldReturnError() + { + var model = faker.Generate(); + model.Number = string.Empty; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Number)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for not valid number + /// + [Fact] + private async Task ValidateForNotValidNumberShouldReturnError() + { + var model = faker.Generate(); + model.Number = "}{)(*&*^%#!#!:"; + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Number)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return error for too long number + /// + [Fact] + private async Task ValidateForTooLongNumberShouldReturnError() + { + var model = faker.Generate(); + var stringBuilder = new StringBuilder(); + stringBuilder.Append('g', ConfigurationConstraints.ReentryPermitNumberLength + 1); + model.Number = stringBuilder.ToString(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Where(error => error.PropertyName == nameof(model.Number)) + .Should().HaveCount(1); + } + + /// + /// Test for validator that should return no errors for valid model + /// + [Fact] + private async Task ValidateForValidShouldReturnNoErrors() + { + var model = faker.Generate(); + + var result = await validator.ValidateAsync(model); + + result.Errors.Should().BeEmpty(); + } + } +}