diff --git a/README.md b/README.md
index e7c4526..2db5c57 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,11 @@
+
+
---


@@ -29,7 +31,7 @@
# Table des matières
-[Présentation](#présentation) | [Répartition du Git](#répartition-du-git) | [Documentation](#documentation) | [Prérequis](#prerequisites) | [Pour commencer](#getting-started) | [Ce que nous avons fait](#ce-que-nous-avons-fait) | [Fabriqué avec](#fabriqué-avec) | [Contributeurs](#contributeurs) | [Comment contribuer](#comment-contribuer) | [License](#license) | [Remerciements](#remerciements)
+[Présentation](#présentation) | [Répartition du Git](#répartition-du-git) | [Documentation](#documentation) | [Prerequisites](#prerequisites) | [Getting Started](#getting-started) | [Features](#features) | [Ce que nous avons fait](#ce-que-nous-avons-fait) | [Fabriqué avec](#fabriqué-avec) | [Contributeurs](#contributeurs) | [Comment contribuer](#comment-contribuer) | [License](#license) | [Remerciements](#remerciements)
@@ -48,10 +50,12 @@ Le projet HeartTrack, avec son application HeartTrack, vise à offrir une soluti
## Répartition du Git
-[**Sources**](src/) : **Code de l'application**
+[**Sources**](Sources/) : **Code de l'application**
[**Documents**](docs/Diagramme/README_DIAGRAMMES.md) : **Documentation de l'application et diagrammes**
+[**Wiki**](https://codefirst.iut.uca.fr/git/HeartDev/Web/wiki/PHP) : **Wiki de notre projet (attendus PHP)**
+
---
Le projet HeartTrack utilise un modèle de flux de travail Git (Gitflow) pour organiser le développement. Voici une brève explication des principales branches :
@@ -76,56 +80,54 @@ Documentation et informations à propos de `HearthTrack` disponible [ici](https:
* [](https://git-scm.com/)
## Getting Started
-Lancer le projet via le projet HeartTrackAPI afin de démarrer la base de donnée pour swagger en http.
-Les méthodes PUT sont en cours de production. Les autres routes sont finalisés et en cours de tests.
## Ce que nous avons fait
### Entity Framework
réalisé | niveau | description | coeff | jalon
--- | --- | --- | --- | ---
-✅ | ☢️ | Le dépôt doit être accessible par l'enseignant | ☢️ | J1
-✅ | ☢️ | un .gitignore doit exister au premier push | ☢️ | J1
-✅ | 🎬 | les *projets* et les tests compilent | 1 | J1 & J2
-✅ | 🎬 | le projet et le tests s'exécutent sans bug (concernant la partie persistance) | 3 | J1 & J2
-✅ | 🟢 | Transcription du modèle : Modèle vers entités (et inversement) | 2 | J1
-✅ | 🟢 | Requêtes CRUD simples (sur une table) | 1 | J1
-✅ | 🟢 | Utilisation de LINQ to Entities | 2 | J1
-✅ | 🟡 | Injection / indépendance du fournisseur | 1 | J1
-✅ | 🟡 | Requêtes CRUD sur des données complexes (images par exemple) | 2 | J1
-✅ | 🟢 | Tests - Appli Console | 1 | J1
-✅ | 🟢 | Tests - Tests unitaires (avec SQLite in memory) | 2 | J1
-✅ | 🟢 | Tests - Données stubbées et/ou Moq | 1 | J1
-✅ | 🟡 | CI : build, tests, Sonar (doc?) | 1 | J1
-✅ | 🟡 | Utilisation de relations (One-to-One, One-to-Many, Many-to-Many) (+ mapping, TU, Requêtes) | 4 | J1
-✅ | 🟢 | Liens avec le web service | 2 | J1
-✅ | 🟡 | Utilisation d'un *Logger* | 1 | J1
-❌ | 🟡 | Déploiement | 4 | J2
-❌ | 🔴 | Unit of Work / Repository + extras (héritage, accès concurrents...) | 8 | J2
-❌ | 🟢 | Utilisation dans le projet | 2 | J2
-✅ | 🟢 | mon dépôt possède un readme qui apporte quelque chose... | 2 | J2
+[ ] | ☢️ | Le dépôt doit être accessible par l'enseignant | ☢️ | J1
+[ ] | ☢️ | un .gitignore doit exister au premier push | ☢️ | J1
+[ ] | 🎬 | les *projets* et les tests compilent | 1 | J1 & J2
+[ ] | 🎬 | le projet et le tests s'exécutent sans bug (concernant la partie persistance) | 3 | J1 & J2
+[ ] | 🟢 | Transcription du modèle : Modèle vers entités (et inversement) | 2 | J1
+[ ] | 🟢 | Requêtes CRUD simples (sur une table) | 1 | J1
+[ ] | 🟢 | Utilisation de LINQ to Entities | 2 | J1
+[ ] | 🟡 | Injection / indépendance du fournisseur | 1 | J1
+[ ] | 🟡 | Requêtes CRUD sur des données complexes (images par exemple) | 2 | J1
+[ ] | 🟢 | Tests - Appli Console | 1 | J1
+[ ] | 🟢 | Tests - Tests unitaires (avec SQLite in memory) | 2 | J1
+[ ] | 🟢 | Tests - Données stubbées et/ou Moq | 1 | J1
+[ ] | 🟡 | CI : build, tests, Sonar (doc?) | 1 | J1
+[ ] | 🟡 | Utilisation de relations (One-to-One, One-to-Many, Many-to-Many) (+ mapping, TU, Requêtes) | 4 | J1
+[ ] | 🟢 | Liens avec le web service | 2 | J1
+[ ] | 🟡 | Utilisation d'un *Logger* | 1 | J1
+[ ] | 🟡 | Déploiement | 4 | J2
+[ ] | 🔴 | Unit of Work / Repository + extras (héritage, accès concurrents...) | 8 | J2
+[ ] | 🟢 | Utilisation dans le projet | 2 | J2
+[ ] | 🟢 | mon dépôt possède un readme qui apporte quelque chose... | 2 | J2
### API
réalisé | niveau | description | coeff | jalon
--- | --- | --- | --- | ---
-✅ | ☢️ | Le dépôt doit être accessible par l'enseignant | ☢️ | J1
-✅ | ☢️ | un .gitignore doit exister au premier push | ☢️ | J1
-✅ | 🎬 | les *projets* et les tests compilent | 1 | J1 & J2
-✅ | 🎬 | le projet et le tests s'exécutent sans bug (concernant la partie persistance) | 4 | J1 & J2
-✅ | 🟢 | Modèle <-> DTO | 1 | J1
-✅ | 🟢 | Entities <-> DTO | 1 | J1
-✅ | 🟡 | Authentification | 4 | J1
-✅ | 🟢 | Requêtes GET, PUT, POST, DELETE sur des données simples (1 seul type d'objet en retour, propriétés de types natifs) | 2 | J1
-✅ | 🟡 | Pagination & filtrage | 2 | J1
-✅ | 🟢 | Injection de service | 2 | J1
-✅ | 🟡 | Requêtes GET, PUT, POST, DELETE sur des données complexes (plusieurs données complexes en retour) | 4 | J1
-✅ | 🟢 | Tests - Appli Console (consommation des requêtes) | 4 | J1
-✅ | 🟢 | Tests - Tests unitaires (avec Stub et/ou Moq) | 2 | J1
-✅ | 🟡 | CI : build, tests, Sonar, Documentation (en particulier Swagger avec exemples...) | 1 | J1
-✅ | 🟢 | Liens avec la persistance en base de données | 4 | J1
-✅ | 🟡 | Utilisation d'un *Logger* | 1 | J1
-❌ | 🟡 | Déploiement | 4 | J2
+[ ] | ☢️ | Le dépôt doit être accessible par l'enseignant | ☢️ | J1
+[ ] | ☢️ | un .gitignore doit exister au premier push | ☢️ | J1
+[ ] | 🎬 | les *projets* et les tests compilent | 1 | J1 & J2
+[ ] | 🎬 | le projet et le tests s'exécutent sans bug (concernant la partie persistance) | 4 | J1 & J2
+[ ] | 🟢 | Modèle <-> DTO | 1 | J1
+[ ] | 🟢 | Entities <-> DTO | 1 | J1
+[ ] | 🟡 | Authentification | 4 | J1
+[ ] | 🟢 | Requêtes GET, PUT, POST, DELETE sur des données simples (1 seul type d'objet en retour, propriétés de types natifs) | 2 | J1
+[ ] | 🟡 | Pagination & filtrage | 2 | J1
+[ ] | 🟢 | Injection de service | 2 | J1
+[ ] | 🟡 | Requêtes GET, PUT, POST, DELETE sur des données complexes (plusieurs données complexes en retour) | 4 | J1
+[ ] | 🟢 | Tests - Appli Console (consommation des requêtes) | 4 | J1
+[ ] | 🟢 | Tests - Tests unitaires (avec Stub et/ou Moq) | 2 | J1
+[ ] | 🟡 | CI : build, tests, Sonar, Documentation (en particulier Swagger avec exemples...) | 1 | J1
+[ ] | 🟢 | Liens avec la persistance en base de données | 4 | J1
+[ ] | 🟡 | Utilisation d'un *Logger* | 1 | J1
+[ ] | 🟡 | Déploiement | 4 | J2
❌ | 🟡 | Utilisation dans le projet | 4 | J2
-✅ | 🎬 | mon dépôt possède un readme qui apporte quelque chose... | 1 | J2
+✅ | 🎬 | mon dépôt possède un readme qui apporte quelque chose... | 1 | J2
## Fabriqué avec

diff --git a/src/HeartTrack.sln b/src/HeartTrack.sln
index a20b9ff..f9c60dd 100644
--- a/src/HeartTrack.sln
+++ b/src/HeartTrack.sln
@@ -45,6 +45,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestsModel", "Tests\Uni
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Entities2Dto", "Entities2Dto\Entities2Dto.csproj", "{1B15D383-1DFA-47E8-86EC-AC631B15FBEB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RepositoriesUnitTest", "Tests\RepositoriesUnitTest\RepositoriesUnitTest.csproj", "{707B1AC4-F896-4270-BC2F-1A589F48979D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebAPIConsoleTests", "Tests\WebAPIConsoleTests\WebAPIConsoleTests.csproj", "{D0EE112F-3151-4C28-A6EC-B1CEC7883FAE}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -123,10 +127,6 @@ Global
{508D380F-145C-437E-A7DF-7A17C526B2F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{508D380F-145C-437E-A7DF-7A17C526B2F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{508D380F-145C-437E-A7DF-7A17C526B2F3}.Release|Any CPU.Build.0 = Release|Any CPU
- {1B15D383-1DFA-47E8-86EC-AC631B15FBEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1B15D383-1DFA-47E8-86EC-AC631B15FBEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1B15D383-1DFA-47E8-86EC-AC631B15FBEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1B15D383-1DFA-47E8-86EC-AC631B15FBEB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/Model/EnumMappeur.cs b/src/Model/EnumMappeur.cs
index b939ee9..38ca1a3 100644
--- a/src/Model/EnumMappeur.cs
+++ b/src/Model/EnumMappeur.cs
@@ -9,6 +9,7 @@ public static class EnumMappeur
return value switch
{
"None" => Shared.AthleteOrderCriteria.None,
+ "ById" => Shared.AthleteOrderCriteria.ById,
"ByUsername" => Shared.AthleteOrderCriteria.ByUsername,
"ByFirstName" => Shared.AthleteOrderCriteria.ByFirstName,
"ByLastName" => Shared.AthleteOrderCriteria.ByLastName,
@@ -17,7 +18,7 @@ public static class EnumMappeur
"ByWeight" => Shared.AthleteOrderCriteria.ByWeight,
"ByDateOfBirth" => Shared.AthleteOrderCriteria.ByDateOfBirth,
"ByEmail" => Shared.AthleteOrderCriteria.ByEmail,
- "ByIsCoach" => Shared.AthleteOrderCriteria.ByIsCoach,
+ "ByRole" => Shared.AthleteOrderCriteria.ByRole,
_ => Shared.AthleteOrderCriteria.None
};
}
diff --git a/src/Shared/AthleteOrderCriteria.cs b/src/Shared/AthleteOrderCriteria.cs
index aad08e4..3faa935 100644
--- a/src/Shared/AthleteOrderCriteria.cs
+++ b/src/Shared/AthleteOrderCriteria.cs
@@ -3,15 +3,16 @@
public enum AthleteOrderCriteria
{
None,
+ ById,
ByUsername,
ByFirstName,
ByLastName,
+ ByEmail,
BySexe,
ByLenght,
ByWeight,
ByDateOfBirth,
- ByEmail,
- ByIsCoach
+ ByRole
}
}
diff --git a/src/Tests/ConsoleTestEFMapper/Program.cs b/src/Tests/ConsoleTestEFMapper/Program.cs
index e5acca0..5079527 100644
--- a/src/Tests/ConsoleTestEFMapper/Program.cs
+++ b/src/Tests/ConsoleTestEFMapper/Program.cs
@@ -49,7 +49,7 @@ namespace ConsoleTestEFMapper;
}
Console.WriteLine();
- // // Test de la méthode AddActivity
+ // Test de la méthode AddActivity
Console.WriteLine("Testing AddActivity method...");
var user = new User
{
diff --git a/src/Tests/RepositoriesUnitTest/ActivityRepository.cs b/src/Tests/RepositoriesUnitTest/ActivityRepository.cs
new file mode 100644
index 0000000..a366bfb
--- /dev/null
+++ b/src/Tests/RepositoriesUnitTest/ActivityRepository.cs
@@ -0,0 +1,114 @@
+using Xunit;
+using Model2Entities;
+using Microsoft.EntityFrameworkCore;
+using DbContextLib;
+using StubbedContextLib;
+using System.Linq;
+using Microsoft.Data.Sqlite;
+using System;
+using EFMappers;
+using Shared;
+using Model;
+using Moq;
+using Microsoft.Extensions.Logging;
+using Entities;
+/*
+namespace UnitTestsEntities
+{
+ public class ActivityRepositoryTests : IClassFixture
+ {
+ private readonly DatabaseFixture _fixture;
+
+ public ActivityRepositoryTests(DatabaseFixture fixture)
+ {
+ _fixture = fixture;
+ }
+
+ [Fact]
+ public async Task GetActivities_ReturnsActivities()
+ {
+ var options = new DbContextOptionsBuilder()
+ .UseSqlite(_fixture._connection)
+ .Options;
+
+ using (var context = new HeartTrackContext(options))
+ {
+ context.Database.EnsureCreated();
+ }
+
+ using (var context = new HeartTrackContext(options))
+ {
+ var repository = new DbDataManager.ActivityRepository(new DbDataManager(context), null);
+ var activities = await repository.GetActivities(0, 10, ActivityOrderCriteria.None);
+
+ Assert.NotNull(activities);
+ Assert.Equal(10, activities.Count());
+ }
+ }
+ [Fact]
+ public async Task GetActivityByIdAsync_ReturnsCorrectActivity_WhenIdExists()
+ {
+ // Arrange
+ var activityId = 1;
+ var expectedActivity = new Activity { Id = activityId, Type = "Running" };
+
+ var mockDataManager = new Mock();
+ mockDataManager.Setup(dm => dm.DbContext.ActivitiesSet.SingleOrDefaultAsync(a => a.IdActivity == activityId))
+ .ReturnsAsync(expectedActivity.ToEntity());
+
+ var loggerMock = new Mock>();
+ var activityRepository = new DbDataManager.ActivityRepository(mockDataManager.Object, loggerMock.Object);
+
+ // Act
+ var result = await activityRepository.GetActivityByIdAsync(activityId);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal(expectedActivity.Id, result.Id);
+ Assert.Equal(expectedActivity.Type, result.Type);
+ }
+
+ [Fact]
+ public async Task GetActivityByIdAsync_ReturnsNull_WhenIdDoesNotExist()
+ {
+ // Arrange
+ var activityId = 999;
+
+ var mockDataManager = new Mock();
+ mockDataManager.Setup(dm => dm.DbContext.ActivitiesSet.SingleOrDefaultAsync(a => a.IdActivity == activityId))
+ .ReturnsAsync((ActivityEntity)null);
+
+ var loggerMock = new Mock>();
+ var activityRepository = new DbDataManager.ActivityRepository(mockDataManager.Object, loggerMock.Object);
+
+ // Act
+ var result = await activityRepository.GetActivityByIdAsync(activityId);
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public async Task AddActivity_SuccessfullyAddsNewActivity()
+ {
+ // Arrange
+ var newActivity = new Activity { Type = "Walking" };
+
+ var mockDataManager = new Mock();
+ mockDataManager.Setup(dm => dm.DbContext.AddItem(It.IsAny()))
+ .ReturnsAsync(newActivity.ToEntity());
+
+ var loggerMock = new Mock>();
+ var activityRepository = new DbDataManager.ActivityRepository(mockDataManager.Object, loggerMock.Object);
+
+ // Act
+ var result = await activityRepository.AddActivity(newActivity);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal(newActivity.Type, result.Type);
+ }
+
+ }
+}
+*/
diff --git a/src/Tests/RepositoriesUnitTest/GlobalUsings.cs b/src/Tests/RepositoriesUnitTest/GlobalUsings.cs
new file mode 100644
index 0000000..8c927eb
--- /dev/null
+++ b/src/Tests/RepositoriesUnitTest/GlobalUsings.cs
@@ -0,0 +1 @@
+global using Xunit;
\ No newline at end of file
diff --git a/src/Tests/RepositoriesUnitTest/RepositoriesUnitTest.csproj b/src/Tests/RepositoriesUnitTest/RepositoriesUnitTest.csproj
new file mode 100644
index 0000000..417f28f
--- /dev/null
+++ b/src/Tests/RepositoriesUnitTest/RepositoriesUnitTest.csproj
@@ -0,0 +1,31 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/src/Tests/RepositoriesUnitTest/UnitTest1.cs b/src/Tests/RepositoriesUnitTest/UnitTest1.cs
new file mode 100644
index 0000000..392318c
--- /dev/null
+++ b/src/Tests/RepositoriesUnitTest/UnitTest1.cs
@@ -0,0 +1,10 @@
+namespace RepositoriesUnitTest;
+
+public class UnitTest1
+{
+ [Fact]
+ public void Test1()
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/TestApi/GlobalUsings.cs b/src/Tests/TestApi/GlobalUsings.cs
deleted file mode 100644
index ab67c7e..0000000
--- a/src/Tests/TestApi/GlobalUsings.cs
+++ /dev/null
@@ -1 +0,0 @@
-global using Microsoft.VisualStudio.TestTools.UnitTesting;
\ No newline at end of file
diff --git a/src/Tests/TestApi/TestApi.csproj b/src/Tests/TestApi/TestApi.csproj
deleted file mode 100644
index 719074b..0000000
--- a/src/Tests/TestApi/TestApi.csproj
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- net8.0
- enable
- enable
-
- false
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Tests/TestApi/UserControllerTest.cs b/src/Tests/TestApi/UserControllerTest.cs
deleted file mode 100644
index e69de29..0000000
diff --git a/src/Tests/UnitTestsEntities/DatabaseFixture.cs b/src/Tests/UnitTestsEntities/DatabaseFixture.cs
index eaae26d..00dc9bf 100644
--- a/src/Tests/UnitTestsEntities/DatabaseFixture.cs
+++ b/src/Tests/UnitTestsEntities/DatabaseFixture.cs
@@ -7,7 +7,7 @@ namespace UnitTestsEntities;
public class DatabaseFixture : IDisposable
{
- private readonly SqliteConnection _connection;
+ public readonly SqliteConnection _connection;
public readonly DbContextOptions _options;
public DatabaseFixture()
{
diff --git a/src/Tests/UnitTestsModel/EnumMapperTest.cs b/src/Tests/UnitTestsModel/EnumMapperTest.cs
index e2dc382..5d3c0d7 100644
--- a/src/Tests/UnitTestsModel/EnumMapperTest.cs
+++ b/src/Tests/UnitTestsModel/EnumMapperTest.cs
@@ -17,7 +17,7 @@ namespace UnitTestsModel
[InlineData("ByWeight", Shared.AthleteOrderCriteria.ByWeight)]
[InlineData("ByDateOfBirth", Shared.AthleteOrderCriteria.ByDateOfBirth)]
[InlineData("ByEmail", Shared.AthleteOrderCriteria.ByEmail)]
- [InlineData("ByIsCoach", Shared.AthleteOrderCriteria.ByIsCoach)]
+ [InlineData("ByRole", Shared.AthleteOrderCriteria.ByRole)]
[InlineData(null, Shared.AthleteOrderCriteria.None)]
[InlineData("InvalidValue", Shared.AthleteOrderCriteria.None)]
public void ToEnum_WithValidValue_ReturnsCorrectEnumValue(string? value, Shared.AthleteOrderCriteria expected)
diff --git a/src/Tests/WebAPIConsoleTests/ActivityServiceAPI.cs b/src/Tests/WebAPIConsoleTests/ActivityServiceAPI.cs
new file mode 100644
index 0000000..976808a
--- /dev/null
+++ b/src/Tests/WebAPIConsoleTests/ActivityServiceAPI.cs
@@ -0,0 +1,113 @@
+/*!
+ * \file BookDataServiceAPI.cs
+ * \author HeartTeam
+ * \brief Fichier contenant la classe BookDataServiceAPI.
+ */
+
+using System.Diagnostics;
+using Dto;
+using Model.Repository;
+using Shared;
+using APIMappers;
+using Model;
+
+namespace WebAPIConsoleTests;
+
+/*!
+ * \brief Implémentation de l'interface IActivityRepository pour récupérer des activités via un service HTTP.
+ */
+public class ActivityServiceAPI : IActivityRepository
+{
+ private HttpRequest myRequest = new HttpRequest();
+
+ /*!
+ * \brief Constructeur de la classe ActivityServiceAPI.
+ * Initialise l'adresse de base du client HTTP.
+ */
+ public ActivityServiceAPI()
+ {
+ myRequest.HttpClient.BaseAddress = new Uri("http://localhost:5030/api/v1/Activity/");
+ }
+
+ /*!
+ * \brief Récupère toutes les Activités de manière asynchrone.
+ * \return Une tâche représentant l'opération asynchrone qui retourne une liste d'Activity.
+ */
+ public async Task?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false)
+ {
+ var activityDtos = await myRequest.GetAllAsync();
+ return activityDtos?.ToModels();
+ }
+
+ /*!
+ * \brief Récupère les activités par index et compte de manière asynchrone.
+ * \param index L'index de départ pour la pagination.
+ * \param count Le nombre d'éléments à récupérer.
+ * \return Une tâche représentant l'opération asynchrone qui retourne une liste d'Activity.
+ */
+ public async Task> GetBooksAsync(ActivityOrderCriteria criteria, bool descending, int index, int count)
+ {
+ var activityDtos = await myRequest.GetAsync(criteria, descending, index, count);
+ return (List)activityDtos.ToModels();
+ }
+
+ /*!
+ * \brief Récupère une activité par son identifiant de manière asynchrone.
+ * \param id L'identifiant du livre à récupérer.
+ * \return Une tâche représentant l'opération asynchrone qui retourne une liste d'Activity.
+ */
+ public async Task GetActivityByIdAsync(int id)
+ {
+ var activityDtos = await myRequest.GetByIdAsync(id);
+ return activityDtos.ToModel();
+ }
+
+ /*!
+ * \brief Ajoute une activité de manière asynchrone.
+ * \param activity L'Activity à ajouter.
+ * \return Une tâche représentant l'opération asynchrone qui retourne l'activité ajouté (Activity).
+ */
+ public async Task AddActivity(Model.Activity activity)
+ {
+ return (await myRequest.PostAsync(activity.ToDto())).ToModel();
+ }
+
+ /*!
+ * \brief Met à jour une activité de manière asynchrone.
+ * \param id L'identifiant de l'activité à mettre à jour.
+ * \param activity Les nouvelles données de l'activité à mettre à jour.
+ * \return Une tâche représentant l'opération asynchrone qui retourne l'activité mis à jour (Activity).
+ */
+ public async Task UpdateActivity(int id, Model.Activity activity)
+ {
+ var activityDto = activity.ToDto();
+ var updatedActivityDto = await myRequest.PutAsync(id, activityDto);
+ return updatedActivityDto?.ToModel();
+ }
+
+ /*!
+ * \brief Supprime une activité de manière asynchrone.
+ * \param id L'identifiant de l'activité à supprimer.
+ * \return Une tâche représentant l'opération asynchrone.
+ */
+ public async Task DeleteActivity(int id)
+ {
+ await myRequest.DeleteAsync(id);
+ return true;
+ }
+
+ public Task GetNbItems()
+ {
+ return myRequest.GetNbItems();
+ }
+
+ public async Task?> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria orderCriteria, bool descending = false)
+ {
+ return (await myRequest.GetActivitiesByUser(userId, index, count, orderCriteria, descending)).ToModels();
+ }
+
+ public Task GetNbActivitiesByUser(int userId)
+ {
+ return myRequest.GetNbActivitiesByUser(userId);
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/WebAPIConsoleTests/HttpRequest.cs b/src/Tests/WebAPIConsoleTests/HttpRequest.cs
new file mode 100644
index 0000000..2b83ab6
--- /dev/null
+++ b/src/Tests/WebAPIConsoleTests/HttpRequest.cs
@@ -0,0 +1,101 @@
+/*!
+ * \file HttpRequest.cs
+ * \brief Fichier contenant la classe HttpRequest.
+ */
+
+using System.Diagnostics;
+using System.Net.Http.Json;
+using Dto;
+using Shared;
+
+namespace WebAPIConsoleTests;
+
+/*!
+ * \brief Classe représentant un client HTTP pour les requêtes vers un service de gestion de elément.
+ */
+public class HttpRequest where T : class
+{
+ private HttpClient _httpClient { get; } = new HttpClient();
+ public HttpClient HttpClient => _httpClient;
+
+ /*!
+ * \brief Récupère tous les activitée de manière asynchrone.
+ * \return Une tâche représentant l'opération asynchrone qui retourne une liste de T.
+ */
+ public async Task> GetAllAsync()
+ {
+ return await _httpClient.GetFromJsonAsync>("");
+ }
+
+ /*!
+ * \brief Récupère les élements par index et compte de manière asynchrone.
+ * \param index L'index de départ pour la pagination.
+ * \param count Le nombre d'éléments à récupérer.
+ * \return Une tâche représentant l'opération asynchrone qui retourne une liste de T.
+ */
+ // [TODO] enum
+ public async Task> GetAsync(Enum criteria, bool descending, int index, int count)
+ {
+ return await _httpClient.GetFromJsonAsync>($"?OrderingPropertyName={criteria}&Descending={descending}&Index={index}&Count={count}");
+ }
+
+ /*!
+ * \brief Récupère un elément par son identifiant de manière asynchrone.
+ * \param id L'identifiant du elément à récupérer.
+ * \return Une tâche représentant l'opération asynchrone qui retourne une liste de T.
+ */
+ public async Task GetByIdAsync(int id)
+ {
+ return await _httpClient.GetFromJsonAsync($"{id}");
+ }
+
+ public Task GetNbItems()
+ {
+ return _httpClient.GetFromJsonAsync("count");
+ }
+
+ public Task?> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria orderCriteria, bool descending = false)
+ {
+ return _httpClient.GetFromJsonAsync?>($"?userId={userId}&index={index}&count={count}&orderCriteria={orderCriteria}&descending={descending}");
+ }
+
+ public Task GetNbActivitiesByUser(int userId)
+ {
+ return _httpClient.GetFromJsonAsync($"count?userId={userId}");
+ }
+
+ /*!
+ * \brief Ajoute une activity de manière asynchrone.
+ * \param book Le elément à ajouter.
+ * \return Une tâche représentant l'opération asynchrone qui retourne le activity ajouté (T).
+ */
+ public async Task PostAsync(T activity)
+ {
+ var response = await _httpClient.PostAsJsonAsync("", activity);
+
+ return await response.Content.ReadFromJsonAsync();
+ }
+
+ /*!
+ * \brief Met à jour un elément de manière asynchrone.
+ * \param id L'identifiant du elément à mettre à jour.
+ * \param book Les nouvelles données du elément à mettre à jour.
+ * \return Une tâche représentant l'opération asynchrone qui retourne le elément mis à jour (T).
+ */
+ public async Task PutAsync(int id, T activity)
+ {
+ var response = await _httpClient.PutAsJsonAsync($"{id}", activity);
+
+ return await response.Content.ReadFromJsonAsync();
+ }
+
+ /*!
+ * \brief Supprime un elément de manière asynchrone.
+ * \param id L'identifiant du elément à supprimer.
+ * \return Une tâche représentant l'opération asynchrone.
+ */
+ public async Task DeleteAsync(int id)
+ {
+ await _httpClient.DeleteAsync($"{id}");
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/WebAPIConsoleTests/Program.cs b/src/Tests/WebAPIConsoleTests/Program.cs
new file mode 100644
index 0000000..8db0f5f
--- /dev/null
+++ b/src/Tests/WebAPIConsoleTests/Program.cs
@@ -0,0 +1,66 @@
+using APIMappers;
+using Dto;
+using Model;
+using Model.Repository;
+using Shared;
+using WebAPIConsoleTests;
+
+
+IActivityRepository myConsoleTest = new ActivityServiceAPI();
+
+// defini un delais d'attente du déploiement de l'API
+await Task.Delay(5000);
+
+// Affiche toutes les activités
+Console.WriteLine("Affichage de toutes les Activités : ");
+var res = await myConsoleTest.GetActivities(0, 10, ActivityOrderCriteria.ByAthleteId, false);
+foreach(var myActivity in res)
+{
+ Console.WriteLine(myActivity.Id + ", " + myActivity.Type + ", " + myActivity.StartTime + ", " + myActivity.EndTime + ", " + myActivity.DataSource + ", " + myActivity.Athlete);
+}
+
+// Affiche les activités par id
+Console.WriteLine("Affichage du livre d'id 1 : ");
+res = (IEnumerable)await myConsoleTest.GetActivityByIdAsync(1);
+foreach (var myActivity in res)
+{
+ Console.WriteLine(myActivity.Id + ", " + myActivity.Type + ", " + myActivity.StartTime + ", " + myActivity.EndTime + ", " + myActivity.DataSource + ", " + myActivity.Athlete);
+}
+
+// Ajouter une nouvelle activité
+Console.WriteLine("Ajout d'un nouveau livre : ");
+var newActivity = new ActivityDto { Type = "New Activity", StartTime = DateTime.Now, EndTime = DateTime.Now, DataSource = new DataSourceDto{}, Athlete = new UserDto{ Username = "Hello", FirstName = "feee", Email = "exemple.com", LastName = "dddd", Sexe = "M" } };
+var addedActivity = await myConsoleTest.AddActivity(newActivity.ToModel());
+Console.WriteLine($"Id: {addedActivity.Id}, Type: {addedActivity.Type}, StartTime: {addedActivity.StartTime}, EndTime: {addedActivity.EndTime}, DataSource: {addedActivity.DataSource}, Athlete: {addedActivity.Athlete}");
+
+// Mettre à jour l'activity ajouté
+Console.WriteLine("Mise à jour du livre ajouté : ");
+var activity = await myConsoleTest.UpdateActivity(1, new ActivityDto { Id = 1, Type = "Updated Activity", StartTime = DateTime.Now, EndTime = DateTime.Now, DataSource = new DataSourceDto{}, Athlete = new UserDto{ Username = "Hello", FirstName = "feee", Email = "exemple.com", LastName = "dddd", Sexe = "M" } }.ToModel());
+Console.WriteLine($"Id: {activity.Id}, Type: {activity.Type}, StartTime: {activity.StartTime}, EndTime: {activity.EndTime}, DataSource: {activity.DataSource}, Athlete: {activity.Athlete}");
+
+// Supprimer l'activity ajouté
+Console.WriteLine("Suppression du livre ajouté : ");
+await myConsoleTest.DeleteActivity(newActivity.Id);
+res = await myConsoleTest.GetActivities(0, 10, ActivityOrderCriteria.ByAthleteId, false);
+foreach (var activity1 in res)
+{
+ Console.WriteLine(activity1.Id + ", " + activity1.Type + ", " + activity1.StartTime + ", " + activity1.EndTime + ", " + activity1.DataSource + ", " + activity1.Athlete);
+}
+
+// Affiche le nombre d'activités
+Console.WriteLine("Affichage du nombre d'activités : ");
+var nb = await myConsoleTest.GetNbItems();
+Console.WriteLine(nb);
+
+// Affiche les activités par utilisateur
+Console.WriteLine("Affichage des activités par utilisateur : ");
+res = await myConsoleTest.GetActivitiesByUser(1, 0, 10, ActivityOrderCriteria.ByAthleteId, false);
+foreach (var activity3 in res)
+{
+ Console.WriteLine(activity3.Id + ", " + activity3.Type + ", " + activity3.StartTime + ", " + activity3.EndTime + ", " + activity3.DataSource + ", " + activity3.Athlete);
+}
+
+// Affiche le nombre d'activités par utilisateur
+Console.WriteLine("Affichage du nombre d'activités par utilisateur : ");
+nb = await myConsoleTest.GetNbActivitiesByUser(1);
+Console.WriteLine(nb);
\ No newline at end of file
diff --git a/src/Tests/WebAPIConsoleTests/WebAPIConsoleTests.csproj b/src/Tests/WebAPIConsoleTests/WebAPIConsoleTests.csproj
new file mode 100644
index 0000000..8f402c3
--- /dev/null
+++ b/src/Tests/WebAPIConsoleTests/WebAPIConsoleTests.csproj
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+