Skip to content
This repository was archived by the owner on Mar 17, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ea3c319
chore: setup development environment and remove angular
annogram Aug 5, 2024
029522a
feat: add typescript, redux, and create skelletons
annogram Aug 5, 2024
f4732a2
feat: add react-query for api layer
annogram Aug 6, 2024
2e5ba06
feat: hook up api and front-end
annogram Aug 6, 2024
944dff3
chore: remove unnecessary debounce in App
annogram Aug 6, 2024
c0d64c6
feat: hookup create and update correctly
annogram Aug 6, 2024
f950e5d
feat: add delete verb
annogram Aug 6, 2024
1843484
test: add tests and fix for use case that i just thought of
annogram Aug 6, 2024
ccb4950
feat: add drity background for period before debounce is called
annogram Aug 6, 2024
c85e5e3
chore: test failures must have been coming from app.test.tsx
annogram Aug 6, 2024
244e1f2
feat: use webapplication instead of webhost builder
annogram Aug 6, 2024
b877fef
Merge pull request #1 from annogram/chore/setup_environment
annogram Aug 6, 2024
3c6cdd1
feat: make backend follow clean code architecture
annogram Aug 6, 2024
c0cfb33
feat: add requests to run from ide
annogram Aug 6, 2024
e5a2c09
chore: add global runner for codespace
annogram Aug 6, 2024
df012df
Merge pull request #2 from annogram/chore/cleanup_backend
annogram Aug 6, 2024
4cd4dd5
feat: create docker compose for running project
annogram Aug 7, 2024
6f2c5a8
feat: actually do one of the required tasks
annogram Aug 7, 2024
0171837
feat: add healthcheck for docker
annogram Aug 7, 2024
5f3c928
fix: update command and modify validation slightly
annogram Aug 7, 2024
a7d75c4
feat: do not allow modification of completed tasks
annogram Aug 7, 2024
4adfcaf
test: add some tests and add some nice libraries
annogram Aug 7, 2024
e688f69
feat: add unit tests for important pathways
annogram Aug 7, 2024
9efab5a
Merge pull request #3 from annogram/feat/docker
annogram Aug 7, 2024
bc96bd4
docs: final readme touchups
annogram Aug 7, 2024
6a70de2
docs: update readme with some information on how to make it work for …
annogram Aug 7, 2024
c32550c
chore: remove initial code
annogram Aug 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions Backend/TodoList.Api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["TodoList.Api/TodoList.Api.csproj", "TodoList.Api/"]
RUN dotnet restore "TodoList.Api/TodoList.Api.csproj"
COPY . .

RUN dotnet restore "TodoList.Api/TodoList.Api.csproj"
WORKDIR "/src/TodoList.Api"
RUN dotnet build "TodoList.Api.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "TodoList.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false

FROM base AS final
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
WORKDIR /app
COPY --from=publish /app/publish .
RUN apt-get update && apt-get install -y curl
ENTRYPOINT ["dotnet", "TodoList.Api.dll"]
12 changes: 0 additions & 12 deletions Backend/TodoList.Api/TodoList.Api.UnitTests/DummyTestShould.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoFixture.AutoMoq" Version="4.18.1" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.18.1" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using AutoFixture.Xunit2;
using FluentAssertions;
using Moq;
using System;
using System.Threading.Tasks;
using TodoList.Application.TodoList.Commands;
using TodoList.Application.TodoList.Ports;
using TodoList.Domain;
using Xunit;

namespace TodoList.Api.UnitTests.TodoList.Commands;

public class CreateTodoItemTests
{
private readonly CreateTodoItemCommandHanlder sut;
private readonly Mock<ITodoListRepository> todolistRepository = new();

public CreateTodoItemTests()
{
sut = new CreateTodoItemCommandHanlder(todolistRepository.Object);
}

[Theory]
[AutoData]
public async Task Handle_ShouldCreateItem(TodoItem item)
{
// Arrange
var command = new CreateTodoItemCommand
{
Item = item
};

todolistRepository.Setup(x => x.CreateItem(It.IsAny<TodoItem>())).ReturnsAsync(Guid.NewGuid());

// Act
var result = await sut.Handle(command, default);

// Assert
result.Should().NotBe(Guid.Empty);
todolistRepository.Verify(x => x.CreateItem(item), Times.Once);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using AutoFixture.Xunit2;
using FluentAssertions;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TodoList.Application.TodoList.Ports;
using TodoList.Application.TodoList.Queries;
using TodoList.Domain;
using Xunit;

namespace TodoList.Api.UnitTests.TodoList.Queries;

public class GetTodoItemsQueryTests
{

private readonly GetTodoItemsQueryHandler sut;
private readonly Mock<ITodoListRepository> todolistRepository = new();

public GetTodoItemsQueryTests()
{
sut = new GetTodoItemsQueryHandler(todolistRepository.Object);
}

[Theory]
[AutoData]
public async Task Handle_Should_ReturnAllItems_When_NoItemsSpecified(List<TodoItem> mockData)
{
// Arrange
var query = new GetTodoItemsQuery();


todolistRepository.Setup(x => x.GetAllItems()).ReturnsAsync(mockData);

// Act
var result = await sut.Handle(query, default);

// Assert
result.Should().BeEquivalentTo(mockData);
}

[Theory]
[AutoData]
public async Task Handle_ShouldReturnSelectedItems_When_Specified(List<TodoItem> mockData)
{
var query = new GetTodoItemsQuery
{
Items = mockData.Select(x => x.Id!.Value).Take(1)
};

todolistRepository.Setup(x => x.GetById(It.IsAny<Guid[]>())).ReturnsAsync(mockData.Take(1));

var result = await sut.Handle(query, default);

result.Should().BeEquivalentTo(result.Take(1));
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using AutoFixture.Xunit2;
using FluentAssertions;
using Moq;
using System;
using System.Collections.Generic;
using System.Formats.Asn1;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TodoList.Application.TodoList.Commands;
using TodoList.Application.TodoList.Ports;
using TodoList.Application.TodoList.Validations;
using TodoList.Domain;
using Xunit;

namespace TodoList.Api.UnitTests.TodoList.Validators;

public class CreateTodoItemValidatorTests
{
private readonly CreateTodoItemValidator sut;
private readonly Mock<ITodoListRepository> todolistRepository = new();

public CreateTodoItemValidatorTests()
{
sut = new CreateTodoItemValidator(todolistRepository.Object);
}

[Theory]
[AutoData]
public async Task Validate_ShouldReturnTrue_WhenItemIsValid(TodoItem item)
{
// Arrange
var command = new CreateTodoItemCommand
{
Item = item
};

todolistRepository.Setup(x => x.GetAllItems()).ReturnsAsync([]);

// Act
var result = await sut.ValidateAsync(command);

// Assert
result.IsValid.Should().BeTrue();
}

[Theory]
[AutoData]
public async Task Validate_ShouldReturnFalse_WhenItemHasNoDescription(TodoItem item)
{
// Arrange
var command = new CreateTodoItemCommand
{
Item = item with { Description = string.Empty }
};

// Act
var result = await sut.ValidateAsync(command);

// Assert
result.IsValid.Should().BeFalse();
}

[Theory]
[AutoData]
public async Task Validate_ShouldReturnFalse_WhenItemWithSameDescriptionAlreadyExists(TodoItem item)
{
// Arrange
var command = new CreateTodoItemCommand
{
Item = item
};

todolistRepository.Setup(x => x.GetAllItems()).ReturnsAsync([item]);

// Act
var result = await sut.ValidateAsync(command);

// Assert
result.IsValid.Should().BeFalse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using AutoFixture.Xunit2;
using FluentAssertions;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TodoList.Application.TodoList.Commands;
using TodoList.Application.TodoList.Ports;
using TodoList.Application.TodoList.Validations;
using TodoList.Domain;
using Xunit;

namespace TodoList.Api.UnitTests.TodoList.Validators;

public class UpdateTodoItemValidtorTests
{
private readonly UpdateTodoItemValidator sut;
private readonly Mock<ITodoListRepository> todolistRepository = new();

public UpdateTodoItemValidtorTests()
{
sut = new UpdateTodoItemValidator(todolistRepository.Object);
}

[Theory]
[AutoData]
public async Task Validate_ShouldReturnTrue_WhenItemExists(TodoItem item)
{
// Arrange
var command = new UpdateTodoItemCommand
{
Item = item
};

todolistRepository.Setup(x => x.GetAllItems()).ReturnsAsync([item]);

// Act
var result = await sut.ValidateAsync(command);

// Assert
result.IsValid.Should().BeTrue();
}

[Theory]
[AutoData]
public async Task Validate_ShouldReturnFalse_WhenItemHasNoDescription(TodoItem item)
{
// Arrange
var command = new UpdateTodoItemCommand
{
Item = item with { Description = string.Empty }
};

// Act
var result = await sut.ValidateAsync(command);

// Assert
result.IsValid.Should().BeFalse();
result.Errors.Should().Contain(x => x.ErrorMessage == "Cannot update to empty item");
}

[Theory]
[AutoData]
public async Task Validate_ShouldReturnFalse_WhenItemWithSameDescriptionAlreadyExists(TodoItem newItem, TodoItem oldItem)
{
// Arrange
var command = new UpdateTodoItemCommand
{
Item = newItem with { Description = oldItem.Description }
};

todolistRepository.Setup(x => x.GetAllItems()).ReturnsAsync([oldItem]);

// Act
var result = await sut.ValidateAsync(command);

// Assert
result.IsValid.Should().BeFalse();
result.Errors.Should().Contain(x => x.ErrorMessage == "Item with this description already exists");
}
}
23 changes: 20 additions & 3 deletions Backend/TodoList.Api/TodoList.Api.sln
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31613.86
# Visual Studio Version 17
VisualStudioVersion = 17.10.35122.118
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TodoList.Api", "TodoList.Api\TodoList.Api.csproj", "{065CE954-2618-4A24-A613-9C336C2154C6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TodoList.Api.UnitTests", "TodoList.Api.UnitTests\TodoList.Api.UnitTests.csproj", "{2BBBFEED-85B6-4361-85B2-F9E08C86C55B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TodoList.Api.UnitTests", "TodoList.Api.UnitTests\TodoList.Api.UnitTests.csproj", "{2BBBFEED-85B6-4361-85B2-F9E08C86C55B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TodoList.Domain", "TodoList.Domain\TodoList.Domain.csproj", "{26634C70-082E-4182-87BF-53A2BE1C2873}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TodoList.Application", "TodoList.Application\TodoList.Application.csproj", "{CA1453D4-F075-411E-B99C-BDB1D5BA96C8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{F6B2573F-D9BE-4EF0-861A-21ED3DA2ABEC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -21,10 +27,21 @@ Global
{2BBBFEED-85B6-4361-85B2-F9E08C86C55B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2BBBFEED-85B6-4361-85B2-F9E08C86C55B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2BBBFEED-85B6-4361-85B2-F9E08C86C55B}.Release|Any CPU.Build.0 = Release|Any CPU
{26634C70-082E-4182-87BF-53A2BE1C2873}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26634C70-082E-4182-87BF-53A2BE1C2873}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26634C70-082E-4182-87BF-53A2BE1C2873}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26634C70-082E-4182-87BF-53A2BE1C2873}.Release|Any CPU.Build.0 = Release|Any CPU
{CA1453D4-F075-411E-B99C-BDB1D5BA96C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA1453D4-F075-411E-B99C-BDB1D5BA96C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA1453D4-F075-411E-B99C-BDB1D5BA96C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA1453D4-F075-411E-B99C-BDB1D5BA96C8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2BBBFEED-85B6-4361-85B2-F9E08C86C55B} = {F6B2573F-D9BE-4EF0-861A-21ED3DA2ABEC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {061F7879-5D14-4C5E-A4A9-782C6FEB1132}
EndGlobalSection
Expand Down
Loading