diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index de52f99..3319c11 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -48,6 +48,11 @@ jobs:
- name: Test solution
run: dotnet test --no-build --configuration Release --filter "FullyQualifiedName!~AcceptanceTests"
+ - name: Analyze with SonarCloud
+ uses: sonarsource/sonarcloud-github-action@v3.0.0
+ env:
+ SONAR_TOKEN: ${{ secrets.SONARCLOUND_TOKEN }}
+
- name: Publish website
if: ${{ inputs.build-artifacts == true }}
run: |
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 6a0b298..f133200 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -36,8 +36,6 @@ jobs:
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- env:
- SkipNSwag: True
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
diff --git a/README.md b/README.md
index 781ee8e..e0d52ec 100644
--- a/README.md
+++ b/README.md
@@ -87,7 +87,7 @@ The template includes a full CI/CD pipeline. The pipeline is responsible for bui
* [Maspter](https://github.com/MapsterMapper/Mapster)
* [FluentResult](https://github.com/altmann/FluentResults)
* [FluentValidation](https://fluentvalidation.net/)
-* [NUnit](https://nunit.org/), [FluentAssertions](https://fluentassertions.com/), [NetArchTest.Rules](https://github.com/BenMorris/NetArchTest), [Moq](https://github.com/devlooped/moq) & [Respawn](https://github.com/jbogard/Respawn)
+* [NUnit](https://nunit.org/), [FluentAssertions](https://fluentassertions.com/), [NetArchTest.Rules](https://github.com/BenMorris/NetArchTest), [TestContainer](https://dotnet.testcontainers.org/) & [Moq](https://github.com/devlooped/moq)
## Versions
The main branch is now on .NET 8.0.
diff --git a/docker-compose.dcproj b/docker-compose.dcproj
index 2cf72fa..4e64cc9 100644
--- a/docker-compose.dcproj
+++ b/docker-compose.dcproj
@@ -7,7 +7,7 @@
LaunchBrowser
{Scheme}://localhost:{ServicePort}/swagger
api
- FastCleanArchitecture
+ fast-clean-architecture
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index dc6e890..320d3d1 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -1,7 +1,7 @@
version: '3.4'
services:
- web-api:
+ api:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_HTTP_PORTS=8080
diff --git a/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs b/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs
index 0148cf4..83b9450 100644
--- a/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs
+++ b/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs
@@ -2,7 +2,6 @@
using FastCleanArchitecture.Domain.Common;
using FastCleanArchitecture.Domain.TodoItems;
using FluentResults;
-using MediatR;
namespace FastCleanArchitecture.Application.TodoItems.Commands.DeleteTodoItem;
diff --git a/src/Application/TodoLists/Commands/Update/UpdateTodoListCommandValidator.cs b/src/Application/TodoLists/Commands/Update/UpdateTodoListCommandValidator.cs
index 3d27624..cc2e1ce 100644
--- a/src/Application/TodoLists/Commands/Update/UpdateTodoListCommandValidator.cs
+++ b/src/Application/TodoLists/Commands/Update/UpdateTodoListCommandValidator.cs
@@ -23,6 +23,7 @@ public UpdateTodoListCommandValidator(ITodoListRepository todoListRepository)
public async Task BeUniqueTitle(UpdateTodoListCommand request, string title, CancellationToken cancellationToken)
{
var entity = await _todoListRepository.GetByIdAsync(request.Id, cancellationToken);
- return entity is not null && entity!.Title!.Equals(title, StringComparison.OrdinalIgnoreCase);
+
+ return entity is null || !entity!.Title!.Equals(title, StringComparison.OrdinalIgnoreCase);
}
}
diff --git a/src/Domain/TodoItems/TodoItem.cs b/src/Domain/TodoItems/TodoItem.cs
index 20ae6a6..16c3a46 100644
--- a/src/Domain/TodoItems/TodoItem.cs
+++ b/src/Domain/TodoItems/TodoItem.cs
@@ -44,6 +44,7 @@ public static TodoItem Update(string? title, bool Done, TodoItem todoItem)
{
todoItem.Title = title;
todoItem.Done = Done;
+ todoItem.ModifiedAtUtc = DateTime.UtcNow;
return todoItem;
}
@@ -52,6 +53,7 @@ public static TodoItem UpdateDetail(Guid listId, PriorityLevel priority, string?
todoItem.ListId = listId;
todoItem.Priority = priority;
todoItem.Note = note;
+ todoItem.ModifiedAtUtc = DateTime.UtcNow;
return todoItem;
}
}
diff --git a/tests/Application.IntegrationTests/Infrastructure/BaseIntegrationTest.cs b/tests/Application.IntegrationTests/Infrastructure/BaseIntegrationTest.cs
index fbb61a0..9b1711b 100644
--- a/tests/Application.IntegrationTests/Infrastructure/BaseIntegrationTest.cs
+++ b/tests/Application.IntegrationTests/Infrastructure/BaseIntegrationTest.cs
@@ -1,5 +1,6 @@
using FastCleanArchitecture.Infrastructure.Data;
using MediatR;
+using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace Application.IntegrationTests.Infrastructure;
@@ -32,4 +33,18 @@ public async Task OneTimeTearDown()
_scope.Dispose();
DbContext.Dispose();
}
+
+ protected async Task FindAsync(params object[] keyValues) where TEntity : class
+ {
+ var context = _scope.ServiceProvider.GetRequiredService();
+
+ return await context.FindAsync(keyValues);
+ }
+
+ protected async Task CountAsync() where TEntity : class
+ {
+ var context = _scope.ServiceProvider.GetRequiredService();
+
+ return await context.Set().CountAsync();
+ }
}
diff --git a/tests/Application.IntegrationTests/TodoItems/Commands/CreateTodoItemTests.cs b/tests/Application.IntegrationTests/TodoItems/Commands/CreateTodoItemTests.cs
new file mode 100644
index 0000000..78c75d0
--- /dev/null
+++ b/tests/Application.IntegrationTests/TodoItems/Commands/CreateTodoItemTests.cs
@@ -0,0 +1,46 @@
+using Application.IntegrationTests.Infrastructure;
+using FastCleanArchitecture.Application.Common.Exceptions;
+using FastCleanArchitecture.Application.TodoItems.Commands.CreateTodoItem;
+using FastCleanArchitecture.Application.TodoLists.Commands.Create;
+using FastCleanArchitecture.Domain.TodoItems;
+using FluentAssertions;
+
+namespace Application.IntegrationTests.TodoItems.Commands;
+
+internal sealed class CreateTodoItemTests : BaseIntegrationTest
+{
+ [Test]
+ public async Task CreateTodoItem_ShouldThrowValidation_WhenRequireMinimumFields()
+ {
+ // Arrange
+ var command = new CreateTodoItemCommand();
+
+ // Act & Assert
+ await FluentActions.Invoking(() =>
+ Sender.Send(command)).Should().ThrowAsync();
+ }
+
+ [Test]
+ public async Task CreateTodoItem_ShouldCreateTodoItem_WhenRequestIsValid()
+ {
+ // Arrange
+ var listId = await Sender.Send(new CreateTodoListCommand() { Title = "New List" });
+
+ var command = new CreateTodoItemCommand
+ {
+ ListId = listId.Value,
+ Title = "Tasks"
+ };
+
+ // Act
+ var itemId = await Sender.Send(command);
+
+ // Assert
+ var item = await FindAsync(itemId.Value);
+
+ item.Should().NotBeNull();
+ item!.ListId.Should().Be(command.ListId);
+ item.Title.Should().Be(command.Title);
+ item.CreatedAtUtc.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromMilliseconds(10000));
+ }
+}
diff --git a/tests/Application.IntegrationTests/TodoItems/Commands/DeleteTodoItemTests.cs b/tests/Application.IntegrationTests/TodoItems/Commands/DeleteTodoItemTests.cs
new file mode 100644
index 0000000..9505fb9
--- /dev/null
+++ b/tests/Application.IntegrationTests/TodoItems/Commands/DeleteTodoItemTests.cs
@@ -0,0 +1,40 @@
+using System.ComponentModel;
+using Application.IntegrationTests.Infrastructure;
+using FastCleanArchitecture.Application.TodoItems.Commands.CreateTodoItem;
+using FastCleanArchitecture.Application.TodoItems.Commands.DeleteTodoItem;
+using FastCleanArchitecture.Application.TodoLists.Commands.Create;
+using FastCleanArchitecture.Domain.TodoItems;
+using FluentAssertions;
+using FluentResults;
+
+namespace Application.IntegrationTests.TodoItems.Commands;
+
+internal sealed class DeleteTodoItemTests : BaseIntegrationTest
+{
+ private Result _listId;
+
+ [OneTimeSetUp]
+ public async Task SetUp() => _listId = await Sender.Send(new CreateTodoListCommand
+ {
+ Title = "New lists"
+ });
+
+ [TestCase(true)]
+ [TestCase(false)]
+ public async Task DeleteTodoItem_ShouldDeleteTodoItem_WhenValidParam(bool itemExists)
+ {
+ // Arrange
+ var itemId = itemExists ? await Sender.Send(new CreateTodoItemCommand
+ {
+ ListId = _listId.Value,
+ Title = "New item"
+ }) : Guid.NewGuid();
+
+ // Act
+ await Sender.Send(new DeleteTodoItemCommand(itemId.Value));
+
+ // Assert
+ var item = await FindAsync(itemId.Value);
+ item.Should().BeNull();
+ }
+}
diff --git a/tests/Application.IntegrationTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs b/tests/Application.IntegrationTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs
new file mode 100644
index 0000000..57c9afd
--- /dev/null
+++ b/tests/Application.IntegrationTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs
@@ -0,0 +1,64 @@
+using Application.IntegrationTests.Infrastructure;
+using FastCleanArchitecture.Application.TodoItems.Commands.CreateTodoItem;
+using FastCleanArchitecture.Application.TodoItems.Commands.UpdateTodoItemDetail;
+using FastCleanArchitecture.Application.TodoLists.Commands.Create;
+using FastCleanArchitecture.Domain.TodoItems;
+using FastCleanArchitecture.Domain.TodoItems.Enums;
+using FluentAssertions;
+
+namespace Application.IntegrationTests.TodoItems.Commands;
+
+internal sealed class UpdateTodoItemDetailTests : BaseIntegrationTest
+{
+ [Test]
+ public async Task UpdateTodoItemDetail_ShouldReturnFailure_WhenItemNotFound()
+ {
+ // Arrange
+ var command = new UpdateTodoItemDetailCommand
+ {
+ Id = Guid.NewGuid(),
+ Body = new UpdateTodoItemDetailCommand.BodyItemDetailRequest { }
+ };
+
+ // Act
+ var result = await Sender.Send(command);
+
+ // Assert
+ result.IsFailed.Should().BeTrue();
+ }
+
+ [Test]
+ public async Task UpdateTodoItemDetail_ShouldUpdateDetail_WhenValidParam()
+ {
+ // Arrange
+ var listId = await Sender.Send(new CreateTodoListCommand { Title = "New list" });
+ var itemId = await Sender.Send(new CreateTodoItemCommand
+ {
+ ListId = listId.Value,
+ Title = "New Item"
+ });
+
+ var command = new UpdateTodoItemDetailCommand
+ {
+ Id = itemId.Value,
+ Body = new UpdateTodoItemDetailCommand.BodyItemDetailRequest
+ {
+ ListId = listId.Value,
+ Note = "A nother note...",
+ Priority = PriorityLevel.High
+ }
+ };
+
+ // Act
+ await Sender.Send(command);
+
+ // Assert
+ var item = await FindAsync(itemId.Value);
+
+ item.Should().NotBeNull();
+ item!.ListId.Should().Be(listId.Value);
+ item.Note.Should().Be(command.Body.Note);
+ item.Priority.Should().Be(command.Body.Priority);
+ item.ModifiedAtUtc.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromMilliseconds(10000));
+ }
+}
diff --git a/tests/Application.IntegrationTests/TodoItems/Commands/UpdateTodoItemTests.cs b/tests/Application.IntegrationTests/TodoItems/Commands/UpdateTodoItemTests.cs
new file mode 100644
index 0000000..d034cd1
--- /dev/null
+++ b/tests/Application.IntegrationTests/TodoItems/Commands/UpdateTodoItemTests.cs
@@ -0,0 +1,60 @@
+using Application.IntegrationTests.Infrastructure;
+using FastCleanArchitecture.Application.TodoItems.Commands.CreateTodoItem;
+using FastCleanArchitecture.Application.TodoItems.Commands.UpdateTodoItem;
+using FastCleanArchitecture.Application.TodoLists.Commands.Create;
+using FastCleanArchitecture.Domain.TodoItems;
+using FluentAssertions;
+
+namespace Application.IntegrationTests.TodoItems.Commands;
+
+internal sealed class UpdateTodoItemTests : BaseIntegrationTest
+{
+ [Test]
+ public async Task UpdateTodoItem_ShouldReturnFailure_WhenItemNotFound()
+ {
+ // Arrange
+ var command = new UpdateTodoItemCommand
+ {
+ Id = Guid.NewGuid(),
+ Body = new UpdateTodoItemCommand.BodyItemRequest() { Title = "New Title" }
+ };
+
+ // Act
+ var result = await Sender.Send(command);
+
+ // Assert
+ result.IsFailed.Should().BeTrue();
+ }
+
+ [Test]
+ public async Task UpdateTodoItem_ShouldUpdate_WhenValidParams()
+ {
+ // Arrange
+ var listId = await Sender.Send(new CreateTodoListCommand
+ {
+ Title = "New list",
+ });
+
+ var itemId = await Sender.Send(new CreateTodoItemCommand
+ {
+ ListId = listId.Value,
+ Title = "New item"
+ });
+
+ var command = new UpdateTodoItemCommand
+ {
+ Id = itemId.Value,
+ Body = new UpdateTodoItemCommand.BodyItemRequest { Title = "Updated item title" }
+ };
+
+ // Act
+ await Sender.Send(command);
+
+ // Assert
+ var item = await FindAsync(itemId.Value);
+
+ item.Should().NotBeNull();
+ item!.Title.Should().Be(command.Body.Title);
+ item.ModifiedAtUtc.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromMilliseconds(10000));
+ }
+}
diff --git a/tests/Application.IntegrationTests/TodoLists/Commands/CreateTodoListTests.cs b/tests/Application.IntegrationTests/TodoLists/Commands/CreateTodoListTests.cs
new file mode 100644
index 0000000..76bef72
--- /dev/null
+++ b/tests/Application.IntegrationTests/TodoLists/Commands/CreateTodoListTests.cs
@@ -0,0 +1,52 @@
+using Application.IntegrationTests.Infrastructure;
+using FastCleanArchitecture.Application.Common.Exceptions;
+using FastCleanArchitecture.Application.TodoLists.Commands.Create;
+using FastCleanArchitecture.Application.TodoLists.Queries.GetTodos;
+using FluentAssertions;
+
+namespace Application.IntegrationTests.TodoLists.Commands;
+
+internal class CreateTodoListTests : BaseIntegrationTest
+{
+ [Test]
+ public async Task CreateTodoList_ShouldThrowValidationException_WhenRequireAMinimunFields()
+ {
+ // Act
+ var act = () => Sender.Send(new CreateTodoListCommand());
+
+ // Assert
+ await act.Should().ThrowAsync();
+ }
+
+ [Test]
+ public async Task CreatTodoList_ShouldThrowValidationException_WhenRequireUniqueTitle()
+ {
+ // Arrange
+ var command = new CreateTodoListCommand { Title = "Homeworks" };
+ await Sender.Send(command);
+
+ // Act and Assert
+ await FluentActions
+ .Invoking(() => Sender
+ .Send(command))
+ .Should()
+ .ThrowAsync();
+ }
+
+ [Test]
+ public async Task CreateTodoList_ShouldCreateTodoList_WhenRequestIsValidAndSuccessful()
+ {
+ // Arrange
+ var command = new CreateTodoListCommand { Title = "Participate in a daily meeting." };
+
+ // Act
+ var result = await Sender.Send(command);
+
+ // Assert
+ var lists = await Sender.Send(new GetTodosQuery());
+ var list = lists.Value.Lists.FirstOrDefault(x => x.Id!.Equals(result.Value));
+
+ result.Value.Should().NotBeEmpty();
+ list!.Title.Should().Be(command.Title);
+ }
+}
diff --git a/tests/Application.IntegrationTests/TodoLists/Commands/DeleteTodoListTests.cs b/tests/Application.IntegrationTests/TodoLists/Commands/DeleteTodoListTests.cs
new file mode 100644
index 0000000..22ca55e
--- /dev/null
+++ b/tests/Application.IntegrationTests/TodoLists/Commands/DeleteTodoListTests.cs
@@ -0,0 +1,23 @@
+using Application.IntegrationTests.Infrastructure;
+using FastCleanArchitecture.Application.TodoLists.Commands.Create;
+using FastCleanArchitecture.Application.TodoLists.Commands.Delete;
+using FastCleanArchitecture.Domain.TodoLists;
+using FluentAssertions;
+
+namespace Application.IntegrationTests.TodoLists.Commands;
+
+internal class DeleteTodoListTests : BaseIntegrationTest
+{
+ [Test]
+ public async Task DeleteTodoList_ShouldDeleteTodoList_WhenRequestIsSuccessful()
+ {
+ var listId = await Sender.Send(new CreateTodoListCommand { Title = "New list" });
+
+ // Act
+ await Sender.Send(new DeleteTodoListCommand(listId.Value));
+
+ // Assert
+ var list = await FindAsync(listId.Value);
+ list.Should().BeNull();
+ }
+}
diff --git a/tests/Application.IntegrationTests/TodoLists/Commands/PurgeTodoListsTests.cs b/tests/Application.IntegrationTests/TodoLists/Commands/PurgeTodoListsTests.cs
new file mode 100644
index 0000000..bad5541
--- /dev/null
+++ b/tests/Application.IntegrationTests/TodoLists/Commands/PurgeTodoListsTests.cs
@@ -0,0 +1,20 @@
+using Application.IntegrationTests.Infrastructure;
+using FastCleanArchitecture.Application.TodoLists.Commands.Purge;
+using FastCleanArchitecture.Domain.TodoLists;
+using FluentAssertions;
+
+namespace Application.IntegrationTests.TodoLists.Commands;
+
+internal sealed class PurgeTodoListsTests : BaseIntegrationTest
+{
+ [Test]
+ public async Task PurgeTodoLists_ShouldDeleteAllLists_WhenValidRequest()
+ {
+ // Act
+ await Sender.Send(new PurgeTodoListsCommand());
+
+ // Assert
+ var count = await CountAsync();
+ count.Should().Be(0);
+ }
+}
diff --git a/tests/Application.IntegrationTests/TodoLists/Commands/UpdateTodoListTests.cs b/tests/Application.IntegrationTests/TodoLists/Commands/UpdateTodoListTests.cs
new file mode 100644
index 0000000..425d2f4
--- /dev/null
+++ b/tests/Application.IntegrationTests/TodoLists/Commands/UpdateTodoListTests.cs
@@ -0,0 +1,69 @@
+using Application.IntegrationTests.Infrastructure;
+using FastCleanArchitecture.Application.Common.Exceptions;
+using FastCleanArchitecture.Application.TodoLists.Commands.Create;
+using FastCleanArchitecture.Application.TodoLists.Commands.Update;
+using FastCleanArchitecture.Domain.TodoLists;
+using FluentAssertions;
+using FluentResults;
+
+namespace Application.IntegrationTests.TodoLists.Commands;
+
+internal sealed class UpdateTodoListTests : BaseIntegrationTest
+{
+ [Test]
+ public async Task UpdateTodoList_ShouldReturnAFailure_WhenTodoListNotFound()
+ {
+ // Arrange
+ var command = new UpdateTodoListCommand
+ {
+ Id = Guid.NewGuid(),
+ Body = new UpdateTodoListCommand.BodyListRequest { Title = "Title to update" }
+ };
+
+ // Act
+ var result = await Sender.Send(command);
+
+ // Assert
+ result.IsFailed.Should().BeTrue();
+ }
+
+ [Test]
+ public async Task UpdateTodoList_ShouldThrowValidationException_WhenTitleIsNotUnique()
+ {
+ // Arrange
+ var listId = await Sender.Send(new CreateTodoListCommand { Title = "New List" });
+ var command = new UpdateTodoListCommand
+ {
+ Id = listId.Value,
+ Body = new UpdateTodoListCommand.BodyListRequest { Title = "New List" }
+ };
+
+ // Act
+ var action = () => Sender.Send(command);
+
+ // Assert
+ (await action.Should().ThrowAsync()
+ .Where(ex => ex.Errors.First().PropertyName.Contains("Title")))
+ .And.Errors.First().ErrorMessage.Should().Contain("'Title' must be unique.");
+ }
+
+ [Test]
+ public async Task UpdateTodoList_ShouldUpdateTodoList_WhenValidParam()
+ {
+ // Arrange
+ var listId = await Sender.Send(new CreateTodoListCommand { Title = "Other List" });
+ var command = new UpdateTodoListCommand
+ {
+ Id = listId.Value,
+ Body = new UpdateTodoListCommand.BodyListRequest { Title = "Updated List" }
+ };
+
+ // Act
+ var result = await Sender.Send(command);
+
+ // Assert
+ result.IsSuccess.Should().BeTrue();
+ var item = await FindAsync(command.Id);
+ item!.Title.Should().Be(command.Body.Title);
+ }
+}
diff --git a/tests/Application.IntegrationTests/TodoLists/Queries/GetTodos/GetTodosTests.cs b/tests/Application.IntegrationTests/TodoLists/Queries/GetTodos/GetTodosTests.cs
deleted file mode 100644
index 5927df3..0000000
--- a/tests/Application.IntegrationTests/TodoLists/Queries/GetTodos/GetTodosTests.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Application.IntegrationTests.Infrastructure;
-using FastCleanArchitecture.Application.TodoLists.Queries.GetTodos;
-using FluentAssertions;
-
-namespace Application.IntegrationTests.TodoLists.Queries.GetTodos;
-
-internal class GetTodosTests : BaseIntegrationTest
-{
- [Test]
- public async Task GetTodos_ShouldReturnPriorityLevels_WhenListIsNotEmpty()
- {
- // Arrange
- var query = new GetTodosQuery();
-
- // Act
- var result = await Sender.Send(query);
-
- // Assert
- result.IsSuccess.Should().BeTrue();
- result.ValueOrDefault.PriorityLevels.Should().NotBeEmpty();
- }
-}
diff --git a/tests/Application.IntegrationTests/TodoLists/Queries/GetTodosTests.cs b/tests/Application.IntegrationTests/TodoLists/Queries/GetTodosTests.cs
new file mode 100644
index 0000000..dfa1b9f
--- /dev/null
+++ b/tests/Application.IntegrationTests/TodoLists/Queries/GetTodosTests.cs
@@ -0,0 +1,32 @@
+using Application.IntegrationTests.Infrastructure;
+using FastCleanArchitecture.Application.TodoLists.Queries.GetTodos;
+using FluentAssertions;
+
+namespace Application.IntegrationTests.TodoLists.Queries;
+
+internal class GetTodosTests : BaseIntegrationTest
+{
+ private readonly GetTodosQuery _query = new();
+
+ [Test]
+ public async Task GetTodos_ShouldReturnPriorityLevels_WhenListIsNotEmpty()
+ {
+ // Act
+ var result = await Sender.Send(_query);
+
+ // Assert
+ result.IsSuccess.Should().BeTrue();
+ result.Value.PriorityLevels.Should().NotBeEmpty();
+ }
+
+ [Test]
+ public async Task GetTodos_ShouldReturnAllListAndItems_WhenThereAreDataAndIsSuccessful()
+ {
+ // Act
+ var result = await Sender.Send(_query);
+
+ // Assert
+ result.Value.Lists.Should().NotBeEmpty();
+ result.Value.Lists.First().Items.Should().NotBeEmpty();
+ }
+}