update Ci, add test and add db
continuous-integration/drone/push Build encountered an error Details

merging_EF-API
David D'ALMEIDA 1 year ago
parent 3994b52ca9
commit 6a32c2cbfe

@ -15,6 +15,14 @@ steps:
- dotnet build HeartTrack.sln -c Release --no-restore - dotnet build HeartTrack.sln -c Release --no-restore
- dotnet publish HeartTrack.sln -c Release --no-restore -o CI_PROJECT_DIR/build/release - dotnet publish HeartTrack.sln -c Release --no-restore -o CI_PROJECT_DIR/build/release
- name: tests
image: mcr.microsoft.com/dotnet/sdk:8.0
commands:
- cd src/
- dotnet restore HeartTrack.sln
- dotnet test HeartTrack.sln --no-restore
depends_on: [build]
- name: code-analysis - name: code-analysis
image: hub.codefirst.iut.uca.fr/marc.chevaldonne/codefirst-dronesonarplugin-dotnet8 image: hub.codefirst.iut.uca.fr/marc.chevaldonne/codefirst-dronesonarplugin-dotnet8
secrets: [ SECRET_SONAR_LOGIN ] secrets: [ SECRET_SONAR_LOGIN ]
@ -33,8 +41,54 @@ steps:
- reportgenerator -reports:"**/coverage.cobertura.xml" -reporttypes:SonarQube -targetdir:"coveragereport" - reportgenerator -reports:"**/coverage.cobertura.xml" -reporttypes:SonarQube -targetdir:"coveragereport"
- dotnet publish HeartTrack.sln -c Release --no-restore -o $CI_PROJECT_DIR/build/release - dotnet publish HeartTrack.sln -c Release --no-restore -o $CI_PROJECT_DIR/build/release
- dotnet sonarscanner end /d:sonar.login=$${PLUGIN_SONAR_TOKEN} - dotnet sonarscanner end /d:sonar.login=$${PLUGIN_SONAR_TOKEN}
depends_on: [ tests ]
- name: swagger
image: mcr.microsoft.com/dotnet/sdk:8.0
failure: ignore
volumes:
- name: docs
path: /docs
commands:
- cd src/
- dotnet restore HeartTrack.sln
- cd HeartTrack
- dotnet new tool-manifest
- dotnet tool install -g --version 6.5.0 Swashbuckle.AspNetCore.Cli
- cd ../
- dotnet build HeartTrack.sln -c Release --no-restore
- dotnet publish HeartTrack.sln -c Release --no-restore -o CI_PROJECT_DIR/build/release
- export PATH="$PATH:/root/.dotnet/tools"
- swagger tofile --output /docs/swagger.json HeartTrack/bin/Release/net8.0/HeartTrack.dll v1
- name: generate-and-deploy-docs
image: hub.codefirst.iut.uca.fr/maxime.batista/codefirst-docdeployer
failure: ignore
commands:
- /entrypoint.sh -l docs/doxygen -t doxygen
when:
event:
- push
depends_on: [ build ] depends_on: [ build ]
volumes:
- name: docs
temp: {}
---
kind: pipeline
type: docker
name: HeartTrack-API-CD
trigger:
event:
- push
steps:
- name: hadolint
image: hadolint/hadolint:latest-alpine
commands:
- cd src/HeartTrackAPI
- hadolint Dockerfile
- name: docker-build-and-push - name: docker-build-and-push
image: plugins/docker image: plugins/docker
settings: settings:
@ -48,23 +102,64 @@ steps:
from_secret: SECRET_REGISTRY_PASSWORD from_secret: SECRET_REGISTRY_PASSWORD
depends_on: [ build ] depends_on: [ build ]
- name: deploy-container # database container stub
- name: deploy-container-stub
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
environment: environment:
CODEFIRST_CLIENTDRONE_ENV_TYPE: STUB
IMAGENAME: hub.codefirst.iut.uca.fr/david.d_almeida/api:latest IMAGENAME: hub.codefirst.iut.uca.fr/david.d_almeida/api:latest
CONTAINERNAME: api CONTAINERNAME: heart_stub
CODEFIRST_CLIENTDRONE_ENV_PORT: 8080
ADMINS: davidd_almeida,kevinmonteiro,antoineperederii,paullevrault,antoinepinagot,nicolas.raymond
COMMAND: create COMMAND: create
OVERWRITE: true OVERWRITE: true
depends_on: [ docker-build-and-push ] depends_on: [ docker-build-and-push ]
- name: generate-and-deploy-docs # - name: deploy-container
image: hub.codefirst.iut.uca.fr/maxime.batista/codefirst-docdeployer # image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
failure: ignore # environment:
commands: # IMAGENAME: hub.codefirst.iut.uca.fr/david.d_almeida/api:latest
- /entrypoint.sh -l docs/doxygen -t doxygen # CONTAINERNAME: heart_api
when: # CODEFIRST_CLIENTDRONE_ENV_TYPE: API
event: # CODEFIRST_CLIENTDRONE_ENV_PORT: 8080
- push # ADMINS: davidd_almeida,kevinmonteiro,antoineperederii,paullevrault,antoinepinagot,nicolas.raymond
depends_on: [ build ] # COMMAND: create
# OVERWRITE: true
# depends_on: [ docker-build-and-push, deploy-container-stub ]
# database container deployment
- name: deploy-container-mysql
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
environment:
IMAGENAME: mariadb:10
CONTAINERNAME: mysql
COMMAND: create
# OVERWRITE: false
PRIVATE: true
CODEFIRST_CLIENTDRONE_ENV_MARIADB_ROOT_PASSWORD:
from_secret: db_root_password
CODEFIRST_CLIENTDRONE_ENV_MARIADB_DATABASE:
from_secret: db_database
CODEFIRST_CLIENTDRONE_ENV_MARIADB_USER:
from_secret: db_user
CODEFIRST_CLIENTDRONE_ENV_MARIADB_PASSWORD:
from_secret: db_password
# database container bdd
- name: deploy-container-bdd
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
environment:
CODEFIRST_CLIENTDRONE_ENV_TYPE: BDD
CODEFIRST_CLIENTDRONE_ENV_HOST: dadalmeida-mysql
CODEFIRST_CLIENTDRONE_ENV_PORT: 3306
CODEFIRST_CLIENTDRONE_ENV_DATABASE:
from_secret: db_database
CODEFIRST_CLIENTDRONE_ENV_USERNAME:
from_secret: db_user
CODEFIRST_CLIENTDRONE_ENV_PASSWORD:
from_secret: db_password
IMAGENAME: hub.codefirst.iut.uca.fr/david.d_almeida/api:latest:latest
CONTAINERNAME: heart_api
COMMAND: create
OVERWRITE: true
depends_on: [deploy-container-mysql, docker-build-and-push, deploy-container-stub]

@ -10,6 +10,7 @@
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.2" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -65,6 +65,22 @@ namespace DbContextLib
public HeartTrackContext(DbContextOptions<HeartTrackContext> options) : base(options) public HeartTrackContext(DbContextOptions<HeartTrackContext> options) : base(options)
{ } { }
public HeartTrackContext(string dbPlatformPath)
: this(InitPlaformDb(dbPlatformPath))
{
}
private static DbContextOptions<HeartTrackContext> InitPlaformDb(string dbPlatformPath)
{
var options = new DbContextOptionsBuilder<HeartTrackContext>()
.UseMySql($"{dbPlatformPath}", new MySqlServerVersion(new Version(10, 11, 1)))
.Options;
return options;
}
/// <summary> /// <summary>
/// Configures the database options if they are not already configured. /// Configures the database options if they are not already configured.
/// </summary> /// </summary>

@ -25,8 +25,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestsAPI", "TestsAPI", "{30
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientTests", "Tests\TestsAPI\ClientTests\ClientTests.csproj", "{9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientTests", "Tests\TestsAPI\ClientTests\ClientTests.csproj", "{9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsXUnit", "Tests\TestsAPI\TestsXUnit\TestsXUnit.csproj", "{44C367DC-5FE0-4CF2-9E76-A0282E931853}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj", "{30AB7FAA-6072-40B6-A15E-9188B59144F9}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj", "{30AB7FAA-6072-40B6-A15E-9188B59144F9}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestApi", "Tests\TestsAPI\UnitTestApi\UnitTestApi.csproj", "{E515C8B6-6282-4D8B-8523-7B3A13E4AF58}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestApi", "Tests\TestsAPI\UnitTestApi\UnitTestApi.csproj", "{E515C8B6-6282-4D8B-8523-7B3A13E4AF58}"
@ -88,10 +86,6 @@ Global
{9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}.Debug|Any CPU.Build.0 = Debug|Any CPU {9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}.Release|Any CPU.ActiveCfg = Release|Any CPU {9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}.Release|Any CPU.Build.0 = Release|Any CPU {9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}.Release|Any CPU.Build.0 = Release|Any CPU
{44C367DC-5FE0-4CF2-9E76-A0282E931853}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44C367DC-5FE0-4CF2-9E76-A0282E931853}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44C367DC-5FE0-4CF2-9E76-A0282E931853}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44C367DC-5FE0-4CF2-9E76-A0282E931853}.Release|Any CPU.Build.0 = Release|Any CPU
{30AB7FAA-6072-40B6-A15E-9188B59144F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {30AB7FAA-6072-40B6-A15E-9188B59144F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30AB7FAA-6072-40B6-A15E-9188B59144F9}.Debug|Any CPU.Build.0 = Debug|Any CPU {30AB7FAA-6072-40B6-A15E-9188B59144F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30AB7FAA-6072-40B6-A15E-9188B59144F9}.Release|Any CPU.ActiveCfg = Release|Any CPU {30AB7FAA-6072-40B6-A15E-9188B59144F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -146,7 +140,6 @@ Global
{2D166FAD-4934-474B-96A8-6C0635156EC2} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18} {2D166FAD-4934-474B-96A8-6C0635156EC2} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18}
{30FC2BE9-7397-445A-84AD-043CE70F4281} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18} {30FC2BE9-7397-445A-84AD-043CE70F4281} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18}
{9E4D3AC5-E6CA-4753-BD96-BF5EE793931A} = {30FC2BE9-7397-445A-84AD-043CE70F4281} {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} {E515C8B6-6282-4D8B-8523-7B3A13E4AF58} = {30FC2BE9-7397-445A-84AD-043CE70F4281}
{31FA8E5E-D642-4C43-A2B2-02B9832B2CEC} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18} {31FA8E5E-D642-4C43-A2B2-02B9832B2CEC} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18}
{73EA27F2-9F0C-443F-A5EE-2960C983A422} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18} {73EA27F2-9F0C-443F-A5EE-2960C983A422} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18}

@ -1,6 +1,8 @@
using System.Reflection;
using DbContextLib; using DbContextLib;
using DbContextLib.Identity; using DbContextLib.Identity;
using Entities; using Entities;
using HeartTrackAPI.Utils;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.ApiExplorer;
@ -12,6 +14,7 @@ using Microsoft.OpenApi.Models;
using Model.Manager; using Model.Manager;
using Model2Entities; using Model2Entities;
using StubAPI; using StubAPI;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace HeartTrackAPI; namespace HeartTrackAPI;
@ -23,16 +26,14 @@ public class AppBootstrap(IConfiguration configuration)
{ {
services.AddControllers(); services.AddControllers();
services.AddEndpointsApiExplorer(); services.AddEndpointsApiExplorer();
//services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOption>(); AddSwagger(services);
// include Xml comment // include Xml comment
// addsecurityRequiment // addsecurityRequiment
// securityDef // securityDef
services.AddSwaggerGen();
AddHeartTrackContextServices(services); AddHeartTrackContextServices(services);
AddModelService(services); AddModelService(services);
AddIdentityServices(services); AddIdentityServices(services);
AddApiVersioning(services); AddApiVersioning(services);
AddSwagger(services);
services.AddHealthChecks(); services.AddHealthChecks();
@ -40,18 +41,35 @@ public class AppBootstrap(IConfiguration configuration)
private void AddHeartTrackContextServices(IServiceCollection services) private void AddHeartTrackContextServices(IServiceCollection services)
{ {
var connectionString = Configuration.GetConnectionString("HeartTrackAuthConnection"); string connectionString;
if (string.IsNullOrWhiteSpace(connectionString))
switch (System.Environment.GetEnvironmentVariable("TYPE"))
{ {
throw new InvalidOperationException("The connection string for the database is not set."); case "BDD":
var HOST = System.Environment.GetEnvironmentVariable("HOST");
var PORT = System.Environment.GetEnvironmentVariable("PORT");
var DATABASE = System.Environment.GetEnvironmentVariable("DATABASE");
var USERNAME = System.Environment.GetEnvironmentVariable("USERNAME");
var PASSWORD = System.Environment.GetEnvironmentVariable("PASSWORD");
connectionString = $"server={HOST};port={PORT};database={DATABASE};user={USERNAME};password={PASSWORD}";
services.AddSingleton<IDataManager>(provider => new DbDataManager(connectionString));
break;
default:
connectionString = Configuration.GetConnectionString("HeartTrackAuthConnection");
if (string.IsNullOrWhiteSpace(connectionString))
{
services.AddDbContext<AuthDbContext>(options => options.UseInMemoryDatabase("AuthDb"));
//options => options.UseSqlite(connectionString)
//services.AddDbContext<HeartTrackContext>();
services.AddDbContext<HeartTrackContext>(options =>
options.UseSqlite(connectionString), ServiceLifetime.Singleton);
}
break;
} }
else
{
services.AddDbContext<AuthDbContext>(options => options.UseInMemoryDatabase("AuthDb"));
//options => options.UseSqlite(connectionString)
//services.AddDbContext<HeartTrackContext>();
services.AddDbContext<HeartTrackContext>(options =>
options.UseSqlite(connectionString), ServiceLifetime.Singleton);
/* /*
services.AddSingleton<DbContextOptions<HeartTrackContext>>(provider => services.AddSingleton<DbContextOptions<HeartTrackContext>>(provider =>
{ {
@ -64,9 +82,8 @@ public class AppBootstrap(IConfiguration configuration)
return options; return options;
});*/ });*/
}
} }
private void AddModelService(IServiceCollection services) private void AddModelService(IServiceCollection services)
{ {
//services.AddSingleton<IDataManager>(provider => new DbDataManager(provider.GetService<HeartTrackContext>())); //services.AddSingleton<IDataManager>(provider => new DbDataManager(provider.GetService<HeartTrackContext>()));
@ -104,16 +121,57 @@ public class AppBootstrap(IConfiguration configuration)
private void AddSwagger(IServiceCollection services) private void AddSwagger(IServiceCollection services)
{ {
services.AddSwaggerGen(options => services.AddSwaggerGen(options =>
{
options.OperationFilter<SwaggerDefaultValues>();
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description =
"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
var scheme = new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
}
};
options.AddSecurityRequirement(scheme);
});
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, SwaggerOptions>();
services.AddSwaggerGen(options =>
{
options.OperationFilter<SwaggerDefaultValues>();
});
/* services.AddSwaggerGen(options =>
{ {
options.SwaggerDoc("v1", new OpenApiInfo { Title = "HeartTrackAPI", Version = "v1" }); options.SwaggerDoc("v1", new OpenApiInfo { Title = "HeartTrackAPI", Version = "v1" });
options.SwaggerDoc("v2", new OpenApiInfo { Title = "HeartTrackAPI", Version = "v2" }); options.SwaggerDoc("v2", new OpenApiInfo { Title = "HeartTrackAPI", Version = "v2" });
}); });*/
services.AddVersionedApiExplorer(setup => services.AddVersionedApiExplorer(setup =>
{ {
setup.GroupNameFormat = "'v'VVV"; setup.GroupNameFormat = "'v'VVV";
setup.SubstituteApiVersionInUrl = true; setup.SubstituteApiVersionInUrl = true;
}); });
} }
public void Configure(WebApplication app, IWebHostEnvironment env) public void Configure(WebApplication app, IWebHostEnvironment env)

@ -10,7 +10,8 @@ using Model.Repository;
namespace HeartTrackAPI.Controllers; namespace HeartTrackAPI.Controllers;
[ApiController] [ApiController]
[Route("api/activities")] [ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class ActivityController : Controller public class ActivityController : Controller
{ {
private readonly IActivityRepository _activityService; private readonly IActivityRepository _activityService;

@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations;
using APIMappers; using APIMappers;
using Dto; using Dto;
using HeartTrackAPI.Request; using HeartTrackAPI.Request;
@ -9,10 +10,13 @@ using Model.Repository;
using Shared; using Shared;
namespace HeartTrackAPI.Controllers; namespace HeartTrackAPI.Controllers;
/// <summary>
/// Contrôle les actions liées aux utilisateurs dans l'application HeartTrack.
/// Gère les opérations CRUD sur les utilisateurs, leurs amis, et leurs activités.
/// </summary>
[ApiController] [ApiController]
[ApiVersion("1.0")] [ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/users")] [Route("api/v{version:apiVersion}/[controller]")]
public class UsersController : Controller public class UsersController : Controller
{ {
private readonly ILogger<UsersController> _logger; private readonly ILogger<UsersController> _logger;
@ -25,6 +29,14 @@ public class UsersController : Controller
_activityService = dataManager.ActivityRepo; _activityService = dataManager.ActivityRepo;
} }
/// <summary>
/// Récupère une page d'utilisateurs en fonction des critères de pagination et de tri fournis.
/// </summary>
/// <param name="request">Les critères de pagination et de tri pour les utilisateurs.</param>
/// <returns>Une page de données utilisateur selon les critères spécifiés.</returns>
/// <response code="200">Retourne la page demandée d'utilisateurs.</response>
/// <response code="400">La demande de pagination est invalide.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpGet] [HttpGet]
[ProducesResponseType(typeof(PageResponse<UserDto>), 200)] [ProducesResponseType(typeof(PageResponse<UserDto>), 200)]
[ProducesResponseType(400)] [ProducesResponseType(400)]
@ -49,15 +61,23 @@ public class UsersController : Controller
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting all athletes"); _logger.LogError(e, "Error while getting all athletes");
return StatusCode(500); return Problem();
} }
} }
/// <summary>
/// Récupère un utilisateur spécifique par son identifiant.
/// </summary>
/// <param name="id">L'identifiant de l'utilisateur à récupérer.</param>
/// <returns>L'utilisateur correspondant à l'identifiant spécifié.</returns>
/// <response code="200">Retourne l'utilisateur demandé.</response>
/// <response code="404">Aucun utilisateur trouvé pour l'identifiant spécifié.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpGet("{id}")] [HttpGet("{id}")]
[ProducesResponseType(typeof(UserDto), 200)] [ProducesResponseType(typeof(UserDto), 200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
[ProducesResponseType(500)] [ProducesResponseType(500)]
public async Task<ActionResult<UserDto>> GetById(int id) public async Task<ActionResult<UserDto>> GetById([Range(0,int.MaxValue)]int id)
{ {
try try
{ {
@ -73,11 +93,16 @@ public class UsersController : Controller
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting athlete by id {id}", id); _logger.LogError(e, "Error while getting athlete by id {id}", id);
return StatusCode(500); return Problem();
} }
} }
/// <summary>
/// Obtient le nombre total d'utilisateurs.
/// </summary>
/// <returns>Le nombre total d'utilisateurs.</returns>
/// <response code="200">Retourne le nombre total d'utilisateurs.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpGet("count")] [HttpGet("count")]
[ProducesResponseType(typeof(int), 200)] [ProducesResponseType(typeof(int), 200)]
[ProducesResponseType(500)] [ProducesResponseType(500)]
@ -92,10 +117,19 @@ public class UsersController : Controller
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting the number of users"); _logger.LogError(e, "Error while getting the number of users");
return StatusCode(500); return Problem();
} }
} }
/// <summary>
/// Met à jour les informations d'un utilisateur spécifique.
/// </summary>
/// <param name="id">L'identifiant de l'utilisateur à mettre à jour.</param>
/// <param name="user">Les données de l'utilisateur pour la mise à jour.</param>
/// <returns>L'utilisateur mis à jour.</returns>
/// <response code="200">Retourne l'utilisateur mis à jour.</response>
/// <response code="404">Utilisateur non trouvé.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpPut("{id}")] [HttpPut("{id}")]
[ProducesResponseType(typeof(UserDto), 200)] [ProducesResponseType(typeof(UserDto), 200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
@ -115,7 +149,7 @@ public class UsersController : Controller
if(updatedAthlete == null) if(updatedAthlete == null)
{ {
_logger.LogError("Error while updating athlete with id {id}", id); _logger.LogError("Error while updating athlete with id {id}", id);
return StatusCode(500); return Problem();
} }
return Ok(updatedAthlete.ToDto()); return Ok(updatedAthlete.ToDto());
@ -123,10 +157,18 @@ public class UsersController : Controller
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting the number of users"); _logger.LogError(e, "Error while getting the number of users");
return StatusCode(500); return Problem();
} }
} }
/// <summary>
/// Supprime un utilisateur spécifique.
/// </summary>
/// <param name="id">L'identifiant de l'utilisateur à supprimer.</param>
/// <returns>Action result.</returns>
/// <response code="200">Utilisateur supprimé avec succès.</response>
/// <response code="404">Utilisateur non trouvé.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpDelete("{id}")] [HttpDelete("{id}")]
[ProducesResponseType(200)] [ProducesResponseType(200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
@ -148,17 +190,26 @@ public class UsersController : Controller
if(!isDeleted) if(!isDeleted)
{ {
_logger.LogError("Error while deleting athlete with id {id}", id); _logger.LogError("Error while deleting athlete with id {id}", id);
return StatusCode(500); return Problem();
} }
return Ok(); return Ok();
} }
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting the number of users"); _logger.LogError(e, "Error while getting the number of users");
return StatusCode(500); return Problem();
} }
} }
/// <summary>
/// Obtient la liste des amis d'un utilisateur spécifique.
/// </summary>
/// <param name="id">L'identifiant de l'utilisateur.</param>
/// <param name="request">Les critères de pagination et de tri.</param>
/// <returns>La liste paginée des amis.</returns>
/// <response code="200">Retourne la liste paginée des amis de l'utilisateur.</response>
/// <response code="404">Utilisateur non trouvé.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpGet("{id}/friends")] [HttpGet("{id}/friends")]
[ProducesResponseType(typeof(PageResponse<UserDto>), 200)] [ProducesResponseType(typeof(PageResponse<UserDto>), 200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
@ -188,11 +239,19 @@ public class UsersController : Controller
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting the number of users"); _logger.LogError(e, "Error while getting the number of users");
return StatusCode(500); return Problem();
} }
} }
/// <summary>
/// Ajoute un ami à un utilisateur spécifique.
/// </summary>
/// <param name="id">L'identifiant de l'utilisateur.</param>
/// <param name="friendId">L'identifiant de l'ami à ajouter.</param>
/// <returns>Action result.</returns>
/// <response code="200">Ami ajouté avec succès.</response>
/// <response code="404">Utilisateur ou ami non trouvé.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpPost("{id}/friend/{friendId}")] [HttpPost("{id}/friend/{friendId}")]
[ProducesResponseType(200)] [ProducesResponseType(200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
@ -218,17 +277,27 @@ public class UsersController : Controller
if(!isAdded) if(!isAdded)
{ {
_logger.LogError("Error while adding friend with id {friendId} to athlete with id {id}", friendId, id); _logger.LogError("Error while adding friend with id {friendId} to athlete with id {id}", friendId, id);
return StatusCode(500); return Problem();
} }
return Ok(); return Ok();
} }
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting the number of users"); _logger.LogError(e, "Error while getting the number of users");
return StatusCode(500); return Problem();
} }
} }
/// <summary>
/// Supprime un ami d'un utilisateur spécifique.
/// </summary>
/// <param name="id">L'identifiant de l'utilisateur.</param>
/// <param name="friendId">L'identifiant de l'ami à supprimer.</param>
/// <returns>Action result.</returns>
/// <response code="200">Ami supprimé avec succès.</response>
/// <response code="404">Utilisateur ou ami non trouvé.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpDelete("{id}/friend/{friendId}")] [HttpDelete("{id}/friend/{friendId}")]
[ProducesResponseType(200)] [ProducesResponseType(200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
@ -254,19 +323,28 @@ public class UsersController : Controller
if(!isRemoved) if(!isRemoved)
{ {
_logger.LogError("Error while removing friend with id {friendId} to athlete with id {id}", friendId, id); _logger.LogError("Error while removing friend with id {friendId} to athlete with id {id}", friendId, id);
return StatusCode(500); return Problem();
} }
return Ok(); return Ok();
} }
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting the number of users"); _logger.LogError(e, "Error while getting the number of users");
return StatusCode(500); return Problem();
} }
} }
// ou faire un get qui si le role est coach resend les athletes et si le role est athlete resend les coach // #[TODO] [Dave] ou faire un get qui si le role est coach resend les athletes et si le role est athlete resend les coach
/// <summary>
/// Obtient la liste des athlètes d'un coach spécifique.
/// </summary>
/// <param name="coachId">L'identifiant du coach.</param>
/// <param name="request">Les critères de pagination et de tri.</param>
/// <returns>La liste paginée des athlètes.</returns>
/// <response code="200">Retourne la liste paginée des athlètes du coach.</response>
/// <response code="404">Coach non trouvé.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpGet("{coachId}/athletes")] [HttpGet("{coachId}/athletes")]
[ProducesResponseType(typeof(PageResponse<UserDto>), 200)] [ProducesResponseType(typeof(PageResponse<UserDto>), 200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
@ -296,10 +374,19 @@ public class UsersController : Controller
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting the number of users"); _logger.LogError(e, "Error while getting the number of users");
return StatusCode(500); return Problem();
} }
} }
/// <summary>
/// Obtient la liste des activités d'un utilisateur spécifique.
/// </summary>
/// <param name="userId">L'identifiant de l'utilisateur.</param>
/// <param name="pageRequest">Les critères de pagination et de tri.</param>
/// <returns>La liste paginée des activités de l'utilisateur.</returns>
/// <response code="200">Retourne la liste paginée des activités.</response>
/// <response code="404">Aucune activité trouvée.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpGet("{userId}/activities")] [HttpGet("{userId}/activities")]
// should be tiny DTOActivity returned with only the necessary information (will be used in the list of activities of a user) // should be tiny DTOActivity returned with only the necessary information (will be used in the list of activities of a user)
public async Task<ActionResult<PageResponse<ActivityDto>>> GetActivitiesByUser(int userId, [FromQuery] PageRequest pageRequest) public async Task<ActionResult<PageResponse<ActivityDto>>> GetActivitiesByUser(int userId, [FromQuery] PageRequest pageRequest)
@ -324,20 +411,26 @@ public class UsersController : Controller
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting all activities"); _logger.LogError(e, "Error while getting all activities");
return StatusCode(500); return Problem();
} }
} }
/* /* [TODO] [Dave]
[HttpGet("{userId}/trainings")] [HttpGet("{userId}/trainings")]
[ProducesResponseType(typeof(PageResponse<TrainingDto>), 200)] [ProducesResponseType(typeof(PageResponse<TrainingDto>), 200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
[ProducesResponseType(500)] [ProducesResponseType(500)]
public async Task<ActionResult<PageResponse<TrainingDto>> GetTrainings(int userId, [FromQuery] PageRequest request) public async Task<ActionResult<PageResponse<TrainingDto>> GetTrainings(int userId, [FromQuery] PageRequest request)
*/ */
/// <summary>
/// Déconnecte l'utilisateur actuel.
/// </summary>
/// <param name="signInManager">Le gestionnaire de connexion.</param>
/// <param name="empty">Paramètre vide utilisé pour s'assurer que la requête provient bien d'un client.</param>
/// <returns>Action result.</returns>
/// <response code="200">Déconnexion réussie.</response>
/// <response code="401">Déconnexion non autorisée.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpPost("logout")] [HttpPost("logout")]
[ProducesResponseType(200)] [ProducesResponseType(200)]
[ProducesResponseType(401)] [ProducesResponseType(401)]

@ -5,6 +5,8 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization> <InvariantGlobalization>true</InvariantGlobalization>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

@ -1,10 +1,16 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace HeartTrackAPI.Request; namespace HeartTrackAPI.Request;
public class PageRequest public class PageRequest
{ {
public string? OrderingPropertyName { get; set; } = null;
public string? OrderingPropertyName { get; set; } = null;// need to be map on the dto OrderCriteria
public bool? Descending { get; set; } = false; public bool? Descending { get; set; } = false;
[Range(1, int.MaxValue, ErrorMessage = "Count must be greater than 0")]
public int Index { get; set; } = 0; public int Index { get; set; } = 0;
public int Count { get; set; } = 5;
[Range(1, int.MaxValue, ErrorMessage = "Count must be greater than 0")]
public int Count { get; set; } = 1;
} }

@ -0,0 +1,53 @@
using System.Text.Json;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace HeartTrackAPI.Utils;
public class SwaggerDefaultValues : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var apiDescription = context.ApiDescription;
operation.Deprecated |= apiDescription.IsDeprecated();
foreach (var responseType in context.ApiDescription.SupportedResponseTypes)
{
var responseKey = responseType.IsDefaultResponse ? "default" : responseType.StatusCode.ToString();
var response = operation.Responses[responseKey];
foreach (var contentType in response.Content.Keys)
{
if (responseType.ApiResponseFormats.All(x => x.MediaType != contentType))
{
response.Content.Remove(contentType);
}
}
}
if (operation.Parameters == null)
{
return;
}
foreach (var parameter in operation.Parameters)
{
var description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name);
parameter.Description ??= description.ModelMetadata?.Description;
if (parameter.Schema.Default == null &&
description.DefaultValue != null &&
description.DefaultValue is not DBNull &&
description.ModelMetadata is ModelMetadata modelMetadata)
{
var json = JsonSerializer.Serialize(description.DefaultValue, modelMetadata.ModelType);
parameter.Schema.Default = OpenApiAnyFactory.CreateFromJson(json);
}
parameter.Required |= description.IsRequired;
}
}
}

@ -50,8 +50,12 @@ public class SwaggerOptions: IConfigureNamedOptions<SwaggerGenOptions>
{ {
var info = new OpenApiInfo() var info = new OpenApiInfo()
{ {
Title = ".NET Core (.NET 6) Web API For Lol", Title = "Web API For HeartTrack .NET 8",
Version = desc.ApiVersion.ToString() Version = desc.ApiVersion.ToString(),
Description = "The HeartTrack project API, aims to provide an Open Source solution for heart rate data analysis.",
Contact = new OpenApiContact { Name = "HeartTrackDev", Email = "toto@toto.fr" },
License = new OpenApiLicense { Name = "MIT", Url = new Uri("https://opensource.org/licenses/MIT") }
}; };
if (desc.IsDeprecated) if (desc.IsDeprecated)

@ -23,6 +23,13 @@ public partial class DbDataManager: IDataManager
// Faire pour les autres reset() des autres mappers // Faire pour les autres reset() des autres mappers
} }
public DbDataManager(string dbPlatformPath)
: this(new HeartTrackContext(dbPlatformPath))
{
DbContext.Database.EnsureCreated();
}
public DbDataManager() public DbDataManager()
{ {
DbContext = new HeartTrackContext(); DbContext = new HeartTrackContext();

@ -1,25 +0,0 @@
<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="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>

@ -1,10 +0,0 @@
namespace TestsXUnit;
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}

@ -0,0 +1,225 @@
using ApiMappeur;
using Dto;
using HeartTrackAPI.Controllers;
using HeartTrackAPI.Request;
using HeartTrackAPI.Responce;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging.Abstractions;
using Model;
using Model.Manager;
using Model.Repository;
using Moq;
using Shared;
using StubAPI;
namespace UnitTestApi.Controllers;
[TestClass]
[TestSubject(typeof(UsersController))]
public class UsersControllerTest
{
private Mock<IDataManager> _dataManagerMock;
private IDataManager _dataManager;
private UsersController _usersController;
private readonly List<User> _users =
[
new User
{
Id = 1, Username = "DoeDoe",
ProfilePicture =
"https://images.unsplash.com/photo-1682687982134-2ac563b2228b?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
FirstName = "John", LastName = "Doe",
Sexe = "M", Lenght = 180, Weight = 70, DateOfBirth = new DateTime(1990, 1, 1),
Email = "john.doe@example.com", Role = new Athlete()
},
new User
{
Id = 2, Username = "SmithSmith",
ProfilePicture =
"https://images.unsplash.com/photo-1709507779917-242b560288be?q=80&w=2080&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
FirstName = "Jane", LastName = "Smith",
Sexe = "F", Lenght = 170, Weight = 60, DateOfBirth = new DateTime(1992, 2, 2),
Email = "athlete2@example.com", Role = new Coach()
},
new User
{
Id = 3, Username = "Athlete3",
ProfilePicture =
"https://plus.unsplash.com/premium_photo-1705091981693-6006f8a20479?q=80&w=1974&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
FirstName = "First3", LastName = "Last3",
Sexe = "M", Lenght = 190, Weight = 80, DateOfBirth = new DateTime(1994, 3, 3), Email = "ath@ex.fr",
Role = new Athlete()
}
];
[TestInitialize]
public void SetUp()
{
_dataManagerMock = new Mock<IDataManager>();
_dataManagerMock.Setup(dm => dm.UserRepo.GetNbItems()).ReturnsAsync(_users.Count);
_dataManagerMock.Setup(dm =>
dm.UserRepo.GetUsers(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<AthleteOrderCriteria>(),
It.IsAny<bool>())).ReturnsAsync(
(int index, int count, AthleteOrderCriteria criteria, bool descending) =>
_users.GetItemsWithFilterAndOrdering(c => true, index, count,
criteria != AthleteOrderCriteria.None ? criteria : null, descending)
);
_usersController = new UsersController(new NullLogger<UsersController>(), _dataManagerMock.Object);
}
/*
[TestInitialize]
public void SetUp()
{
_dataManager = new StubData();
_usersController = new UsersController(new NullLogger<UsersController>(), _dataManager);
}*/
[TestMethod]
public async Task Get_ReturnsPageResponse_WhenRequestIsValid()
{
// Arrange
var request = new PageRequest
{
Index = 0,
Count = 3,
OrderingPropertyName = "Id",
Descending = false
};
// Act
var result = await _usersController.Get(request);
Assert.IsInstanceOfType(result.Result, typeof(OkObjectResult));
var okResult = result.Result as OkObjectResult;
// Assert
Assert.IsNotNull(okResult);
Assert.IsInstanceOfType(okResult.Value, typeof(PageResponse<UserDto>));
var pageResponse = okResult.Value as PageResponse<UserDto>;
Assert.IsNotNull(pageResponse);
Assert.AreEqual(3, pageResponse.Items.Count());
Assert.AreEqual(3, pageResponse.Total);
Assert.AreEqual(0, pageResponse.Index);
Assert.AreEqual(3, pageResponse.Count);
Assert.AreEqual(3, pageResponse.Count);
}
[DataTestMethod]
[DataRow(0, 2, "Id", false, 2)]
[DataRow(1, 1, "Id", false, 1)]
[DataRow(0, 3, "Id", true, 3)]
public async Task Get_ReturnsCorrectPaginationAndOrdering(int index, int count, string orderingProperty,
bool descending, int expectedItemCount)
{
// Arrange
var request = new PageRequest
{
Index = index,
Count = count,
OrderingPropertyName = orderingProperty,
Descending = descending
};
// Act
var result = await _usersController.Get(request);
Assert.IsInstanceOfType(result.Result, typeof(OkObjectResult));
var okResult = result.Result as OkObjectResult;
// Assert
Assert.IsNotNull(okResult);
Assert.IsInstanceOfType(okResult.Value, typeof(PageResponse<UserDto>));
var pageResponse = okResult.Value as PageResponse<UserDto>;
Assert.IsNotNull(pageResponse);
Assert.AreEqual(expectedItemCount, pageResponse.Items.Count());
}
[TestMethod]
public async Task Get_ReturnsInternalServerError_OnException()
{
_dataManagerMock.Setup(dm =>
dm.UserRepo.GetUsers(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<AthleteOrderCriteria>(),
It.IsAny<bool>()))
.ThrowsAsync(new Exception("Simulated database failure."));
var request = new PageRequest { Index = 0, Count = 3 };
var result = await _usersController.Get(request);
Assert.IsInstanceOfType(result.Result, typeof(ObjectResult));
var objectResult = result.Result as ObjectResult;
Assert.AreEqual(500, objectResult.StatusCode);
}
[TestMethod]
public async Task GetById_ReturnsUserDto_WhenRequestIsValid()
{
// Arrange
var id = 1;
_dataManagerMock.Setup(dm => dm.UserRepo.GetItemById(id)).ReturnsAsync(_users.First(x => x.Id == id));
// Act
var result = await _usersController.GetById(id) ;
Assert.IsInstanceOfType(result.Result, typeof(OkObjectResult));
var okResult = result.Result as OkObjectResult;
// Assert
Assert.IsNotNull(okResult);
var resultObject = result.Result as OkObjectResult;
Assert.IsNotNull(resultObject);
Assert.IsInstanceOfType(resultObject.Value, typeof(UserDto));
var user = resultObject.Value as UserDto;
Assert.IsNotNull(user);
var tmp = _users.First(x => x.Id == id).ToDto();
Assert.AreEqual(tmp.Id, user.Id);
}
[TestMethod]
public async Task GetById_ReturnsUserDto_WhenRequestUserDoesNotExist()
{
// Arrange
var id = 0;
_dataManagerMock.Setup(dm => dm.UserRepo.GetItemById(id)).ReturnsAsync((User)null!);
// Act
var result = await _usersController.GetById(id) ;
// Assert
Assert.IsInstanceOfType(result.Result, typeof(NotFoundObjectResult));
}
[TestMethod]
public async Task GetById_Returns404_WhenIdIsInvalid()
{
// Arrange
var id = -2;
// Act
var result = await _usersController.GetById(id);
// Assert
Assert.IsInstanceOfType(result.Result, typeof(NotFoundObjectResult));
}
[TestMethod]
public async Task Count_ReturnsInt_WhenRequestIsValid()
{
// Act
var result = await _usersController.Count();
Assert.IsNotNull(result);
result = result.Result as OkObjectResult;
// Assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result.Value, typeof(int));
}
}

@ -10,7 +10,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4"/> <PackageReference Include="MSTest.TestAdapter" Version="3.0.4"/>
<PackageReference Include="MSTest.TestFramework" Version="3.0.4"/> <PackageReference Include="MSTest.TestFramework" Version="3.0.4"/>
<PackageReference Include="coverlet.collector" Version="6.0.0"/> <PackageReference Include="coverlet.collector" Version="6.0.0"/>

@ -1,124 +0,0 @@
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