From 7a22263e13eff8340a473330025f060dbacb2cac Mon Sep 17 00:00:00 2001 From: Nikita Date: Tue, 12 May 2026 23:56:24 +0300 Subject: [PATCH 01/15] Add test Handle_ReturnsNullResult_WhenTextNotFoundButStreetcodeExists --- .../Text/GetTextByStreetcodeIdHandlerTests.cs | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs new file mode 100644 index 0000000..1e48ab7 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs @@ -0,0 +1,85 @@ +using AutoMapper; +using FluentAssertions; +using Microsoft.EntityFrameworkCore.Query; +using Moq; +using Streetcode.BLL.Interfaces.Logging; +using Streetcode.BLL.Interfaces.Text; +using Streetcode.BLL.MediatR.Streetcode.Text.GetByStreetcodeId; +using Streetcode.DAL.Entities.Streetcode; +using Streetcode.DAL.Entities.Streetcode.TextContent; +using Streetcode.DAL.Repositories.Interfaces.Base; +using Streetcode.DAL.Repositories.Interfaces.Streetcode; +using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; +using System.Linq.Expressions; +using Xunit; + +namespace Streetcode.XUnitTest.MediatRTests.Streetcode.Text.GetByStreetcodeId; + +public class GetTextByStreetcodeIdHandlerTests +{ + private readonly Mock repositoryWrapperMock; + private readonly Mock textRepositoryMock; + private readonly Mock streetcodeRepositoryMock; + private readonly Mock mapperMock; + private readonly Mock textServiceMock; + private readonly Mock loggerMock; + private readonly GetTextByStreetcodeIdHandler handler; + + public GetTextByStreetcodeIdHandlerTests() + { + this.repositoryWrapperMock = new Mock(); + this.textRepositoryMock = new Mock(); + this.streetcodeRepositoryMock = new Mock(); + this.mapperMock = new Mock(); + this.textServiceMock = new Mock(); + this.loggerMock = new Mock(); + + this.repositoryWrapperMock + .Setup(w => w.TextRepository) + .Returns(this.textRepositoryMock.Object); + + this.repositoryWrapperMock + .Setup(w => w.StreetcodeRepository) + .Returns(this.streetcodeRepositoryMock.Object); + + this.handler = new GetTextByStreetcodeIdHandler( + this.repositoryWrapperMock.Object, + this.mapperMock.Object, + this.textServiceMock.Object, + this.loggerMock.Object); + } + + [Fact] + public async Task Handle_ReturnsNullResult_WhenTextNotFoundButStreetcodeExists() + { + // Arrange + var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); + + this.textRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((DAL.Entities.Streetcode.TextContent.Text?)null); + + this.streetcodeRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(new StreetcodeContent { Id = 1 }); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().BeNull(); + + this.loggerMock.Verify( + l => l.LogError(It.IsAny(), It.IsAny()), + Times.Never); + + this.textServiceMock.Verify( + s => s.AddTermsTag(It.IsAny()), + Times.Never); + } +} From 094dccddef8b2fc72ff88ba7b83b5e0f235826b2 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 00:03:30 +0300 Subject: [PATCH 02/15] Add test Handle_ReturnsError_WhenStreetcodeDoesNotExist --- .../Text/GetTextByStreetcodeIdHandlerTests.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs index 1e48ab7..a572ddb 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs @@ -82,4 +82,37 @@ public async Task Handle_ReturnsNullResult_WhenTextNotFoundButStreetcodeExists() s => s.AddTermsTag(It.IsAny()), Times.Never); } + + [Fact] + public async Task Handle_ReturnsError_WhenStreetcodeDoesNotExist() + { + // Arrange + var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); + + this.textRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((DAL.Entities.Streetcode.TextContent.Text?)null); + + this.streetcodeRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((StreetcodeContent?)null); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsFailed.Should().BeTrue(); + + this.loggerMock.Verify( + l => l.LogError(query, It.Is(msg => msg.Contains("1"))), + Times.Once); + + this.textServiceMock.Verify( + s => s.AddTermsTag(It.IsAny()), + Times.Never); + } } From f2da0cc374fe6917e596ba3e348276eb0d4bb44d Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 00:07:07 +0300 Subject: [PATCH 03/15] Add test Handle_UsesAddTermsTagResult_AsTextContent --- .../Text/GetTextByStreetcodeIdHandlerTests.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs index a572ddb..8d77db1 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs @@ -2,6 +2,7 @@ using FluentAssertions; using Microsoft.EntityFrameworkCore.Query; using Moq; +using Streetcode.BLL.DTO.Streetcode.TextContent.Text; using Streetcode.BLL.Interfaces.Logging; using Streetcode.BLL.Interfaces.Text; using Streetcode.BLL.MediatR.Streetcode.Text.GetByStreetcodeId; @@ -115,4 +116,45 @@ public async Task Handle_ReturnsError_WhenStreetcodeDoesNotExist() s => s.AddTermsTag(It.IsAny()), Times.Never); } + + [Fact] + public async Task Handle_UsesAddTermsTagResult_AsTextContent() + { + // Arrange + const string originalContent = "Text about streetcode"; + const string taggedContent = "streetcodedescription"; + var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); + var textEntity = new DAL.Entities.Streetcode.TextContent.Text + { + Id = 1, + StreetcodeId = 1, + TextContent = originalContent + }; + + this.textRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(textEntity); + + this.textServiceMock + .Setup(s => s.AddTermsTag(originalContent)) + .ReturnsAsync(taggedContent); + + DAL.Entities.Streetcode.TextContent.Text? capturedEntity = null; + this.mapperMock + .Setup(m => m.Map(It.IsAny())) + .Callback(obj => capturedEntity = obj as DAL.Entities.Streetcode.TextContent.Text) + .Returns(new TextDTO { TextContent = taggedContent }); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + capturedEntity.Should().NotBeNull(); + capturedEntity!.TextContent.Should().Be(taggedContent); + result.Value!.TextContent.Should().Be(taggedContent); + } + } From 88b6c9644fba577f0766bb0e4f05368367bc48f1 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 00:31:48 +0300 Subject: [PATCH 04/15] Add test AddTermsTag_ReturnsNull_WhenInputIsNull --- .../Text/GetTextByStreetcodeIdHandlerTests.cs | 281 +++++++++--------- .../Text/AddTermsToTextServiceTests.cs | 33 ++ 2 files changed, 174 insertions(+), 140 deletions(-) create mode 100644 Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs index 8d77db1..54a930a 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs @@ -14,147 +14,148 @@ using System.Linq.Expressions; using Xunit; -namespace Streetcode.XUnitTest.MediatRTests.Streetcode.Text.GetByStreetcodeId; - -public class GetTextByStreetcodeIdHandlerTests +namespace Streetcode.XUnitTest.MediatRTests.Streetcode.Text.GetByStreetcodeId { - private readonly Mock repositoryWrapperMock; - private readonly Mock textRepositoryMock; - private readonly Mock streetcodeRepositoryMock; - private readonly Mock mapperMock; - private readonly Mock textServiceMock; - private readonly Mock loggerMock; - private readonly GetTextByStreetcodeIdHandler handler; - - public GetTextByStreetcodeIdHandlerTests() - { - this.repositoryWrapperMock = new Mock(); - this.textRepositoryMock = new Mock(); - this.streetcodeRepositoryMock = new Mock(); - this.mapperMock = new Mock(); - this.textServiceMock = new Mock(); - this.loggerMock = new Mock(); - - this.repositoryWrapperMock - .Setup(w => w.TextRepository) - .Returns(this.textRepositoryMock.Object); - - this.repositoryWrapperMock - .Setup(w => w.StreetcodeRepository) - .Returns(this.streetcodeRepositoryMock.Object); - - this.handler = new GetTextByStreetcodeIdHandler( - this.repositoryWrapperMock.Object, - this.mapperMock.Object, - this.textServiceMock.Object, - this.loggerMock.Object); - } - - [Fact] - public async Task Handle_ReturnsNullResult_WhenTextNotFoundButStreetcodeExists() + public class GetTextByStreetcodeIdHandlerTests { - // Arrange - var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); - - this.textRepositoryMock - .Setup(repo => repo.GetFirstOrDefaultAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>?>())) - .ReturnsAsync((DAL.Entities.Streetcode.TextContent.Text?)null); - - this.streetcodeRepositoryMock - .Setup(repo => repo.GetFirstOrDefaultAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>?>())) - .ReturnsAsync(new StreetcodeContent { Id = 1 }); - - // Act - var result = await this.handler.Handle(query, CancellationToken.None); - - // Assert - result.IsSuccess.Should().BeTrue(); - result.Value.Should().BeNull(); - - this.loggerMock.Verify( - l => l.LogError(It.IsAny(), It.IsAny()), - Times.Never); - - this.textServiceMock.Verify( - s => s.AddTermsTag(It.IsAny()), - Times.Never); - } - - [Fact] - public async Task Handle_ReturnsError_WhenStreetcodeDoesNotExist() - { - // Arrange - var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); - - this.textRepositoryMock - .Setup(repo => repo.GetFirstOrDefaultAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>?>())) - .ReturnsAsync((DAL.Entities.Streetcode.TextContent.Text?)null); - - this.streetcodeRepositoryMock - .Setup(repo => repo.GetFirstOrDefaultAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>?>())) - .ReturnsAsync((StreetcodeContent?)null); - - // Act - var result = await this.handler.Handle(query, CancellationToken.None); - - // Assert - result.IsFailed.Should().BeTrue(); - - this.loggerMock.Verify( - l => l.LogError(query, It.Is(msg => msg.Contains("1"))), - Times.Once); - - this.textServiceMock.Verify( - s => s.AddTermsTag(It.IsAny()), - Times.Never); - } - - [Fact] - public async Task Handle_UsesAddTermsTagResult_AsTextContent() - { - // Arrange - const string originalContent = "Text about streetcode"; - const string taggedContent = "streetcodedescription"; - var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); - var textEntity = new DAL.Entities.Streetcode.TextContent.Text + private readonly Mock repositoryWrapperMock; + private readonly Mock textRepositoryMock; + private readonly Mock streetcodeRepositoryMock; + private readonly Mock mapperMock; + private readonly Mock textServiceMock; + private readonly Mock loggerMock; + private readonly GetTextByStreetcodeIdHandler handler; + + public GetTextByStreetcodeIdHandlerTests() { - Id = 1, - StreetcodeId = 1, - TextContent = originalContent - }; - - this.textRepositoryMock - .Setup(repo => repo.GetFirstOrDefaultAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>?>())) - .ReturnsAsync(textEntity); - - this.textServiceMock - .Setup(s => s.AddTermsTag(originalContent)) - .ReturnsAsync(taggedContent); - - DAL.Entities.Streetcode.TextContent.Text? capturedEntity = null; - this.mapperMock - .Setup(m => m.Map(It.IsAny())) - .Callback(obj => capturedEntity = obj as DAL.Entities.Streetcode.TextContent.Text) - .Returns(new TextDTO { TextContent = taggedContent }); - - // Act - var result = await this.handler.Handle(query, CancellationToken.None); - - // Assert - result.IsSuccess.Should().BeTrue(); - capturedEntity.Should().NotBeNull(); - capturedEntity!.TextContent.Should().Be(taggedContent); - result.Value!.TextContent.Should().Be(taggedContent); - } + this.repositoryWrapperMock = new Mock(); + this.textRepositoryMock = new Mock(); + this.streetcodeRepositoryMock = new Mock(); + this.mapperMock = new Mock(); + this.textServiceMock = new Mock(); + this.loggerMock = new Mock(); + + this.repositoryWrapperMock + .Setup(w => w.TextRepository) + .Returns(this.textRepositoryMock.Object); + + this.repositoryWrapperMock + .Setup(w => w.StreetcodeRepository) + .Returns(this.streetcodeRepositoryMock.Object); + + this.handler = new GetTextByStreetcodeIdHandler( + this.repositoryWrapperMock.Object, + this.mapperMock.Object, + this.textServiceMock.Object, + this.loggerMock.Object); + } + + [Fact] + public async Task Handle_ReturnsNullResult_WhenTextNotFoundButStreetcodeExists() + { + // Arrange + var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); + + this.textRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((DAL.Entities.Streetcode.TextContent.Text?)null); + + this.streetcodeRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(new StreetcodeContent { Id = 1 }); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().BeNull(); + + this.loggerMock.Verify( + l => l.LogError(It.IsAny(), It.IsAny()), + Times.Never); + + this.textServiceMock.Verify( + s => s.AddTermsTag(It.IsAny()), + Times.Never); + } + + [Fact] + public async Task Handle_ReturnsError_WhenStreetcodeDoesNotExist() + { + // Arrange + var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); + + this.textRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((DAL.Entities.Streetcode.TextContent.Text?)null); + + this.streetcodeRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((StreetcodeContent?)null); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsFailed.Should().BeTrue(); + + this.loggerMock.Verify( + l => l.LogError(query, It.Is(msg => msg.Contains("1"))), + Times.Once); + + this.textServiceMock.Verify( + s => s.AddTermsTag(It.IsAny()), + Times.Never); + } + + [Fact] + public async Task Handle_UsesAddTermsTagResult_AsTextContent() + { + // Arrange + const string originalContent = "Text about streetcode"; + const string taggedContent = "streetcodedescription"; + var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); + var textEntity = new DAL.Entities.Streetcode.TextContent.Text + { + Id = 1, + StreetcodeId = 1, + TextContent = originalContent + }; + + this.textRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(textEntity); + + this.textServiceMock + .Setup(s => s.AddTermsTag(originalContent)) + .ReturnsAsync(taggedContent); + + DAL.Entities.Streetcode.TextContent.Text? capturedEntity = null; + this.mapperMock + .Setup(m => m.Map(It.IsAny())) + .Callback(obj => capturedEntity = obj as DAL.Entities.Streetcode.TextContent.Text) + .Returns(new TextDTO { TextContent = taggedContent }); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + capturedEntity.Should().NotBeNull(); + capturedEntity!.TextContent.Should().Be(taggedContent); + result.Value!.TextContent.Should().Be(taggedContent); + } -} + } +} \ No newline at end of file diff --git a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs new file mode 100644 index 0000000..ebfea99 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs @@ -0,0 +1,33 @@ +using FluentAssertions; +using Moq; +using Streetcode.BLL.Services.Text; +using Streetcode.DAL.Repositories.Interfaces.Base; +using Xunit; + +namespace Streetcode.XUnitTest.BLL.Services.Text +{ + public class AddTermsToTextServiceTests + { + private readonly Mock repositoryWrapperMock; + private readonly AddTermsToTextService service; + + public AddTermsToTextServiceTests() + { + this.repositoryWrapperMock = new Mock(); + this.service = new AddTermsToTextService(this.repositoryWrapperMock.Object); + } + + [Fact] + public async Task AddTermsTag_ReturnsNull_WhenInputIsNull() + { + // Arrange + string? input = null; + + // Act + var result = await this.service.AddTermsTag(input!); + + // Assert + result.Should().BeNull(); + } + } +} From 574d79d080b6dbefc75f65f5410fcf9216bec1e8 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 00:47:18 +0300 Subject: [PATCH 05/15] Add test AddTermsTag_WrapsWord_WhenDirectTermMatchFound --- .../Text/AddTermsToTextServiceTests.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs index ebfea99..db055e8 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs @@ -1,7 +1,11 @@ using FluentAssertions; +using Microsoft.EntityFrameworkCore.Query; using Moq; using Streetcode.BLL.Services.Text; +using Streetcode.DAL.Entities.Streetcode.TextContent; using Streetcode.DAL.Repositories.Interfaces.Base; +using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; +using System.Linq.Expressions; using Xunit; namespace Streetcode.XUnitTest.BLL.Services.Text @@ -9,11 +13,18 @@ namespace Streetcode.XUnitTest.BLL.Services.Text public class AddTermsToTextServiceTests { private readonly Mock repositoryWrapperMock; + private readonly Mock termRepositoryMock; private readonly AddTermsToTextService service; public AddTermsToTextServiceTests() { this.repositoryWrapperMock = new Mock(); + this.termRepositoryMock = new Mock(); + + this.repositoryWrapperMock + .Setup(w => w.TermRepository) + .Returns(this.termRepositoryMock.Object); + this.service = new AddTermsToTextService(this.repositoryWrapperMock.Object); } @@ -29,5 +40,25 @@ public async Task AddTermsTag_ReturnsNull_WhenInputIsNull() // Assert result.Should().BeNull(); } + + [Fact] + public async Task AddTermsTag_WrapsWord_WhenDirectTermMatchFound() + { + // Arrange + const string input = "hello"; + var term = new Term { Id = 1, Title = "hello", Description = "test description" }; + + this.termRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(term); + + // Act + var result = await this.service.AddTermsTag(input); + + // Assert + result.Should().Contain("hellotest description"); + } } } From 3af1ce76aa74c36d9928daf28161e38830623114 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 00:49:47 +0300 Subject: [PATCH 06/15] Add test AddTermsTag_WrapsFirstOccurrence_AndSkipsSubsequent --- .../Text/AddTermsToTextServiceTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs index db055e8..2fd579f 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs @@ -60,5 +60,27 @@ public async Task AddTermsTag_WrapsWord_WhenDirectTermMatchFound() // Assert result.Should().Contain("hellotest description"); } + + [Fact] + public async Task AddTermsTag_WrapsFirstOccurrence_AndSkipsSubsequent() + { + // Arrange + const string input = "hello hello"; + const string expectedTag = "hellotest description"; + var term = new Term { Id = 1, Title = "hello", Description = "test description" }; + + this.termRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(term); + + // Act + var result = await this.service.AddTermsTag(input); + + // Assert + result.Should().Contain(expectedTag); + result.Split("").Should().HaveCount(2); // рівно одне входження + } } } From e682907abe0d436db17ea0fbbd3113b2d7b80e10 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 00:57:52 +0300 Subject: [PATCH 07/15] Add test AddTermsTag_SkipsHTMLTags_WhenSplittingWords --- .../Text/AddTermsToTextServiceTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs index 2fd579f..a9275ab 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs @@ -82,5 +82,31 @@ public async Task AddTermsTag_WrapsFirstOccurrence_AndSkipsSubsequent() result.Should().Contain(expectedTag); result.Split("").Should().HaveCount(2); // рівно одне входження } + + [Fact] + public async Task AddTermsTag_SkipsHTMLTags_WhenSplittingWords() + { + // Arrange + const string input = "hello"; + var term = new Term { Id = 1, Title = "strong", Description = "HTML element" }; + + this.termRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(term); + + // Act + var result = await this.service.AddTermsTag(input); + + // Assert + result.Should().NotContain("strong"); + + this.termRepositoryMock.Verify( + repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>()), + Times.Once); + } } } From 5402dd3234c2eda6185f8c7e39fddf48bd52edb4 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 01:01:08 +0300 Subject: [PATCH 08/15] Add test Handle_ReturnsError_WhenServiceReturnsNull --- .../GetParsedTextAdminPreviewHandlerTests.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs new file mode 100644 index 0000000..64ad8a4 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs @@ -0,0 +1,37 @@ +using FluentAssertions; +using Moq; +using Streetcode.BLL.Interfaces.Text; +using Streetcode.BLL.MediatR.Streetcode.Text.GetParsed; +using Xunit; + +namespace Streetcode.XUnitTest.BLL.MediatR.Streetcode.Text; + +public class GetParsedTextAdminPreviewHandlerTests +{ + private readonly Mock textServiceMock; + private readonly GetParsedTextAdminPreviewHandler handler; + + public GetParsedTextAdminPreviewHandlerTests() + { + this.textServiceMock = new Mock(); + this.handler = new GetParsedTextAdminPreviewHandler(this.textServiceMock.Object); + } + + [Fact] + public async Task Handle_ReturnsError_WhenServiceReturnsNull() + { + // Arrange + var command = new GetParsedTextForAdminPreviewCommand(textToParse: "some text"); + + this.textServiceMock + .Setup(s => s.AddTermsTag(command.textToParse)) + .ReturnsAsync((string?)null); + + // Act + var result = await this.handler.Handle(command, CancellationToken.None); + + // Assert + result.IsFailed.Should().BeTrue(); + result.Errors.Should().ContainSingle(e => e.Message == "text was not parsed successfully"); + } +} From 66f2fccceb35e74dfe4a5a5aa3d0fce8a5864926 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 01:14:13 +0300 Subject: [PATCH 09/15] Replased AddTermsTag_ReturnsNull_WhenInputIsNull with AddTermsTag_ThrowArgumentNullException_WhenInputIsNull --- .../BLL/Services/Text/AddTermsToTextServiceTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs index a9275ab..7428bb9 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs @@ -29,16 +29,16 @@ public AddTermsToTextServiceTests() } [Fact] - public async Task AddTermsTag_ReturnsNull_WhenInputIsNull() + public async Task AddTermsTag_ThrowArgumentNullException_WhenInputIsNull() { // Arrange string? input = null; // Act - var result = await this.service.AddTermsTag(input!); + var result = async () => await this.service.AddTermsTag(input!); // Assert - result.Should().BeNull(); + await result.Should().ThrowAsync(); } [Fact] From 660ba2816af8ff150356a6b6c737c936187203a0 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 08:37:13 +0300 Subject: [PATCH 10/15] Add test Handle_ReturnsProcessedText_WhenTextExists --- .../Text/GetTextByStreetcodeIdHandlerTests.cs | 79 ++++++++++++++++--- 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs index 54a930a..0ff3b60 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs @@ -7,12 +7,12 @@ using Streetcode.BLL.Interfaces.Text; using Streetcode.BLL.MediatR.Streetcode.Text.GetByStreetcodeId; using Streetcode.DAL.Entities.Streetcode; -using Streetcode.DAL.Entities.Streetcode.TextContent; using Streetcode.DAL.Repositories.Interfaces.Base; using Streetcode.DAL.Repositories.Interfaces.Streetcode; using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; using System.Linq.Expressions; using Xunit; +using TextEntity = Streetcode.DAL.Entities.Streetcode.TextContent.Text; namespace Streetcode.XUnitTest.MediatRTests.Streetcode.Text.GetByStreetcodeId { @@ -50,6 +50,59 @@ public GetTextByStreetcodeIdHandlerTests() this.loggerMock.Object); } + [Fact] + public async Task Handle_ReturnsProcessedText_WhenTextExists() + { + // Arrange + const string originalContent = "Text about Maidan"; + const string taggedContent = "MaidanCentral square"; + var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); + + var textEntity = new TextEntity + { + Id = 1, + StreetcodeId = 1, + TextContent = originalContent + }; + + var textDto = new TextDTO + { + Id = 1, + StreetcodeId = 1, + TextContent = taggedContent + }; + + this.textRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(textEntity); + + this.textServiceMock + .Setup(s => s.AddTermsTag(originalContent)) + .ReturnsAsync(taggedContent); + + this.mapperMock + .Setup(m => m.Map(It.IsAny())) + .Returns(textDto); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().NotBeNull(); + result.Value!.TextContent.Should().Be(taggedContent); + + this.textServiceMock.Verify( + s => s.AddTermsTag(originalContent), + Times.Once); + + this.loggerMock.Verify( + l => l.LogError(It.IsAny(), It.IsAny()), + Times.Never); + } + [Fact] public async Task Handle_ReturnsNullResult_WhenTextNotFoundButStreetcodeExists() { @@ -58,9 +111,9 @@ public async Task Handle_ReturnsNullResult_WhenTextNotFoundButStreetcodeExists() this.textRepositoryMock .Setup(repo => repo.GetFirstOrDefaultAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>?>())) - .ReturnsAsync((DAL.Entities.Streetcode.TextContent.Text?)null); + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((TextEntity?)null); this.streetcodeRepositoryMock .Setup(repo => repo.GetFirstOrDefaultAsync( @@ -92,9 +145,9 @@ public async Task Handle_ReturnsError_WhenStreetcodeDoesNotExist() this.textRepositoryMock .Setup(repo => repo.GetFirstOrDefaultAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>?>())) - .ReturnsAsync((DAL.Entities.Streetcode.TextContent.Text?)null); + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((TextEntity?)null); this.streetcodeRepositoryMock .Setup(repo => repo.GetFirstOrDefaultAsync( @@ -124,7 +177,7 @@ public async Task Handle_UsesAddTermsTagResult_AsTextContent() const string originalContent = "Text about streetcode"; const string taggedContent = "streetcodedescription"; var query = new GetTextByStreetcodeIdQuery(StreetcodeId: 1); - var textEntity = new DAL.Entities.Streetcode.TextContent.Text + var textEntity = new TextEntity { Id = 1, StreetcodeId = 1, @@ -133,18 +186,18 @@ public async Task Handle_UsesAddTermsTagResult_AsTextContent() this.textRepositoryMock .Setup(repo => repo.GetFirstOrDefaultAsync( - It.IsAny>>(), - It.IsAny, IIncludableQueryable>?>())) + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) .ReturnsAsync(textEntity); this.textServiceMock .Setup(s => s.AddTermsTag(originalContent)) .ReturnsAsync(taggedContent); - DAL.Entities.Streetcode.TextContent.Text? capturedEntity = null; + TextEntity? capturedEntity = null; this.mapperMock - .Setup(m => m.Map(It.IsAny())) - .Callback(obj => capturedEntity = obj as DAL.Entities.Streetcode.TextContent.Text) + .Setup(m => m.Map(It.IsAny())) + .Callback(obj => capturedEntity = obj as TextEntity) .Returns(new TextDTO { TextContent = taggedContent }); // Act From 34c46e558c8c053225ccbc64e36abf1403fa1cae Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 08:38:14 +0300 Subject: [PATCH 11/15] Add tests Handle_ReturnsProcessedText_WhenServiceSucceeds and Handle_PassesOriginalText_ToService --- .../GetParsedTextAdminPreviewHandlerTests.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs index 64ad8a4..fc5b7a7 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs @@ -34,4 +34,44 @@ public async Task Handle_ReturnsError_WhenServiceReturnsNull() result.IsFailed.Should().BeTrue(); result.Errors.Should().ContainSingle(e => e.Message == "text was not parsed successfully"); } + + [Fact] + public async Task Handle_ReturnsProcessedText_WhenServiceSucceeds() + { + // Arrange + const string parsedText = "МайданЦентральна площа"; + var command = new GetParsedTextForAdminPreviewCommand(textToParse: "some text"); + + this.textServiceMock + .Setup(s => s.AddTermsTag(command.textToParse)) + .ReturnsAsync(parsedText); + + // Act + var result = await this.handler.Handle(command, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().Be(parsedText); + } + + [Fact] + public async Task Handle_PassesOriginalText_ToService() + { + // Arrange + const string originalText = "raw input text"; + var command = new GetParsedTextForAdminPreviewCommand(textToParse: originalText); + + this.textServiceMock + .Setup(s => s.AddTermsTag(originalText)) + .ReturnsAsync("processed"); + + // Act + await this.handler.Handle(command, CancellationToken.None); + + // Assert + this.textServiceMock.Verify( + s => s.AddTermsTag(originalText), + Times.Once); + } + } From d0729b3e4eec4c08de1c1fc136eec9cbd8765cce Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 08:39:06 +0300 Subject: [PATCH 12/15] Add GetTextByIdHandler tests --- .../Text/GetTextByIdHandlerTests.cs | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs new file mode 100644 index 0000000..596ba65 --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs @@ -0,0 +1,115 @@ +using AutoMapper; +using FluentAssertions; +using Microsoft.EntityFrameworkCore.Query; +using Moq; +using Streetcode.BLL.DTO.Streetcode.TextContent.Text; +using Streetcode.BLL.Interfaces.Logging; +using Streetcode.BLL.MediatR.Streetcode.Text.GetById; +using Streetcode.DAL.Repositories.Interfaces.Base; +using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; +using System.Linq.Expressions; +using Xunit; +using TextEntity = Streetcode.DAL.Entities.Streetcode.TextContent.Text; + +namespace Streetcode.XUnitTest.BLL.MediatR.Streetcode.Text +{ + public class GetTextByIdHandlerTests + { + private readonly Mock repositoryWrapperMock; + private readonly Mock textRepositoryMock; + private readonly Mock mapperMock; + private readonly Mock loggerMock; + private readonly GetTextByIdHandler handler; + + public GetTextByIdHandlerTests() + { + this.repositoryWrapperMock = new Mock(); + this.textRepositoryMock = new Mock(); + this.mapperMock = new Mock(); + this.loggerMock = new Mock(); + + this.repositoryWrapperMock + .Setup(w => w.TextRepository) + .Returns(this.textRepositoryMock.Object); + + this.handler = new GetTextByIdHandler( + this.repositoryWrapperMock.Object, + this.mapperMock.Object, + this.loggerMock.Object); + } + + [Fact] + public async Task Handle_ReturnsTextDTO_WhenTextExists() + { + // Arrange + const int textId = 1; + var query = new GetTextByIdQuery(Id: textId); + + var textEntity = new TextEntity + { + Id = textId, + Title = "Test Title", + TextContent = "Test Content", + StreetcodeId = 1, + }; + + var textDto = new TextDTO + { + Id = textId, + Title = "Test Title", + TextContent = "Test Content", + StreetcodeId = 1, + }; + + this.textRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(textEntity); + + this.mapperMock + .Setup(m => m.Map(textEntity)) + .Returns(textDto); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().BeEquivalentTo(textDto); + + this.loggerMock.Verify( + l => l.LogError(It.IsAny(), It.IsAny()), + Times.Never); + } + + [Fact] + public async Task Handle_ReturnsError_WhenTextNotFound() + { + // Arrange + const int textId = 42; + var query = new GetTextByIdQuery(Id: textId); + + this.textRepositoryMock + .Setup(repo => repo.GetFirstOrDefaultAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((TextEntity?)null); + + // Act + var result = await handler.Handle(query, CancellationToken.None); + + // Assert + result.IsFailed.Should().BeTrue(); + result.Errors[0].Message.Should().Be($"Cannot find any text with corresponding id: {textId}"); + + this.loggerMock.Verify( + l => l.LogError(query, $"Cannot find any text with corresponding id: {textId}"), + Times.Once); + + this.mapperMock.Verify( + m => m.Map(It.IsAny()), + Times.Never); + } + } +} From b5c67e212bc1c25b933a127f6c2533a3371df3a8 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 13 May 2026 08:39:39 +0300 Subject: [PATCH 13/15] Add GetAllTextsHandler tests --- .../Text/GetAllTextsHandlerTests.cs | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs new file mode 100644 index 0000000..8d05eef --- /dev/null +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs @@ -0,0 +1,139 @@ +using AutoMapper; +using FluentAssertions; +using Microsoft.EntityFrameworkCore.Query; +using Moq; +using Streetcode.BLL.DTO.Streetcode.TextContent.Text; +using Streetcode.BLL.Interfaces.Logging; +using Streetcode.BLL.MediatR.Streetcode.Text.GetAll; +using Streetcode.DAL.Repositories.Interfaces.Base; +using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; +using System.Linq.Expressions; +using Xunit; +using TextEntity = Streetcode.DAL.Entities.Streetcode.TextContent.Text; + +namespace Streetcode.XUnitTest.BLL.MediatR.Streetcode.Text +{ + public class GetAllTextsHandlerTests + { + private readonly Mock repositoryWrapperMock; + private readonly Mock textRepositoryMock; + private readonly Mock mapperMock; + private readonly Mock loggerMock; + private readonly GetAllTextsHandler handler; + + public GetAllTextsHandlerTests() + { + this.repositoryWrapperMock = new Mock(); + this.textRepositoryMock = new Mock(); + this.mapperMock = new Mock(); + this.loggerMock = new Mock(); + + this.repositoryWrapperMock + .Setup(w => w.TextRepository) + .Returns(this.textRepositoryMock.Object); + + this.handler = new GetAllTextsHandler( + this.repositoryWrapperMock.Object, + this.mapperMock.Object, + this.loggerMock.Object); + } + + [Fact] + public async Task Handle_ReturnsAllTexts_WhenTextsExist() + { + // Arrange + var query = new GetAllTextsQuery(); + + var texts = new List + { + new TextEntity { Id = 1, Title = "Title 1", TextContent = "Content 1", StreetcodeId = 1 }, + new TextEntity { Id = 2, Title = "Title 2", TextContent = "Content 2", StreetcodeId = 2 }, + }; + + var textDtos = new List + { + new TextDTO { Id = 1, Title = "Title 1", TextContent = "Content 1", StreetcodeId = 1 }, + new TextDTO { Id = 2, Title = "Title 2", TextContent = "Content 2", StreetcodeId = 2 }, + }; + + this.textRepositoryMock + .Setup(repo => repo.GetAllAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(texts); + + this.mapperMock + .Setup(m => m.Map>(texts)) + .Returns(textDtos); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().BeEquivalentTo(textDtos); + + this.loggerMock.Verify( + l => l.LogError(It.IsAny(), It.IsAny()), + Times.Never); + } + + [Fact] + public async Task Handle_ReturnsError_WhenRepositoryReturnsNull() + { + // Arrange + var query = new GetAllTextsQuery(); + + this.textRepositoryMock + .Setup(repo => repo.GetAllAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync((IEnumerable)null!); + + // Act + var result = await this.handler.Handle(query, CancellationToken.None); + + // Assert + result.IsFailed.Should().BeTrue(); + result.Errors[0].Message.Should().Be("Cannot find any text"); + + this.loggerMock.Verify( + l => l.LogError(query, "Cannot find any text"), + Times.Once); + + this.mapperMock.Verify( + m => m.Map>(It.IsAny>()), + Times.Never); + } + + [Fact] + public async Task Handle_CallsMapper_WithCorrectEntity() + { + // Arrange + var query = new GetAllTextsQuery(); + + var texts = new List + { + new TextEntity { Id = 1, Title = "Title 1", TextContent = "Content 1", StreetcodeId = 1 }, + }; + + this.textRepositoryMock + .Setup(repo => repo.GetAllAsync( + It.IsAny>>(), + It.IsAny, IIncludableQueryable>?>())) + .ReturnsAsync(texts); + + this.mapperMock + .Setup(m => m.Map>(texts)) + .Returns(new List()); + + // Act + await this.handler.Handle(query, CancellationToken.None); + + // Assert + this.mapperMock.Verify( + m => m.Map>(texts), + Times.Once); + } + } +} From b4a681798e35a8a45d89e5d16565fdd787bea30d Mon Sep 17 00:00:00 2001 From: Nikita Date: Fri, 15 May 2026 14:15:27 +0300 Subject: [PATCH 14/15] Replaced mapper mock with mapper, add descriptions --- .../Text/GetAllTextsHandlerTests.cs | 76 ++++---- .../GetParsedTextAdminPreviewHandlerTests.cs | 168 ++++++++++-------- .../Text/GetTextByIdHandlerTests.cs | 63 ++++--- .../Text/GetTextByStreetcodeIdHandlerTests.cs | 91 +++++----- .../Text/AddTermsToTextServiceTests.cs | 46 +++-- 5 files changed, 260 insertions(+), 184 deletions(-) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs index 8d05eef..753b913 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs @@ -1,31 +1,42 @@ -using AutoMapper; -using FluentAssertions; -using Microsoft.EntityFrameworkCore.Query; -using Moq; -using Streetcode.BLL.DTO.Streetcode.TextContent.Text; -using Streetcode.BLL.Interfaces.Logging; -using Streetcode.BLL.MediatR.Streetcode.Text.GetAll; -using Streetcode.DAL.Repositories.Interfaces.Base; -using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; -using System.Linq.Expressions; -using Xunit; -using TextEntity = Streetcode.DAL.Entities.Streetcode.TextContent.Text; - -namespace Streetcode.XUnitTest.BLL.MediatR.Streetcode.Text +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Streetcode.XUnitTest.BLL.MediatR.StreetCode.Text { + using System.Linq.Expressions; + using AutoMapper; + using FluentAssertions; + using Microsoft.EntityFrameworkCore.Query; + using Moq; + using Streetcode.BLL.DTO.Streetcode.TextContent.Text; + using Streetcode.BLL.Interfaces.Logging; + using Streetcode.BLL.Mapping.Streetcode.TextContent; + using Streetcode.BLL.MediatR.Streetcode.Text.GetAll; + using Streetcode.DAL.Repositories.Interfaces.Base; + using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; + using Xunit; + using TextEntity = Streetcode.DAL.Entities.Streetcode.TextContent.Text; + + /// + /// Unit tests for . + /// public class GetAllTextsHandlerTests { private readonly Mock repositoryWrapperMock; private readonly Mock textRepositoryMock; - private readonly Mock mapperMock; + private readonly IMapper mapper; private readonly Mock loggerMock; private readonly GetAllTextsHandler handler; + /// + /// Initializes a new instance of the class. + /// public GetAllTextsHandlerTests() { this.repositoryWrapperMock = new Mock(); this.textRepositoryMock = new Mock(); - this.mapperMock = new Mock(); + this.mapper = new MapperConfiguration(cfg => cfg.AddProfile()).CreateMapper(); this.loggerMock = new Mock(); this.repositoryWrapperMock @@ -34,10 +45,14 @@ public GetAllTextsHandlerTests() this.handler = new GetAllTextsHandler( this.repositoryWrapperMock.Object, - this.mapperMock.Object, + this.mapper, this.loggerMock.Object); } + /// + /// Tests that the Handle method returns all texts when they exist in the repository. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task Handle_ReturnsAllTexts_WhenTextsExist() { @@ -62,10 +77,6 @@ public async Task Handle_ReturnsAllTexts_WhenTextsExist() It.IsAny, IIncludableQueryable>?>())) .ReturnsAsync(texts); - this.mapperMock - .Setup(m => m.Map>(texts)) - .Returns(textDtos); - // Act var result = await this.handler.Handle(query, CancellationToken.None); @@ -78,6 +89,10 @@ public async Task Handle_ReturnsAllTexts_WhenTextsExist() Times.Never); } + /// + /// Tests that the Handle method returns an error when the repository returns null. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task Handle_ReturnsError_WhenRepositoryReturnsNull() { @@ -100,12 +115,12 @@ public async Task Handle_ReturnsError_WhenRepositoryReturnsNull() this.loggerMock.Verify( l => l.LogError(query, "Cannot find any text"), Times.Once); - - this.mapperMock.Verify( - m => m.Map>(It.IsAny>()), - Times.Never); } + /// + /// Tests that the Handle method calls the mapper with the correct entity when texts are retrieved from the repository. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task Handle_CallsMapper_WithCorrectEntity() { @@ -123,17 +138,12 @@ public async Task Handle_CallsMapper_WithCorrectEntity() It.IsAny, IIncludableQueryable>?>())) .ReturnsAsync(texts); - this.mapperMock - .Setup(m => m.Map>(texts)) - .Returns(new List()); - // Act - await this.handler.Handle(query, CancellationToken.None); + var result = await this.handler.Handle(query, CancellationToken.None); // Assert - this.mapperMock.Verify( - m => m.Map>(texts), - Times.Once); + result.IsSuccess.Should().BeTrue(); + result.Value.Should().ContainSingle(dto => dto.Id == 1 && dto.Title == "Title 1"); } } } diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs index fc5b7a7..607543f 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs @@ -1,77 +1,99 @@ -using FluentAssertions; -using Moq; -using Streetcode.BLL.Interfaces.Text; -using Streetcode.BLL.MediatR.Streetcode.Text.GetParsed; -using Xunit; +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// -namespace Streetcode.XUnitTest.BLL.MediatR.Streetcode.Text; - -public class GetParsedTextAdminPreviewHandlerTests +namespace Streetcode.XUnitTest.BLL.MediatR.StreetCode.Text { - private readonly Mock textServiceMock; - private readonly GetParsedTextAdminPreviewHandler handler; - - public GetParsedTextAdminPreviewHandlerTests() + using FluentAssertions; + using Moq; + using Streetcode.BLL.Interfaces.Text; + using Streetcode.BLL.MediatR.Streetcode.Text.GetParsed; + using Xunit; + + /// + /// Unit tests for . + /// + public class GetParsedTextAdminPreviewHandlerTests { - this.textServiceMock = new Mock(); - this.handler = new GetParsedTextAdminPreviewHandler(this.textServiceMock.Object); + private readonly Mock textServiceMock; + private readonly GetParsedTextAdminPreviewHandler handler; + + /// + /// Initializes a new instance of the class. + /// + public GetParsedTextAdminPreviewHandlerTests() + { + this.textServiceMock = new Mock(); + this.handler = new GetParsedTextAdminPreviewHandler(this.textServiceMock.Object); + } + + /// + /// Tests that the Handle method returns an error when the text service returns null, indicating that parsing was unsuccessful. + /// + /// A representing the result of the asynchronous operation. + [Fact] + public async Task Handle_ReturnsError_WhenServiceReturnsNull() + { + // Arrange + var command = new GetParsedTextForAdminPreviewCommand(textToParse: "some text"); + + this.textServiceMock + .Setup(s => s.AddTermsTag(command.textToParse)) + .ReturnsAsync((string?)null); + + // Act + var result = await this.handler.Handle(command, CancellationToken.None); + + // Assert + result.IsFailed.Should().BeTrue(); + result.Errors.Should().ContainSingle(e => e.Message == "text was not parsed successfully"); + } + + /// + /// Tests that the Handle method returns the processed text when the text service successfully parses the input text. + /// + /// A representing the result of the asynchronous operation. + [Fact] + public async Task Handle_ReturnsProcessedText_WhenServiceSucceeds() + { + // Arrange + const string parsedText = "МайданЦентральна площа"; + var command = new GetParsedTextForAdminPreviewCommand(textToParse: "some text"); + + this.textServiceMock + .Setup(s => s.AddTermsTag(command.textToParse)) + .ReturnsAsync(parsedText); + + // Act + var result = await this.handler.Handle(command, CancellationToken.None); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Value.Should().Be(parsedText); + } + + /// + /// Tests that the Handle method calls the text service with the original input text, ensuring that the correct data is passed for processing. + /// + /// A representing the result of the asynchronous operation. + [Fact] + public async Task Handle_PassesOriginalText_ToService() + { + // Arrange + const string originalText = "raw input text"; + var command = new GetParsedTextForAdminPreviewCommand(textToParse: originalText); + + this.textServiceMock + .Setup(s => s.AddTermsTag(originalText)) + .ReturnsAsync("processed"); + + // Act + await this.handler.Handle(command, CancellationToken.None); + + // Assert + this.textServiceMock.Verify( + s => s.AddTermsTag(originalText), + Times.Once); + } } - - [Fact] - public async Task Handle_ReturnsError_WhenServiceReturnsNull() - { - // Arrange - var command = new GetParsedTextForAdminPreviewCommand(textToParse: "some text"); - - this.textServiceMock - .Setup(s => s.AddTermsTag(command.textToParse)) - .ReturnsAsync((string?)null); - - // Act - var result = await this.handler.Handle(command, CancellationToken.None); - - // Assert - result.IsFailed.Should().BeTrue(); - result.Errors.Should().ContainSingle(e => e.Message == "text was not parsed successfully"); - } - - [Fact] - public async Task Handle_ReturnsProcessedText_WhenServiceSucceeds() - { - // Arrange - const string parsedText = "МайданЦентральна площа"; - var command = new GetParsedTextForAdminPreviewCommand(textToParse: "some text"); - - this.textServiceMock - .Setup(s => s.AddTermsTag(command.textToParse)) - .ReturnsAsync(parsedText); - - // Act - var result = await this.handler.Handle(command, CancellationToken.None); - - // Assert - result.IsSuccess.Should().BeTrue(); - result.Value.Should().Be(parsedText); - } - - [Fact] - public async Task Handle_PassesOriginalText_ToService() - { - // Arrange - const string originalText = "raw input text"; - var command = new GetParsedTextForAdminPreviewCommand(textToParse: originalText); - - this.textServiceMock - .Setup(s => s.AddTermsTag(originalText)) - .ReturnsAsync("processed"); - - // Act - await this.handler.Handle(command, CancellationToken.None); - - // Assert - this.textServiceMock.Verify( - s => s.AddTermsTag(originalText), - Times.Once); - } - -} +} \ No newline at end of file diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs index 596ba65..824f353 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs @@ -1,31 +1,42 @@ -using AutoMapper; -using FluentAssertions; -using Microsoft.EntityFrameworkCore.Query; -using Moq; -using Streetcode.BLL.DTO.Streetcode.TextContent.Text; -using Streetcode.BLL.Interfaces.Logging; -using Streetcode.BLL.MediatR.Streetcode.Text.GetById; -using Streetcode.DAL.Repositories.Interfaces.Base; -using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; -using System.Linq.Expressions; -using Xunit; -using TextEntity = Streetcode.DAL.Entities.Streetcode.TextContent.Text; - -namespace Streetcode.XUnitTest.BLL.MediatR.Streetcode.Text +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Streetcode.XUnitTest.BLL.MediatR.StreetCode.Text { + using System.Linq.Expressions; + using AutoMapper; + using FluentAssertions; + using Microsoft.EntityFrameworkCore.Query; + using Moq; + using Streetcode.BLL.DTO.Streetcode.TextContent.Text; + using Streetcode.BLL.Interfaces.Logging; + using Streetcode.BLL.Mapping.Streetcode.TextContent; + using Streetcode.BLL.MediatR.Streetcode.Text.GetById; + using Streetcode.DAL.Repositories.Interfaces.Base; + using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; + using Xunit; + using TextEntity = Streetcode.DAL.Entities.Streetcode.TextContent.Text; + + /// + /// Unit tests for . + /// public class GetTextByIdHandlerTests { private readonly Mock repositoryWrapperMock; private readonly Mock textRepositoryMock; - private readonly Mock mapperMock; + private readonly IMapper mapper; private readonly Mock loggerMock; private readonly GetTextByIdHandler handler; + /// + /// Initializes a new instance of the class. + /// public GetTextByIdHandlerTests() { this.repositoryWrapperMock = new Mock(); this.textRepositoryMock = new Mock(); - this.mapperMock = new Mock(); + this.mapper = new MapperConfiguration(cfg => cfg.AddProfile()).CreateMapper(); this.loggerMock = new Mock(); this.repositoryWrapperMock @@ -34,10 +45,14 @@ public GetTextByIdHandlerTests() this.handler = new GetTextByIdHandler( this.repositoryWrapperMock.Object, - this.mapperMock.Object, + this.mapper, this.loggerMock.Object); } + /// + /// Tests that the Handle method returns a TextDTO when a text with the specified ID exists in the repository. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task Handle_ReturnsTextDTO_WhenTextExists() { @@ -67,10 +82,6 @@ public async Task Handle_ReturnsTextDTO_WhenTextExists() It.IsAny, IIncludableQueryable>?>())) .ReturnsAsync(textEntity); - this.mapperMock - .Setup(m => m.Map(textEntity)) - .Returns(textDto); - // Act var result = await this.handler.Handle(query, CancellationToken.None); @@ -83,6 +94,10 @@ public async Task Handle_ReturnsTextDTO_WhenTextExists() Times.Never); } + /// + /// Tests that the Handle method returns an error when no text with the specified ID exists in the repository. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task Handle_ReturnsError_WhenTextNotFound() { @@ -97,7 +112,7 @@ public async Task Handle_ReturnsError_WhenTextNotFound() .ReturnsAsync((TextEntity?)null); // Act - var result = await handler.Handle(query, CancellationToken.None); + var result = await this.handler.Handle(query, CancellationToken.None); // Assert result.IsFailed.Should().BeTrue(); @@ -106,10 +121,6 @@ public async Task Handle_ReturnsError_WhenTextNotFound() this.loggerMock.Verify( l => l.LogError(query, $"Cannot find any text with corresponding id: {textId}"), Times.Once); - - this.mapperMock.Verify( - m => m.Map(It.IsAny()), - Times.Never); } } } diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs index 0ff3b60..e8bf149 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs @@ -1,37 +1,48 @@ -using AutoMapper; -using FluentAssertions; -using Microsoft.EntityFrameworkCore.Query; -using Moq; -using Streetcode.BLL.DTO.Streetcode.TextContent.Text; -using Streetcode.BLL.Interfaces.Logging; -using Streetcode.BLL.Interfaces.Text; -using Streetcode.BLL.MediatR.Streetcode.Text.GetByStreetcodeId; -using Streetcode.DAL.Entities.Streetcode; -using Streetcode.DAL.Repositories.Interfaces.Base; -using Streetcode.DAL.Repositories.Interfaces.Streetcode; -using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; -using System.Linq.Expressions; -using Xunit; -using TextEntity = Streetcode.DAL.Entities.Streetcode.TextContent.Text; - -namespace Streetcode.XUnitTest.MediatRTests.Streetcode.Text.GetByStreetcodeId +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Streetcode.XUnitTest.BLL.MediatR.StreetCode.Text { + using System.Linq.Expressions; + using AutoMapper; + using FluentAssertions; + using Microsoft.EntityFrameworkCore.Query; + using Moq; + using Streetcode.BLL.DTO.Streetcode.TextContent.Text; + using Streetcode.BLL.Interfaces.Logging; + using Streetcode.BLL.Interfaces.Text; + using Streetcode.BLL.Mapping.Streetcode.TextContent; + using Streetcode.BLL.MediatR.Streetcode.Text.GetByStreetcodeId; + using Streetcode.DAL.Entities.Streetcode; + using Streetcode.DAL.Repositories.Interfaces.Base; + using Streetcode.DAL.Repositories.Interfaces.Streetcode; + using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; + using Xunit; + using TextEntity = Streetcode.DAL.Entities.Streetcode.TextContent.Text; + + /// + /// Unit tests for . + /// public class GetTextByStreetcodeIdHandlerTests { private readonly Mock repositoryWrapperMock; private readonly Mock textRepositoryMock; private readonly Mock streetcodeRepositoryMock; - private readonly Mock mapperMock; + private readonly IMapper mapper; private readonly Mock textServiceMock; private readonly Mock loggerMock; private readonly GetTextByStreetcodeIdHandler handler; + /// + /// Initializes a new instance of the class. + /// public GetTextByStreetcodeIdHandlerTests() { this.repositoryWrapperMock = new Mock(); this.textRepositoryMock = new Mock(); this.streetcodeRepositoryMock = new Mock(); - this.mapperMock = new Mock(); + this.mapper = new MapperConfiguration(cfg => cfg.AddProfile()).CreateMapper(); this.textServiceMock = new Mock(); this.loggerMock = new Mock(); @@ -45,11 +56,15 @@ public GetTextByStreetcodeIdHandlerTests() this.handler = new GetTextByStreetcodeIdHandler( this.repositoryWrapperMock.Object, - this.mapperMock.Object, + this.mapper, this.textServiceMock.Object, this.loggerMock.Object); } + /// + /// Tests that the Handle method returns a TextDTO with processed text content when a text associated with the specified streetcode ID exists in the repository. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task Handle_ReturnsProcessedText_WhenTextExists() { @@ -62,14 +77,7 @@ public async Task Handle_ReturnsProcessedText_WhenTextExists() { Id = 1, StreetcodeId = 1, - TextContent = originalContent - }; - - var textDto = new TextDTO - { - Id = 1, - StreetcodeId = 1, - TextContent = taggedContent + TextContent = originalContent, }; this.textRepositoryMock @@ -82,10 +90,6 @@ public async Task Handle_ReturnsProcessedText_WhenTextExists() .Setup(s => s.AddTermsTag(originalContent)) .ReturnsAsync(taggedContent); - this.mapperMock - .Setup(m => m.Map(It.IsAny())) - .Returns(textDto); - // Act var result = await this.handler.Handle(query, CancellationToken.None); @@ -103,6 +107,10 @@ public async Task Handle_ReturnsProcessedText_WhenTextExists() Times.Never); } + /// + /// Tests that the Handle method returns a successful result with a null value when no text is found for the specified streetcode ID, but the streetcode itself exists in the repository. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task Handle_ReturnsNullResult_WhenTextNotFoundButStreetcodeExists() { @@ -137,6 +145,10 @@ public async Task Handle_ReturnsNullResult_WhenTextNotFoundButStreetcodeExists() Times.Never); } + /// + /// Tests that the Handle method returns an error when no streetcode is found for the specified streetcode ID, regardless of whether a text exists or not. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task Handle_ReturnsError_WhenStreetcodeDoesNotExist() { @@ -170,6 +182,10 @@ public async Task Handle_ReturnsError_WhenStreetcodeDoesNotExist() Times.Never); } + /// + /// Tests that the Handle method processes the text content using the text service and updates the TextDTO with the processed content before returning it in the result when a text is found for the specified streetcode ID. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task Handle_UsesAddTermsTagResult_AsTextContent() { @@ -181,7 +197,7 @@ public async Task Handle_UsesAddTermsTagResult_AsTextContent() { Id = 1, StreetcodeId = 1, - TextContent = originalContent + TextContent = originalContent, }; this.textRepositoryMock @@ -194,21 +210,12 @@ public async Task Handle_UsesAddTermsTagResult_AsTextContent() .Setup(s => s.AddTermsTag(originalContent)) .ReturnsAsync(taggedContent); - TextEntity? capturedEntity = null; - this.mapperMock - .Setup(m => m.Map(It.IsAny())) - .Callback(obj => capturedEntity = obj as TextEntity) - .Returns(new TextDTO { TextContent = taggedContent }); - // Act var result = await this.handler.Handle(query, CancellationToken.None); // Assert result.IsSuccess.Should().BeTrue(); - capturedEntity.Should().NotBeNull(); - capturedEntity!.TextContent.Should().Be(taggedContent); result.Value!.TextContent.Should().Be(taggedContent); } - } } \ No newline at end of file diff --git a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs index 7428bb9..fc5001b 100644 --- a/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs +++ b/Streetcode/Streetcode.XUnitTest/BLL/Services/Text/AddTermsToTextServiceTests.cs @@ -1,21 +1,31 @@ -using FluentAssertions; -using Microsoft.EntityFrameworkCore.Query; -using Moq; -using Streetcode.BLL.Services.Text; -using Streetcode.DAL.Entities.Streetcode.TextContent; -using Streetcode.DAL.Repositories.Interfaces.Base; -using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; -using System.Linq.Expressions; -using Xunit; +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// namespace Streetcode.XUnitTest.BLL.Services.Text { + using System.Linq.Expressions; + using FluentAssertions; + using Microsoft.EntityFrameworkCore.Query; + using Moq; + using Streetcode.BLL.Services.Text; + using Streetcode.DAL.Entities.Streetcode.TextContent; + using Streetcode.DAL.Repositories.Interfaces.Base; + using Streetcode.DAL.Repositories.Interfaces.Streetcode.TextContent; + using Xunit; + + /// + /// Unit tests for . + /// public class AddTermsToTextServiceTests { private readonly Mock repositoryWrapperMock; private readonly Mock termRepositoryMock; private readonly AddTermsToTextService service; + /// + /// Initializes a new instance of the class. + /// public AddTermsToTextServiceTests() { this.repositoryWrapperMock = new Mock(); @@ -28,6 +38,10 @@ public AddTermsToTextServiceTests() this.service = new AddTermsToTextService(this.repositoryWrapperMock.Object); } + /// + /// Tests that the AddTermsTag method throws an ArgumentNullException when the input string is null. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task AddTermsTag_ThrowArgumentNullException_WhenInputIsNull() { @@ -41,6 +55,10 @@ public async Task AddTermsTag_ThrowArgumentNullException_WhenInputIsNull() await result.Should().ThrowAsync(); } + /// + /// Tests that the AddTermsTag method wraps a word with a Popover tag when a direct term match is found in the repository. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task AddTermsTag_WrapsWord_WhenDirectTermMatchFound() { @@ -61,6 +79,10 @@ public async Task AddTermsTag_WrapsWord_WhenDirectTermMatchFound() result.Should().Contain("hellotest description"); } + /// + /// Tests that the AddTermsTag method wraps only the first occurrence of a word with a Popover tag when multiple occurrences of the same word are present in the input string, and skips subsequent occurrences. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task AddTermsTag_WrapsFirstOccurrence_AndSkipsSubsequent() { @@ -80,9 +102,13 @@ public async Task AddTermsTag_WrapsFirstOccurrence_AndSkipsSubsequent() // Assert result.Should().Contain(expectedTag); - result.Split("").Should().HaveCount(2); // рівно одне входження + result.Split("").Should().HaveCount(2); } + /// + /// Tests that the AddTermsTag method does not wrap words that are part of HTML tags and does not query the repository for terms that are HTML tags, ensuring that HTML tags are skipped when splitting words. + /// + /// A representing the result of the asynchronous operation. [Fact] public async Task AddTermsTag_SkipsHTMLTags_WhenSplittingWords() { From 0ef0628f6588ffcfc273e2e1c68c7fcf6076a4e2 Mon Sep 17 00:00:00 2001 From: Nikita Date: Fri, 15 May 2026 14:29:15 +0300 Subject: [PATCH 15/15] renamed Streetcode to StreetCode in Streetcode.XUnitTest.BLL.MediatR folder --- .../{Streetcode => StreetCode}/Text/GetAllTextsHandlerTests.cs | 0 .../Text/GetParsedTextAdminPreviewHandlerTests.cs | 0 .../{Streetcode => StreetCode}/Text/GetTextByIdHandlerTests.cs | 0 .../Text/GetTextByStreetcodeIdHandlerTests.cs | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename Streetcode/Streetcode.XUnitTest/BLL/MediatR/{Streetcode => StreetCode}/Text/GetAllTextsHandlerTests.cs (100%) rename Streetcode/Streetcode.XUnitTest/BLL/MediatR/{Streetcode => StreetCode}/Text/GetParsedTextAdminPreviewHandlerTests.cs (100%) rename Streetcode/Streetcode.XUnitTest/BLL/MediatR/{Streetcode => StreetCode}/Text/GetTextByIdHandlerTests.cs (100%) rename Streetcode/Streetcode.XUnitTest/BLL/MediatR/{Streetcode => StreetCode}/Text/GetTextByStreetcodeIdHandlerTests.cs (100%) diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/StreetCode/Text/GetAllTextsHandlerTests.cs similarity index 100% rename from Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetAllTextsHandlerTests.cs rename to Streetcode/Streetcode.XUnitTest/BLL/MediatR/StreetCode/Text/GetAllTextsHandlerTests.cs diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/StreetCode/Text/GetParsedTextAdminPreviewHandlerTests.cs similarity index 100% rename from Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetParsedTextAdminPreviewHandlerTests.cs rename to Streetcode/Streetcode.XUnitTest/BLL/MediatR/StreetCode/Text/GetParsedTextAdminPreviewHandlerTests.cs diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/StreetCode/Text/GetTextByIdHandlerTests.cs similarity index 100% rename from Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByIdHandlerTests.cs rename to Streetcode/Streetcode.XUnitTest/BLL/MediatR/StreetCode/Text/GetTextByIdHandlerTests.cs diff --git a/Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs b/Streetcode/Streetcode.XUnitTest/BLL/MediatR/StreetCode/Text/GetTextByStreetcodeIdHandlerTests.cs similarity index 100% rename from Streetcode/Streetcode.XUnitTest/BLL/MediatR/Streetcode/Text/GetTextByStreetcodeIdHandlerTests.cs rename to Streetcode/Streetcode.XUnitTest/BLL/MediatR/StreetCode/Text/GetTextByStreetcodeIdHandlerTests.cs