merge with EF

WORK-WebAPI
David D'ALMEIDA 1 year ago
parent cc255de979
commit 0bbf0f9bb9

@ -0,0 +1,49 @@
using Dto;
using Model;
namespace ApiMappeur;
public static class ActivityMappeur
{
/*public static ActivityDto ToDto(this Activity activity)
{
return new ActivityDto
{
Id = activity.Id,
Name = activity.Name,
Type = activity.Type,
Date = activity.Date,
Duration = activity.EndTime - activity.StartTime,
Distance = activity.Distance,
Elevation = activity.Elevation,
AverageSpeed = activity.AverageSpeed,
AverageHeartRate = activity.AverageHeartRate,
Calories = activity.Calories,
Description = activity.Description,
Gpx = activity.Gpx,
Image = activity.Image,
AthleteId = activity.AthleteId
};
}
public static Activity ToModel(this ActivityDto activityDto)
{
return new Activity
{
Id = activityDto.Id,
Name = activityDto.Name,
Type = activityDto.Type,
Date = activityDto.Date,
Duration = activityDto.Duration,
Distance = activityDto.Distance,
Elevation = activityDto.Elevation,
AverageSpeed = activityDto.AverageSpeed,
AverageHeartRate = activityDto.AverageHeartRate,
Calories = activityDto.Calories,
Description = activityDto.Description,
Gpx = activityDto.Gpx,
Image = activityDto.Image,
AthleteId = activityDto.AthleteId
};
}*/
}

@ -33,6 +33,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiMappeur", "ApiMappeur\Ap
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StubAPI", "StubAPI\StubAPI.csproj", "{B9679DCA-F4C8-45BE-A849-44E2BA814083}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestApi", "Tests\TestsAPI\UnitTestApi\UnitTestApi.csproj", "{E515C8B6-6282-4D8B-8523-7B3A13E4AF58}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -94,6 +96,10 @@ Global
{B9679DCA-F4C8-45BE-A849-44E2BA814083}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9679DCA-F4C8-45BE-A849-44E2BA814083}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9679DCA-F4C8-45BE-A849-44E2BA814083}.Release|Any CPU.Build.0 = Release|Any CPU
{E515C8B6-6282-4D8B-8523-7B3A13E4AF58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E515C8B6-6282-4D8B-8523-7B3A13E4AF58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E515C8B6-6282-4D8B-8523-7B3A13E4AF58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E515C8B6-6282-4D8B-8523-7B3A13E4AF58}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{477D2129-A6C9-4FF8-8BE9-5E9E8E5282F8} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18}
@ -101,5 +107,6 @@ Global
{30FC2BE9-7397-445A-84AD-043CE70F4281} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18}
{9E4D3AC5-E6CA-4753-BD96-BF5EE793931A} = {30FC2BE9-7397-445A-84AD-043CE70F4281}
{44C367DC-5FE0-4CF2-9E76-A0282E931853} = {30FC2BE9-7397-445A-84AD-043CE70F4281}
{E515C8B6-6282-4D8B-8523-7B3A13E4AF58} = {30FC2BE9-7397-445A-84AD-043CE70F4281}
EndGlobalSection
EndGlobal

@ -1,24 +1,26 @@
using ApiMappeur;
using Dto;
using HeartTrackAPI.Request;
using HeartTrackAPI.Responce;
using Microsoft.AspNetCore.Mvc;
using Shared;
using Model;
/*
using Model.Repository;
namespace HeartTrackAPI.Controllers;
[ApiController]
[Route("api/activities")]
public class ActivityController : Controller
{
private readonly IActivityService _activityService;
private readonly IActivityRepository _activityService;
private readonly ILogger<ActivityController> _logger;
public ActivityController(IActivityService activityService, ILogger<ActivityController> logger)
public ActivityController(IActivityRepository activityService, ILogger<ActivityController> logger)
{
_activityService = activityService;
_logger = logger;
}
/*
[HttpGet]
[ProducesResponseType(typeof(PageResponse<ActivityDto>), 200)]
[ProducesResponseType(400)]
@ -34,9 +36,8 @@ public class ActivityController : Controller
return BadRequest("To many object is asked the max is : " + totalCount);
}
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetActivities), pageRequest);
// request.OrderingPropertyName
var activities = await _activityService.GetActivities(pageRequest.Index, pageRequest.Count, ActivityOrderCriteria.None, pageRequest.Descending ?? false);
var pageResponse = new PageResponse<UserDto>(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto()));
var pageResponse = new PageResponse<ActivityDto>(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto()));
return Ok(pageResponse);
}
catch (Exception e)
@ -45,7 +46,7 @@ public class ActivityController : Controller
return StatusCode(500);
}
}
/*
[HttpGet("{id}")]
public async Task<ActionResult<ActivityDto>> GetActivity(int id)
{
@ -94,5 +95,5 @@ public class ActivityController : Controller
return NotFound();
}
return NoContent();
}
}*/
}

@ -4,6 +4,8 @@ using HeartTrackAPI.Request;
using HeartTrackAPI.Responce;
using Microsoft.AspNetCore.Mvc;
using Model;
using Model.Manager;
using Model.Repository;
using Shared;
namespace HeartTrackAPI.Controllers;
@ -13,18 +15,18 @@ namespace HeartTrackAPI.Controllers;
public class UsersController : Controller
{
private readonly ILogger<UsersController> _logger;
private readonly IUserService _userService;
public UsersController(ILogger<UsersController> logger, IUserService usersService)
private readonly IUserRepository _userService;
public UsersController(ILogger<UsersController> logger, IDataManager dataManager)
{
_logger = logger;
_userService = usersService;
_userService = dataManager.UserRepository;
}
[HttpGet]
[ProducesResponseType(typeof(PageResponse<UserDto>), 200)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<ActionResult<PageResponse<UserDto>>> GetAllAthletes([FromQuery] PageRequest request)
public async Task<ActionResult<PageResponse<UserDto>>> Get([FromQuery] PageRequest request)
{
try
{
@ -35,7 +37,7 @@ public class UsersController : Controller
return BadRequest("To many object is asked the max is : " + totalCount);
}
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetAllAthletes), null);
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Get), null);
var athletes = await _userService.GetUsers(request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false);
var pageResponse = new PageResponse<UserDto>(request.Index, request.Count, totalCount, athletes.Select(a => a.ToDto()));
@ -52,12 +54,12 @@ public class UsersController : Controller
[ProducesResponseType(typeof(UserDto), 200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task<ActionResult<UserDto>> GetAthleteById(int id)
public async Task<ActionResult<UserDto>> GetById(int id)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetAthleteById), id);
var athlete = await _userService.GetUserByIdAsync(id);
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetById), id);
var athlete = await _userService.GetItemById(id);
if (athlete == null)
{
_logger.LogError("Athlete with id {id} not found", id);
@ -76,11 +78,11 @@ public class UsersController : Controller
[HttpGet("count")]
[ProducesResponseType(typeof(int), 200)]
[ProducesResponseType(500)]
public async Task<ActionResult<int>> GetNbUsers()
public async Task<ActionResult<int>> Count()
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetNbUsers), null);
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Count), null);
var nbUsers = await _userService.GetNbItems();
return Ok(nbUsers);
}
@ -95,18 +97,18 @@ public class UsersController : Controller
[ProducesResponseType(typeof(UserDto), 200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task<ActionResult<UserDto>> UpdateUser(int id, [FromBody] UserDto user)
public async Task<ActionResult<UserDto>> Update(int id, [FromBody] UserDto user)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(UpdateUser), user,id);
var athlete = await _userService.GetUserByIdAsync(id);
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Update), user,id);
var athlete = await _userService.GetItemById(id);
if (athlete == null)
{
_logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found");
}
var updatedAthlete = await _userService.UpdateUser(id, user.ToModel());
var updatedAthlete = await _userService.UpdateItem(id, user.ToModel());
if(updatedAthlete == null)
{
_logger.LogError("Error while updating athlete with id {id}", id);
@ -126,20 +128,20 @@ public class UsersController : Controller
[ProducesResponseType(200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task<IActionResult> DeleteUser(int id)
public async Task<IActionResult> Delete(int id)
{
try
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(DeleteUser), null,id);
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Delete), null,id);
var athlete = await _userService.GetUserByIdAsync(id);
var athlete = await _userService.GetItemById(id);
if (athlete == null)
{
_logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found");
}
var isDeleted = await _userService.DeleteUser(id);
var isDeleted = await _userService.DeleteItem(id);
if(!isDeleted)
{
_logger.LogError("Error while deleting athlete with id {id}", id);

@ -1,4 +1,6 @@
using Model;
using Model.Manager;
using Model.Repository;
using StubAPI;
var builder = WebApplication.CreateBuilder(args);
@ -8,7 +10,7 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddControllers();
builder.Services.AddSingleton<IUserService, UserService>();
builder.Services.AddSingleton<IDataManager, StubData>();
var app = builder.Build();
// Configure the HTTP request pipeline.

@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations;
namespace Model;
public class Activity
{
public int IdActivity { get; private set; }
public int Id { get; set; }
public string Type { get; set; }
public DateTime Date { get; set; }
public DateTime StartTime { get; set; }
@ -36,7 +36,7 @@ public class Activity
int effort, float variability, float variance, float standardDeviation,
float average, int maximum, int minimum, float averageTemperature, bool hasAutoPause)
{
IdActivity = idActivity;
Id = idActivity;
Type = type;
Date = date;
StartTime = startTime;
@ -55,7 +55,7 @@ public class Activity
public override string ToString()
{
return $"Activity #{IdActivity}: {Type} on {Date:d/M/yyyy} from {StartTime:HH:mm:ss} to {EndTime:HH:mm:ss}" +
return $"Activity #{Id}: {Type} on {Date:d/M/yyyy} from {StartTime:HH:mm:ss} to {EndTime:HH:mm:ss}" +
$" with an effort of {Effort}/5 and an average temperature of {AverageTemperature}°C" +
$" and a heart rate variability of {Variability} bpm" +
$" and a variance of {Variance} bpm" +

@ -1,8 +1,10 @@
namespace ApiMappeur;
using Model.Repository;
namespace Model;
public static class EnumMappeur
{
public static Shared.AthleteOrderCriteria ToEnum(this string value)
public static Shared.AthleteOrderCriteria ToEnum(this IUserRepository repository, string? value)
{
return value switch
{

@ -1,15 +0,0 @@
using Dto;
using Model;
using Shared;
namespace Model;
public interface IUserService
{
public Task<IEnumerable<User>> GetUsers(int index, int count, AthleteOrderCriteria criteria , bool descending = false);
public Task<User?> GetUserByIdAsync(int id);
public Task<User?> AddUser(User athlete);
public Task<User?> UpdateUser(int id, User user);
public Task<bool> DeleteUser(int id);
public Task<int> GetNbItems();
}

@ -0,0 +1,9 @@
using Model.Repository;
namespace Model.Manager;
public interface IDataManager
{
IUserRepository UserRepository { get; }
IActivityRepository ActivityRepository { get; }
}

@ -1,8 +1,8 @@
using Shared;
namespace Model;
namespace Model.Repository;
public interface IActivityService
public interface IActivityRepository
{
public Task<IEnumerable<Activity>> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false);
public Task<Activity?> GetActivityByIdAsync(int id);

@ -0,0 +1,8 @@
using Shared;
namespace Model.Repository;
public interface IUserRepository : IGenericRepository<User>
{
public Task<IEnumerable<User>> GetUsers(int index, int count, AthleteOrderCriteria? criteria , bool descending = false);
}

@ -0,0 +1,12 @@
namespace Shared;
public interface IGenericRepository<T>
{
Task<IEnumerable<T>> GetItems(int index, int count, string? orderingProperty = null, bool descending = false);
Task<T?> GetItemById(int id);
Task<T?> UpdateItem(int oldItem, T newItem);
Task<T?> AddItem(T item);
Task<bool> DeleteItem(int item);
Task<int> GetNbItems();
}

@ -0,0 +1,38 @@
using Model;
using Model.Repository;
using Shared;
namespace StubAPI;
public class ActivityService: IActivityRepository
{
public async Task<IEnumerable<Activity>> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false)
{
throw new NotImplementedException();
}
public async Task<Activity?> GetActivityByIdAsync(int id)
{
throw new NotImplementedException();
}
public async Task<Activity?> AddActivity(Activity activity)
{
throw new NotImplementedException();
}
public async Task<Activity?> UpdateActivity(int id, Activity activity)
{
throw new NotImplementedException();
}
public async Task<bool> DeleteActivity(int id)
{
throw new NotImplementedException();
}
public async Task<int> GetNbItems()
{
throw new NotImplementedException();
}
}

@ -1,9 +1,10 @@
using Model;
using Model.Repository;
using Shared;
namespace StubAPI;
public class UserService : IUserService
public class UserService : IUserRepository
{
private List<User> athletes =
[
@ -30,28 +31,34 @@ public class UserService : IUserService
];
public async Task<IEnumerable<User>> GetUsers(int index, int count, AthleteOrderCriteria criteria,
bool descending = false)
=> athletes.GetItemsWithFilterAndOrdering(c=>true,index, count, criteria != AthleteOrderCriteria.None ? criteria: null , descending);
public async Task<IEnumerable<User>> GetUsers(int index, int count, AthleteOrderCriteria? orderingProperty = null, bool descending = false)
=> athletes.GetItemsWithFilterAndOrdering(c=>true,index, count,orderingProperty != AthleteOrderCriteria.None ? orderingProperty: null , descending);
public async Task<User?> GetUserByIdAsync(int id)
public async Task<IEnumerable<User>> GetItems(int index, int count, string? orderingProperty = null,
bool descending = false)
{
return await Task.FromResult(athletes.FirstOrDefault(s => s.Id == id));
return await this.GetUsers(index, count, this.ToEnum(orderingProperty), descending);
}
public async Task<User?> AddUser(User athlete)
public async Task<User?> GetItemById(int id)
=>await Task.FromResult(athletes.FirstOrDefault(s => s.Id == id));
public async Task<User?> AddItem(User user)
{
return await athletes.AddItem(athlete);
return await athletes.AddItem(user);
}
public async Task<User?> UpdateUser(int id, User user)
public async Task<User?> UpdateItem(int id, User user)
{
var oldUser = athletes.FirstOrDefault(s => s.Id == id);
if (oldUser == null) return null;
return await athletes.UpdateItem(oldUser, user);
}
public async Task<bool> DeleteUser(int id)
public async Task<bool> DeleteItem(int id)
{
var user = athletes.FirstOrDefault(s => s.Id == id);
if (user == null) return false;

@ -0,0 +1,16 @@
using Model.Manager;
using Model.Repository;
namespace StubAPI;
public class StubData : IDataManager
{
public IUserRepository UserRepository { get; }
public IActivityRepository ActivityRepository { get; }
public StubData()
{
UserRepository = new UserService();
ActivityRepository = new ActivityService();
}
}

@ -0,0 +1 @@
global using Microsoft.VisualStudio.TestTools.UnitTesting;

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4"/>
<PackageReference Include="MSTest.TestFramework" Version="3.0.4"/>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\HeartTrackAPI\HeartTrackAPI.csproj" />
<ProjectReference Include="..\..\Model\Model.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
<ProjectReference Include="..\..\StubAPI\StubAPI.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,5 @@
namespace TestConsoleApi;
public class Class1
{
}

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -0,0 +1,12 @@
namespace ClientTests;
public class HttpClientManager
{
protected readonly HttpClient _httpClient;
public HttpClientManager(HttpClient httpClient)
{
_httpClient = httpClient;
_httpClient.BaseAddress = new Uri("https://localhost:7252");
}
}

@ -0,0 +1 @@
global using Microsoft.VisualStudio.TestTools.UnitTesting;

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4"/>
<PackageReference Include="MSTest.TestFramework" Version="3.0.4"/>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\HeartTrackAPI\HeartTrackAPI.csproj" />
<ProjectReference Include="..\..\..\Model\Model.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,124 @@
using Dto;
using HeartTrackAPI.Controllers;
using HeartTrackAPI.Request;
using HeartTrackAPI.Responce;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging.Abstractions;
using Model.Manager;
using Model.Repository;
using StubAPI;
namespace UnitTestApi;
[TestClass]
public class UserControllerTest
{
private readonly IDataManager StubDataManager;
private readonly UsersController _usersController;
public UserControllerTest()
{
StubDataManager = new StubData();
_usersController = new UsersController(new NullLogger<UsersController>(), StubDataManager);
}
[TestMethod]
public void Get_ReturnsPageResponse_WhenRequestIsValid()
{
// Arrange
var request = new PageRequest
{
Index = 0,
Count = 10,
OrderingPropertyName = "Id",
Descending = false
};
// Act
var result = _usersController.Get(request).Result as OkObjectResult;
// Assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result.Value, typeof(PageResponse<UserDto>));
}
/*
[TestMethod]
public void GetById_ReturnsUserDto_WhenRequestIsValid()
{
// Arrange
var id = 1;
// Act
var result = _usersController.GetById(id).Result as OkObjectResult;
// Assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result.Value, typeof(UserDto));
}
[TestMethod]
public void GetById_Returns404_WhenIdIsInvalid()
{
// Arrange
var id = 0;
// Act
var result = _usersController.GetById(id).Result as NotFoundResult;
// Assert
Assert.IsNotNull(result);
}
[TestMethod]
public void GetById_Returns500_WheExceptionIsThrown()
{
// Arrange
var id = 0;
// Act
var result = _usersController.GetById(id).Result as StatusCodeResult;
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(500, result.StatusCode);
}
[TestMethod]
public void Count_ReturnsInt_WhenRequestIsValid()
{
// Act
var result = _usersController.Count().Result as OkObjectResult;
// Assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result.Value, typeof(int));
}
[TestMethod]
public void Count_Returns500_WheExceptionIsThrown()
{
// Act
var result = _usersController.Count().Result as StatusCodeResult;
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(500, result.StatusCode);
}
[TestMethod]
public void Update_ReturnsUserDto_WhenRequestIsValid()
{
// Arrange
var id = 1;
var user = new UserDto
{
Id = 1,
FirstName = "John",
LastName = "Doe",
Email = "toto@eoeo.fr",
};
}*/
}
Loading…
Cancel
Save