diff --git a/.gitignore b/.gitignore index f4848c0..fc4c4df 100644 --- a/.gitignore +++ b/.gitignore @@ -344,4 +344,6 @@ healthchecksdb # BlobStorage BlobStorageFolder/ -BlobStorageTestFolder/ \ No newline at end of file +BlobStorageTestFolder/ +/Streetcode/Streetcode.WebApi/appsettings.json +/Streetcode/Streetcode.WebApi/appsettings.Local.json diff --git a/Streetcode/Streetcode.DAL/Persistence/Migrations/StreetcodeDbContextModelSnapshot.cs b/Streetcode/Streetcode.DAL/Persistence/Migrations/StreetcodeDbContextModelSnapshot.cs index 84f1c0e..a5092ca 100644 --- a/Streetcode/Streetcode.DAL/Persistence/Migrations/StreetcodeDbContextModelSnapshot.cs +++ b/Streetcode/Streetcode.DAL/Persistence/Migrations/StreetcodeDbContextModelSnapshot.cs @@ -842,7 +842,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("HistoricalContextId"); - b.ToTable("HistoricalContextsTimelines"); + b.ToTable("HistoricalContextsTimelines", (string)null); }); modelBuilder.Entity("Streetcode.DAL.Entities.Timeline.TimelineItem", b => diff --git a/Streetcode/Streetcode.WebApi/Program.cs b/Streetcode/Streetcode.WebApi/Program.cs index 02523a8..d0ce7a8 100644 --- a/Streetcode/Streetcode.WebApi/Program.cs +++ b/Streetcode/Streetcode.WebApi/Program.cs @@ -27,7 +27,7 @@ await app.ApplyMigrations(); -// await app.SeedDataAsync(); // uncomment for seeding data in local +await app.SeedDataAsync(); // uncomment for seeding data in local app.UseCors(); app.UseHttpsRedirection(); app.UseRouting(); diff --git a/Streetcode/Streetcode.WebApi/appsettings.Local.json b/Streetcode/Streetcode.WebApi/appsettings.Local.json deleted file mode 100644 index 14b4447..0000000 --- a/Streetcode/Streetcode.WebApi/appsettings.Local.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ConnectionStrings": { - "DefaultConnection": "Server=127.0.0.1;Database=StreetcodeDb;User Id=sa;Password=Admin@1234;MultipleActiveResultSets=true" - }, - "CORS": { - "AllowedOrigins": [ "http://localhost:3000" ], - "AllowedHeaders": [ "*" ], - "AllowedMethods": [ "*" ], - "PreflightMaxAge": 1 - } -} diff --git a/Streetcode/Streetcode.WebApi/appsettings.json b/Streetcode/Streetcode.WebApi/appsettings.json deleted file mode 100644 index 7e1e684..0000000 --- a/Streetcode/Streetcode.WebApi/appsettings.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "ConnectionStrings": { - "DefaultConnection": "Server=127.0.0.1;Database=StreetcodeDb;User Id=sa;Password=Admin@1234;MultipleActiveResultSets=true" - }, - "EmailConfiguration": { - "From": "streetcodefeedback@gmail.com", - "To": "streetcodeua@gmail.com", - "SmtpServer": "smtp.gmail.com", - "Port": 465, - "Username": "streetcodefeedback@gmail.com" - }, - "Serilog": { - "Using": [], - "MinimumLevel": { - "Default": "Information", - "Microsoft": "Warning", - "System": "Warning" - }, - "Enrich": [ - "FromLogContext", - "WithMachineName", - "WithProcessId", - "WithThreadId" - ], - "WriteTo": [ - { - "Name": "Console" - } - ] - }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*", - "Blob": { - "BlobStoreKey": "SlavaKasterovSuperGoodInshalaKey", - "BlobStorePath": "../../BlobStorageFolder/" - }, - "Payment": { - "Token": "BombasticTokenForMonobank" - }, - "Instagram": { - "InstagramID": "NiceIdForInstagram", - "InstagramToken": "SuperNiceTokenForInstagram" - }, - "CORS": { - "AllowedOrigins": [], - "AllowedHeaders": [], - "AllowedMethods": [], - "PreflightMaxAge": 1 - } -} diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Art/GetAll/GetAllArtsHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Art/GetAll/GetAllArtsHandlerTests.cs new file mode 100644 index 0000000..21174cf --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Art/GetAll/GetAllArtsHandlerTests.cs @@ -0,0 +1,111 @@ +using AutoMapper; +using FluentResults; +using Microsoft.EntityFrameworkCore.Query; +using Moq; +using Repositories.Interfaces; +using Streetcode.BLL.DTO.Media.Art; +using Streetcode.BLL.Interfaces.Logging; +using Streetcode.BLL.MediatR.Media.Art.GetAll; +using Streetcode.DAL.Entities.Media.Images; +using Streetcode.DAL.Repositories.Interfaces.Base; +using System.Linq.Expressions; +using Xunit; + +namespace Streetcode.XUnitTest.BLL.MediatR.Media.Art.GetAll; + +/// +/// Tests for GetAllArtsHandler. +/// +public class GetAllArtsHandlerTests +{ + private GetAllArtsHandler handler; + + private Mock mockMapper; + private Mock mockRepository; + private Mock mockArtRepository; + private Mock mockLoggerService; + + private IMapper mapper; + + /// + /// Initializes a new instance of the class. + /// + public GetAllArtsHandlerTests() + { + this.mockMapper = new Mock(); + this.mockRepository = new Mock(); + this.mockArtRepository = new Mock(); + this.mockLoggerService = new Mock(); + + this.mockRepository + .Setup(r => r.ArtRepository) + .Returns(this.mockArtRepository.Object); + + this.mapper = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + }).CreateMapper(); + + this.handler = new GetAllArtsHandler( + this.mockRepository.Object, + this.mapper, + this.mockLoggerService.Object); + } + + /// + /// Method Handel returns all Arts, if they are. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task Handle_ArtsNotEmpty_ReturnAllArts() + { + var query = new GetAllArtsQuery(); + + int expectedCount = 1; + + var arts = new List() + { + new DAL.Entities.Media.Images.Art() + { + Id = 1, + Description = "Description art 1", + ImageId = 1, + Title = "Title art 1", + }, + }; + + this.mockArtRepository + .Setup(r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, + IIncludableQueryable>>())) + .ReturnsAsync(arts); + + var result = await this.handler.Handle(query, CancellationToken.None); + + Assert.Equal(expectedCount, result.Value.Count()); + } + + /// + /// Method Handle return error message, if Arts do not exist. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task Handle_ArtsIsEmpty_ReturnErrorMessage() + { + var query = new GetAllArtsQuery(); + + var expectedError = new Error($"Cannot find any arts"); + + this.mockArtRepository + .Setup(r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, + IIncludableQueryable>>())) + .ReturnsAsync((List?)null); + + var result = await this.handler.Handle(query, CancellationToken.None); + + Assert.Equal(expectedError.Message, result.Errors.First().Message); + } +} diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Art/GetById/GetArtByIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Art/GetById/GetArtByIdHandlerTests.cs new file mode 100644 index 0000000..1681ff7 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Art/GetById/GetArtByIdHandlerTests.cs @@ -0,0 +1,117 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore.Query; +using Moq; +using Org.BouncyCastle.Asn1.Ocsp; +using Repositories.Interfaces; +using Streetcode.BLL.DTO.Media.Art; +using Streetcode.BLL.Interfaces.Logging; +using Streetcode.BLL.MediatR.Media.Art.GetById; +using Streetcode.DAL.Repositories.Interfaces.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Streetcode.XUnitTest.BLL.MediatR.Media.Art.GetById +{ + /// + /// Checking class GetArtByIdHandler. + /// + public class GetArtByIdHandlerTests + { + private GetArtByIdHandler handler; + + private Mock mockMapper; + private Mock mockRepository; + private Mock mockArtRepository; + private Mock mockLoggerService; + + /// + /// Initializes a new instance of the class. + /// + public GetArtByIdHandlerTests() + { + this.mockMapper = new Mock(); + this.mockArtRepository = new Mock(); + this.mockRepository = new Mock(); + this.mockLoggerService = new Mock(); + + this.mockRepository + .Setup(r => r.ArtRepository) + .Returns(this.mockArtRepository.Object); + + this.handler = new GetArtByIdHandler( + this.mockRepository.Object, + this.mockMapper.Object, + this.mockLoggerService.Object); + } + + /// + /// Method returns correct art, if entered valid id. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task Handle_ValidId_ReturnArt() + { + var query = new GetArtByIdQuery(1); + + var art = new DAL.Entities.Media.Images.Art() + { + Id = 1, + Description = "Description art 1", + ImageId = 1, + Title = "Title art 1", + }; + + var artDTO = new ArtDTO() + { + Id = 1, + Description = "Description art 1", + ImageId = 1, + Title = "Title art 1", + }; + + this.mockArtRepository + .Setup(r => r.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, + IIncludableQueryable>>())) + .ReturnsAsync(art); + + this.mockMapper + .Setup(m => m.Map( + It.IsAny())) + .Returns(artDTO); + + var result = await this.handler.Handle(query, CancellationToken.None); + + Assert.Equal(artDTO.Id, result.Value.Id); + } + + /// + /// Method returns error message, if entered not valid id. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task Handle_NotValidId_ReturnError() + { + var query = new GetArtByIdQuery(2); + + string expectedErrorMsg = $"Cannot find an art with corresponding id: {query.Id}"; + + this.mockArtRepository + .Setup(r => r.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, + IIncludableQueryable>>())) + .ReturnsAsync((DAL.Entities.Media.Images.Art?)null); + + var result = await this.handler.Handle(query, CancellationToken.None); + + Assert.Equal(expectedErrorMsg, result.Errors.First().Message); + } + } +} diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Art/GetByStreetcodeId/GetArtByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Art/GetByStreetcodeId/GetArtByStreetcodeIdHandlerTests.cs new file mode 100644 index 0000000..4605e58 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Media/Art/GetByStreetcodeId/GetArtByStreetcodeIdHandlerTests.cs @@ -0,0 +1,131 @@ +using AutoMapper; +using Castle.Core.Logging; +using Microsoft.EntityFrameworkCore.Query; +using Moq; +using Org.BouncyCastle.Asn1.Ocsp; +using Repositories.Interfaces; +using Streetcode.BLL.DTO.Media.Art; +using Streetcode.BLL.Interfaces.BlobStorage; +using Streetcode.BLL.Interfaces.Logging; +using Streetcode.BLL.MediatR.Media.Art.GetByStreetcodeId; +using Streetcode.DAL.Entities.Media.Images; +using Streetcode.DAL.Entities.Streetcode; +using Streetcode.DAL.Repositories.Interfaces.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Streetcode.XUnitTest.BLL.MediatR.Media.Art.GetByStreetcodeId +{ + /// + /// Checking class GetArtByStreetcodeIdHandler. + /// + public class GetArtByStreetcodeIdHandlerTests + { + private GetArtsByStreetcodeIdHandler handler; + + private Mock mockRepository; + private Mock mockMapper; + private Mock mockBlobService; + private Mock mockLoggerService; + private Mock mockArtRepository; + + private IMapper mapper; + + /// + /// Initializes a new instance of the class. + /// + public GetArtByStreetcodeIdHandlerTests() + { + this.mockRepository = new Mock(); + this.mockMapper = new Mock(); + this.mockBlobService = new Mock(); + this.mockLoggerService = new Mock(); + this.mockArtRepository = new Mock(); + + this.mockRepository + .Setup(r => r.ArtRepository) + .Returns(this.mockArtRepository.Object); + + this.mapper = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + }).CreateMapper(); + + this.handler = new GetArtsByStreetcodeIdHandler( + this.mockRepository.Object, + this.mapper, + this.mockBlobService.Object, + this.mockLoggerService.Object); + } + + /// + /// Method returns correct arts, if entered valid streetcodeId. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task Handle_ValidStreetcodeId_ReturnCorrectArts() + { + var query = new GetArtsByStreetcodeIdQuery(1); + + var expectedCount = 1; + + var arts = new List() + { + new DAL.Entities.Media.Images.Art() + { + Id = 1, + Description = "Description art 1", + ImageId = 1, + Title = "Title art 1", + StreetcodeArts = new List() + { + new StreetcodeArt() + { + ArtId = 1, + StreetcodeId = 1, + }, + }, + }, + }; + + this.mockArtRepository + .Setup(r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, + IIncludableQueryable>>())) + .ReturnsAsync(arts); + + var result = await this.handler.Handle(query, CancellationToken.None); + + Assert.Equal(expectedCount, result.Value.Count()); + } + + /// + /// Method returns error message, if streetcode not exist arts. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task Handle_ValidStretcodeIdWithEmptyArts_ReturnErrorMessage() + { + var query = new GetArtsByStreetcodeIdQuery(1); + + var expectedErrorMessage = $"Cannot find any art with corresponding streetcode id: {query.StreetcodeId}"; + + this.mockArtRepository + .Setup(r => r.GetAllAsync( + It.IsAny>>(), + It.IsAny, + IIncludableQueryable>>())) + .ReturnsAsync((List?)null); + + var result = await this.handler.Handle(query, CancellationToken.None); + + Assert.Equal(expectedErrorMessage, result.Errors.First().Message); + } + } +} diff --git a/Streetcode/Streetcode.XUnitTest/stylecop.json b/Streetcode/Streetcode.XUnitTest/stylecop.json new file mode 100644 index 0000000..42fb1f8 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/stylecop.json @@ -0,0 +1,14 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "PlaceholderCompany" + } + } +} diff --git a/build/_build.csproj.DotSettings b/build/_build.csproj.DotSettings index 7bc2848..0306022 100644 --- a/build/_build.csproj.DotSettings +++ b/build/_build.csproj.DotSettings @@ -16,6 +16,8 @@ False <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></Policy> True True True @@ -24,4 +26,5 @@ True True True - True + True + True