diff --git a/.drone.yml b/.drone.yml
index 51019cc..643d17f 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -3,9 +3,6 @@ type: docker
name: HeartTrack-API
trigger:
- branch:
- - WORK-CD
- - WORK-EF_WebAPI
event:
- push
@@ -18,6 +15,14 @@ steps:
- dotnet build HeartTrack.sln -c Release --no-restore
- 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
image: hub.codefirst.iut.uca.fr/marc.chevaldonne/codefirst-dronesonarplugin-dotnet8
secrets: [ SECRET_SONAR_LOGIN ]
@@ -36,8 +41,55 @@ steps:
- reportgenerator -reports:"**/coverage.cobertura.xml" -reporttypes:SonarQube -targetdir:"coveragereport"
- dotnet publish HeartTrack.sln -c Release --no-restore -o $CI_PROJECT_DIR/build/release
- dotnet sonarscanner end /d:sonar.login=$${PLUGIN_SONAR_TOKEN}
- depends_on: [ build ]
+ depends_on: [ tests ]
+ - name: swagger
+ image: mcr.microsoft.com/dotnet/sdk:8.0
+ failure: ignore
+ volumes:
+ - name: docs
+ path: /docs
+ environment:
+ CODEFIRST_CLIENTDRONE_ENV_DOTNET_ROLL_FORWARD: LatestMajor
+ CODEFIRST_CLIENTDRONE_ENV_DOTNET_ROLL_FORWARD_TO_PRERELEASE: 1
+ commands:
+ - cd src/
+ - dotnet restore HeartTrack.sln
+ - cd HeartTrackAPI
+ - 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 HeartTrackAPI/bin/Release/net8.0/HeartTrackAPI.dll v1
+ depends_on: [build,tests]
+
+ - 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 ]
+
+volumes:
+- name: docs
+ temp: {}
+
+---
+
+kind: pipeline
+type: docker
+name: HeartTrack-API-CD
+
+trigger:
+ event:
+ - push
+steps:
+
- name: docker-build-and-push
image: plugins/docker
settings:
@@ -49,25 +101,70 @@ steps:
from_secret: SECRET_REGISTRY_USERNAME
password:
from_secret: SECRET_REGISTRY_PASSWORD
- depends_on: [ build ]
+
+ # database container stub
+ - name: deploy-container-stub
+ image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
+ environment:
+ CODEFIRST_CLIENTDRONE_ENV_TYPE: STUB
+ IMAGENAME: hub.codefirst.iut.uca.fr/david.d_almeida/api:latest
+ CONTAINERNAME: heart_stub
+ COMMAND: create
+ ADMINS: davidd_almeida,kevinmonteiro,antoineperederii,paullevrault,antoinepinagot,nicolas.raymond
+ OVERWRITE: true
+ depends_on: [ docker-build-and-push ]
- - name: deploy-container
+ # - name: deploy-container
+ # image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
+ # environment:
+ # IMAGENAME: hub.codefirst.iut.uca.fr/david.d_almeida/api:latest
+ # CONTAINERNAME: heart_api
+ # CODEFIRST_CLIENTDRONE_ENV_TYPE: API
+ # CODEFIRST_CLIENTDRONE_ENV_PORT: 8080
+ # ADMINS: davidd_almeida,kevinmonteiro,antoineperederii,paullevrault,antoinepinagot,nicolas.raymond
+ # 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: true
+ PRIVATE: false
+ 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
+ ADMINS: davidd_almeida,kevinmonteiro,antoineperederii,paullevrault,antoinepinagot,nicolas.raymond
+
+
+ # 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: HeartDev-mysql
+ CODEFIRST_CLIENTDRONE_ENV_PORTDB: 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
CONTAINERNAME: api
CODEFIRST_CLIENTDRONE_ENV_PORT: 8080
ADMINS: davidd_almeida,kevinmonteiro,antoineperederii,paullevrault,antoinepinagot,nicolas.raymond
COMMAND: create
OVERWRITE: true
- depends_on: [ docker-build-and-push ]
-
- - 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 ]
\ No newline at end of file
+ depends_on: [deploy-container-mysql, docker-build-and-push, deploy-container-stub]
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index a7bcc21..70b6c0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -565,4 +565,7 @@ xcuserdata/
/dataSources.local.xml
.ideaMigration/
Migration/
+Migrations/
+
+
*.db
\ No newline at end of file
diff --git a/README.md b/README.md
index e00e2f0..97126b3 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,16 @@
# EF_WebAPI
-This repository make a meeting of EF and WebAPI parts.
\ No newline at end of file
+This repository make a meeting of EF and WebAPI parts.
+
+FROM /src dir
+
+do
+
+```bash
+dotnet ef migrations add --project StubbedContextLib/StubbedContextLib.csproj --startup-project HeartTrackAPI/HeartTrackAPI.csproj --context StubbedContextLib.TrainingStubbedContext --configuration Debug Initial --output-dir Migrations
+```
+then
+
+```bash
+dotnet ef database update --project StubbedContextLib/StubbedContextLib.csproj --startup-project HeartTrackAPI/HeartTrackAPI.csproj --context StubbedContextLib.TrainingStubbedContext --configuration Debug
+```
diff --git a/src/APIMappers/APIMappers.csproj b/src/APIMappers/APIMappers.csproj
new file mode 100644
index 0000000..3bb04a5
--- /dev/null
+++ b/src/APIMappers/APIMappers.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/src/APIMappers/ActivityMapper.cs b/src/APIMappers/ActivityMapper.cs
new file mode 100644
index 0000000..6013e57
--- /dev/null
+++ b/src/APIMappers/ActivityMapper.cs
@@ -0,0 +1,53 @@
+using Dto;
+using Model;
+using Shared;
+
+namespace APIMappers;
+
+public static class ActivityMapper
+{
+ private static GenericMapper _mapper = new GenericMapper();
+
+ public static ActivityDto ToDto(this Activity activity)
+ {
+ return activity.ToU(_mapper, activityDto => new ActivityDto
+ {
+ Id = activity.Id,
+ Type = activity.Type,
+ Date = activity.Date,
+ StartTime = activity.StartTime,
+ EndTime = activity.EndTime,
+ EffortFelt = activity.Effort,
+ Variability = activity.Variability,
+ Variance = activity.Variance,
+ StandardDeviation = activity.StandardDeviation,
+ Average = activity.Average,
+ Maximum = activity.Maximum,
+ Minimum = activity.Minimum,
+ AverageTemperature = activity.AverageTemperature,
+ HasAutoPause = activity.HasAutoPause
+ });
+ }
+
+ public static Activity ToModel(this ActivityDto activityDto)
+ {
+ return activityDto.ToT(_mapper, activity => new Activity
+ {
+ Id = activityDto.Id,
+ Type = activityDto.Type,
+ Date = activityDto.Date,
+ StartTime = activityDto.StartTime,
+ EndTime = activityDto.EndTime,
+ Effort = activityDto.EffortFelt,
+ Variability = activityDto.Variability,
+ Variance = activityDto.Variance,
+ StandardDeviation = activityDto.StandardDeviation,
+ Average = activityDto.Average,
+ Maximum = activityDto.Maximum,
+ Minimum = activityDto.Minimum,
+ AverageTemperature = activityDto.AverageTemperature,
+ HasAutoPause = activityDto.HasAutoPause
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/src/APIMappers/UserMappeur.cs b/src/APIMappers/UserMappeur.cs
new file mode 100644
index 0000000..48a8cda
--- /dev/null
+++ b/src/APIMappers/UserMappeur.cs
@@ -0,0 +1,51 @@
+using Dto;
+using Model;
+using Shared;
+
+namespace APIMappers;
+
+public static class UserMappeur
+{
+ private static GenericMapper _mapper = new GenericMapper();
+
+ public static UserDto ToDto(this User user)
+ {
+ return user.ToU(_mapper, userDto => new UserDto
+ {
+ Id = user.Id,
+ Username = user.Username,
+ ProfilePicture = user.ProfilePicture,
+ LastName = user.LastName,
+ FirstName = user.FirstName,
+ Email = user.Email,
+ Password = user.MotDePasse,
+ Sexe = user.Sexe,
+ Lenght = user.Lenght,
+ Weight = user.Weight,
+ DateOfBirth = user.DateOfBirth,
+ IsCoach = user.Role is Coach
+ });
+
+ }
+
+
+ public static User ToModel(this UserDto userDto)
+ {
+ return userDto.ToT(_mapper, user => new User
+ {
+ Username = userDto.Username,
+ ProfilePicture = userDto.ProfilePicture,
+ LastName = userDto.LastName,
+ FirstName = userDto.FirstName,
+ Email = userDto.Email,
+ MotDePasse = userDto.Password,
+ Sexe = userDto.Sexe,
+ Lenght = userDto.Lenght,
+ Weight = userDto.Weight,
+ DateOfBirth = userDto.DateOfBirth,
+ Role = userDto.IsCoach ? new Coach() : new Athlete()
+
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/src/DbContextLib/DbContextLib.csproj b/src/DbContextLib/DbContextLib.csproj
index 928ae7a..cd47dbc 100644
--- a/src/DbContextLib/DbContextLib.csproj
+++ b/src/DbContextLib/DbContextLib.csproj
@@ -6,13 +6,15 @@
enable
-
-
-
+
+
+
+
+
-
-
+
+
diff --git a/src/DbContextLib/HeartTrackContext.cs b/src/DbContextLib/HeartTrackContext.cs
index 5dbb584..1ce7564 100644
--- a/src/DbContextLib/HeartTrackContext.cs
+++ b/src/DbContextLib/HeartTrackContext.cs
@@ -55,13 +55,31 @@ namespace DbContextLib
///
/// Initializes a new instance of the class.
///
- public HeartTrackContext() : base() { }
+ public HeartTrackContext() : base()
+ { }
///
/// Initializes a new instance of the class with the specified options.
///
/// The options for the context.
- public HeartTrackContext(DbContextOptions options) : base(options) { }
+ public HeartTrackContext(DbContextOptions options) : base(options)
+ { }
+
+ public HeartTrackContext(string dbPlatformPath)
+ : this(InitPlaformDb(dbPlatformPath))
+ {
+ }
+
+ private static DbContextOptions InitPlaformDb(string dbPlatformPath)
+ {
+ var options = new DbContextOptionsBuilder()
+ .UseMySql($"{dbPlatformPath}", new MySqlServerVersion(new Version(10, 11, 1)))
+ .Options;
+ return options;
+ }
+
+
+
///
/// Configures the database options if they are not already configured.
diff --git a/src/DbContextLib/Identity/AuthDbContext.cs b/src/DbContextLib/Identity/AuthDbContext.cs
new file mode 100644
index 0000000..89924a7
--- /dev/null
+++ b/src/DbContextLib/Identity/AuthDbContext.cs
@@ -0,0 +1,25 @@
+using Entities;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+
+namespace DbContextLib.Identity;
+
+public class AuthDbContext: IdentityDbContext
+{
+
+ public AuthDbContext(DbContextOptions options) : base(options) { }
+ public AuthDbContext() { }
+ /*
+ ///
+ /// Configures the database options if they are not already configured.
+ ///
+ /// The options builder instance.
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ if (!optionsBuilder.IsConfigured)
+ {
+ optionsBuilder.UseSqlite($"Data Source=uca.HeartTrack.db");
+ }
+ }*/
+}
\ No newline at end of file
diff --git a/src/Dto/ActivityDto.cs b/src/Dto/ActivityDto.cs
index d4bf5f1..fcb108c 100644
--- a/src/Dto/ActivityDto.cs
+++ b/src/Dto/ActivityDto.cs
@@ -3,17 +3,17 @@ namespace Dto;
public class ActivityDto
{
public int Id { get; set; }
- public string Name { get; set; }
- public string Type { get; set; }
+ public string? Type { get; set; }
public DateTime Date { get; set; }
- public TimeSpan Duration { get; set; }
- public float Distance { get; set; }
- public float Elevation { get; set; }
- public float AverageSpeed { get; set; }
- public int AverageHeartRate { get; set; }
- public int Calories { get; set; }
- public string Description { get; set; }
- public string? Gpx { get; set; }
- public string? Image { get; set; }
- public int AthleteId { get; set; }
+ public DateTime StartTime { get; set; }
+ public DateTime EndTime { get; set; }
+ public int EffortFelt { get; set; }
+ public float Variability { get; set; }
+ public float Variance { get; set; }
+ public float StandardDeviation { get; set; }
+ public float Average { get; set; }
+ public int Maximum { get; set; }
+ public int Minimum { get; set; }
+ public float AverageTemperature { get; set; }
+ public bool HasAutoPause { get; set; }
}
\ No newline at end of file
diff --git a/src/Dto/ActivityFitFileDto.cs b/src/Dto/ActivityFitFileDto.cs
new file mode 100644
index 0000000..f68fbd1
--- /dev/null
+++ b/src/Dto/ActivityFitFileDto.cs
@@ -0,0 +1,16 @@
+namespace Dto;
+
+public class ActivityFitFileDto
+{
+ public ActivityFitFileDto(string activityName, string activityType, int effortFeel)
+ {
+ ActivityName = activityName;
+ ActivityType = activityType;
+ EffortFeel = effortFeel;
+ }
+
+ public string ActivityName { get; set; }
+ public string ActivityType { get; set; }
+ public int EffortFeel { get; set; }
+ //public IFormFile
+}
\ No newline at end of file
diff --git a/src/EFMappers/AthleteMappeur.cs b/src/EFMappers/AthleteMappeur.cs
index 219305d..48dea10 100644
--- a/src/EFMappers/AthleteMappeur.cs
+++ b/src/EFMappers/AthleteMappeur.cs
@@ -1,10 +1,13 @@
-using Dto;
+using System.Buffers;
+using Dto;
using Model;
namespace ApiMappeur;
-// anotine
public static class UserMappeur
{
+ private static readonly ArrayPool UserDtoPool = ArrayPool.Create();
+ private static readonly Dictionary userToDtoMap = new Dictionary();
+ private static readonly Dictionary dtoToUserMap = new Dictionary();
public static UserDto ToDto(this User user)
{
return new UserDto
@@ -26,8 +29,71 @@ public static class UserMappeur
public static User ToModel(this UserDto userDto)
{
- if (userDto.IsCoach)
+ return new User
{
+ Username = userDto.Username,
+ ProfilePicture = userDto.ProfilePicture,
+ LastName = userDto.LastName,
+ FirstName = userDto.FirstName,
+ Email = userDto.Email,
+ MotDePasse = userDto.Password,
+ Sexe = userDto.Sexe,
+ Lenght = userDto.Lenght,
+ Weight = userDto.Weight,
+ DateOfBirth = userDto.DateOfBirth,
+ Role = userDto.IsCoach ? new Coach() : new Athlete()
+
+ };
+ }
+}
+/*
+using Dto;
+using Model;
+using System.Buffers;
+
+namespace ApiMappeur
+{
+ // anotine
+ public static class UserMappeur
+ {
+ private static readonly ArrayPool UserDtoPool = ArrayPool.Create();
+
+ public static UserDto ToDto(this User user)
+ {
+ UserDto userDto = UserDtoPool.Rent();
+ userDto.Id = user.Id;
+ userDto.Username = user.Username;
+ userDto.ProfilePicture = user.ProfilePicture;
+ userDto.LastName = user.LastName;
+ userDto.FirstName = user.FirstName;
+ userDto.Email = user.Email;
+ userDto.Password = user.MotDePasse;
+ userDto.Sexe = user.Sexe;
+ userDto.Lenght = user.Lenght;
+ userDto.Weight = user.Weight;
+ userDto.DateOfBirth = user.DateOfBirth;
+ userDto.IsCoach = user.Role is Coach;
+ return userDto;
+ }
+
+ public static User ToModel(this UserDto userDto)
+ {
+ if (userDto.IsCoach)
+ {
+ return new User(
+ userDto.Username,
+ userDto.ProfilePicture,
+ userDto.LastName,
+ userDto.FirstName,
+ userDto.Email,
+ userDto.Password,
+ userDto.Sexe,
+ userDto.Lenght,
+ userDto.Weight,
+ userDto.DateOfBirth,
+ new Coach()
+ );
+ }
return new User(
userDto.Username,
userDto.ProfilePicture,
@@ -39,20 +105,13 @@ public static class UserMappeur
userDto.Lenght,
userDto.Weight,
userDto.DateOfBirth,
- new Coach()
- );
+ new Athlete());
+ }
+
+ public static void ReturnToPool(this UserDto userDto)
+ {
+ UserDtoPool.Return(userDto);
}
- return new User(
- userDto.Username,
- userDto.ProfilePicture,
- userDto.LastName,
- userDto.FirstName,
- userDto.Email,
- userDto.Password,
- userDto.Sexe,
- userDto.Lenght,
- userDto.Weight,
- userDto.DateOfBirth,
- new Athlete());
}
-}
\ No newline at end of file
+}
+*/
\ No newline at end of file
diff --git a/src/Entities/ActivityEntity.cs b/src/Entities/ActivityEntity.cs
index ab26369..5dc7761 100644
--- a/src/Entities/ActivityEntity.cs
+++ b/src/Entities/ActivityEntity.cs
@@ -29,7 +29,7 @@ namespace Entities
///
[Required]
[MaxLength(100)]
- public string Type { get; set; } = null!;
+ public string? Type { get; set; } = null!;
///
/// Gets or sets the date of the activity.
diff --git a/src/Entities/AthleteEntity.cs b/src/Entities/AthleteEntity.cs
index cc883d6..6d6f351 100644
--- a/src/Entities/AthleteEntity.cs
+++ b/src/Entities/AthleteEntity.cs
@@ -15,8 +15,10 @@ namespace Entities
/// Represents an athlete entity in the database.
///
[Table("Athlete")]
- public class AthleteEntity
+ public class AthleteEntity
{
+ public AthleteEntity() : base() { }
+
///
/// Gets or sets the unique identifier of the athlete.
///
@@ -28,35 +30,35 @@ namespace Entities
/// Gets or sets the username of the athlete.
///
[MaxLength(100)]
- [Required(ErrorMessage = "Athlete Username is required")]
+ [Required(ErrorMessage = "Athlete Username is ")]
public required string Username { get; set; }
///
/// Gets or sets the last name of the athlete.
///
[MaxLength(100)]
- [Required(ErrorMessage = "Athlete Last Name is required")]
+ [Required(ErrorMessage = "Athlete Last Name is ")]
public required string LastName { get; set; }
///
/// Gets or sets the first name of the athlete.
///
[MaxLength(150)]
- [Required(ErrorMessage = "Athlete First Name is required")]
+ [Required(ErrorMessage = "Athlete First Name is ")]
public required string FirstName { get; set; }
///
/// Gets or sets the email of the athlete.
///
[MaxLength(100)]
- [Required(ErrorMessage = "Athlete Email is required")]
+ [Required(ErrorMessage = "Athlete Email is ")]
public required string Email { get; set; }
///
/// Gets or sets the gender of the athlete.
///
[MaxLength(1)]
- [Required(ErrorMessage = "Athlete Sexe is required")]
+ [Required(ErrorMessage = "Athlete Sexe is ")]
public required string Sexe { get; set; }
///
@@ -72,13 +74,13 @@ namespace Entities
///
/// Gets or sets the password of the athlete.
///
- [Required(ErrorMessage = "Athlete Password is required")]
+ [Required(ErrorMessage = "Athlete Password is ")]
public required string Password { get; set; }
///
/// Gets or sets the date of birth of the athlete.
///
- [Required(ErrorMessage = "Athlete Date of Birth is required")]
+ [Required(ErrorMessage = "Athlete Date of Birth is ")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateOnly DateOfBirth { get; set; }
@@ -87,7 +89,7 @@ namespace Entities
///
public bool IsCoach { get; set; }
- public required byte[] ProfilPicture { get; set; }
+ public byte[]? ProfilPicture { get; set; }
diff --git a/src/Entities/Entities.csproj b/src/Entities/Entities.csproj
index bb23fb7..b007a4d 100644
--- a/src/Entities/Entities.csproj
+++ b/src/Entities/Entities.csproj
@@ -5,5 +5,4 @@
enable
enable
-
diff --git a/src/HeartTrack.sln b/src/HeartTrack.sln
index 57167ac..8947e4c 100644
--- a/src/HeartTrack.sln
+++ b/src/HeartTrack.sln
@@ -3,52 +3,49 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DbContextLib", "DbContextLib\DbContextLib.csproj", "{330A5DA0-0B4E-48D4-9AF3-6DCB39EE9622}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbContextLib", "DbContextLib\DbContextLib.csproj", "{330A5DA0-0B4E-48D4-9AF3-6DCB39EE9622}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Entities", "Entities\Entities.csproj", "{A07F86B3-555B-4B35-8BB1-25E844825A38}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Entities", "Entities\Entities.csproj", "{A07F86B3-555B-4B35-8BB1-25E844825A38}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StubbedContextLib", "StubbedContextLib\StubbedContextLib.csproj", "{2F44DE6E-EFFC-42FE-AFF6-79CDC762E6D8}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StubbedContextLib", "StubbedContextLib\StubbedContextLib.csproj", "{2F44DE6E-EFFC-42FE-AFF6-79CDC762E6D8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{2B227C67-3BEC-4A83-BDA0-F3918FBC0D18}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTestEntities", "Tests\ConsoleTestEntities\ConsoleTestEntities.csproj", "{477D2129-A6C9-4FF8-8BE9-5E9E8E5282F8}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleTestEntities", "Tests\ConsoleTestEntities\ConsoleTestEntities.csproj", "{477D2129-A6C9-4FF8-8BE9-5E9E8E5282F8}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTestRelationships", "Tests\ConsoleTestRelationships\ConsoleTestRelationships.csproj", "{2D166FAD-4934-474B-96A8-6C0635156EC2}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleTestRelationships", "Tests\ConsoleTestRelationships\ConsoleTestRelationships.csproj", "{2D166FAD-4934-474B-96A8-6C0635156EC2}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dto", "Dto\Dto.csproj", "{562019BC-0F61-41B0-9BAE-259B92C6BFBA}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dto", "Dto\Dto.csproj", "{562019BC-0F61-41B0-9BAE-259B92C6BFBA}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeartTrackAPI", "HeartTrackAPI\HeartTrackAPI.csproj", "{C1C2EAC3-3347-466B-BFB6-2A9F11A3AE12}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HeartTrackAPI", "HeartTrackAPI\HeartTrackAPI.csproj", "{C1C2EAC3-3347-466B-BFB6-2A9F11A3AE12}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csproj", "{F80C60E1-1E06-46C2-96DE-42B1C7DE65BC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{F80C60E1-1E06-46C2-96DE-42B1C7DE65BC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestsAPI", "TestsAPI", "{30FC2BE9-7397-445A-84AD-043CE70F4281}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientTests", "Tests\TestsAPI\ClientTests\ClientTests.csproj", "{9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientTests", "Tests\TestsAPI\ClientTests\ClientTests.csproj", "{9E4D3AC5-E6CA-4753-BD96-BF5EE793931A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsXUnit", "Tests\TestsAPI\TestsXUnit\TestsXUnit.csproj", "{44C367DC-5FE0-4CF2-9E76-A0282E931853}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Model", "Model\Model.csproj", "{30AB7FAA-6072-40B6-A15E-9188B59144F9}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj", "{30AB7FAA-6072-40B6-A15E-9188B59144F9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTestApi", "Tests\TestsAPI\UnitTestApi\UnitTestApi.csproj", "{E515C8B6-6282-4D8B-8523-7B3A13E4AF58}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestApi", "Tests\TestsAPI\UnitTestApi\UnitTestApi.csproj", "{E515C8B6-6282-4D8B-8523-7B3A13E4AF58}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTestsEntities", "Tests\UnitTestsEntities\UnitTestsEntities.csproj", "{31FA8E5E-D642-4C43-A2B2-02B9832B2CEC}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestsEntities", "Tests\UnitTestsEntities\UnitTestsEntities.csproj", "{31FA8E5E-D642-4C43-A2B2-02B9832B2CEC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Model2Entities", "Model2Entities\Model2Entities.csproj", "{FA329DEF-4756-4A8B-84E9-5A625FF94CBF}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model2Entities", "Model2Entities\Model2Entities.csproj", "{FA329DEF-4756-4A8B-84E9-5A625FF94CBF}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StubAPI", "StubAPI\StubAPI.csproj", "{C9BD0310-DC18-4356-B8A7-2B6959AF7813}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StubAPI", "StubAPI\StubAPI.csproj", "{C9BD0310-DC18-4356-B8A7-2B6959AF7813}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleTestEFMapper", "Tests\ConsoleTestEFMapper\ConsoleTestEFMapper.csproj", "{73EA27F2-9F0C-443F-A5EE-2960C983A422}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTestEFMapper", "Tests\ConsoleTestEFMapper\ConsoleTestEFMapper.csproj", "{73EA27F2-9F0C-443F-A5EE-2960C983A422}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFMappers", "EFMappers\EFMappers.csproj", "{9397795D-F482-44C4-8443-A20AC26671AA}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMappers", "EFMappers\EFMappers.csproj", "{9397795D-F482-44C4-8443-A20AC26671AA}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "APIMappers", "APIMappers\APIMappers.csproj", "{41D18203-1688-43BD-A3AC-FD0C2BD81909}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{330A5DA0-0B4E-48D4-9AF3-6DCB39EE9622}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{330A5DA0-0B4E-48D4-9AF3-6DCB39EE9622}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -86,22 +83,10 @@ Global
{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.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.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.Build.0 = Release|Any CPU
- {CB142F6B-0FF1-45B3-AB46-6F8DCD096C20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CB142F6B-0FF1-45B3-AB46-6F8DCD096C20}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CB142F6B-0FF1-45B3-AB46-6F8DCD096C20}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CB142F6B-0FF1-45B3-AB46-6F8DCD096C20}.Release|Any CPU.Build.0 = Release|Any CPU
- {B9679DCA-F4C8-45BE-A849-44E2BA814083}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {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
@@ -118,31 +103,32 @@ Global
{C9BD0310-DC18-4356-B8A7-2B6959AF7813}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9BD0310-DC18-4356-B8A7-2B6959AF7813}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9BD0310-DC18-4356-B8A7-2B6959AF7813}.Release|Any CPU.Build.0 = Release|Any CPU
- {06DBE9E4-6AA5-4D09-8544-D3ED91E2D980}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {06DBE9E4-6AA5-4D09-8544-D3ED91E2D980}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {06DBE9E4-6AA5-4D09-8544-D3ED91E2D980}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {06DBE9E4-6AA5-4D09-8544-D3ED91E2D980}.Release|Any CPU.Build.0 = Release|Any CPU
{73EA27F2-9F0C-443F-A5EE-2960C983A422}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73EA27F2-9F0C-443F-A5EE-2960C983A422}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73EA27F2-9F0C-443F-A5EE-2960C983A422}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73EA27F2-9F0C-443F-A5EE-2960C983A422}.Release|Any CPU.Build.0 = Release|Any CPU
- {C9C9F2A5-9132-4067-B240-B299D2FCF4E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C9C9F2A5-9132-4067-B240-B299D2FCF4E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C9C9F2A5-9132-4067-B240-B299D2FCF4E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C9C9F2A5-9132-4067-B240-B299D2FCF4E9}.Release|Any CPU.Build.0 = Release|Any CPU
{9397795D-F482-44C4-8443-A20AC26671AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9397795D-F482-44C4-8443-A20AC26671AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9397795D-F482-44C4-8443-A20AC26671AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9397795D-F482-44C4-8443-A20AC26671AA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {41D18203-1688-43BD-A3AC-FD0C2BD81909}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {41D18203-1688-43BD-A3AC-FD0C2BD81909}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {41D18203-1688-43BD-A3AC-FD0C2BD81909}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {41D18203-1688-43BD-A3AC-FD0C2BD81909}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{477D2129-A6C9-4FF8-8BE9-5E9E8E5282F8} = {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}
{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}
{31FA8E5E-D642-4C43-A2B2-02B9832B2CEC} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18}
{73EA27F2-9F0C-443F-A5EE-2960C983A422} = {2B227C67-3BEC-4A83-BDA0-F3918FBC0D18}
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {0F3487F4-66CA-4034-AC66-1BC899C9B523}
+ EndGlobalSection
EndGlobal
diff --git a/src/HeartTrackAPI/AppBootstrap.cs b/src/HeartTrackAPI/AppBootstrap.cs
new file mode 100644
index 0000000..fdbe6a0
--- /dev/null
+++ b/src/HeartTrackAPI/AppBootstrap.cs
@@ -0,0 +1,224 @@
+using System.Reflection;
+using DbContextLib;
+using DbContextLib.Identity;
+using Entities;
+using HeartTrackAPI.Utils;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Identity.UI.Services;
+using Microsoft.AspNetCore.Mvc.ApiExplorer;
+using Microsoft.AspNetCore.Mvc.Versioning;
+using Microsoft.Data.Sqlite;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Options;
+using Microsoft.OpenApi.Models;
+using Model.Manager;
+using Model2Entities;
+using StubAPI;
+using Swashbuckle.AspNetCore.SwaggerGen;
+
+
+namespace HeartTrackAPI;
+
+public class AppBootstrap(IConfiguration configuration)
+{
+ private IConfiguration Configuration { get; } = configuration;
+
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddControllers();
+ services.AddEndpointsApiExplorer();
+ AddSwagger(services);
+ // include Xml comment
+ // addsecurityRequiment
+ // securityDef
+ AddHeartTrackContextServices(services);
+ AddModelService(services);
+ AddIdentityServices(services);
+ AddApiVersioning(services);
+
+ services.AddHealthChecks();
+
+ }
+
+ private void AddHeartTrackContextServices(IServiceCollection services)
+ {
+ string connectionString;
+
+ switch (Environment.GetEnvironmentVariable("TYPE"))
+ {
+ case "BDD":
+ var HOST = System.Environment.GetEnvironmentVariable("HOST");
+ var PORT = System.Environment.GetEnvironmentVariable("PORTDB");
+ 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}";
+ Console.WriteLine(connectionString);
+ Console.WriteLine("======================");
+ Console.WriteLine($"server={HOST};port={PORT};database={DATABASE};user={USERNAME};password={PASSWORD}");
+ Console.WriteLine(connectionString);
+ services.AddDbContext(options =>
+ options.UseMySql($"{connectionString}", new MySqlServerVersion(new Version(10, 11, 1)))
+ , ServiceLifetime.Singleton);
+ break;
+ default:
+ connectionString = Configuration.GetConnectionString("HeartTrackAuthConnection");
+ if (!string.IsNullOrWhiteSpace(connectionString))
+ {
+ services.AddDbContext(options => options.UseInMemoryDatabase("AuthDb"));
+ Console.WriteLine(connectionString);
+ Console.WriteLine("======================");
+ //options => options.UseSqlite(connectionString)
+ //services.AddDbContext();
+ services.AddDbContext(options =>
+ options.UseSqlite(connectionString), ServiceLifetime.Singleton);
+ }
+ else
+ {
+ services.AddDbContext(options => options.UseInMemoryDatabase("AuthDb"));
+ services.AddDbContext(options => options.UseInMemoryDatabase("HeartTrackDb"));
+ }
+ break;
+
+ }
+
+/*
+ services.AddSingleton>(provider =>
+ {
+ var connection = new SqliteConnection("DataSource=:memory:");
+ connection.Open();
+
+ var options = new DbContextOptionsBuilder()
+ .UseSqlite(connection)
+ .Options;
+
+ return options;
+ });*/
+ }
+
+ private void AddModelService(IServiceCollection services)
+ {
+ //services.AddSingleton(provider => new DbDataManager(provider.GetService()));
+ //services.AddSingleton();
+ services.AddSingleton(provider => new DbDataManager(provider.GetRequiredService()));
+
+ //services.AddTransient();
+ }
+
+ private void AddIdentityServices(IServiceCollection services)
+ {
+// services.AddTransient, EmailSender>();
+ services.AddAuthorization();
+
+ services.AddIdentityApiEndpoints()
+ .AddEntityFrameworkStores();
+ //services.AddIdentity()
+ // .AddEntityFrameworkStores().AddDefaultTokenProviders();
+ }
+
+ private void AddApiVersioning(IServiceCollection services)
+ {
+
+ services.AddApiVersioning(opt =>
+ {
+ opt.ReportApiVersions = true;
+ opt.AssumeDefaultVersionWhenUnspecified = true;
+ opt.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
+// options.ApiVersionReader = new HeaderApiVersionReader("api-version");
+
+ opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
+ new HeaderApiVersionReader("x-api-version"),
+ new MediaTypeApiVersionReader("x-api-version"));
+ });
+
+ }
+ private void AddSwagger(IServiceCollection services)
+ {
+ services.AddSwaggerGen(options =>
+ {
+ options.OperationFilter();
+
+ 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()
+ }
+ };
+ options.AddSecurityRequirement(scheme);
+ });
+ services.AddTransient, SwaggerOptions>();
+ services.AddSwaggerGen(options =>
+ {
+ options.OperationFilter();
+ });
+ /* services.AddSwaggerGen(options =>
+ {
+ options.SwaggerDoc("v1", new OpenApiInfo { Title = "HeartTrackAPI", Version = "v1" });
+ options.SwaggerDoc("v2", new OpenApiInfo { Title = "HeartTrackAPI", Version = "v2" });
+ });*/
+
+ services.AddVersionedApiExplorer(setup =>
+ {
+ setup.GroupNameFormat = "'v'VVV";
+ setup.SubstituteApiVersionInUrl = true;
+ });
+
+ }
+
+ public void Configure(WebApplication app, IWebHostEnvironment env)
+ {
+ app.UseHttpsRedirection();
+ app.MapIdentityApi();
+
+ app.MapControllers();
+ app.UseAuthorization();
+
+ app.MapHealthChecks("/health");
+
+ // Configure the HTTP request pipeline.
+ if (true)
+ {
+ var apiVersionDescriptionProvider = app.Services.GetRequiredService();
+ app.UseSwagger();
+ app.UseSwaggerUI();
+ app.MapSwagger();
+ app.UseSwaggerUI(options =>
+ {
+ foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
+
+ //foreach (var description in apiVersionDescriptionProvider)
+ {
+ options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
+ description.GroupName.ToUpperInvariant());
+ }
+ });
+
+ }
+
+
+ }
+}
diff --git a/src/HeartTrackAPI/Controllers/ActivityController.cs b/src/HeartTrackAPI/Controllers/ActivityController.cs
index 5aaf722..d20e167 100644
--- a/src/HeartTrackAPI/Controllers/ActivityController.cs
+++ b/src/HeartTrackAPI/Controllers/ActivityController.cs
@@ -1,22 +1,25 @@
+using APIMappers;
using Dto;
using HeartTrackAPI.Request;
using HeartTrackAPI.Responce;
using Microsoft.AspNetCore.Mvc;
-using Shared;
using Model;
+using Shared;
+using Model.Manager;
using Model.Repository;
namespace HeartTrackAPI.Controllers;
[ApiController]
-[Route("api/activities")]
+[ApiVersion("1.0")]
+[Route("api/v{version:apiVersion}/[controller]")]
public class ActivityController : Controller
{
private readonly IActivityRepository _activityService;
private readonly ILogger _logger;
- public ActivityController(IActivityRepository activityService, ILogger logger)
+ public ActivityController(IDataManager dataManager, ILogger logger)
{
- _activityService = activityService;
+ _activityService = dataManager.ActivityRepo;
_logger = logger;
}
@@ -36,9 +39,12 @@ public class ActivityController : Controller
}
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetActivities), pageRequest);
var activities = await _activityService.GetActivities(pageRequest.Index, pageRequest.Count, ActivityOrderCriteria.None, pageRequest.Descending ?? false);
- // var pageResponse = new PageResponse(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto()));
- // return Ok(pageResponse);
- return Ok();
+ if(activities == null)
+ {
+ return NotFound("No activities found");
+ }
+ var pageResponse = new PageResponse(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto()));
+ return Ok(pageResponse);
}
catch (Exception e)
{
@@ -46,7 +52,64 @@ public class ActivityController : Controller
return StatusCode(500);
}
}
-/*
+ /*
+ [HttpPost]
+ [ProducesResponseType(StatusCodes.Status201Created)]
+ [ProducesResponseType(StatusCodes.Status415UnsupportedMediaType)]
+ [MultipartFormData]
+ [DisableFormValueModelBinding]
+ public async Task PostFitFile( Stream file, string contentType) // [FromForm]
+ {
+ if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
+ {
+ ModelState.AddModelError("File",
+ $"The request couldn't be processed (Error 1).");
+ // Log error
+
+ return BadRequest(ModelState);
+ }
+ if (file == null)
+ {
+ return BadRequest("No file was provided");
+ }
+ //var fileUploadSummary = await _fileService.UploadFileAsync(HttpContext.Request.Body, Request.ContentType);
+// var activity = await _activityManager.AddActivityFromFitFile(file);
+ var activity = new Activity
+ {
+ Id = 1,
+ Type = "Running",
+ Date = new DateTime(2021, 10, 10),
+ StartTime = new DateTime(2021, 10, 10, 10, 0, 0),
+ EndTime = new DateTime(2021, 10, 10, 11, 0, 0),
+ Effort = 3,
+ Variability = 0.5f,
+ Variance = 0.5f,
+ StandardDeviation = 0.5f,
+ Average = 5.0f,
+ Maximum = 10,
+ Minimum = 0,
+ AverageTemperature = 20.0f,
+ HasAutoPause = false,
+ Users =
+ {
+ 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()
+ }
+ }
+ };
+ if (activity == null)
+ {
+ return BadRequest("The file provided is not a valid fit file");
+ }
+ return CreatedAtAction(nameof(GetActivity), new { id = activity.Id }, activity.ToDto());
+ }*/
+
[HttpGet("{id}")]
public async Task> GetActivity(int id)
{
@@ -58,18 +121,6 @@ public class ActivityController : Controller
return Ok(activity.ToDto());
}
- [HttpPost]
- public async Task> PostActivity(ActivityDto activityDto)
- {
- var activity = activityDto.ToModel();
- var result = await _activityService.AddActivity(activity);
- if (result == null)
- {
- return BadRequest();
- }
- return CreatedAtAction(nameof(GetActivity), new { id = result.Id }, result.ToDto());
- }
-
[HttpPut("{id}")]
public async Task PutActivity(int id, ActivityDto activityDto)
{
@@ -95,5 +146,35 @@ public class ActivityController : Controller
return NotFound();
}
return NoContent();
+ }
+
+/*
+ public async Task UploadFileAsync(Stream fileStream, string contentType)
+ {
+ var fileCount = 0;
+ long totalSizeInBytes = 0;
+ var boundary = GetBoundary(MediaTypeHeaderValue.Parse(contentType));
+ var multipartReader = new MultipartReader(boundary, fileStream);
+ var section = await multipartReader.ReadNextSectionAsync();
+ var filePaths = new List();
+ var notUploadedFiles = new List();
+
+ while (section != null)
+ {
+ var fileSection = section.AsFileSection();
+ if (fileSection != null)
+ {
+ totalSizeInBytes += await SaveFileAsync(fileSection, filePaths, notUploadedFiles);
+ fileCount++;
+ }
+ section = await multipartReader.ReadNextSectionAsync();
+ }
+ return new FileUploadSummary
+ {
+ TotalFilesUploaded = fileCount,
+ TotalSizeUploaded = ConvertSizeToString(totalSizeInBytes),
+ FilePaths = filePaths,
+ NotUploadedFiles = notUploadedFiles
+ };
}*/
}
\ No newline at end of file
diff --git a/src/HeartTrackAPI/Controllers/UsersController.cs b/src/HeartTrackAPI/Controllers/UsersController.cs
index a8d0a09..69d2bc9 100644
--- a/src/HeartTrackAPI/Controllers/UsersController.cs
+++ b/src/HeartTrackAPI/Controllers/UsersController.cs
@@ -1,26 +1,42 @@
+using System.ComponentModel.DataAnnotations;
+using APIMappers;
using Dto;
using HeartTrackAPI.Request;
using HeartTrackAPI.Responce;
+using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
-using Model;
using Model.Manager;
using Model.Repository;
using Shared;
namespace HeartTrackAPI.Controllers;
-
+///
+/// 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.
+///
[ApiController]
-[Route("api/users")]
+[ApiVersion("1.0")]
+[Route("api/v{version:apiVersion}/[controller]")]
public class UsersController : Controller
{
private readonly ILogger _logger;
+ private readonly IActivityRepository _activityService;
private readonly IUserRepository _userService;
public UsersController(ILogger logger, IDataManager dataManager)
{
_logger = logger;
_userService = dataManager.UserRepo;
+ _activityService = dataManager.ActivityRepo;
}
-
+
+ ///
+ /// Récupère une page d'utilisateurs en fonction des critères de pagination et de tri fournis.
+ ///
+ /// Les critères de pagination et de tri pour les utilisateurs.
+ /// Une page de données utilisateur selon les critères spécifiés.
+ /// Retourne la page demandée d'utilisateurs.
+ /// La demande de pagination est invalide.
+ /// Erreur interne du serveur.
[HttpGet]
[ProducesResponseType(typeof(PageResponse), 200)]
[ProducesResponseType(400)]
@@ -39,22 +55,29 @@ public class UsersController : Controller
_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(request.Index, request.Count, totalCount, athletes.Select(a => a.ToDto()));
- // return Ok(pageResponse);
- return Ok();
+ var pageResponse = new PageResponse(request.Index, request.Count, totalCount, athletes!.Select(a => a.ToDto()));
+ return Ok(pageResponse);
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting all athletes");
- return StatusCode(500);
+ return Problem();
}
}
+ ///
+ /// Récupère un utilisateur spécifique par son identifiant.
+ ///
+ /// L'identifiant de l'utilisateur à récupérer.
+ /// L'utilisateur correspondant à l'identifiant spécifié.
+ /// Retourne l'utilisateur demandé.
+ /// Aucun utilisateur trouvé pour l'identifiant spécifié.
+ /// Erreur interne du serveur.
[HttpGet("{id}")]
[ProducesResponseType(typeof(UserDto), 200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
- public async Task> GetById(int id)
+ public async Task> GetById([Range(0,int.MaxValue)]int id)
{
try
{
@@ -65,17 +88,21 @@ public class UsersController : Controller
_logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found");
}
- // return Ok(athlete.ToDto());
- return Ok();
+ return Ok(athlete.ToDto());
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting athlete by id {id}", id);
- return StatusCode(500);
+ return Problem();
}
}
-
+ ///
+ /// Obtient le nombre total d'utilisateurs.
+ ///
+ /// Le nombre total d'utilisateurs.
+ /// Retourne le nombre total d'utilisateurs.
+ /// Erreur interne du serveur.
[HttpGet("count")]
[ProducesResponseType(typeof(int), 200)]
[ProducesResponseType(500)]
@@ -90,10 +117,19 @@ public class UsersController : Controller
catch (Exception e)
{
_logger.LogError(e, "Error while getting the number of users");
- return StatusCode(500);
+ return Problem();
}
}
+ ///
+ /// Met à jour les informations d'un utilisateur spécifique.
+ ///
+ /// L'identifiant de l'utilisateur à mettre à jour.
+ /// Les données de l'utilisateur pour la mise à jour.
+ /// L'utilisateur mis à jour.
+ /// Retourne l'utilisateur mis à jour.
+ /// Utilisateur non trouvé.
+ /// Erreur interne du serveur.
[HttpPut("{id}")]
[ProducesResponseType(typeof(UserDto), 200)]
[ProducesResponseType(404)]
@@ -109,23 +145,30 @@ public class UsersController : Controller
_logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found");
}
- // var updatedAthlete = await _userService.UpdateItem(id, user.ToModel());
- // if(updatedAthlete == null)
- // {
- // _logger.LogError("Error while updating athlete with id {id}", id);
- // return StatusCode(500);
- // }
- // return Ok(updatedAthlete.ToDto());
- return Ok();
+ var updatedAthlete = await _userService.UpdateItem(id, user.ToModel());
+ if(updatedAthlete == null)
+ {
+ _logger.LogError("Error while updating athlete with id {id}", id);
+ return Problem();
+ }
+ return Ok(updatedAthlete.ToDto());
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting the number of users");
- return StatusCode(500);
+ return Problem();
}
}
+ ///
+ /// Supprime un utilisateur spécifique.
+ ///
+ /// L'identifiant de l'utilisateur à supprimer.
+ /// Action result.
+ /// Utilisateur supprimé avec succès.
+ /// Utilisateur non trouvé.
+ /// Erreur interne du serveur.
[HttpDelete("{id}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
@@ -147,16 +190,256 @@ public class UsersController : Controller
if(!isDeleted)
{
_logger.LogError("Error while deleting athlete with id {id}", id);
- return StatusCode(500);
+ return Problem();
}
return Ok();
}
catch (Exception e)
{
_logger.LogError(e, "Error while getting the number of users");
- return StatusCode(500);
+ return Problem();
}
}
-
+ ///
+ /// Obtient la liste des amis d'un utilisateur spécifique.
+ ///
+ /// L'identifiant de l'utilisateur.
+ /// Les critères de pagination et de tri.
+ /// La liste paginée des amis.
+ /// Retourne la liste paginée des amis de l'utilisateur.
+ /// Utilisateur non trouvé.
+ /// Erreur interne du serveur.
+ [HttpGet("{id}/friends")]
+ [ProducesResponseType(typeof(PageResponse), 200)]
+ [ProducesResponseType(404)]
+ [ProducesResponseType(500)]
+ public async Task>> GetFriends(int id, [FromQuery] PageRequest request)
+ {
+ try
+ {
+ _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(GetFriends), null,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 totalCount = await _userService.GetNbFriends(athlete);
+ if (request.Count * request.Index >= totalCount)
+ {
+ _logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount);
+ return BadRequest("To many object is asked the max is : " + totalCount);
+ }
+ var friends = await _userService.GetFriends(athlete, request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false);
+ if (friends == null) return NotFound();
+ var pageResponse = new PageResponse(request.Index, request.Count, totalCount, friends.Select(a => a.ToDto()));
+ return Ok(pageResponse);
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Error while getting the number of users");
+ return Problem();
+ }
+ }
+
+ ///
+ /// Ajoute un ami à un utilisateur spécifique.
+ ///
+ /// L'identifiant de l'utilisateur.
+ /// L'identifiant de l'ami à ajouter.
+ /// Action result.
+ /// Ami ajouté avec succès.
+ /// Utilisateur ou ami non trouvé.
+ /// Erreur interne du serveur.
+ [HttpPost("{id}/friend/{friendId}")]
+ [ProducesResponseType(200)]
+ [ProducesResponseType(404)]
+ [ProducesResponseType(500)]
+ public async Task AddFriend(int id, int friendId)
+ {
+ try
+ {
+ _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(AddFriend), friendId,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 friend = await _userService.GetItemById(friendId);
+ if (friend == null)
+ {
+ _logger.LogError("Athlete with id {id} not found", friendId);
+ return NotFound($"Athlete with id {friendId} not found");
+ }
+ var isAdded = await _userService.AddFriend(athlete, friend);
+ if(!isAdded)
+ {
+ _logger.LogError("Error while adding friend with id {friendId} to athlete with id {id}", friendId, id);
+ return Problem();
+ }
+ return Ok();
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Error while getting the number of users");
+ return Problem();
+ }
+ }
+
+
+ ///
+ /// Supprime un ami d'un utilisateur spécifique.
+ ///
+ /// L'identifiant de l'utilisateur.
+ /// L'identifiant de l'ami à supprimer.
+ /// Action result.
+ /// Ami supprimé avec succès.
+ /// Utilisateur ou ami non trouvé.
+ /// Erreur interne du serveur.
+ [HttpDelete("{id}/friend/{friendId}")]
+ [ProducesResponseType(200)]
+ [ProducesResponseType(404)]
+ [ProducesResponseType(500)]
+ public async Task RemoveFriend(int id, int friendId)
+ {
+ try
+ {
+ _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(RemoveFriend), friendId,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 friend = await _userService.GetItemById(friendId);
+ if (friend == null)
+ {
+ _logger.LogError("Athlete with id {id} not found", friendId);
+ return NotFound($"Athlete with id {friendId} not found");
+ }
+ var isRemoved = await _userService.RemoveFriend(athlete, friend);
+ if(!isRemoved)
+ {
+ _logger.LogError("Error while removing friend with id {friendId} to athlete with id {id}", friendId, id);
+ return Problem();
+ }
+ return Ok();
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Error while getting the number of users");
+ return Problem();
+ }
+ }
+
+
+ // #[TODO] [Dave] ou faire un get qui si le role est coach resend les athletes et si le role est athlete resend les coach
+ ///
+ /// Obtient la liste des athlètes d'un coach spécifique.
+ ///
+ /// L'identifiant du coach.
+ /// Les critères de pagination et de tri.
+ /// La liste paginée des athlètes.
+ /// Retourne la liste paginée des athlètes du coach.
+ /// Coach non trouvé.
+ /// Erreur interne du serveur.
+ [HttpGet("{coachId}/athletes")]
+ [ProducesResponseType(typeof(PageResponse), 200)]
+ [ProducesResponseType(404)]
+ [ProducesResponseType(500)]
+ public async Task>> GetAthletes(int coachId, [FromQuery] PageRequest request)
+ {
+ try
+ {
+ _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(GetAthletes), null,coachId);
+ var coach = await _userService.GetItemById(coachId);
+ if (coach == null)
+ {
+ _logger.LogError("Athlete with id {id} not found", coachId);
+ return NotFound($"Athlete with id {coachId} not found");
+ }
+ var totalCount = await _userService.GetNbFriends(coach);
+ if (request.Count * request.Index >= totalCount)
+ {
+ _logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount);
+ return BadRequest("To many object is asked the max is : " + totalCount);
+ }
+ var athletes = await _userService.GetFriends(coach, request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false);
+ if (athletes == null) return NotFound();
+ var pageResponse = new PageResponse(request.Index, request.Count, totalCount, athletes.Select(a => a.ToDto()));
+ return Ok(pageResponse);
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Error while getting the number of users");
+ return Problem();
+ }
+ }
+
+ ///
+ /// Obtient la liste des activités d'un utilisateur spécifique.
+ ///
+ /// L'identifiant de l'utilisateur.
+ /// Les critères de pagination et de tri.
+ /// La liste paginée des activités de l'utilisateur.
+ /// Retourne la liste paginée des activités.
+ /// Aucune activité trouvée.
+ /// Erreur interne du serveur.
+ [HttpGet("{userId}/activities")]
+ // should be tiny DTOActivity returned with only the necessary information (will be used in the list of activities of a user)
+ public async Task>> GetActivitiesByUser(int userId, [FromQuery] PageRequest pageRequest)
+ {
+ try
+ {
+ var totalCount = await _activityService.GetNbActivitiesByUser(userId);
+ if (pageRequest.Count * pageRequest.Index >= totalCount)
+ {
+ _logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount);
+ return BadRequest("To many object is asked the max is : " + totalCount);
+ }
+ _logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetActivitiesByUser), pageRequest);
+ var activities = await _activityService.GetActivitiesByUser(userId, pageRequest.Index, pageRequest.Count, ActivityOrderCriteria.None, pageRequest.Descending ?? false);
+ if(activities == null)
+ {
+ return NotFound("No activities found");
+ }
+ var pageResponse = new PageResponse(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto()));
+ return Ok(pageResponse);
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Error while getting all activities");
+ return Problem();
+ }
+ }
+ /* [TODO] [Dave]
+ [HttpGet("{userId}/trainings")]
+ [ProducesResponseType(typeof(PageResponse), 200)]
+ [ProducesResponseType(404)]
+ [ProducesResponseType(500)]
+ public async Task> GetTrainings(int userId, [FromQuery] PageRequest request)
+ */
+
+ ///
+ /// Déconnecte l'utilisateur actuel.
+ ///
+ /// Le gestionnaire de connexion.
+ /// Paramètre vide utilisé pour s'assurer que la requête provient bien d'un client.
+ /// Action result.
+ /// Déconnexion réussie.
+ /// Déconnexion non autorisée.
+ /// Erreur interne du serveur.
+ [HttpPost("logout")]
+ [ProducesResponseType(200)]
+ [ProducesResponseType(401)]
+ [ProducesResponseType(500)]
+ public async Task Logout(SignInManager signInManager, [FromBody] object? empty)
+ {
+ if (empty == null) return Unauthorized();
+ await signInManager.SignOutAsync();
+ return Ok();
+ }
+
}
\ No newline at end of file
diff --git a/src/HeartTrackAPI/Dockerfile b/src/HeartTrackAPI/Dockerfile
index c8f3264..a00c03b 100644
--- a/src/HeartTrackAPI/Dockerfile
+++ b/src/HeartTrackAPI/Dockerfile
@@ -12,25 +12,34 @@ COPY ["StubbedContextLib/StubbedContextLib.csproj", "StubbedContextLib/"]
COPY ["Shared/Shared.csproj", "Shared/"]
COPY ["Entities/Entities.csproj", "Entities/"]
COPY ["Dto/Dto.csproj", "Dto/"]
-COPY ["ApiMappeur/ApiMappeur.csproj", "ApiMappeur/"]
+COPY ["APIMappers/APIMappers.csproj", "APIMappers/"]
+COPY ["EFMappers/EFMappers.csproj", "EFMappers/"]
COPY ["DbContextLib/DbContextLib.csproj", "DbContextLib/"]
COPY ["Model/Model.csproj", "Model/"]
COPY ["Model2Entities/Model2Entities.csproj", "Model2Entities/"]
COPY ["StubAPI/StubAPI.csproj", "StubAPI/"]
COPY ["StubbedContextLib/StubbedContextLib.csproj", "StubbedContextLib/"]
-
RUN dotnet restore "HeartTrackAPI/HeartTrackAPI.csproj"
COPY . .
+RUN dotnet tool install --global dotnet-ef --version 8.0
+
+ENV PATH="${PATH}:/root/.dotnet/tools"
+# Add the migrations
+RUN dotnet-ef migrations add --project StubbedContextLib/StubbedContextLib.csproj --startup-project HeartTrackAPI/HeartTrackAPI.csproj --context StubbedContextLib.TrainingStubbedContext --configuration Debug Initial
+# Update the database
+RUN dotnet-ef database update --project StubbedContextLib/StubbedContextLib.csproj --startup-project HeartTrackAPI/HeartTrackAPI.csproj --context StubbedContextLib.TrainingStubbedContext --configuration Debug
+RUN chmod 777 HeartTrackAPI/uca.HeartTrack.db
+
WORKDIR "/src/HeartTrackAPI"
-RUN ls
RUN dotnet build "HeartTrackAPI.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "HeartTrackAPI.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
-
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
-RUN ls
+COPY --from=publish /src/HeartTrackAPI/uca.HeartTrack.db .
+RUN ls -l uca.HeartTrack.db
+
ENTRYPOINT ["dotnet", "HeartTrackAPI.dll"]
\ No newline at end of file
diff --git a/src/HeartTrackAPI/FileUploadSummary.cs b/src/HeartTrackAPI/FileUploadSummary.cs
new file mode 100644
index 0000000..1721ae7
--- /dev/null
+++ b/src/HeartTrackAPI/FileUploadSummary.cs
@@ -0,0 +1,44 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+
+namespace HeartTrackAPI;
+
+public class FileUploadSummary
+{
+ public int TotalFilesUploaded { get; set; }
+ public string TotalSizeUploaded { get; set; }
+ public IList FilePaths { get; set; } = new List();
+ public IList NotUploadedFiles { get; set; } = new List();
+}
+[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
+public class MultipartFormDataAttribute : ActionFilterAttribute
+{
+ public override void OnActionExecuting(ActionExecutingContext context)
+ {
+ var request = context.HttpContext.Request;
+
+ if (request.HasFormContentType
+ && request.ContentType.StartsWith("multipart/form-data", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+
+ context.Result = new StatusCodeResult(StatusCodes.Status415UnsupportedMediaType);
+ }
+}
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
+public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
+{
+ public void OnResourceExecuting(ResourceExecutingContext context)
+ {
+ var factories = context.ValueProviderFactories;
+ factories.RemoveType();
+ factories.RemoveType();
+ factories.RemoveType();
+ }
+
+ public void OnResourceExecuted(ResourceExecutedContext context)
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/HeartTrackAPI/HeartTrackAPI.csproj b/src/HeartTrackAPI/HeartTrackAPI.csproj
index 2c5e31d..d8fac4c 100644
--- a/src/HeartTrackAPI/HeartTrackAPI.csproj
+++ b/src/HeartTrackAPI/HeartTrackAPI.csproj
@@ -5,24 +5,31 @@
enable
enable
true
+ true
+ $(NoWarn);1591
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
-
-
-
- ..\..\..\..\..\.nuget\packages\newtonsoft.json\13.0.1\lib\netstandard2.0\Newtonsoft.Json.dll
-
-
-
+
diff --git a/src/HeartTrackAPI/HeartTrackAPI.http b/src/HeartTrackAPI/HeartTrackAPI.http
deleted file mode 100644
index 97c9a67..0000000
--- a/src/HeartTrackAPI/HeartTrackAPI.http
+++ /dev/null
@@ -1,6 +0,0 @@
-@HeartTrackAPI_HostAddress = http://localhost:5030
-
-GET {{HeartTrackAPI_HostAddress}}/weatherforecast/
-Accept: application/json
-
-###
diff --git a/src/HeartTrackAPI/Program.cs b/src/HeartTrackAPI/Program.cs
index b43dfbe..04e64af 100644
--- a/src/HeartTrackAPI/Program.cs
+++ b/src/HeartTrackAPI/Program.cs
@@ -1,25 +1,22 @@
-using Model;
-using Model.Manager;
-using Model.Repository;
-using StubAPI;
+using DbContextLib;
+using HeartTrackAPI;
var builder = WebApplication.CreateBuilder(args);
-// Add services to the container.
-// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
-builder.Services.AddEndpointsApiExplorer();
-builder.Services.AddSwaggerGen();
-builder.Services.AddControllers();
-builder.Services.AddSingleton();
-var app = builder.Build();
+builder.Logging.AddConsole();
+builder.WebHost.ConfigureKestrel(serverOptions =>
+{
+ serverOptions.Limits.MaxRequestBodySize = long.MaxValue;
+});
+
+var init = new AppBootstrap(builder.Configuration);
-// Configure the HTTP request pipeline.
+init.ConfigureServices(builder.Services);
- app.UseSwagger();
- app.UseSwaggerUI();
+var app = builder.Build();
+init.Configure(app, app.Environment);
-app.UseHttpsRedirection();
+app.Services.GetService()!.Database.EnsureCreated();
-app.MapControllers();
app.Run();
\ No newline at end of file
diff --git a/src/HeartTrackAPI/Request/PageRequest.cs b/src/HeartTrackAPI/Request/PageRequest.cs
index 9fad40d..a4399f4 100644
--- a/src/HeartTrackAPI/Request/PageRequest.cs
+++ b/src/HeartTrackAPI/Request/PageRequest.cs
@@ -1,10 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+
namespace HeartTrackAPI.Request;
public class PageRequest
{
-
- public string? OrderingPropertyName { get; set; } = null;// need to be map on the dto OrderCriteria
+ public string? OrderingPropertyName { get; set; } = null;
public bool? Descending { get; set; } = false;
+
+// [Range(0, int.MaxValue, ErrorMessage = "Count must be greater than 0")]
public int Index { get; set; } = 0;
- public int Count { get; set; } = 5;
+
+// [Range(0, int.MaxValue, ErrorMessage = "Count must be greater than 0")]
+ public int Count { get; set; } = 1;
}
diff --git a/src/HeartTrackAPI/Utils/SwaggerDefaultValues.cs b/src/HeartTrackAPI/Utils/SwaggerDefaultValues.cs
new file mode 100644
index 0000000..dd8671c
--- /dev/null
+++ b/src/HeartTrackAPI/Utils/SwaggerDefaultValues.cs
@@ -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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/HeartTrackAPI/Utils/SwaggerOptions.cs b/src/HeartTrackAPI/Utils/SwaggerOptions.cs
new file mode 100644
index 0000000..02c92d8
--- /dev/null
+++ b/src/HeartTrackAPI/Utils/SwaggerOptions.cs
@@ -0,0 +1,68 @@
+using Microsoft.AspNetCore.Mvc.ApiExplorer;
+using Microsoft.Extensions.Options;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+namespace HeartTrackAPI.Utils;
+
+public class SwaggerOptions: IConfigureNamedOptions
+
+ {
+ private readonly IApiVersionDescriptionProvider _provider;
+
+ public SwaggerOptions(
+ IApiVersionDescriptionProvider provider)
+ {
+ _provider = provider;
+ }
+
+ ///
+ /// Configure each API discovered for Swagger Documentation
+ ///
+ ///
+ public void Configure(SwaggerGenOptions options)
+ {
+ // add swagger document for every API version discovered
+ foreach (var description in _provider.ApiVersionDescriptions)
+ {
+ options.SwaggerDoc(
+ description.GroupName,
+ CreateVersionInfo(description));
+ }
+ }
+
+ ///
+ /// Configure Swagger Options. Inherited from the Interface
+ ///
+ ///
+ ///
+ public void Configure(string? name, SwaggerGenOptions options)
+ {
+ Configure(options);
+ }
+
+ ///
+ /// Create information about the version of the API
+ ///
+ ///
+ /// Information about the API
+ private OpenApiInfo CreateVersionInfo(
+ ApiVersionDescription desc)
+ {
+ var info = new OpenApiInfo()
+ {
+ Title = "Web API For HeartTrack .NET 8",
+ 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)
+ {
+ info.Description += " This API version has been deprecated. Please use one of the new APIs available from the explorer.";
+ }
+
+ return info;
+ }
+ }
diff --git a/src/HeartTrackAPI/appsettings.Development.json b/src/HeartTrackAPI/appsettings.Development.json
index ff66ba6..c603414 100644
--- a/src/HeartTrackAPI/appsettings.Development.json
+++ b/src/HeartTrackAPI/appsettings.Development.json
@@ -4,5 +4,8 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
+ },
+ "ConnectionStrings": {
+ "HeartTrackAuthConnection": "Data Source=uca.HeartTrack.db"
}
}
diff --git a/src/HeartTrackAPI/appsettings.json b/src/HeartTrackAPI/appsettings.json
index 4d56694..952a46c 100644
--- a/src/HeartTrackAPI/appsettings.json
+++ b/src/HeartTrackAPI/appsettings.json
@@ -5,5 +5,8 @@
"Microsoft.AspNetCore": "Warning"
}
},
- "AllowedHosts": "*"
+ "AllowedHosts": "*",
+ "ConnectionStrings": {
+ "HeartTrackAuthConnection": "Data Source=uca.HeartTrack.db"
+ }
}
diff --git a/src/Model/Activity.cs b/src/Model/Activity.cs
index 06801bf..cef25b7 100644
--- a/src/Model/Activity.cs
+++ b/src/Model/Activity.cs
@@ -4,7 +4,7 @@ namespace Model;
public class Activity
{
public int Id { get; set; }
- public string Type { get; set; }
+ public string? Type { get; set; }
public DateTime Date { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
@@ -31,8 +31,9 @@ public class Activity
public int Minimum { get; set; }
public float AverageTemperature { get; set; }
public bool HasAutoPause { get; set; }
-
- public Activity(int idActivity ,string type, DateTime date, DateTime startTime, DateTime endTime,
+
+ public HashSet Users { get; private set; } = new HashSet();
+ public Activity(int idActivity ,string? type, DateTime date, DateTime startTime, DateTime endTime,
int effort, float variability, float variance, float standardDeviation,
float average, int maximum, int minimum, float averageTemperature, bool hasAutoPause)
{
diff --git a/src/Model/Manager/ActivityManager.cs b/src/Model/Manager/ActivityManager.cs
new file mode 100644
index 0000000..6cd1ef1
--- /dev/null
+++ b/src/Model/Manager/ActivityManager.cs
@@ -0,0 +1,9 @@
+namespace Model.Manager;
+
+public class ActivityManager : IActivityManager
+{
+ public void AddActivityFromFitFile(byte filePath)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/src/Model/Manager/Contract/IActivityManager.cs b/src/Model/Manager/Contract/IActivityManager.cs
new file mode 100644
index 0000000..2be28cc
--- /dev/null
+++ b/src/Model/Manager/Contract/IActivityManager.cs
@@ -0,0 +1,6 @@
+namespace Model.Manager;
+
+public interface IActivityManager
+{
+ public void AddActivityFromFitFile(byte filePath);
+}
\ No newline at end of file
diff --git a/src/Model/Manager/UserManager.cs b/src/Model/Manager/UserManager.cs
new file mode 100644
index 0000000..d1b697a
--- /dev/null
+++ b/src/Model/Manager/UserManager.cs
@@ -0,0 +1,6 @@
+namespace Model.Manager;
+
+public class UserManager
+{
+
+}
\ No newline at end of file
diff --git a/src/Model/Model.csproj b/src/Model/Model.csproj
index 18de4eb..ead9f5a 100644
--- a/src/Model/Model.csproj
+++ b/src/Model/Model.csproj
@@ -7,7 +7,12 @@
-
+
+
+
+
+
+
diff --git a/src/Model/Repository/IActivityRepository.cs b/src/Model/Repository/IActivityRepository.cs
index 258bbd9..eab97da 100644
--- a/src/Model/Repository/IActivityRepository.cs
+++ b/src/Model/Repository/IActivityRepository.cs
@@ -4,10 +4,12 @@ namespace Model.Repository;
public interface IActivityRepository
{
- public Task> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false);
+ public Task?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false);
public Task GetActivityByIdAsync(int id);
public Task AddActivity(Activity activity);
public Task UpdateActivity(int id, Activity activity);
public Task DeleteActivity(int id);
public Task GetNbItems();
+ public Task?> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria orderCriteria, bool descending= false);
+ public Task GetNbActivitiesByUser(int userId);
}
\ No newline at end of file
diff --git a/src/Model/Repository/IUserRepository.cs b/src/Model/Repository/IUserRepository.cs
index d6d528c..6ba01b9 100644
--- a/src/Model/Repository/IUserRepository.cs
+++ b/src/Model/Repository/IUserRepository.cs
@@ -4,5 +4,14 @@ namespace Model.Repository;
public interface IUserRepository : IGenericRepository
{
- public Task> GetUsers(int index, int count, AthleteOrderCriteria? criteria , bool descending = false);
+ public Task?> GetUsers(int index, int count, AthleteOrderCriteria? criteria , bool descending = false);
+
+ public Task AddFriend(User user, User friend);
+
+ public Task RemoveFriend(User user, User friend);
+
+ // should be removed cause i just have to call the GetItem then get the friends
+ public Task?> GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false);
+
+ public Task GetNbFriends(User user);
}
\ No newline at end of file
diff --git a/src/Model/User.cs b/src/Model/User.cs
index 6efffa8..0991ca5 100644
--- a/src/Model/User.cs
+++ b/src/Model/User.cs
@@ -8,7 +8,7 @@ public class User
public string LastName { get; set; }
public string FirstName { get; set; }
public string Email { get; set; }
- public string MotDePasse { get; set; }
+ public string? MotDePasse { get; set; }
public string Sexe { get; set; }
public float Lenght { get; set; }
public float Weight { get; set; }
@@ -17,6 +17,8 @@ public class User
protected List Notifications { get; set; } = new List();
+ public List Users { get; set; } = new List();
+
public User( string username, string profilePicture, string nom, string prenom, string email, string motDePasse, string sexe, float taille, float poids, DateTime dateNaissance, Role role)
{
Username = username;
diff --git a/src/Model2Entities/ActivityRepository.cs b/src/Model2Entities/ActivityRepository.cs
index facb34c..845d6bb 100644
--- a/src/Model2Entities/ActivityRepository.cs
+++ b/src/Model2Entities/ActivityRepository.cs
@@ -38,7 +38,7 @@ public partial class DbDataManager : IDataManager
{
_logger.LogInformation($"GetActivityByIdAsync with id {id}", id);
// ! By None don't pass the filter
- var activity = _dataManager.DbContext.ActivitiesSet.GetItemsWithFilterAndOrdering(b => b.IdActivity == id, 0, 1, ActivityOrderCriteria.ByType, false).First().ToModel();
+ var activity = _dataManager.DbContext.ActivitiesSet.GetItemsWithFilterAndOrdering(b => b.IdActivity == id, 0, 1, ActivityOrderCriteria.None, false).First().ToModel();
if (activity != null)
_logger.LogInformation($"Retrieved activity with ID {id}");
@@ -121,5 +121,15 @@ public partial class DbDataManager : IDataManager
throw;
}
}
+
+ public Task> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria criteria, bool descending = false)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task GetNbActivitiesByUser(int userId)
+ {
+ throw new NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/src/Model2Entities/DbDataManager.cs b/src/Model2Entities/DbDataManager.cs
index 52f441f..6384b43 100644
--- a/src/Model2Entities/DbDataManager.cs
+++ b/src/Model2Entities/DbDataManager.cs
@@ -10,22 +10,30 @@ public partial class DbDataManager: IDataManager
{
public IActivityRepository ActivityRepo { get; }
public IUserRepository UserRepo { get; }
-
protected HeartTrackContext DbContext { get; }
// mettre si pb lors d'une requete si rollback ou pas
public DbDataManager(HeartTrackContext dbContext)
{
DbContext = dbContext;
+ Console.WriteLine("Contexttttttttt");
+ Console.WriteLine($"Database created Context: {DbContext.Database.EnsureCreated()}");
ActivityRepo = new ActivityRepository(this);
UserRepo = new UserRepository(this);
ActivityMapper.Reset();
// Faire pour les autres reset() des autres mappers
}
+
+ public DbDataManager(string dbPlatformPath)
+ : this(new HeartTrackContext(dbPlatformPath))
+ {
+ Console.WriteLine($"Database created String: {DbContext.Database.EnsureCreated()}"); }
+
public DbDataManager()
{
DbContext = new HeartTrackContext();
+ Console.WriteLine($"Database created None: {DbContext.Database.EnsureCreated()}");
ActivityRepo = new ActivityRepository(this);
UserRepo= new UserRepository(this);
}
diff --git a/src/Model2Entities/Extension.cs b/src/Model2Entities/Extension.cs
index 24c1e2b..ea02563 100644
--- a/src/Model2Entities/Extension.cs
+++ b/src/Model2Entities/Extension.cs
@@ -7,28 +7,25 @@ namespace Model2Entities;
public static class Extensions
{
- internal static Task AddItem(this HeartTrackContext context, T? item) where T :class
+ internal static async Task AddItem(this HeartTrackContext context, T? item) where T :class
{
if(item == null || context.Set().Contains(item))
{
- return Task.FromResult(default(T));
+ return await Task.FromResult(null);
}
- context.Set().Add(item);
- context.SaveChangesAsync();
+ var entry = context.Set().Add(item);
+ await context.SaveChangesAsync();
- return Task.FromResult(item);
+ return await Task.FromResult(entry.Entity);
}
- internal static Task DeleteItem(this HeartTrackContext context, int? id) where T:class
+ internal static async Task DeleteItem(this HeartTrackContext context, int? id) where T:class
{
- var item = context.Set().Find(id);
- if(item == null)
- {
- return Task.FromResult(false);
- }
+ var item = await context.Set().FindAsync(id);
+ if(item == null) return await Task.FromResult(false);
context.Set().Remove(item);
- context.SaveChangesAsync();
- return Task.FromResult(true);
+ await context.SaveChangesAsync();
+ return await Task.FromResult(true);
}
internal static async Task UpdateItem(this IList collection, T? oldItem, T? newItem) where T : class
@@ -50,10 +47,11 @@ public static class Extensions
{
var filteredList = list.Where(filter);
- if(orderCriterium != null)
+ if(orderCriterium != null && orderCriterium.ToString() != "None")
{
filteredList = filteredList.OrderByCriteria(orderCriterium, descending);
- }
+ }
+
return filteredList
.Skip(index * count)
.Take(count);
diff --git a/src/Model2Entities/Model2Entities.csproj b/src/Model2Entities/Model2Entities.csproj
index bb068f4..d298015 100644
--- a/src/Model2Entities/Model2Entities.csproj
+++ b/src/Model2Entities/Model2Entities.csproj
@@ -10,6 +10,14 @@
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
diff --git a/src/Model2Entities/UserRepository.cs b/src/Model2Entities/UserRepository.cs
index e9716f1..7791636 100644
--- a/src/Model2Entities/UserRepository.cs
+++ b/src/Model2Entities/UserRepository.cs
@@ -49,5 +49,25 @@ public partial class DbDataManager
{
throw new NotImplementedException();
}
+
+ public async Task AddFriend(User user, User friend)
+ {
+ throw new NotImplementedException();
+ }
+
+ public async Task RemoveFriend(User user, User friend)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task?>? GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task GetNbFriends(User user)
+ {
+ throw new NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/src/Shared/Extension.cs b/src/Shared/Extension.cs
index 121352c..6301ad7 100644
--- a/src/Shared/Extension.cs
+++ b/src/Shared/Extension.cs
@@ -2,7 +2,7 @@ namespace Shared;
public static class Extensions
{
- public static U? ToU(this T t, GenericMapper mapper, Func func) where U :class where T :class
+ public static U ToU(this T t, GenericMapper mapper, Func func) where U :class where T :class
{
var u = mapper.GetU(t);
if (u != null) {
@@ -14,7 +14,7 @@ public static class Extensions
return u;
}
// , Action action
- public static T? ToT(this U u, GenericMapper mapper, Func func) where U :class where T :class
+ public static T ToT(this U u, GenericMapper mapper, Func func) where U :class where T :class
{
var t = mapper.GetT(u);
if (t != null) {
diff --git a/src/StubAPI/ActivityService.cs b/src/StubAPI/ActivityService.cs
index 0e87004..2b274ae 100644
--- a/src/StubAPI/ActivityService.cs
+++ b/src/StubAPI/ActivityService.cs
@@ -6,33 +6,73 @@ namespace StubAPI;
public class ActivityService: IActivityRepository
{
- public async Task> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private List _activities = new List(
+ new Activity[]
+ {
+ new Activity
+ {
+ Id = 1,
+ Type = "Running",
+ Date = new DateTime(2021, 10, 10),
+ StartTime = new DateTime(2021, 10, 10, 10, 0, 0),
+ EndTime = new DateTime(2021, 10, 10, 11, 0, 0),
+ Effort = 3,
+ Variability = 0.5f,
+ Variance = 0.5f,
+ StandardDeviation = 0.5f,
+ Average = 5.0f,
+ Maximum = 10,
+ Minimum = 0,
+ AverageTemperature = 20.0f,
+ HasAutoPause = false,
+ Users = {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()
+ }}
+ },
+ }
+ );
+
+ public async Task?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false)
+ => await Task.FromResult(_activities.GetItemsWithFilterAndOrdering(c=>true,index, count,criteria != ActivityOrderCriteria.None ? criteria: null , descending));
- public async Task GetActivityByIdAsync(int id)
+ public Task GetActivityByIdAsync(int id)
{
- throw new NotImplementedException();
+ return Task.FromResult(_activities.FirstOrDefault(s => s.Id == id));
}
- public async Task AddActivity(Activity activity)
+ public Task AddActivity(Activity activity)
+ => _activities.AddItem(activity);
+
+
+ public async Task UpdateActivity(int id, Activity activity)
{
- throw new NotImplementedException();
+ var oldActivity = _activities.FirstOrDefault(s => s.Id == id);
+ if (oldActivity == null) return null;
+ return await _activities.UpdateItem(oldActivity, activity);
}
- public async Task UpdateActivity(int id, Activity activity)
+ public Task DeleteActivity(int id)
{
- throw new NotImplementedException();
+ var activity = _activities.FirstOrDefault(s => s.Id == id);
+ if (activity == null) return Task.FromResult(false);
+ return _activities.DeleteItem(activity);
}
- public async Task DeleteActivity(int id)
+ public Task GetNbItems()
+ => Task.FromResult(_activities.Count);
+
+ public async Task?> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria criteria, bool descending = false)
{
- throw new NotImplementedException();
+ var activities = _activities.GetItemsWithFilterAndOrdering(c => c.Users.Any(u => u.Id == userId), index, count,
+ criteria != ActivityOrderCriteria.None ? criteria : null, descending);
+ return await Task.FromResult(activities);
}
- public async Task GetNbItems()
+ public Task GetNbActivitiesByUser(int userId)
{
- throw new NotImplementedException();
+ return Task.FromResult(_activities.Count(a => a.Users.Any(u => u.Id == userId)));
}
}
\ No newline at end of file
diff --git a/src/StubAPI/AthleteService.cs b/src/StubAPI/AthleteService.cs
index b1b1a28..7729296 100644
--- a/src/StubAPI/AthleteService.cs
+++ b/src/StubAPI/AthleteService.cs
@@ -34,14 +34,53 @@ public class UserService : IUserRepository
public async Task> 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> GetItems(int index, int count, string? orderingProperty = null,
- bool descending = false)
+ public async Task AddFriend(User user, User friend)
{
+ if (user == null || friend == null)
+ {
+ return false;
+ }
+
+ if (user.Users.Contains(friend))
+ {
+ return false;
+ }
- return await this.GetUsers(index, count, this.ToEnum(orderingProperty), descending);
+ user.Users.Add(friend);
+ return true;
}
+ public async Task RemoveFriend(User user, User friend)
+ {
+ if (user == null || friend == null)
+ {
+ return false;
+ }
+
+ if (!user.Users.Contains(friend))
+ {
+ return false;
+ }
+
+ user.Users.Remove(friend);
+
+ return true;
+ }
+
+ public async Task?>? GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false)
+ =>await Task.FromResult(athletes.FirstOrDefault(s => s.Id == user.Id)?.Users.GetItemsWithFilterAndOrdering(c=>true,index, count,criteria, descending));
+
+ public Task GetNbFriends(User user)
+ {
+ return Task.FromResult(athletes.FirstOrDefault(s => s.Id == user.Id)?.Users.Count ?? 0);
+ }
+
+ public async Task> GetItems(int index, int count, string? orderingProperty = null,
+ bool descending = false)
+ =>await GetUsers(index, count, this.ToEnum(orderingProperty), descending);
+
+
public async Task GetItemById(int id)
=>await Task.FromResult(athletes.FirstOrDefault(s => s.Id == id));
diff --git a/src/StubAPI/Extensions.cs b/src/StubAPI/Extensions.cs
index 9917cac..af6f004 100644
--- a/src/StubAPI/Extensions.cs
+++ b/src/StubAPI/Extensions.cs
@@ -39,13 +39,15 @@ public static class Extensions
public static IEnumerable GetItemsWithFilterAndOrdering(this IEnumerable list, Func filter, int index, int count, Enum? orderCriterium, bool descending = false ) where T : class
{
- var filteredList = list.Where(filter);
+ IEnumerable query = list;
+
+ query = query.Where(filter);
if(orderCriterium != null)
{
- filteredList = filteredList.OrderByCriteria(orderCriterium, descending);
+ query = query.OrderByCriteria(orderCriterium, descending);
}
- return filteredList
+ return query
.Skip(index * count)
.Take(count);
}
diff --git a/src/StubbedContextLib/StubbedContextLib.csproj b/src/StubbedContextLib/StubbedContextLib.csproj
index ecea2c4..0c5f479 100644
--- a/src/StubbedContextLib/StubbedContextLib.csproj
+++ b/src/StubbedContextLib/StubbedContextLib.csproj
@@ -1,16 +1,20 @@
-
-
-
+
+
+
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
diff --git a/src/Tests/TestsAPI/TestsXUnit/GlobalUsings.cs b/src/Tests/TestsAPI/TestsXUnit/GlobalUsings.cs
deleted file mode 100644
index 8c927eb..0000000
--- a/src/Tests/TestsAPI/TestsXUnit/GlobalUsings.cs
+++ /dev/null
@@ -1 +0,0 @@
-global using Xunit;
\ No newline at end of file
diff --git a/src/Tests/TestsAPI/TestsXUnit/UnitTest1.cs b/src/Tests/TestsAPI/TestsXUnit/UnitTest1.cs
deleted file mode 100644
index 70d745a..0000000
--- a/src/Tests/TestsAPI/TestsXUnit/UnitTest1.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace TestsXUnit;
-
-public class UnitTest1
-{
- [Fact]
- public void Test1()
- {
-
- }
-}
\ No newline at end of file
diff --git a/src/Tests/TestsAPI/UnitTestApi/Controllers/UsersControllerTest.cs b/src/Tests/TestsAPI/UnitTestApi/Controllers/UsersControllerTest.cs
new file mode 100644
index 0000000..1d1500c
--- /dev/null
+++ b/src/Tests/TestsAPI/UnitTestApi/Controllers/UsersControllerTest.cs
@@ -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 _dataManagerMock;
+ private IDataManager _dataManager;
+ private UsersController _usersController;
+
+ private readonly List _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();
+
+ _dataManagerMock.Setup(dm => dm.UserRepo.GetNbItems()).ReturnsAsync(_users.Count);
+ _dataManagerMock.Setup(dm =>
+ dm.UserRepo.GetUsers(It.IsAny(), It.IsAny(), It.IsAny(),
+ It.IsAny())).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(), _dataManagerMock.Object);
+ }
+/*
+ [TestInitialize]
+ public void SetUp()
+ {
+ _dataManager = new StubData();
+ _usersController = new UsersController(new NullLogger(), _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));
+ var pageResponse = okResult.Value as PageResponse;
+ 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));
+ var pageResponse = okResult.Value as PageResponse;
+ Assert.IsNotNull(pageResponse);
+ Assert.AreEqual(expectedItemCount, pageResponse.Items.Count());
+ }
+
+ [TestMethod]
+ public async Task Get_ReturnsInternalServerError_OnException()
+ {
+ _dataManagerMock.Setup(dm =>
+ dm.UserRepo.GetUsers(It.IsAny(), It.IsAny(), It.IsAny(),
+ It.IsAny()))
+ .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));
+ }
+
+}
\ No newline at end of file
diff --git a/src/Tests/TestsAPI/UnitTestApi/UnitTestApi.csproj b/src/Tests/TestsAPI/UnitTestApi/UnitTestApi.csproj
index 45b5c8f..9931d8b 100644
--- a/src/Tests/TestsAPI/UnitTestApi/UnitTestApi.csproj
+++ b/src/Tests/TestsAPI/UnitTestApi/UnitTestApi.csproj
@@ -10,7 +10,9 @@
+
+
diff --git a/src/Tests/TestsAPI/UnitTestApi/UserControllerTest.cs b/src/Tests/TestsAPI/UnitTestApi/UserControllerTest.cs
deleted file mode 100644
index dd511e7..0000000
--- a/src/Tests/TestsAPI/UnitTestApi/UserControllerTest.cs
+++ /dev/null
@@ -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(), 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));
- }
- /*
- [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",
- };
-
- }*/
-
-}
\ No newline at end of file
diff --git a/src/Tests/UnitTestsEntities/ActivityEntityTests.cs b/src/Tests/UnitTestsEntities/ActivityEntityTests.cs
new file mode 100644
index 0000000..62caaae
--- /dev/null
+++ b/src/Tests/UnitTestsEntities/ActivityEntityTests.cs
@@ -0,0 +1,140 @@
+namespace UnitTestsEntities;
+using Xunit;
+using System.Linq;
+using Entities;
+using Microsoft.EntityFrameworkCore;
+
+public class ActivityEntityTests
+{
+ [Fact]
+ public void Add_Activity_Success()
+ {
+
+
+ var activity = new ActivityEntity
+ {
+ Type = "Running",
+ Date = new DateOnly(2024, 3, 15),
+ StartTime = new TimeOnly(9, 0),
+ EndTime = new TimeOnly(10, 0),
+ EffortFelt = 7,
+ Variability = 0.5f,
+ Variance = 0.2f,
+ StandardDeviation = 0.3f,
+ Average = 0.4f,
+ Maximum = 200,
+ Minimum = 100,
+ AverageTemperature = 25.5f,
+ HasAutoPause = true,
+ DataSourceId = 1,
+ AthleteId = 1
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Activities.Add(activity);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedActivity = context.Activities.First(a => a.Type == "Running");
+ Assert.NotNull(savedActivity);
+ Assert.Equal("Running", savedActivity.Type );
+
+ }*/
+ }
+
+ [Fact]
+ public void Update_Activity_Success()
+ {
+ var activity = new ActivityEntity
+ {
+ Type = "Running",
+ Date = new DateOnly(2024, 3, 15),
+ StartTime = new TimeOnly(9, 0),
+ EndTime = new TimeOnly(10, 0),
+ EffortFelt = 7,
+ Variability = 0.5f,
+ Variance = 0.2f,
+ StandardDeviation = 0.3f,
+ Average = 0.4f,
+ Maximum = 200,
+ Minimum = 100,
+ AverageTemperature = 25.5f,
+ HasAutoPause = true,
+ DataSourceId = 1,
+ AthleteId = 1
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Activities.Add(activity);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedActivity = context.Activities.First(a => a.Type == "Running");
+ savedActivity.Type = "Walking";
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var updatedActivity = context.Activities.First(a => a.Type == "Walking");
+ Assert.NotNull(updatedActivity);
+ Assert.Equal("Walking", updatedActivity.Type );
+ Assert.Equal(7, updatedActivity.EffortFelt );
+ }*/
+ }
+
+ [Fact]
+ public void Delete_Activity_Success()
+ {
+ var activity = new ActivityEntity
+ {
+ Type = "Running",
+ Date = new DateOnly(2024, 3, 15),
+ StartTime = new TimeOnly(9, 0),
+ EndTime = new TimeOnly(10, 0),
+ EffortFelt = 7,
+ Variability = 0.5f,
+ Variance = 0.2f,
+ StandardDeviation = 0.3f,
+ Average = 0.4f,
+ Maximum = 200,
+ Minimum = 100,
+ AverageTemperature = 25.5f,
+ HasAutoPause = true,
+ DataSourceId = 1,
+ AthleteId = 1
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Activities.Add(activity);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedActivity = context.Activities.First(a => a.Type == "Running");
+ context.Activities.Remove(savedActivity);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var deletedActivity = context.Activities.FirstOrDefault(a => a.Type == "Running");
+ Assert.Null(deletedActivity);
+ }*/
+ }
+}
+
diff --git a/src/Tests/UnitTestsEntities/AthleteEntityTests.cs b/src/Tests/UnitTestsEntities/AthleteEntityTests.cs
new file mode 100644
index 0000000..878d7d8
--- /dev/null
+++ b/src/Tests/UnitTestsEntities/AthleteEntityTests.cs
@@ -0,0 +1,122 @@
+namespace UnitTestsEntities;
+using Xunit;
+using System.Linq;
+using Entities;
+using Microsoft.EntityFrameworkCore;
+
+public class AthleteEntityTests
+{
+ [Fact]
+ public void Add_Athlete_Success()
+ {
+ var athlete = new AthleteEntity
+ {
+ Username = "john_doe",
+ LastName = "Doe",
+ FirstName = "John",
+ Email = "john.doe@example.com",
+ Sexe = "M",
+ Length = 180.0,
+ Weight = 75.5f,
+ Password = "password",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(athlete);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedAthlete = context.Athletes.First(a => a.Username == "john_doe");
+ Assert.NotNull(savedAthlete);
+ Assert.Equal("john_doe", savedAthlete.Username);
+ }*/
+ }
+
+ [Fact]
+ public void Update_Athlete_Success()
+ {
+ var athlete = new AthleteEntity
+ {
+ Username = "jane_smith",
+ LastName = "Smith",
+ FirstName = "Jane",
+ Email = "jane.smith@example.com",
+ Sexe = "F",
+ Length = 165.0,
+ Weight = 60.0f,
+ Password = "password123",
+ DateOfBirth = new DateOnly(1995, 5, 10),
+ IsCoach = false
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(athlete);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedAthlete = context.Athletes.First(a => a.Username == "jane_smith");
+ savedAthlete.Username = "jane_doe";
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var updatedAthlete = context.Athletes.First(a => a.Username == "jane_doe");
+ Assert.NotNull(updatedAthlete);
+ Assert.Equal("jane_doe", updatedAthlete.Username);
+ Assert.Equal("Smith", updatedAthlete.LastName);
+ }*/
+ }
+
+ [Fact]
+ public void Delete_Athlete_Success()
+ {
+ var athlete = new AthleteEntity
+ {
+ Username = "test_user",
+ LastName = "Test",
+ FirstName = "User",
+ Email = "test.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "testpassword",
+ DateOfBirth = new DateOnly(1985, 10, 20),
+ IsCoach = false
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(athlete);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedAthlete = context.Athletes.First(a => a.Username == "test_user");
+ context.Athletes.Remove(savedAthlete);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var deletedAthlete = context.Athletes.FirstOrDefault(a => a.Username == "test_user");
+ Assert.Null(deletedAthlete);
+ }*/
+ }
+}
+
diff --git a/src/Tests/UnitTestsEntities/DataSourceEntityTests.cs b/src/Tests/UnitTestsEntities/DataSourceEntityTests.cs
new file mode 100644
index 0000000..6f4c1db
--- /dev/null
+++ b/src/Tests/UnitTestsEntities/DataSourceEntityTests.cs
@@ -0,0 +1,102 @@
+namespace UnitTestsEntities;
+using Xunit;
+using System.Linq;
+using Entities;
+using Microsoft.EntityFrameworkCore;
+
+
+public class DataSourceEntityTests
+{
+ [Fact]
+ public void Add_DataSource_Success()
+ {
+ var dataSource = new DataSourceEntity
+ {
+ Type = "GPS",
+ Model = "Garmin Forerunner 945",
+ Precision = 0.1f
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.DataSources.Add(dataSource);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedDataSource = context.DataSources.First(d => d.Type == "GPS");
+ Assert.NotNull(savedDataSource);
+ Assert.Equal("Garmin Forerunner 945", savedDataSource.Model);
+ }*/
+ }
+
+ [Fact]
+ public void Update_DataSource_Success()
+ {
+ var dataSource = new DataSourceEntity
+ {
+ Type = "Heart Rate Monitor",
+ Model = "Polar H10",
+ Precision = 0.2f
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.DataSources.Add(dataSource);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedDataSource = context.DataSources.First(d => d.Type == "Heart Rate Monitor");
+ savedDataSource.Model = "Polar H9";
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var updatedDataSource = context.DataSources.First(d => d.Model == "Polar H9");
+ Assert.NotNull(updatedDataSource);
+ Assert.Equal("Heart Rate Monitor", updatedDataSource.Type);
+ Assert.Equal(0.2f, updatedDataSource.Precision);
+ }*/
+ }
+
+ [Fact]
+ public void Delete_DataSource_Success()
+ {
+ var dataSource = new DataSourceEntity
+ {
+ Type = "Smartwatch",
+ Model = "Apple Watch Series 6",
+ Precision = 0.05f
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.DataSources.Add(dataSource);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedDataSource = context.DataSources.First(d => d.Type == "Smartwatch");
+ context.DataSources.Remove(savedDataSource);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var deletedDataSource = context.DataSources.FirstOrDefault(d => d.Type == "Smartwatch");
+ Assert.Null(deletedDataSource);
+ }*/
+ }
+}
+
diff --git a/src/Tests/UnitTestsEntities/FriendshipEntityTests.cs b/src/Tests/UnitTestsEntities/FriendshipEntityTests.cs
new file mode 100644
index 0000000..492506c
--- /dev/null
+++ b/src/Tests/UnitTestsEntities/FriendshipEntityTests.cs
@@ -0,0 +1,206 @@
+namespace UnitTestsEntities;
+using Xunit;
+using System.Linq;
+using Entities;
+using Microsoft.EntityFrameworkCore;
+
+public class FriendshipEntityTests
+{
+ [Fact]
+ public void Add_Friendship_Success()
+ {
+ var follower = new AthleteEntity
+ {
+ Username = "follower_user",
+ LastName = "Follower",
+ FirstName = "User",
+ Email = "follower.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "followerpassword",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ var following = new AthleteEntity
+ {
+ Username = "following_user",
+ LastName = "Following",
+ FirstName = "User",
+ Email = "following.user@example.com",
+ Sexe = "F",
+ Length = 165.0,
+ Weight = 60.0f,
+ Password = "followingpassword",
+ DateOfBirth = new DateOnly(1995, 5, 10),
+ IsCoach = false
+ };
+
+ var friendship = new FriendshipEntity
+ {
+ Follower = follower,
+ Following = following,
+ StartDate = DateTime.Now
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(follower);
+ context.Athletes.Add(following);
+ context.Friendships.Add(friendship);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedFriendship = context.Friendships.FirstOrDefault();
+ Assert.NotNull(savedFriendship);
+ Assert.Equal(follower.IdAthlete, savedFriendship.FollowerId);
+ Assert.Equal(following.IdAthlete, savedFriendship.FollowingId);
+ }*/
+ }
+
+ [Fact]
+ public void Update_Friendship_Success()
+ {
+ var follower = new AthleteEntity
+ {
+ Username = "follower_user",
+ LastName = "Follower",
+ FirstName = "User",
+ Email = "follower.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "followerpassword",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ var following = new AthleteEntity
+ {
+ Username = "following_user",
+ LastName = "Following",
+ FirstName = "User",
+ Email = "following.user@example.com",
+ Sexe = "F",
+ Length = 165.0,
+ Weight = 60.0f,
+ Password = "followingpassword",
+ DateOfBirth = new DateOnly(1995, 5, 10),
+ IsCoach = false
+ };
+
+ var thirdAthlete = new AthleteEntity
+ {
+ Username = "third_user",
+ LastName = "Third",
+ FirstName = "User",
+ Email = "third.user@example.com",
+ Sexe = "M",
+ Length = 180.0,
+ Weight = 75.0f,
+ Password = "thirdpassword",
+ DateOfBirth = new DateOnly(1988, 3, 15),
+ IsCoach = false
+ };
+
+ var friendship = new FriendshipEntity
+ {
+ Follower = follower,
+ Following = following,
+ StartDate = DateTime.Now
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(follower);
+ context.Athletes.Add(following);
+ context.Athletes.Add(thirdAthlete);
+ context.Friendships.Add(friendship);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedFriendship = context.Friendships.FirstOrDefault();
+ savedFriendship.Follower = thirdAthlete; // Update the follower
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var updatedFriendship = context.Friendships.FirstOrDefault();
+ Assert.NotNull(updatedFriendship);
+ Assert.Equal(thirdAthlete.IdAthlete, updatedFriendship.FollowerId);
+ }*/
+ }
+
+ [Fact]
+ public void Delete_Friendship_Success()
+ {
+ var follower = new AthleteEntity
+ {
+ Username = "follower_user",
+ LastName = "Follower",
+ FirstName = "User",
+ Email = "follower.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "followerpassword",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ var following = new AthleteEntity
+ {
+ Username = "following_user",
+ LastName = "Following",
+ FirstName = "User",
+ Email = "following.user@example.com",
+ Sexe = "F",
+ Length = 165.0,
+ Weight = 60.0f,
+ Password = "followingpassword",
+ DateOfBirth = new DateOnly(1995, 5, 10),
+ IsCoach = false
+ };
+
+ var friendship = new FriendshipEntity
+ {
+ Follower = follower,
+ Following = following,
+ StartDate = DateTime.Now
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(follower);
+ context.Athletes.Add(following);
+ context.Friendships.Add(friendship);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedFriendship = context.Friendships.FirstOrDefault();
+ context.Friendships.Remove(savedFriendship);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var deletedFriendship = context.Friendships.FirstOrDefault();
+ Assert.Null(deletedFriendship);
+ }*/
+ }
+}
+
diff --git a/src/Tests/UnitTestsEntities/HeartRateEntityTests.cs b/src/Tests/UnitTestsEntities/HeartRateEntityTests.cs
new file mode 100644
index 0000000..c3bc36f
--- /dev/null
+++ b/src/Tests/UnitTestsEntities/HeartRateEntityTests.cs
@@ -0,0 +1,172 @@
+namespace UnitTestsEntities;
+using Xunit;
+using System.Linq;
+using Entities;
+using Microsoft.EntityFrameworkCore;
+
+public class HeartRateEntityTests
+{
+ [Fact]
+ public void Add_HeartRate_Success()
+ {
+ var activity = new ActivityEntity
+ {
+ Type = "Running",
+ Date = new DateOnly(2024, 3, 15),
+ StartTime = new TimeOnly(9, 0),
+ EndTime = new TimeOnly(10, 0),
+ EffortFelt = 7,
+ Variability = 0.5f,
+ Variance = 0.2f,
+ StandardDeviation = 0.3f,
+ Average = 0.4f,
+ Maximum = 200,
+ Minimum = 100,
+ AverageTemperature = 25.5f,
+ HasAutoPause = true,
+ DataSourceId = 1,
+ AthleteId = 1
+ };
+
+ var heartRateEntry = new HeartRateEntity
+ {
+ Altitude = 100.0,
+ Time = new TimeOnly(9, 30),
+ Temperature = 20.0f,
+ Bpm = 150,
+ Longitude = 45.12345f,
+ Latitude = 35.6789f,
+ Activity = activity
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Activities.Add(activity);
+ context.HeartRates.Add(heartRateEntry);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedHeartRate = context.HeartRates.First();
+ Assert.NotNull(savedHeartRate);
+ Assert.Equal(150, savedHeartRate.Bpm);
+ }*/
+ }
+
+ [Fact]
+ public void Update_HeartRate_Success()
+ {
+ var activity = new ActivityEntity
+ {
+ Type = "Running",
+ Date = new DateOnly(2024, 3, 15),
+ StartTime = new TimeOnly(9, 0),
+ EndTime = new TimeOnly(10, 0),
+ EffortFelt = 7,
+ Variability = 0.5f,
+ Variance = 0.2f,
+ StandardDeviation = 0.3f,
+ Average = 0.4f,
+ Maximum = 200,
+ Minimum = 100,
+ AverageTemperature = 25.5f,
+ HasAutoPause = true,
+ DataSourceId = 1,
+ AthleteId = 1
+ };
+
+ var heartRateEntry = new HeartRateEntity
+ {
+ Altitude = 100.0,
+ Time = new TimeOnly(9, 30),
+ Temperature = 20.0f,
+ Bpm = 150,
+ Longitude = 45.12345f,
+ Latitude = 35.6789f,
+ Activity = activity
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Activities.Add(activity);
+ context.HeartRates.Add(heartRateEntry);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedHeartRate = context.HeartRates.First();
+ savedHeartRate.Bpm = 160;
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var updatedHeartRate = context.HeartRates.First();
+ Assert.NotNull(updatedHeartRate);
+ Assert.Equal(160, updatedHeartRate.Bpm);
+ }*/
+ }
+
+ [Fact]
+ public void Delete_HeartRate_Success()
+ {
+ var activity = new ActivityEntity
+ {
+ Type = "Running",
+ Date = new DateOnly(2024, 3, 15),
+ StartTime = new TimeOnly(9, 0),
+ EndTime = new TimeOnly(10, 0),
+ EffortFelt = 7,
+ Variability = 0.5f,
+ Variance = 0.2f,
+ StandardDeviation = 0.3f,
+ Average = 0.4f,
+ Maximum = 200,
+ Minimum = 100,
+ AverageTemperature = 25.5f,
+ HasAutoPause = true,
+ DataSourceId = 1,
+ AthleteId = 1
+ };
+
+ var heartRateEntry = new HeartRateEntity
+ {
+ Altitude = 100.0,
+ Time = new TimeOnly(9, 30),
+ Temperature = 20.0f,
+ Bpm = 150,
+ Longitude = 45.12345f,
+ Latitude = 35.6789f,
+ Activity = activity
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Activities.Add(activity);
+ context.HeartRates.Add(heartRateEntry);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedHeartRate = context.HeartRates.First();
+ context.HeartRates.Remove(savedHeartRate);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var deletedHeartRate = context.HeartRates.FirstOrDefault();
+ Assert.Null(deletedHeartRate);
+ }*/
+ }
+}
+
diff --git a/src/Tests/UnitTestsEntities/NotificationEntityTests.cs b/src/Tests/UnitTestsEntities/NotificationEntityTests.cs
new file mode 100644
index 0000000..6d656a4
--- /dev/null
+++ b/src/Tests/UnitTestsEntities/NotificationEntityTests.cs
@@ -0,0 +1,151 @@
+namespace UnitTestsEntities;
+using Xunit;
+using System.Linq;
+using Entities;
+using Microsoft.EntityFrameworkCore;
+
+public class NotificationEntityTests
+{
+ [Fact]
+ public void Add_Notification_Success()
+ {
+ var sender = new AthleteEntity
+ {
+ Username = "sender_user",
+ LastName = "Sender",
+ FirstName = "User",
+ Email = "sender.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "senderpassword",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ var notification = new NotificationEntity
+ {
+ Message = "Test notification",
+ Date = DateTime.Now,
+ Statut = false,
+ Urgence = "High",
+ Sender = sender
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(sender);
+ context.Notifications.Add(notification);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedNotification = context.Notifications.First();
+ Assert.NotNull(savedNotification);
+ Assert.Equal("Test notification", savedNotification.Message);
+ }*/
+ }
+
+ [Fact]
+ public void Update_Notification_Success()
+ {
+ var sender = new AthleteEntity
+ {
+ Username = "sender_user",
+ LastName = "Sender",
+ FirstName = "User",
+ Email = "sender.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "senderpassword",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ var notification = new NotificationEntity
+ {
+ Message = "Test notification",
+ Date = DateTime.Now,
+ Statut = false,
+ Urgence = "High",
+ Sender = sender
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(sender);
+ context.Notifications.Add(notification);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedNotification = context.Notifications.First();
+ savedNotification.Message = "Updated message";
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var updatedNotification = context.Notifications.First();
+ Assert.NotNull(updatedNotification);
+ Assert.Equal("Updated message", updatedNotification.Message);
+ }*/
+ }
+
+ [Fact]
+ public void Delete_Notification_Success()
+ {
+ var sender = new AthleteEntity
+ {
+ Username = "sender_user",
+ LastName = "Sender",
+ FirstName = "User",
+ Email = "sender.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "senderpassword",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ var notification = new NotificationEntity
+ {
+ Message = "Test notification",
+ Date = DateTime.Now,
+ Statut = false,
+ Urgence = "High",
+ Sender = sender
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(sender);
+ context.Notifications.Add(notification);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedNotification = context.Notifications.First();
+ context.Notifications.Remove(savedNotification);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var deletedNotification = context.Notifications.FirstOrDefault();
+ Assert.Null(deletedNotification);
+ }*/
+ }
+}
+
diff --git a/src/Tests/UnitTestsEntities/StatisticEntityTests.cs b/src/Tests/UnitTestsEntities/StatisticEntityTests.cs
new file mode 100644
index 0000000..c91b2ab
--- /dev/null
+++ b/src/Tests/UnitTestsEntities/StatisticEntityTests.cs
@@ -0,0 +1,155 @@
+namespace UnitTestsEntities;
+using Xunit;
+using System.Linq;
+using Entities;
+using Microsoft.EntityFrameworkCore;
+
+
+public class StatisticEntityTests
+{
+ [Fact]
+ public void Add_Statistic_Success()
+ {
+ var athlete = new AthleteEntity
+ {
+ Username = "athlete_user",
+ LastName = "Athlete",
+ FirstName = "User",
+ Email = "athlete.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "athletepassword",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ var statistic = new StatisticEntity
+ {
+ Weight = 75.0f,
+ AverageHeartRate = 150.0,
+ MaximumHeartRate = 180.0,
+ AverageCaloriesBurned = 500.0,
+ Date = new DateOnly(2024, 3, 15),
+ Athlete = athlete
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(athlete);
+ context.Statistics.Add(statistic);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedStatistic = context.Statistics.First();
+ Assert.NotNull(savedStatistic);
+ Assert.Equal(75.0f, savedStatistic.Weight);
+ }*/
+ }
+
+ [Fact]
+ public void Update_Statistic_Success()
+ {
+ var athlete = new AthleteEntity
+ {
+ Username = "athlete_user",
+ LastName = "Athlete",
+ FirstName = "User",
+ Email = "athlete.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "athletepassword",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ var statistic = new StatisticEntity
+ {
+ Weight = 75.0f,
+ AverageHeartRate = 150.0,
+ MaximumHeartRate = 180.0,
+ AverageCaloriesBurned = 500.0,
+ Date = new DateOnly(2024, 3, 15),
+ Athlete = athlete
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(athlete);
+ context.Statistics.Add(statistic);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedStatistic = context.Statistics.First();
+ savedStatistic.Weight = 80.0f;
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var updatedStatistic = context.Statistics.First();
+ Assert.NotNull(updatedStatistic);
+ Assert.Equal(80.0f, updatedStatistic.Weight);
+ }*/
+ }
+
+ [Fact]
+ public void Delete_Statistic_Success()
+ {
+ var athlete = new AthleteEntity
+ {
+ Username = "athlete_user",
+ LastName = "Athlete",
+ FirstName = "User",
+ Email = "athlete.user@example.com",
+ Sexe = "M",
+ Length = 170.0,
+ Weight = 70.0f,
+ Password = "athletepassword",
+ DateOfBirth = new DateOnly(1990, 1, 1),
+ IsCoach = false
+ };
+
+ var statistic = new StatisticEntity
+ {
+ Weight = 75.0f,
+ AverageHeartRate = 150.0,
+ MaximumHeartRate = 180.0,
+ AverageCaloriesBurned = 500.0,
+ Date = new DateOnly(2024, 3, 15),
+ Athlete = athlete
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(athlete);
+ context.Statistics.Add(statistic);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedStatistic = context.Statistics.First();
+ context.Statistics.Remove(savedStatistic);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var deletedStatistic = context.Statistics.FirstOrDefault();
+ Assert.Null(deletedStatistic);
+ }*/
+ }
+}
+
diff --git a/src/Tests/UnitTestsEntities/TrainingEntityTests.cs b/src/Tests/UnitTestsEntities/TrainingEntityTests.cs
new file mode 100644
index 0000000..84ec46e
--- /dev/null
+++ b/src/Tests/UnitTestsEntities/TrainingEntityTests.cs
@@ -0,0 +1,202 @@
+namespace UnitTestsEntities;
+using Xunit;
+using System.Linq;
+using Entities;
+using Microsoft.EntityFrameworkCore;
+
+
+public class TrainingEntityTests
+{
+ [Fact]
+ public void Add_Training_Success()
+ {
+ var coach = new AthleteEntity
+ {
+ Username = "coach_user",
+ LastName = "Coach",
+ FirstName = "User",
+ Email = "coach.user@example.com",
+ Sexe = "M",
+ Length = 180.0,
+ Weight = 75.0f,
+ Password = "coachpassword",
+ DateOfBirth = new DateOnly(1985, 5, 15),
+ IsCoach = true
+ };
+
+ var athlete = new AthleteEntity
+ {
+ Username = "athlete_user",
+ LastName = "Athlete",
+ FirstName = "User",
+ Email = "athlete.user@example.com",
+ Sexe = "F",
+ Length = 165.0,
+ Weight = 60.0f,
+ Password = "athletepassword",
+ DateOfBirth = new DateOnly(1990, 3, 20),
+ IsCoach = false
+ };
+
+ var training = new TrainingEntity
+ {
+ Date = new DateOnly(2024, 3, 15),
+ Description = "Training description",
+ Latitude = 40.12345f,
+ Longitude = -74.56789f,
+ FeedBack = "Training feedback",
+ Coach = coach,
+ Athletes = { athlete }
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(coach);
+ context.Athletes.Add(athlete);
+ context.Trainings.Add(training);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedTraining = context.Trainings.First();
+ Assert.NotNull(savedTraining);
+ Assert.Equal("Training description", savedTraining.Description);
+ }*/
+ }
+
+ [Fact]
+ public void Update_Training_Success()
+ {
+ var coach = new AthleteEntity
+ {
+ Username = "coach_user",
+ LastName = "Coach",
+ FirstName = "User",
+ Email = "coach.user@example.com",
+ Sexe = "M",
+ Length = 180.0,
+ Weight = 75.0f,
+ Password = "coachpassword",
+ DateOfBirth = new DateOnly(1985, 5, 15),
+ IsCoach = true
+ };
+
+ var athlete = new AthleteEntity
+ {
+ Username = "athlete_user",
+ LastName = "Athlete",
+ FirstName = "User",
+ Email = "athlete.user@example.com",
+ Sexe = "F",
+ Length = 165.0,
+ Weight = 60.0f,
+ Password = "athletepassword",
+ DateOfBirth = new DateOnly(1990, 3, 20),
+ IsCoach = false
+ };
+
+ var training = new TrainingEntity
+ {
+ Date = new DateOnly(2024, 3, 15),
+ Description = "Training description",
+ Latitude = 40.12345f,
+ Longitude = -74.56789f,
+ FeedBack = "Training feedback",
+ Coach = coach,
+ Athletes = { athlete }
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(coach);
+ context.Athletes.Add(athlete);
+ context.Trainings.Add(training);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedTraining = context.Trainings.First();
+ savedTraining.Description = "Updated training description";
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var updatedTraining = context.Trainings.First();
+ Assert.NotNull(updatedTraining);
+ Assert.Equal("Updated training description", updatedTraining.Description);
+ }*/
+ }
+
+ [Fact]
+ public void Delete_Training_Success()
+ {
+ var coach = new AthleteEntity
+ {
+ Username = "coach_user",
+ LastName = "Coach",
+ FirstName = "User",
+ Email = "coach.user@example.com",
+ Sexe = "M",
+ Length = 180.0,
+ Weight = 75.0f,
+ Password = "coachpassword",
+ DateOfBirth = new DateOnly(1985, 5, 15),
+ IsCoach = true
+ };
+
+ var athlete = new AthleteEntity
+ {
+ Username = "athlete_user",
+ LastName = "Athlete",
+ FirstName = "User",
+ Email = "athlete.user@example.com",
+ Sexe = "F",
+ Length = 165.0,
+ Weight = 60.0f,
+ Password = "athletepassword",
+ DateOfBirth = new DateOnly(1990, 3, 20),
+ IsCoach = false
+ };
+
+ var training = new TrainingEntity
+ {
+ Date = new DateOnly(2024, 3, 15),
+ Description = "Training description",
+ Latitude = 40.12345f,
+ Longitude = -74.56789f,
+ FeedBack = "Training feedback",
+ Coach = coach,
+ Athletes = { athlete }
+ };
+
+ /*
+ using (var context = new StubbedContext(options))
+ {
+ context.Database.EnsureCreated();
+ context.Athletes.Add(coach);
+ context.Athletes.Add(athlete);
+ context.Trainings.Add(training);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var savedTraining = context.Trainings.First();
+ context.Trainings.Remove(savedTraining);
+ context.SaveChanges();
+ }
+
+ using (var context = new StubbedContext(options))
+ {
+ var deletedTraining = context.Trainings.FirstOrDefault();
+ Assert.Null(deletedTraining);
+ }*/
+ }
+}
diff --git a/src/Tests/UnitTestsEntities/UnitTest1.cs b/src/Tests/UnitTestsEntities/UnitTest1.cs
deleted file mode 100644
index 4494897..0000000
--- a/src/Tests/UnitTestsEntities/UnitTest1.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace UnitTestsEntities;
-
-public class UnitTest1
-{
- [Fact]
- public void Test1()
- {
-
- }
-}
\ No newline at end of file
diff --git a/src/Tests/UnitTestsEntities/UnitTestsEntities.csproj b/src/Tests/UnitTestsEntities/UnitTestsEntities.csproj
index 22b0134..e372137 100644
--- a/src/Tests/UnitTestsEntities/UnitTestsEntities.csproj
+++ b/src/Tests/UnitTestsEntities/UnitTestsEntities.csproj
@@ -10,6 +10,7 @@
+
@@ -22,4 +23,8 @@
+
+
+
+
diff --git a/src/UnitTestsEntities2/UnitTest1.cs b/src/UnitTestsEntities2/UnitTest1.cs
new file mode 100644
index 0000000..8b121a7
--- /dev/null
+++ b/src/UnitTestsEntities2/UnitTest1.cs
@@ -0,0 +1,11 @@
+namespace UnitTestsEntities2
+{
+ public class UnitTest1
+ {
+ [Fact]
+ public void Test1()
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/TestsAPI/TestsXUnit/TestsXUnit.csproj b/src/UnitTestsEntities2/UnitTestsEntities2.csproj
similarity index 53%
rename from src/Tests/TestsAPI/TestsXUnit/TestsXUnit.csproj
rename to src/UnitTestsEntities2/UnitTestsEntities2.csproj
index 22b0134..9c5b30a 100644
--- a/src/Tests/TestsAPI/TestsXUnit/TestsXUnit.csproj
+++ b/src/UnitTestsEntities2/UnitTestsEntities2.csproj
@@ -1,25 +1,23 @@
-
-
-
- net8.0
- enable
- enable
-
- false
- true
-
-
-
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
-
-
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+