From aa537ee29f05b958c68899331ee8ae4fd3245180 Mon Sep 17 00:00:00 2001 From: Ravinder Sandhu Date: Mon, 4 Sep 2023 22:53:45 +1200 Subject: [PATCH 1/3] Added structure and code for todolist --- Backend/TodoList.Api/TodoList.Api.sln | 46 +++++++- .../ApiVersioningAndSwaggerConfiguration.cs | 36 ++++++ .../Configurations/CorsConfiguration.cs | 30 +++++ .../InfrastructureConfiguration.cs | 18 +++ .../Controllers/ApiControllerBase.cs | 8 ++ .../Controllers/TodoItemsController.cs | 107 +++++++----------- .../TodoList.Api/Models/ApiErrorResponse.cs | 14 +++ .../Properties/launchSettings.json | 6 +- Backend/TodoList.Api/TodoList.Api/Startup.cs | 33 ++---- .../TodoList.Api/TodoList.Api/TodoContext.cs | 14 --- .../TodoList.Api/TodoList.Api.csproj | 10 +- .../Entities}/TodoItem.cs | 4 +- .../Repositories/ITodoListRepository.cs | 12 ++ .../TodoList.Domain/TodoList.Domain.csproj | 9 ++ ...ture.Application.Services.UnitTests.csproj | 29 +++++ .../UnitTest1.cs | 11 ++ .../Usings.cs | 1 + .../Extensions/ServiceCollectionExtensions.cs | 27 +++++ .../MappingProfiles/TodoListProfile.cs | 24 ++++ .../Modules/TodoListModule/TodoListService.cs | 73 ++++++++++++ ...Infrastructure.Application.Services.csproj | 20 ++++ .../CreateTodoItemTests.cs | 33 ++++++ ...ucture.Persistence.EFCore.UnitTests.csproj | 26 +++++ .../UnitTest1.cs | 11 ++ .../Usings.cs | 1 + .../Configurations/TodoItemConfiguration.cs | 16 +++ .../Extensions/ServiceCollectionExtensions.cs | 16 +++ .../Repositories/TodoListRepository.cs | 39 +++++++ ...t.Infrastructure.Persistence.EFCore.csproj | 22 ++++ .../TodoListContext.cs | 14 +++ .../Exceptions/TodoItemNotFoundException.cs | 17 +++ .../TodoListModule/ITodoListService.cs | 14 +++ .../Models/CreateTodoItemModel.cs | 7 ++ .../Models/UpdateTodoItemModel.cs | 7 ++ .../CreateTodoItemModelValidator.cs | 13 +++ .../ViewModels/GetTodoItemViewModel.cs | 15 +++ .../TodoList.Services/Shared/ServiceResult.cs | 57 ++++++++++ .../TodoList.Services.csproj | 13 +++ .../TodoList.Shared/TodoList.Shared.csproj | 9 ++ 39 files changed, 744 insertions(+), 118 deletions(-) create mode 100644 Backend/TodoList.Api/TodoList.Api/Configurations/ApiVersioningAndSwaggerConfiguration.cs create mode 100644 Backend/TodoList.Api/TodoList.Api/Configurations/CorsConfiguration.cs create mode 100644 Backend/TodoList.Api/TodoList.Api/Configurations/InfrastructureConfiguration.cs create mode 100644 Backend/TodoList.Api/TodoList.Api/Controllers/ApiControllerBase.cs create mode 100644 Backend/TodoList.Api/TodoList.Api/Models/ApiErrorResponse.cs delete mode 100644 Backend/TodoList.Api/TodoList.Api/TodoContext.cs rename Backend/TodoList.Api/{TodoList.Api => TodoList.Domain/Entities}/TodoItem.cs (82%) create mode 100644 Backend/TodoList.Api/TodoList.Domain/Repositories/ITodoListRepository.cs create mode 100644 Backend/TodoList.Api/TodoList.Domain/TodoList.Domain.csproj create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/UnitTest1.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/Usings.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Extensions/ServiceCollectionExtensions.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/MappingProfiles/TodoListProfile.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Modules/TodoListModule/TodoListService.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/UnitTest1.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/Usings.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Configurations/TodoItemConfiguration.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Repositories/TodoListRepository.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs create mode 100644 Backend/TodoList.Api/TodoList.Services/Exceptions/TodoItemNotFoundException.cs create mode 100644 Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ITodoListService.cs create mode 100644 Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/CreateTodoItemModel.cs create mode 100644 Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/UpdateTodoItemModel.cs create mode 100644 Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Validations/CreateTodoItemModelValidator.cs create mode 100644 Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs create mode 100644 Backend/TodoList.Api/TodoList.Services/Shared/ServiceResult.cs create mode 100644 Backend/TodoList.Api/TodoList.Services/TodoList.Services.csproj create mode 100644 Backend/TodoList.Api/TodoList.Shared/TodoList.Shared.csproj diff --git a/Backend/TodoList.Api/TodoList.Api.sln b/Backend/TodoList.Api/TodoList.Api.sln index de8d1a58..2bf277bc 100644 --- a/Backend/TodoList.Api/TodoList.Api.sln +++ b/Backend/TodoList.Api/TodoList.Api.sln @@ -1,11 +1,27 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31613.86 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33927.249 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", "{693E7B0C-DA2B-446E-B729-03FE4E1B184C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{81EDD5C8-EAE7-4964-80B5-6B90241C7028}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{739BBC78-14C8-425F-9627-8BB80757A021}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentations", "Presentations", "{54522759-2130-4896-822B-E4780B726E31}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{E05B50FF-13BB-495F-9B73-65A5683AE3C2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TodoList.Infrastructure.Persistence.EFCore", "TodoList.Infrastructure.Persistence.EFCore\TodoList.Infrastructure.Persistence.EFCore.csproj", "{9A26C735-BF26-4E9C-BA1E-6BE5BDCF6A4F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TodoList.Services", "TodoList.Services\TodoList.Services.csproj", "{25041BFD-A612-4DDC-BAE9-217ACD3E8188}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TodoList.Infrastructure.Application.Services", "TodoList.Infrastructure.Application.Services\TodoList.Infrastructure.Application.Services.csproj", "{D259C88D-A212-4496-AF88-0CDF210C055C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,10 +37,34 @@ 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 + {693E7B0C-DA2B-446E-B729-03FE4E1B184C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {693E7B0C-DA2B-446E-B729-03FE4E1B184C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {693E7B0C-DA2B-446E-B729-03FE4E1B184C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {693E7B0C-DA2B-446E-B729-03FE4E1B184C}.Release|Any CPU.Build.0 = Release|Any CPU + {9A26C735-BF26-4E9C-BA1E-6BE5BDCF6A4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A26C735-BF26-4E9C-BA1E-6BE5BDCF6A4F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A26C735-BF26-4E9C-BA1E-6BE5BDCF6A4F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A26C735-BF26-4E9C-BA1E-6BE5BDCF6A4F}.Release|Any CPU.Build.0 = Release|Any CPU + {25041BFD-A612-4DDC-BAE9-217ACD3E8188}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25041BFD-A612-4DDC-BAE9-217ACD3E8188}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25041BFD-A612-4DDC-BAE9-217ACD3E8188}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25041BFD-A612-4DDC-BAE9-217ACD3E8188}.Release|Any CPU.Build.0 = Release|Any CPU + {D259C88D-A212-4496-AF88-0CDF210C055C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D259C88D-A212-4496-AF88-0CDF210C055C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D259C88D-A212-4496-AF88-0CDF210C055C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D259C88D-A212-4496-AF88-0CDF210C055C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {065CE954-2618-4A24-A613-9C336C2154C6} = {54522759-2130-4896-822B-E4780B726E31} + {2BBBFEED-85B6-4361-85B2-F9E08C86C55B} = {81EDD5C8-EAE7-4964-80B5-6B90241C7028} + {693E7B0C-DA2B-446E-B729-03FE4E1B184C} = {E05B50FF-13BB-495F-9B73-65A5683AE3C2} + {9A26C735-BF26-4E9C-BA1E-6BE5BDCF6A4F} = {739BBC78-14C8-425F-9627-8BB80757A021} + {25041BFD-A612-4DDC-BAE9-217ACD3E8188} = {E05B50FF-13BB-495F-9B73-65A5683AE3C2} + {D259C88D-A212-4496-AF88-0CDF210C055C} = {739BBC78-14C8-425F-9627-8BB80757A021} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {061F7879-5D14-4C5E-A4A9-782C6FEB1132} EndGlobalSection diff --git a/Backend/TodoList.Api/TodoList.Api/Configurations/ApiVersioningAndSwaggerConfiguration.cs b/Backend/TodoList.Api/TodoList.Api/Configurations/ApiVersioningAndSwaggerConfiguration.cs new file mode 100644 index 00000000..8e213ab9 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Api/Configurations/ApiVersioningAndSwaggerConfiguration.cs @@ -0,0 +1,36 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; + +namespace TodoList.Api.Configurations +{ + public static class ApiVersioningAndSwaggerConfiguration + { + public static void AddApiVersioningAndSwagger(this IServiceCollection services) + { + services.AddApiVersioning(options => + { + options.ReportApiVersions = true; + options.DefaultApiVersion = new ApiVersion(1, 0); + options.ReportApiVersions = true; + options.AssumeDefaultVersionWhenUnspecified = true; + }); + + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new OpenApiInfo { Title = "TodoList.Api" }); + }); + + services.AddSwaggerGen(); + + } + + public static IApplicationBuilder UseSwaggerEndpoint(this IApplicationBuilder app) + { + app.UseSwagger(); + app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoList.Api v1")); + return app; + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Api/Configurations/CorsConfiguration.cs b/Backend/TodoList.Api/TodoList.Api/Configurations/CorsConfiguration.cs new file mode 100644 index 00000000..6e4eea7a --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Api/Configurations/CorsConfiguration.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; + +namespace TodoList.Api.Configurations +{ + public static class CorsConfiguration + { + public static IServiceCollection AddCorsPolicies(this IServiceCollection services, string policyName) + { + services.AddCors(options => + { + options.AddPolicy(policyName, + builder => + { + builder.AllowAnyOrigin() + .AllowAnyHeader() + .AllowAnyMethod(); + }); + }); + + return services; + } + + public static IApplicationBuilder UseCorsPolicy(this IApplicationBuilder applicationBuilder, string poliocyName) + { + applicationBuilder.UseCors(poliocyName); + return applicationBuilder; + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Api/Configurations/InfrastructureConfiguration.cs b/Backend/TodoList.Api/TodoList.Api/Configurations/InfrastructureConfiguration.cs new file mode 100644 index 00000000..ba00958f --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Api/Configurations/InfrastructureConfiguration.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.DependencyInjection; +using TodoList.Infrastructure.Application.Services.Extensions; +using TodoList.Infrastructure.Persistence.EFCore.Extensions; + +namespace TodoList.Api.Configurations +{ + public static class InfrastructureConfiguration + { + public static void AddApplicationServices(this IServiceCollection services) + { + services.AddAppServices(); + } + public static void AddEfCoreAsPersistence(this IServiceCollection services) + { + services.AddInMemoryPersistence(); + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Api/Controllers/ApiControllerBase.cs b/Backend/TodoList.Api/TodoList.Api/Controllers/ApiControllerBase.cs new file mode 100644 index 00000000..ed914a2a --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Api/Controllers/ApiControllerBase.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Mvc; + +namespace TodoList.Api.Controllers +{ + public abstract class ApiControllerBase: ControllerBase + { + } +} diff --git a/Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs b/Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs index c42f2f44..83ced84b 100644 --- a/Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs +++ b/Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs @@ -1,40 +1,43 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; -using System; -using System.Linq; +using System; +using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using TodoList.Services.Modules.TodoListModule; +using TodoList.Services.Modules.TodoListModule.Models; +using TodoList.Services.Shared; namespace TodoList.Api.Controllers { - [Route("api/[controller]")] + + [ApiVersion("1")] + [Route("api/v{version:apiVersion}/[controller]")] [ApiController] - public class TodoItemsController : ControllerBase + public class TodoItemsController : ApiControllerBase { - private readonly TodoContext _context; - private readonly ILogger _logger; + private readonly ILogger logger; + private readonly ITodoListService todoListService; - public TodoItemsController(TodoContext context, ILogger logger) + public TodoItemsController(ILogger logger, ITodoListService todoListService) { - _context = context; - _logger = logger; + this.logger = logger; + this.todoListService = todoListService; } - // GET: api/TodoItems + // GET: api/TodoItems/... [HttpGet] - public async Task GetTodoItems() + public async Task GetTodoItem(CancellationToken token) { - var results = await _context.TodoItems.Where(x => !x.IsCompleted).ToListAsync(); - return Ok(results); + var result = await this.todoListService.GetItems(token).ConfigureAwait(false); + return Ok(result); } - // GET: api/TodoItems/... [HttpGet("{id}")] - public async Task GetTodoItem(Guid id) + public async Task GetTodoItem(Guid id, CancellationToken token) { - var result = await _context.TodoItems.FindAsync(id); + var result = await this.todoListService.GetItem(id, token).ConfigureAwait(false); - if (result == null) + if (result.ResultCode == ResultCode.NotFound) { return NotFound(); } @@ -42,64 +45,32 @@ public async Task GetTodoItem(Guid id) return Ok(result); } - // PUT: api/TodoItems/... - [HttpPut("{id}")] - public async Task PutTodoItem(Guid id, TodoItem todoItem) - { - if (id != todoItem.Id) - { - return BadRequest(); - } - - _context.Entry(todoItem).State = EntityState.Modified; - - try - { - await _context.SaveChangesAsync(); - } - catch (DbUpdateConcurrencyException) - { - if (!TodoItemIdExists(id)) - { - return NotFound(); - } - else - { - throw; - } - } - - return NoContent(); - } - // POST: api/TodoItems [HttpPost] - public async Task PostTodoItem(TodoItem todoItem) + public async Task PostTodoItem(CreateTodoItemModel todoItem, CancellationToken token) { - if (string.IsNullOrEmpty(todoItem?.Description)) + var result = await this.todoListService.CreateTodoItem(todoItem, token).ConfigureAwait(false); + if (result.ResultCode == ResultCode.Created) { - return BadRequest("Description is required"); + return CreatedAtAction(nameof(GetTodoItem), new { id = result.Result.Id }, result.Result); } - else if (TodoItemDescriptionExists(todoItem.Description)) - { - return BadRequest("Description already exists"); - } - _context.TodoItems.Add(todoItem); - await _context.SaveChangesAsync(); - - return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); - } + return BadRequest(result.Errors); - private bool TodoItemIdExists(Guid id) - { - return _context.TodoItems.Any(x => x.Id == id); } - private bool TodoItemDescriptionExists(string description) + // PUT: api/TodoItems/... + [HttpPut("{id}")] + public async Task PutTodoItem(Guid id, UpdateTodoItemModel todoItem, CancellationToken token) { - return _context.TodoItems - .Any(x => x.Description.ToLowerInvariant() == description.ToLowerInvariant() && !x.IsCompleted); + var result = await this.todoListService.UpdateTodoItemStatus(id, todoItem, token).ConfigureAwait(false); + + if (result.ResultCode == ResultCode.NotFound) + { + return NotFound(); + } + + return NoContent(); } } } diff --git a/Backend/TodoList.Api/TodoList.Api/Models/ApiErrorResponse.cs b/Backend/TodoList.Api/TodoList.Api/Models/ApiErrorResponse.cs new file mode 100644 index 00000000..cda8d97a --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Api/Models/ApiErrorResponse.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace TodoList.Api.Models +{ + public class ApiErrorResponse + { + public string Type { get; set; } + public string Title { get; set; } + public string Detail { get; set; } + public int Status { get; set; } + public string Instance { get; set; } + public IEnumerable> Errors { get; set; } + } +} diff --git a/Backend/TodoList.Api/TodoList.Api/Properties/launchSettings.json b/Backend/TodoList.Api/TodoList.Api/Properties/launchSettings.json index 43840e65..b985add6 100644 --- a/Backend/TodoList.Api/TodoList.Api/Properties/launchSettings.json +++ b/Backend/TodoList.Api/TodoList.Api/Properties/launchSettings.json @@ -12,8 +12,7 @@ "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, - //"launchUrl": "swagger", - "launchUrl": "api/todoitems", + "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } @@ -22,8 +21,7 @@ "commandName": "Project", "dotnetRunMessages": "true", "launchBrowser": true, - //"launchUrl": "swagger", - "launchUrl": "api/todoitems", + "launchUrl": "swagger", "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/Backend/TodoList.Api/TodoList.Api/Startup.cs b/Backend/TodoList.Api/TodoList.Api/Startup.cs index 1db21ceb..3ad2808d 100644 --- a/Backend/TodoList.Api/TodoList.Api/Startup.cs +++ b/Backend/TodoList.Api/TodoList.Api/Startup.cs @@ -1,10 +1,9 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.OpenApi.Models; +using TodoList.Api.Configurations; namespace TodoList.Api { @@ -17,27 +16,15 @@ public Startup(IConfiguration configuration) public IConfiguration Configuration { get; } + // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddCors(options => - { - options.AddPolicy("AllowAllHeaders", - builder => - { - builder.AllowAnyOrigin() - .AllowAnyHeader() - .AllowAnyMethod(); - }); - }); - + services.AddCorsPolicies("AllowAllHeaders"); services.AddControllers(); - services.AddSwaggerGen(c => - { - c.SwaggerDoc("v1", new OpenApiInfo { Title = "TodoList.Api", Version = "v1" }); - }); - - services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoItemsDB")); + services.AddApiVersioningAndSwagger(); + services.AddApplicationServices(); + services.AddEfCoreAsPersistence(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -46,22 +33,20 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); - app.UseSwagger(); - app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoList.Api v1")); + app.UseSwaggerEndpoint(); } app.UseHttpsRedirection(); app.UseRouting(); - app.UseCors("AllowAllHeaders"); - - app.UseAuthorization(); + app.UseCorsPolicy("AllowAllHeaders"); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); + } } } diff --git a/Backend/TodoList.Api/TodoList.Api/TodoContext.cs b/Backend/TodoList.Api/TodoList.Api/TodoContext.cs deleted file mode 100644 index 068513bf..00000000 --- a/Backend/TodoList.Api/TodoList.Api/TodoContext.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -namespace TodoList.Api -{ - public class TodoContext : DbContext - { - public TodoContext(DbContextOptions options) - : base(options) - { - } - - public DbSet TodoItems { get; set; } - } -} diff --git a/Backend/TodoList.Api/TodoList.Api/TodoList.Api.csproj b/Backend/TodoList.Api/TodoList.Api/TodoList.Api.csproj index d206ff56..a1ee1a37 100644 --- a/Backend/TodoList.Api/TodoList.Api/TodoList.Api.csproj +++ b/Backend/TodoList.Api/TodoList.Api/TodoList.Api.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -12,7 +12,7 @@ - + all @@ -20,6 +20,12 @@ + + + + + + diff --git a/Backend/TodoList.Api/TodoList.Api/TodoItem.cs b/Backend/TodoList.Api/TodoList.Domain/Entities/TodoItem.cs similarity index 82% rename from Backend/TodoList.Api/TodoList.Api/TodoItem.cs rename to Backend/TodoList.Api/TodoList.Domain/Entities/TodoItem.cs index 75a2774e..05ecd9d7 100644 --- a/Backend/TodoList.Api/TodoList.Api/TodoItem.cs +++ b/Backend/TodoList.Api/TodoList.Domain/Entities/TodoItem.cs @@ -1,6 +1,4 @@ -using System; - -namespace TodoList.Api +namespace TodoList.Domain.Entities { public class TodoItem { diff --git a/Backend/TodoList.Api/TodoList.Domain/Repositories/ITodoListRepository.cs b/Backend/TodoList.Api/TodoList.Domain/Repositories/ITodoListRepository.cs new file mode 100644 index 00000000..a87a1870 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Domain/Repositories/ITodoListRepository.cs @@ -0,0 +1,12 @@ +using TodoList.Domain.Entities; + +namespace TodoList.Domain.Repositories +{ + public interface ITodoListRepository + { + Task CreateTodoItem(TodoItem item, CancellationToken token); + Task UpdateTodoItem(TodoItem item, CancellationToken token); + Task GetTodoItem(Guid itemId, CancellationToken token); + Task> GetTodoItems(CancellationToken token); + } +} diff --git a/Backend/TodoList.Api/TodoList.Domain/TodoList.Domain.csproj b/Backend/TodoList.Api/TodoList.Domain/TodoList.Domain.csproj new file mode 100644 index 00000000..c589380a --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Domain/TodoList.Domain.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + disable + + + diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj new file mode 100644 index 00000000..67362634 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj @@ -0,0 +1,29 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/UnitTest1.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/UnitTest1.cs new file mode 100644 index 00000000..03574eed --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/UnitTest1.cs @@ -0,0 +1,11 @@ +namespace TodoList.Infrastructure.Application.Services.UnitTests +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + + } + } +} \ No newline at end of file diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/Usings.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/Usings.cs new file mode 100644 index 00000000..8c927eb7 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Extensions/ServiceCollectionExtensions.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 00000000..b5b92dd3 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,27 @@ +using FluentValidation; +using FluentValidation.AspNetCore; +using Microsoft.Extensions.DependencyInjection; +using TodoList.Infrastructure.Application.Services.Modules.TodoListModule; +using TodoList.Services.Modules.TodoListModule; +using TodoList.Services.Modules.TodoListModule.Validations; + +namespace TodoList.Infrastructure.Application.Services.Extensions +{ + public static class ServiceCollectionExtensions + { + public static void AddAppServices(this IServiceCollection services) + { + services.AddValidation(); + services.AddTransient(); + } + + private static void AddValidation(this IServiceCollection services) + { + services.AddFluentValidationAutoValidation(_ => + { + _.DisableDataAnnotationsValidation = true; + }); + services.AddValidatorsFromAssemblyContaining(); + } + } +} \ No newline at end of file diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/MappingProfiles/TodoListProfile.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/MappingProfiles/TodoListProfile.cs new file mode 100644 index 00000000..312f5613 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/MappingProfiles/TodoListProfile.cs @@ -0,0 +1,24 @@ +using Mapster; +using TodoList.Domain.Entities; +using TodoList.Services.Modules.TodoListModule.Models; +using TodoList.Services.Modules.TodoListModule.ViewModels; + +namespace TodoList.Infrastructure.Persistence.EFCore.MappingProfiles +{ + public class TodoListProfile : IRegister + { + public void Register(TypeAdapterConfig config) + { + config.ForType() + .Map(dest => dest.Id, src => Guid.NewGuid()) + .Map(dest => dest.Description, src => src.Description) + .Map(dest => dest.IsCompleted, src => false); + + + config.ForType() + .Map(dest => dest.Id, src => src.Id) + .Map(dest => dest.Description, src => src.Description) + .Map(dest => dest.IsCompleted, src => src.IsCompleted); + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Modules/TodoListModule/TodoListService.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Modules/TodoListModule/TodoListService.cs new file mode 100644 index 00000000..ce3b3c94 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Modules/TodoListModule/TodoListService.cs @@ -0,0 +1,73 @@ +using Mapster; +using TodoList.Domain.Entities; +using TodoList.Domain.Repositories; +using TodoList.Services.Modules.TodoListModule; +using TodoList.Services.Modules.TodoListModule.Models; +using TodoList.Services.Modules.TodoListModule.ViewModels; +using TodoList.Services.Shared; + +namespace TodoList.Infrastructure.Application.Services.Modules.TodoListModule +{ + internal class TodoListService : ITodoListService + { + private readonly ITodoListRepository todoListRepository; + public TodoListService(ITodoListRepository todoListRepository) + { + this.todoListRepository = todoListRepository; + } + public async Task> CreateTodoItem(CreateTodoItemModel item, CancellationToken cancellationToken) + { + var result = new ServiceResult(); + if (item == null) + { + result.BadRequestWithMessage("Description is required"); + return result; + } + + var newItem = await this.todoListRepository.CreateTodoItem(item.Adapt(), cancellationToken).ConfigureAwait(false); + if (newItem != null) + { + return result.ToResourceCreatedResult(newItem.Adapt()); + } + + result.WithResultCode(ResultCode.InternalServerError, "An unknown error occurred while creating TodoList Item"); + return result; + } + + public async Task> GetItem(Guid id, CancellationToken cancellationToken) + { + var result = new ServiceResult(); + var item = await this.todoListRepository.GetTodoItem(id, cancellationToken).ConfigureAwait(false); + if (item == null) + { + result.WithResultCode(ResultCode.NotFound, $"Item ({id}) not found"); + return result; + } + + return result.ToSuccessResult(item.Adapt()); + } + + public async Task> GetItems(CancellationToken token) + { + var items= await this.todoListRepository.GetTodoItems(token).ConfigureAwait(false); + return items.Adapt>(); + } + + public async Task UpdateTodoItemStatus(Guid id, UpdateTodoItemModel item, CancellationToken cancellationToken) + { + var result = new ServiceResult(); + var originalItem = await this.todoListRepository.GetTodoItem(id, cancellationToken).ConfigureAwait(false); + if (originalItem == null) + { + result.WithResultCode(ResultCode.NotFound, $"Item ({id}) not found"); + return result; + } + + originalItem.IsCompleted = item.IsCompleted; + + var isUpdated = await this.todoListRepository.UpdateTodoItem(originalItem, cancellationToken).ConfigureAwait(false); + + return result.WithResultCode(isUpdated ? ResultCode.Updated : ResultCode.InternalServerError); + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj new file mode 100644 index 00000000..55eac790 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj @@ -0,0 +1,20 @@ + + + + net6.0 + enable + disable + + + + + + + + + + + + + + diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs new file mode 100644 index 00000000..70ecc49e --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; + +namespace TodoList.Infrastructure.Persistence.EFCore.UnitTests.RepositoriesTests.TodoListRepositoryTests +{ + public class CreateTodoItemTests + { + [Fact] + public async Task CreateTodoItem_Should_Add_Item_To_Context() + { + // Arrange + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: "CreateTodoItem_Database") + .Options; + + using (var context = new TodoListContext(options)) + { + var repository = new TodoListRepository(context); + var item = new TodoItem { /* Initialize your item properties */ }; + + // Act + await repository.CreateTodoItem(item, CancellationToken.None); + + // Assert + Assert.Single(context.TodoItems); + } + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj new file mode 100644 index 00000000..c51e0261 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj @@ -0,0 +1,26 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/UnitTest1.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/UnitTest1.cs new file mode 100644 index 00000000..76c933ad --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/UnitTest1.cs @@ -0,0 +1,11 @@ +namespace TodoList.Infrastructure.Persistence.EFCore.UnitTests +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + + } + } +} \ No newline at end of file diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/Usings.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/Usings.cs new file mode 100644 index 00000000..8c927eb7 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Configurations/TodoItemConfiguration.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Configurations/TodoItemConfiguration.cs new file mode 100644 index 00000000..be7d4991 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Configurations/TodoItemConfiguration.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using TodoList.Domain.Entities; + +namespace TodoList.Infrastructure.Persistence.EFCore.Configurations +{ + internal class TodoItemConfiguration : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(x => x.Id); + builder.Property(x => x.Id).ValueGeneratedOnAdd(); + builder.Property(x => x.Description).HasMaxLength(100); + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 00000000..b3317066 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using TodoList.Domain.Repositories; +using TodoList.Infrastructure.Persistence.EFCore.Repositories; + +namespace TodoList.Infrastructure.Persistence.EFCore.Extensions +{ + public static class ServiceCollectionExtensions + { + public static void AddInMemoryPersistence(this IServiceCollection services) + { + services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoItemsDB")); + services.AddTransient(); + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Repositories/TodoListRepository.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Repositories/TodoListRepository.cs new file mode 100644 index 00000000..fc38524c --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Repositories/TodoListRepository.cs @@ -0,0 +1,39 @@ +using Microsoft.EntityFrameworkCore; +using TodoList.Domain.Entities; +using TodoList.Domain.Repositories; + +namespace TodoList.Infrastructure.Persistence.EFCore.Repositories +{ + internal class TodoListRepository : ITodoListRepository + { + private readonly TodoListContext todoListContext; + public TodoListRepository(TodoListContext todoListContext) + { + this.todoListContext = todoListContext; + } + + public async Task CreateTodoItem(TodoItem item, CancellationToken token) + { + await this.todoListContext.TodoItems.AddAsync(item, token).ConfigureAwait(false); + await this.todoListContext.SaveChangesAsync(token).ConfigureAwait(false); + return item; + } + + public async Task GetTodoItem(Guid itemId, CancellationToken token) + { + return await this.todoListContext.FindAsync(itemId, token).ConfigureAwait(false); + } + + public async Task> GetTodoItems(CancellationToken token) + { + return await this.todoListContext.TodoItems.ToArrayAsync(token).ConfigureAwait(false); + } + + public async Task UpdateTodoItem(TodoItem item, CancellationToken token) + { + this.todoListContext.Update(item); + await this.todoListContext.SaveChangesAsync(token).ConfigureAwait(false); + return true; + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj new file mode 100644 index 00000000..21d34e50 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj @@ -0,0 +1,22 @@ + + + + net6.0 + enable + disable + + + + + + + + + + + + + + + + diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs new file mode 100644 index 00000000..889d9430 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; +using TodoList.Domain.Entities; + +namespace TodoList.Infrastructure.Persistence.EFCore +{ + internal class TodoListContext : DbContext + { + public TodoListContext(DbContextOptions options) : base(options) + { + } + + public DbSet TodoItems { get; set; } + } +} diff --git a/Backend/TodoList.Api/TodoList.Services/Exceptions/TodoItemNotFoundException.cs b/Backend/TodoList.Api/TodoList.Services/Exceptions/TodoItemNotFoundException.cs new file mode 100644 index 00000000..6758b731 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Services/Exceptions/TodoItemNotFoundException.cs @@ -0,0 +1,17 @@ +namespace TodoList.Services.Exceptions +{ + public class TodoItemNotFoundException : Exception + { + public TodoItemNotFoundException() + { + } + + public TodoItemNotFoundException(string? message) : base(message) + { + } + + public TodoItemNotFoundException(string? message, Exception? innerException) : base(message, innerException) + { + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ITodoListService.cs b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ITodoListService.cs new file mode 100644 index 00000000..cda6cfdb --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ITodoListService.cs @@ -0,0 +1,14 @@ +using TodoList.Services.Modules.TodoListModule.Models; +using TodoList.Services.Modules.TodoListModule.ViewModels; +using TodoList.Services.Shared; + +namespace TodoList.Services.Modules.TodoListModule +{ + public interface ITodoListService + { + Task> CreateTodoItem(CreateTodoItemModel item, CancellationToken cancellationToken); + Task UpdateTodoItemStatus(Guid id, UpdateTodoItemModel item, CancellationToken cancellationToken); + Task> GetItem(Guid id, CancellationToken cancellationToken); + Task> GetItems(CancellationToken token); + } +} diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/CreateTodoItemModel.cs b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/CreateTodoItemModel.cs new file mode 100644 index 00000000..99f63984 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/CreateTodoItemModel.cs @@ -0,0 +1,7 @@ +namespace TodoList.Services.Modules.TodoListModule.Models +{ + public class CreateTodoItemModel + { + public string Description { get; set; } + } +} diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/UpdateTodoItemModel.cs b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/UpdateTodoItemModel.cs new file mode 100644 index 00000000..aa7aa265 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/UpdateTodoItemModel.cs @@ -0,0 +1,7 @@ +namespace TodoList.Services.Modules.TodoListModule.Models +{ + public class UpdateTodoItemModel + { + public bool IsCompleted { get; set; } + } +} diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Validations/CreateTodoItemModelValidator.cs b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Validations/CreateTodoItemModelValidator.cs new file mode 100644 index 00000000..46a447c4 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Validations/CreateTodoItemModelValidator.cs @@ -0,0 +1,13 @@ +using FluentValidation; +using TodoList.Services.Modules.TodoListModule.Models; + +namespace TodoList.Services.Modules.TodoListModule.Validations +{ + public class CreateTodoItemModelValidator : AbstractValidator + { + public CreateTodoItemModelValidator() + { + RuleFor(_ => _.Description).NotEmpty().MaximumLength(100); + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs new file mode 100644 index 00000000..b1c0acc6 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TodoList.Services.Modules.TodoListModule.ViewModels +{ + public class GetTodoItemViewModel + { + public Guid Id { get; set; } + public string Description { get; set; } + public bool IsCompleted { get; set; } + } +} diff --git a/Backend/TodoList.Api/TodoList.Services/Shared/ServiceResult.cs b/Backend/TodoList.Api/TodoList.Services/Shared/ServiceResult.cs new file mode 100644 index 00000000..52df0b8a --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Services/Shared/ServiceResult.cs @@ -0,0 +1,57 @@ +namespace TodoList.Services.Shared +{ + public class ServiceResult + { + public ResultCode ResultCode { get; internal set; } + public string Message { get; internal set; } + public List Errors { get; internal set; } + public bool HasErrors => Errors is { Count: > 0 }; + public ServiceResult() + { + Errors = new List(); + } + } + + public class ServiceResult : ServiceResult + { + public TModel Result { get; internal set; } + } + + public enum ResultCode + { + Success, + Created, + Updated, + BadRequest, + InternalServerError, + NotFound + } + + public static class ServiceResultExtension + { + public static ServiceResult BadRequestWithMessage(this ServiceResult serviceResult, string message) + { + serviceResult.ResultCode = ResultCode.BadRequest; + serviceResult.Message = message; + return serviceResult; + } + public static ServiceResult WithResultCode(this ServiceResult serviceResult, ResultCode resultCode, string message = "") + { + serviceResult.ResultCode = resultCode; + serviceResult.Message = message; + return serviceResult; + } + public static ServiceResult ToResourceCreatedResult(this ServiceResult serviceResult, TModel result) + { + serviceResult.ResultCode = ResultCode.Created; + serviceResult.Result = result; + return serviceResult; + } + public static ServiceResult ToSuccessResult(this ServiceResult serviceResult, TModel result) + { + serviceResult.ResultCode = ResultCode.Success; + serviceResult.Result = result; + return serviceResult; + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Services/TodoList.Services.csproj b/Backend/TodoList.Api/TodoList.Services/TodoList.Services.csproj new file mode 100644 index 00000000..a97d23ba --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Services/TodoList.Services.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + disable + + + + + + + diff --git a/Backend/TodoList.Api/TodoList.Shared/TodoList.Shared.csproj b/Backend/TodoList.Api/TodoList.Shared/TodoList.Shared.csproj new file mode 100644 index 00000000..132c02c5 --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Shared/TodoList.Shared.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + enable + + + From 23fc6dca8b300e0e251a0556d885b136c7f89f85 Mon Sep 17 00:00:00 2001 From: Ravinder Sandhu Date: Mon, 4 Sep 2023 23:30:33 +1200 Subject: [PATCH 2/3] Added unit tests for create method for all the projects --- .../PostTodoItemTests.cs | 67 ++++++++++++++++ .../TodoList.Api.UnitTests/DummyTestShould.cs | 12 --- .../TodoList.Api.UnitTests.csproj | 1 + Backend/TodoList.Api/TodoList.Api.sln | 14 ++++ .../Controllers/TodoItemsController.cs | 6 +- .../CreateTodoItemTests.cs | 76 +++++++++++++++++++ ...ture.Application.Services.UnitTests.csproj | 3 +- .../UnitTest1.cs | 11 --- ...Infrastructure.Application.Services.csproj | 5 ++ .../CreateTodoItemTests.cs | 22 +++--- ...ucture.Persistence.EFCore.UnitTests.csproj | 4 + .../UnitTest1.cs | 11 --- ...t.Infrastructure.Persistence.EFCore.csproj | 4 +- 13 files changed, 186 insertions(+), 50 deletions(-) create mode 100644 Backend/TodoList.Api/TodoList.Api.UnitTests/ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs delete mode 100644 Backend/TodoList.Api/TodoList.Api.UnitTests/DummyTestShould.cs create mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/ModulesTests/TodoListModuleTests/TodoListServiceTests/CreateTodoItemTests.cs delete mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/UnitTest1.cs delete mode 100644 Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/UnitTest1.cs diff --git a/Backend/TodoList.Api/TodoList.Api.UnitTests/ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs b/Backend/TodoList.Api/TodoList.Api.UnitTests/ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs new file mode 100644 index 00000000..1115555e --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Api.UnitTests/ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs @@ -0,0 +1,67 @@ +using System.Threading; +using System.Threading.Tasks; +using FakeItEasy; +using Microsoft.AspNetCore.Mvc; +using TodoList.Api.Controllers; +using TodoList.Services.Modules.TodoListModule; +using TodoList.Services.Modules.TodoListModule.Models; +using TodoList.Services.Modules.TodoListModule.ViewModels; +using TodoList.Services.Shared; +using Xunit; + +namespace TodoList.Api.UnitTests.ControllerTests.TodoItemsControllerTests +{ + public class PostTodoItemTests + { + [Fact] + public async Task ShouldReturnCreatedItemWhenValidInputPassed() + { + // Arrange + var cancellationToken = CancellationToken.None; + var description = "Test"; + var todoItemModel = new CreateTodoItemModel { Description = description }; + var itemCreated = new GetTodoItemViewModel { Description = description }; + var serviceResult = new ServiceResult(); + serviceResult.ToResourceCreatedResult(itemCreated); + + var fakeService = A.Fake(); + A.CallTo(() => fakeService.CreateTodoItem(todoItemModel, cancellationToken)) + .Returns(Task.FromResult(serviceResult)); + + var controller = new TodoItemsController(fakeService); + + // Act + var actionResult = await controller.PostTodoItem(todoItemModel, cancellationToken); + + // Assert + A.CallTo(() => fakeService.CreateTodoItem(todoItemModel, cancellationToken)).MustHaveHappenedOnceExactly(); + var createdAtActionResult = Assert.IsType(actionResult); + Assert.Equal(nameof(controller.GetTodoItem), createdAtActionResult.ActionName); + Assert.Equal(itemCreated, createdAtActionResult.Value); + } + + [Fact] + public async Task ShoudlReturnBadRequestWhenInvalidInputPassed() + { + // Arrange + var cancellationToken = CancellationToken.None; + CreateTodoItemModel todoItemModel = null; + + var serviceResult = new ServiceResult(); + serviceResult.BadRequestWithMessage("Description is required"); + + var fakeService = A.Fake(); + A.CallTo(() => fakeService.CreateTodoItem(todoItemModel, cancellationToken)) + .Returns(Task.FromResult(serviceResult)); + + var controller = new TodoItemsController(fakeService); + + // Act + var actionResult = await controller.PostTodoItem(todoItemModel, cancellationToken); + + // Assert + var badRequestResult = Assert.IsType(actionResult); + Assert.Equal("Description is required", badRequestResult.Value); + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Api.UnitTests/DummyTestShould.cs b/Backend/TodoList.Api/TodoList.Api.UnitTests/DummyTestShould.cs deleted file mode 100644 index 63656951..00000000 --- a/Backend/TodoList.Api/TodoList.Api.UnitTests/DummyTestShould.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Xunit; - -namespace TodoList.Api.UnitTests -{ - public class DummyTestShould - { - [Fact] - public void Test_Should_TestSomething() - { - } - } -} diff --git a/Backend/TodoList.Api/TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj b/Backend/TodoList.Api/TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj index 5956ac35..283f7733 100644 --- a/Backend/TodoList.Api/TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj +++ b/Backend/TodoList.Api/TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj @@ -7,6 +7,7 @@ + diff --git a/Backend/TodoList.Api/TodoList.Api.sln b/Backend/TodoList.Api/TodoList.Api.sln index 2bf277bc..c56146ef 100644 --- a/Backend/TodoList.Api/TodoList.Api.sln +++ b/Backend/TodoList.Api/TodoList.Api.sln @@ -23,6 +23,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TodoList.Services", "TodoLi EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TodoList.Infrastructure.Application.Services", "TodoList.Infrastructure.Application.Services\TodoList.Infrastructure.Application.Services.csproj", "{D259C88D-A212-4496-AF88-0CDF210C055C}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TodoList.Infrastructure.Persistence.EFCore.UnitTests", "TodoList.Infrastructure.Persistence.EFCore.UnitTests\TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj", "{4E87ADC6-EE79-4793-84AF-A5F4530C73D1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TodoList.Infrastructure.Application.Services.UnitTests", "TodoList.Infrastructure.Application.Services.UnitTests\TodoList.Infrastructure.Application.Services.UnitTests.csproj", "{164F6FFB-637D-4359-93E4-0D5E84A526BF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -53,6 +57,14 @@ Global {D259C88D-A212-4496-AF88-0CDF210C055C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D259C88D-A212-4496-AF88-0CDF210C055C}.Release|Any CPU.ActiveCfg = Release|Any CPU {D259C88D-A212-4496-AF88-0CDF210C055C}.Release|Any CPU.Build.0 = Release|Any CPU + {4E87ADC6-EE79-4793-84AF-A5F4530C73D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E87ADC6-EE79-4793-84AF-A5F4530C73D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E87ADC6-EE79-4793-84AF-A5F4530C73D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E87ADC6-EE79-4793-84AF-A5F4530C73D1}.Release|Any CPU.Build.0 = Release|Any CPU + {164F6FFB-637D-4359-93E4-0D5E84A526BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {164F6FFB-637D-4359-93E4-0D5E84A526BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {164F6FFB-637D-4359-93E4-0D5E84A526BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {164F6FFB-637D-4359-93E4-0D5E84A526BF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -64,6 +76,8 @@ Global {9A26C735-BF26-4E9C-BA1E-6BE5BDCF6A4F} = {739BBC78-14C8-425F-9627-8BB80757A021} {25041BFD-A612-4DDC-BAE9-217ACD3E8188} = {E05B50FF-13BB-495F-9B73-65A5683AE3C2} {D259C88D-A212-4496-AF88-0CDF210C055C} = {739BBC78-14C8-425F-9627-8BB80757A021} + {4E87ADC6-EE79-4793-84AF-A5F4530C73D1} = {81EDD5C8-EAE7-4964-80B5-6B90241C7028} + {164F6FFB-637D-4359-93E4-0D5E84A526BF} = {81EDD5C8-EAE7-4964-80B5-6B90241C7028} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {061F7879-5D14-4C5E-A4A9-782C6FEB1132} diff --git a/Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs b/Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs index 83ced84b..d7d364a4 100644 --- a/Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs +++ b/Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs @@ -15,12 +15,10 @@ namespace TodoList.Api.Controllers [ApiController] public class TodoItemsController : ApiControllerBase { - private readonly ILogger logger; private readonly ITodoListService todoListService; - public TodoItemsController(ILogger logger, ITodoListService todoListService) + public TodoItemsController(ITodoListService todoListService) { - this.logger = logger; this.todoListService = todoListService; } @@ -55,7 +53,7 @@ public async Task PostTodoItem(CreateTodoItemModel todoItem, Canc return CreatedAtAction(nameof(GetTodoItem), new { id = result.Result.Id }, result.Result); } - return BadRequest(result.Errors); + return BadRequest(result.Message); } diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/ModulesTests/TodoListModuleTests/TodoListServiceTests/CreateTodoItemTests.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/ModulesTests/TodoListModuleTests/TodoListServiceTests/CreateTodoItemTests.cs new file mode 100644 index 00000000..b58ee55f --- /dev/null +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/ModulesTests/TodoListModuleTests/TodoListServiceTests/CreateTodoItemTests.cs @@ -0,0 +1,76 @@ +using FakeItEasy; +using TodoList.Domain.Entities; +using TodoList.Domain.Repositories; +using TodoList.Infrastructure.Application.Services.Modules.TodoListModule; +using TodoList.Services.Modules.TodoListModule.Models; +using TodoList.Services.Shared; + +namespace TodoList.Infrastructure.Application.Services.UnitTests.ModulesTests.TodoListModuleTests.TodoListServiceTests +{ + public class CreateTodoItemTests + { + + [Fact] + public async Task ShouldReturnBadRequestWhenEmptyInputPassed() + { + // Arrange + var cancellationToken = CancellationToken.None; + CreateTodoItemModel itemModel = null; + + var fakeRepository = A.Fake(); + var sut = new TodoListService(fakeRepository); + + // Act + var result = await sut.CreateTodoItem(itemModel, cancellationToken); + + // Assert + Assert.NotNull(result); + Assert.Equal(ResultCode.BadRequest, result.ResultCode); + } + + [Fact] + public async Task ShouldReturnInternalServerErrorWhenNothingReturnedFromRepository() + { + // Arrange + var cancellationToken = CancellationToken.None; + var itemModel = new CreateTodoItemModel(); + TodoItem item = null; + + var fakeRepository = A.Fake(); + A.CallTo(() => fakeRepository.CreateTodoItem(A._, cancellationToken)) + .Returns(item); + + var sut = new TodoListService(fakeRepository); + + // Act + var result = await sut.CreateTodoItem(itemModel, cancellationToken); + + // Assert + Assert.NotNull(result); + Assert.Equal(ResultCode.InternalServerError, result.ResultCode); + } + + [Fact] + public async Task ShouldReturnResourceCreatedResultWhenValidInputPassed() + { + // Arrange + var cancellationToken = CancellationToken.None; + var description = "Test"; + var itemModel = new CreateTodoItemModel { Description = description }; + + var fakeRepository = A.Fake(); + A.CallTo(() => fakeRepository.CreateTodoItem(A._, cancellationToken)) + .Returns(Task.FromResult(new TodoItem { Description = description })); + + var service = new TodoListService(fakeRepository); + + // Act + var result = await service.CreateTodoItem(itemModel, cancellationToken); + + // Assert + Assert.NotNull(result); + Assert.NotNull(result.Result); + Assert.Equal(description, result.Result.Description); + } + } +} diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj index 67362634..a3e035d7 100644 --- a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj @@ -10,6 +10,7 @@ + @@ -23,7 +24,7 @@ - + diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/UnitTest1.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/UnitTest1.cs deleted file mode 100644 index 03574eed..00000000 --- a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/UnitTest1.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace TodoList.Infrastructure.Application.Services.UnitTests -{ - public class UnitTest1 - { - [Fact] - public void Test1() - { - - } - } -} \ No newline at end of file diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj index 55eac790..ea2377de 100644 --- a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj @@ -17,4 +17,9 @@ + + + <_Parameter1>TodoList.Infrastructure.Application.Services.UnitTests + + diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs index 70ecc49e..9cf698ba 100644 --- a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs @@ -1,32 +1,34 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using TodoList.Domain.Entities; +using TodoList.Infrastructure.Persistence.EFCore.Repositories; namespace TodoList.Infrastructure.Persistence.EFCore.UnitTests.RepositoriesTests.TodoListRepositoryTests { public class CreateTodoItemTests { [Fact] - public async Task CreateTodoItem_Should_Add_Item_To_Context() + public async Task ShoudlCreateAnItemWhenCalled() { // Arrange var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(databaseName: "CreateTodoItem_Database") + .UseInMemoryDatabase(databaseName: "CreateTodoItemDatabase") .Options; + var id = Guid.NewGuid(); + var description = "Test"; using (var context = new TodoListContext(options)) { var repository = new TodoListRepository(context); - var item = new TodoItem { /* Initialize your item properties */ }; + var item = new TodoItem { Id = id, Description = description }; // Act await repository.CreateTodoItem(item, CancellationToken.None); // Assert - Assert.Single(context.TodoItems); + var items = context.TodoItems; + Assert.Single(items); + Assert.Equal(id, items.First().Id); + Assert.Equal(description, items.First().Description); } } } diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj index c51e0261..c3b0c7f0 100644 --- a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj @@ -23,4 +23,8 @@ + + + + diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/UnitTest1.cs b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/UnitTest1.cs deleted file mode 100644 index 76c933ad..00000000 --- a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/UnitTest1.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace TodoList.Infrastructure.Persistence.EFCore.UnitTests -{ - public class UnitTest1 - { - [Fact] - public void Test1() - { - - } - } -} \ No newline at end of file diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj index 21d34e50..05ed1a50 100644 --- a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj +++ b/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj @@ -17,6 +17,8 @@ - + + <_Parameter1>TodoList.Infrastructure.Persistence.EFCore.UnitTests + From 73972b11ca7a3f5fc88c87e65dee26391b45c315 Mon Sep 17 00:00:00 2001 From: Ravinder Sandhu Date: Mon, 4 Sep 2023 23:37:14 +1200 Subject: [PATCH 3/3] Refactored folders --- Backend/{TodoList.Api => }/.dockerignore | 0 Backend/{TodoList.Api => }/Dockerfile | 0 .../ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs | 0 .../TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj | 0 Backend/{TodoList.Api => }/TodoList.Api.sln | 0 .../Configurations/ApiVersioningAndSwaggerConfiguration.cs | 0 .../{TodoList.Api => }/Configurations/CorsConfiguration.cs | 0 .../Configurations/InfrastructureConfiguration.cs | 0 .../{TodoList.Api => }/Controllers/ApiControllerBase.cs | 0 .../{TodoList.Api => }/Controllers/TodoItemsController.cs | 0 .../TodoList.Api/{TodoList.Api => }/Models/ApiErrorResponse.cs | 0 Backend/TodoList.Api/{TodoList.Api => }/Program.cs | 0 .../{TodoList.Api => }/Properties/launchSettings.json | 0 Backend/TodoList.Api/{TodoList.Api => }/Startup.cs | 0 Backend/TodoList.Api/{TodoList.Api => }/TodoList.Api.csproj | 0 .../TodoList.Api/{TodoList.Api => }/appsettings.Development.json | 0 Backend/TodoList.Api/{TodoList.Api => }/appsettings.json | 0 Backend/{TodoList.Api => }/TodoList.Domain/Entities/TodoItem.cs | 0 .../TodoList.Domain/Repositories/ITodoListRepository.cs | 0 Backend/{TodoList.Api => }/TodoList.Domain/TodoList.Domain.csproj | 0 .../TodoListServiceTests/CreateTodoItemTests.cs | 0 .../TodoList.Infrastructure.Application.Services.UnitTests.csproj | 0 .../Usings.cs | 0 .../Extensions/ServiceCollectionExtensions.cs | 0 .../MappingProfiles/TodoListProfile.cs | 0 .../Modules/TodoListModule/TodoListService.cs | 0 .../TodoList.Infrastructure.Application.Services.csproj | 0 .../TodoListRepositoryTests/CreateTodoItemTests.cs | 0 .../TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj | 0 .../Usings.cs | 0 .../Configurations/TodoItemConfiguration.cs | 0 .../Extensions/ServiceCollectionExtensions.cs | 0 .../Repositories/TodoListRepository.cs | 0 .../TodoList.Infrastructure.Persistence.EFCore.csproj | 0 .../TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs | 0 .../TodoList.Services/Exceptions/TodoItemNotFoundException.cs | 0 .../TodoList.Services/Modules/TodoListModule/ITodoListService.cs | 0 .../Modules/TodoListModule/Models/CreateTodoItemModel.cs | 0 .../Modules/TodoListModule/Models/UpdateTodoItemModel.cs | 0 .../TodoListModule/Validations/CreateTodoItemModelValidator.cs | 0 .../Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs | 0 .../{TodoList.Api => }/TodoList.Services/Shared/ServiceResult.cs | 0 .../{TodoList.Api => }/TodoList.Services/TodoList.Services.csproj | 0 Backend/{TodoList.Api => }/TodoList.Shared/TodoList.Shared.csproj | 0 44 files changed, 0 insertions(+), 0 deletions(-) rename Backend/{TodoList.Api => }/.dockerignore (100%) rename Backend/{TodoList.Api => }/Dockerfile (100%) rename Backend/{TodoList.Api => }/TodoList.Api.UnitTests/ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj (100%) rename Backend/{TodoList.Api => }/TodoList.Api.sln (100%) rename Backend/TodoList.Api/{TodoList.Api => }/Configurations/ApiVersioningAndSwaggerConfiguration.cs (100%) rename Backend/TodoList.Api/{TodoList.Api => }/Configurations/CorsConfiguration.cs (100%) rename Backend/TodoList.Api/{TodoList.Api => }/Configurations/InfrastructureConfiguration.cs (100%) rename Backend/TodoList.Api/{TodoList.Api => }/Controllers/ApiControllerBase.cs (100%) rename Backend/TodoList.Api/{TodoList.Api => }/Controllers/TodoItemsController.cs (100%) rename Backend/TodoList.Api/{TodoList.Api => }/Models/ApiErrorResponse.cs (100%) rename Backend/TodoList.Api/{TodoList.Api => }/Program.cs (100%) rename Backend/TodoList.Api/{TodoList.Api => }/Properties/launchSettings.json (100%) rename Backend/TodoList.Api/{TodoList.Api => }/Startup.cs (100%) rename Backend/TodoList.Api/{TodoList.Api => }/TodoList.Api.csproj (100%) rename Backend/TodoList.Api/{TodoList.Api => }/appsettings.Development.json (100%) rename Backend/TodoList.Api/{TodoList.Api => }/appsettings.json (100%) rename Backend/{TodoList.Api => }/TodoList.Domain/Entities/TodoItem.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Domain/Repositories/ITodoListRepository.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Domain/TodoList.Domain.csproj (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Application.Services.UnitTests/ModulesTests/TodoListModuleTests/TodoListServiceTests/CreateTodoItemTests.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Application.Services.UnitTests/Usings.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Application.Services/Extensions/ServiceCollectionExtensions.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Application.Services/MappingProfiles/TodoListProfile.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Application.Services/Modules/TodoListModule/TodoListService.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Persistence.EFCore.UnitTests/Usings.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Persistence.EFCore/Configurations/TodoItemConfiguration.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Persistence.EFCore/Repositories/TodoListRepository.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj (100%) rename Backend/{TodoList.Api => }/TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Services/Exceptions/TodoItemNotFoundException.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Services/Modules/TodoListModule/ITodoListService.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Services/Modules/TodoListModule/Models/CreateTodoItemModel.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Services/Modules/TodoListModule/Models/UpdateTodoItemModel.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Services/Modules/TodoListModule/Validations/CreateTodoItemModelValidator.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Services/Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Services/Shared/ServiceResult.cs (100%) rename Backend/{TodoList.Api => }/TodoList.Services/TodoList.Services.csproj (100%) rename Backend/{TodoList.Api => }/TodoList.Shared/TodoList.Shared.csproj (100%) diff --git a/Backend/TodoList.Api/.dockerignore b/Backend/.dockerignore similarity index 100% rename from Backend/TodoList.Api/.dockerignore rename to Backend/.dockerignore diff --git a/Backend/TodoList.Api/Dockerfile b/Backend/Dockerfile similarity index 100% rename from Backend/TodoList.Api/Dockerfile rename to Backend/Dockerfile diff --git a/Backend/TodoList.Api/TodoList.Api.UnitTests/ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs b/Backend/TodoList.Api.UnitTests/ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Api.UnitTests/ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs rename to Backend/TodoList.Api.UnitTests/ControllerTests/TodoItemsControllerTests/PostTodoItemTests.cs diff --git a/Backend/TodoList.Api/TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj b/Backend/TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj similarity index 100% rename from Backend/TodoList.Api/TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj rename to Backend/TodoList.Api.UnitTests/TodoList.Api.UnitTests.csproj diff --git a/Backend/TodoList.Api/TodoList.Api.sln b/Backend/TodoList.Api.sln similarity index 100% rename from Backend/TodoList.Api/TodoList.Api.sln rename to Backend/TodoList.Api.sln diff --git a/Backend/TodoList.Api/TodoList.Api/Configurations/ApiVersioningAndSwaggerConfiguration.cs b/Backend/TodoList.Api/Configurations/ApiVersioningAndSwaggerConfiguration.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/Configurations/ApiVersioningAndSwaggerConfiguration.cs rename to Backend/TodoList.Api/Configurations/ApiVersioningAndSwaggerConfiguration.cs diff --git a/Backend/TodoList.Api/TodoList.Api/Configurations/CorsConfiguration.cs b/Backend/TodoList.Api/Configurations/CorsConfiguration.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/Configurations/CorsConfiguration.cs rename to Backend/TodoList.Api/Configurations/CorsConfiguration.cs diff --git a/Backend/TodoList.Api/TodoList.Api/Configurations/InfrastructureConfiguration.cs b/Backend/TodoList.Api/Configurations/InfrastructureConfiguration.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/Configurations/InfrastructureConfiguration.cs rename to Backend/TodoList.Api/Configurations/InfrastructureConfiguration.cs diff --git a/Backend/TodoList.Api/TodoList.Api/Controllers/ApiControllerBase.cs b/Backend/TodoList.Api/Controllers/ApiControllerBase.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/Controllers/ApiControllerBase.cs rename to Backend/TodoList.Api/Controllers/ApiControllerBase.cs diff --git a/Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs b/Backend/TodoList.Api/Controllers/TodoItemsController.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/Controllers/TodoItemsController.cs rename to Backend/TodoList.Api/Controllers/TodoItemsController.cs diff --git a/Backend/TodoList.Api/TodoList.Api/Models/ApiErrorResponse.cs b/Backend/TodoList.Api/Models/ApiErrorResponse.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/Models/ApiErrorResponse.cs rename to Backend/TodoList.Api/Models/ApiErrorResponse.cs diff --git a/Backend/TodoList.Api/TodoList.Api/Program.cs b/Backend/TodoList.Api/Program.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/Program.cs rename to Backend/TodoList.Api/Program.cs diff --git a/Backend/TodoList.Api/TodoList.Api/Properties/launchSettings.json b/Backend/TodoList.Api/Properties/launchSettings.json similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/Properties/launchSettings.json rename to Backend/TodoList.Api/Properties/launchSettings.json diff --git a/Backend/TodoList.Api/TodoList.Api/Startup.cs b/Backend/TodoList.Api/Startup.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/Startup.cs rename to Backend/TodoList.Api/Startup.cs diff --git a/Backend/TodoList.Api/TodoList.Api/TodoList.Api.csproj b/Backend/TodoList.Api/TodoList.Api.csproj similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/TodoList.Api.csproj rename to Backend/TodoList.Api/TodoList.Api.csproj diff --git a/Backend/TodoList.Api/TodoList.Api/appsettings.Development.json b/Backend/TodoList.Api/appsettings.Development.json similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/appsettings.Development.json rename to Backend/TodoList.Api/appsettings.Development.json diff --git a/Backend/TodoList.Api/TodoList.Api/appsettings.json b/Backend/TodoList.Api/appsettings.json similarity index 100% rename from Backend/TodoList.Api/TodoList.Api/appsettings.json rename to Backend/TodoList.Api/appsettings.json diff --git a/Backend/TodoList.Api/TodoList.Domain/Entities/TodoItem.cs b/Backend/TodoList.Domain/Entities/TodoItem.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Domain/Entities/TodoItem.cs rename to Backend/TodoList.Domain/Entities/TodoItem.cs diff --git a/Backend/TodoList.Api/TodoList.Domain/Repositories/ITodoListRepository.cs b/Backend/TodoList.Domain/Repositories/ITodoListRepository.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Domain/Repositories/ITodoListRepository.cs rename to Backend/TodoList.Domain/Repositories/ITodoListRepository.cs diff --git a/Backend/TodoList.Api/TodoList.Domain/TodoList.Domain.csproj b/Backend/TodoList.Domain/TodoList.Domain.csproj similarity index 100% rename from Backend/TodoList.Api/TodoList.Domain/TodoList.Domain.csproj rename to Backend/TodoList.Domain/TodoList.Domain.csproj diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/ModulesTests/TodoListModuleTests/TodoListServiceTests/CreateTodoItemTests.cs b/Backend/TodoList.Infrastructure.Application.Services.UnitTests/ModulesTests/TodoListModuleTests/TodoListServiceTests/CreateTodoItemTests.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/ModulesTests/TodoListModuleTests/TodoListServiceTests/CreateTodoItemTests.cs rename to Backend/TodoList.Infrastructure.Application.Services.UnitTests/ModulesTests/TodoListModuleTests/TodoListServiceTests/CreateTodoItemTests.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj b/Backend/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj rename to Backend/TodoList.Infrastructure.Application.Services.UnitTests/TodoList.Infrastructure.Application.Services.UnitTests.csproj diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/Usings.cs b/Backend/TodoList.Infrastructure.Application.Services.UnitTests/Usings.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Application.Services.UnitTests/Usings.cs rename to Backend/TodoList.Infrastructure.Application.Services.UnitTests/Usings.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Extensions/ServiceCollectionExtensions.cs b/Backend/TodoList.Infrastructure.Application.Services/Extensions/ServiceCollectionExtensions.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Extensions/ServiceCollectionExtensions.cs rename to Backend/TodoList.Infrastructure.Application.Services/Extensions/ServiceCollectionExtensions.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/MappingProfiles/TodoListProfile.cs b/Backend/TodoList.Infrastructure.Application.Services/MappingProfiles/TodoListProfile.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/MappingProfiles/TodoListProfile.cs rename to Backend/TodoList.Infrastructure.Application.Services/MappingProfiles/TodoListProfile.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Modules/TodoListModule/TodoListService.cs b/Backend/TodoList.Infrastructure.Application.Services/Modules/TodoListModule/TodoListService.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/Modules/TodoListModule/TodoListService.cs rename to Backend/TodoList.Infrastructure.Application.Services/Modules/TodoListModule/TodoListService.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj b/Backend/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj rename to Backend/TodoList.Infrastructure.Application.Services/TodoList.Infrastructure.Application.Services.csproj diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs b/Backend/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs rename to Backend/TodoList.Infrastructure.Persistence.EFCore.UnitTests/RepositoriesTests/TodoListRepositoryTests/CreateTodoItemTests.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj b/Backend/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj rename to Backend/TodoList.Infrastructure.Persistence.EFCore.UnitTests/TodoList.Infrastructure.Persistence.EFCore.UnitTests.csproj diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/Usings.cs b/Backend/TodoList.Infrastructure.Persistence.EFCore.UnitTests/Usings.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore.UnitTests/Usings.cs rename to Backend/TodoList.Infrastructure.Persistence.EFCore.UnitTests/Usings.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Configurations/TodoItemConfiguration.cs b/Backend/TodoList.Infrastructure.Persistence.EFCore/Configurations/TodoItemConfiguration.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Configurations/TodoItemConfiguration.cs rename to Backend/TodoList.Infrastructure.Persistence.EFCore/Configurations/TodoItemConfiguration.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs b/Backend/TodoList.Infrastructure.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs rename to Backend/TodoList.Infrastructure.Persistence.EFCore/Extensions/ServiceCollectionExtensions.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Repositories/TodoListRepository.cs b/Backend/TodoList.Infrastructure.Persistence.EFCore/Repositories/TodoListRepository.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/Repositories/TodoListRepository.cs rename to Backend/TodoList.Infrastructure.Persistence.EFCore/Repositories/TodoListRepository.cs diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj b/Backend/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj rename to Backend/TodoList.Infrastructure.Persistence.EFCore/TodoList.Infrastructure.Persistence.EFCore.csproj diff --git a/Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs b/Backend/TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs rename to Backend/TodoList.Infrastructure.Persistence.EFCore/TodoListContext.cs diff --git a/Backend/TodoList.Api/TodoList.Services/Exceptions/TodoItemNotFoundException.cs b/Backend/TodoList.Services/Exceptions/TodoItemNotFoundException.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Services/Exceptions/TodoItemNotFoundException.cs rename to Backend/TodoList.Services/Exceptions/TodoItemNotFoundException.cs diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ITodoListService.cs b/Backend/TodoList.Services/Modules/TodoListModule/ITodoListService.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ITodoListService.cs rename to Backend/TodoList.Services/Modules/TodoListModule/ITodoListService.cs diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/CreateTodoItemModel.cs b/Backend/TodoList.Services/Modules/TodoListModule/Models/CreateTodoItemModel.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/CreateTodoItemModel.cs rename to Backend/TodoList.Services/Modules/TodoListModule/Models/CreateTodoItemModel.cs diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/UpdateTodoItemModel.cs b/Backend/TodoList.Services/Modules/TodoListModule/Models/UpdateTodoItemModel.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Models/UpdateTodoItemModel.cs rename to Backend/TodoList.Services/Modules/TodoListModule/Models/UpdateTodoItemModel.cs diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Validations/CreateTodoItemModelValidator.cs b/Backend/TodoList.Services/Modules/TodoListModule/Validations/CreateTodoItemModelValidator.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/Validations/CreateTodoItemModelValidator.cs rename to Backend/TodoList.Services/Modules/TodoListModule/Validations/CreateTodoItemModelValidator.cs diff --git a/Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs b/Backend/TodoList.Services/Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Services/Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs rename to Backend/TodoList.Services/Modules/TodoListModule/ViewModels/GetTodoItemViewModel.cs diff --git a/Backend/TodoList.Api/TodoList.Services/Shared/ServiceResult.cs b/Backend/TodoList.Services/Shared/ServiceResult.cs similarity index 100% rename from Backend/TodoList.Api/TodoList.Services/Shared/ServiceResult.cs rename to Backend/TodoList.Services/Shared/ServiceResult.cs diff --git a/Backend/TodoList.Api/TodoList.Services/TodoList.Services.csproj b/Backend/TodoList.Services/TodoList.Services.csproj similarity index 100% rename from Backend/TodoList.Api/TodoList.Services/TodoList.Services.csproj rename to Backend/TodoList.Services/TodoList.Services.csproj diff --git a/Backend/TodoList.Api/TodoList.Shared/TodoList.Shared.csproj b/Backend/TodoList.Shared/TodoList.Shared.csproj similarity index 100% rename from Backend/TodoList.Api/TodoList.Shared/TodoList.Shared.csproj rename to Backend/TodoList.Shared/TodoList.Shared.csproj