using Microsoft.EntityFrameworkCore; using TaskLedger.Api.Domain.Entities; using TaskLedger.Api.Infrastructure.Data; using TaskLedger.Api.Services; using TaskEntity = TaskLedger.Api.Domain.Entities.Task; namespace TaskLedger.Api.Tests.Services; /// /// Unit tests for TaskService. /// public class TaskServiceTests { /// /// Creates an in-memory database context for testing. /// private AppDbContext CreateInMemoryDbContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) .Options; return new AppDbContext(options); } [Fact] public async System.Threading.Tasks.Task CreateTaskAsync_WithValidTitle_ShouldCreateTask() { // Arrange using var context = CreateInMemoryDbContext(); var service = new TaskService(context); var title = "Test Task"; var description = "Test Description"; // Act var result = await service.CreateTaskAsync(title, description); // Assert Assert.NotNull(result); Assert.Equal(title, result.Title); Assert.Equal(description, result.Description); Assert.False(result.IsCompleted); Assert.True(result.CreatedUtc <= DateTime.UtcNow); Assert.True(result.CreatedUtc > DateTime.UtcNow.AddMinutes(-1)); Assert.True(result.Id > 0); // Verify it was saved to database var savedTask = await context.Tasks.FindAsync(result.Id); Assert.NotNull(savedTask); Assert.Equal(title, savedTask!.Title); } [Fact] public async System.Threading.Tasks.Task CreateTaskAsync_WithNullTitle_ShouldThrowArgumentException() { // Arrange using var context = CreateInMemoryDbContext(); var service = new TaskService(context); // Act & Assert await Assert.ThrowsAsync(() => service.CreateTaskAsync(null!, "Description")); } [Fact] public async System.Threading.Tasks.Task CreateTaskAsync_WithEmptyTitle_ShouldThrowArgumentException() { // Arrange using var context = CreateInMemoryDbContext(); var service = new TaskService(context); // Act & Assert await Assert.ThrowsAsync(() => service.CreateTaskAsync(string.Empty, "Description")); } [Fact] public async System.Threading.Tasks.Task CreateTaskAsync_WithWhitespaceTitle_ShouldThrowArgumentException() { // Arrange using var context = CreateInMemoryDbContext(); var service = new TaskService(context); // Act & Assert await Assert.ThrowsAsync(() => service.CreateTaskAsync(" ", "Description")); } [Fact] public async System.Threading.Tasks.Task CreateTaskAsync_WithNullDescription_ShouldCreateTask() { // Arrange using var context = CreateInMemoryDbContext(); var service = new TaskService(context); var title = "Test Task"; // Act var result = await service.CreateTaskAsync(title, null); // Assert Assert.NotNull(result); Assert.Equal(title, result.Title); Assert.Null(result.Description); } [Fact] public async System.Threading.Tasks.Task CreateTaskAsync_ShouldSetCreatedUtcToUtcNow() { // Arrange using var context = CreateInMemoryDbContext(); var service = new TaskService(context); var beforeCreation = DateTime.UtcNow; // Act var result = await service.CreateTaskAsync("Test Task", "Description"); var afterCreation = DateTime.UtcNow; // Assert Assert.True(result.CreatedUtc >= beforeCreation); Assert.True(result.CreatedUtc <= afterCreation); Assert.Equal(DateTimeKind.Utc, result.CreatedUtc.Kind); } [Fact] public async System.Threading.Tasks.Task CreateTaskAsync_ShouldTrimTitleAndDescription() { // Arrange using var context = CreateInMemoryDbContext(); var service = new TaskService(context); var title = " Test Task "; var description = " Test Description "; // Act var result = await service.CreateTaskAsync(title, description); // Assert Assert.Equal("Test Task", result.Title); Assert.Equal("Test Description", result.Description); } [Fact] public async System.Threading.Tasks.Task GetAllTasksAsync_WithNoTasks_ShouldReturnEmptyList() { // Arrange using var context = CreateInMemoryDbContext(); var service = new TaskService(context); // Act var result = await service.GetAllTasksAsync(); // Assert Assert.NotNull(result); Assert.Empty(result); } [Fact] public async System.Threading.Tasks.Task GetAllTasksAsync_WithMultipleTasks_ShouldReturnAllTasksOrderedByCreatedUtc() { // Arrange using var context = CreateInMemoryDbContext(); var service = new TaskService(context); var task1 = await service.CreateTaskAsync("First Task", "First"); await System.Threading.Tasks.Task.Delay(10); // Small delay to ensure different CreatedUtc var task2 = await service.CreateTaskAsync("Second Task", "Second"); await System.Threading.Tasks.Task.Delay(10); var task3 = await service.CreateTaskAsync("Third Task", "Third"); // Act var result = (await service.GetAllTasksAsync()).ToList(); // Assert Assert.Equal(3, result.Count); Assert.Equal("First Task", result[0].Title); Assert.Equal("Second Task", result[1].Title); Assert.Equal("Third Task", result[2].Title); Assert.True(result[0].CreatedUtc <= result[1].CreatedUtc); Assert.True(result[1].CreatedUtc <= result[2].CreatedUtc); } }