From 90dab5667b6020485eef9d5c6b374c50dd269ef1 Mon Sep 17 00:00:00 2001 From: etudiant Date: Thu, 17 Oct 2024 21:23:38 +0200 Subject: [PATCH] initialisation du projet --- API_dotnet.sln | 61 +++ API_dotnet.sln.DotSettings.user | 4 + ConsoleTest/ConsoleTest.csproj | 19 + ConsoleTest/Program.cs | 366 ++++++++++++++++++ Infrastructure/AlumniDbContext.cs | 48 +++ Infrastructure/Base/EntityBase.cs | 8 + Infrastructure/Entities/EventEntity.cs | 0 Infrastructure/Entities/ExperienceEntity.cs | 0 Infrastructure/Entities/FormationEntity.cs | 0 Infrastructure/Entities/User.cs | 51 +++ Infrastructure/Infrastructure.csproj | 20 + .../20240328220800_migV1.Designer.cs | 220 +++++++++++ .../Migrations/20240328220800_migV1.cs | 152 ++++++++ .../AlumniDbContextModelSnapshot.cs | 217 +++++++++++ Infrastructure/Stub/StubbedContext.cs | 157 ++++++++ README.md | 58 +++ Schema_recap_API.png | Bin 0 -> 10529 bytes Server/API_dotnet.csproj.user | 9 + Server/API_dotnet.http | 6 + .../v1/AlumniRestrictedController.cs | 45 +++ Server/Controller/v1/AlumnisController.cs | 56 +++ Server/Controller/v1/EventsController.cs | 85 ++++ Server/Controller/v1/ExperiencesController.cs | 90 +++++ Server/Controller/v1/FormationsController.cs | 86 ++++ Server/Dockerfile | 27 ++ Server/Dto/Request/RequestAlumniDto.cs | 30 ++ Server/Dto/Request/RequestEventDto.cs | 23 ++ Server/Dto/Request/RequestExperienceDto.cs | 23 ++ Server/Dto/Request/RequestFormationDto.cs | 23 ++ Server/Dto/Response/ResponseAlumniDto.cs | 19 + Server/Dto/Response/ResponseEventDto.cs | 13 + Server/Dto/Response/ResponseExperienceDto.cs | 12 + Server/Dto/Response/ResponseFormationDto.cs | 12 + .../Response/ResponseRestrictedAlumniDto.cs | 10 + Server/FirstTest.db | Bin 0 -> 65536 bytes Server/IServices/IAlumnisService.cs | 17 + Server/IServices/IEventsService.cs | 18 + Server/IServices/IExperiencesService.cs | 18 + Server/IServices/IFormationsService.cs | 17 + Server/Mappers/AlumnisMappers.cs | 64 +++ Server/Mappers/EventsMappers.cs | 32 ++ Server/Mappers/ExperiencesMappers.cs | 36 ++ Server/Mappers/FormationsMappers.cs | 35 ++ Server/Program.cs | 56 +++ Server/Properties/launchSettings.json | 41 ++ Server/Server.csproj | 36 ++ Server/Server.csproj.user | 8 + Server/Services/AlumniService.cs | 83 ++++ Server/Services/EventServices.cs | 73 ++++ Server/Services/ExperienceServices.cs | 82 ++++ Server/Services/FormationServices.cs | 79 ++++ Server/appsettings.Development.json | 8 + Server/appsettings.json | 9 + Shared/Criteria/AlumniOrderCriteria.cs | 7 + Shared/Criteria/EventOrderCriteria.cs | 8 + Shared/Criteria/ExperienceOrderCriteria.cs | 8 + Shared/Criteria/FormationOrderCriteria.cs | 10 + Shared/Enums/EContract.cs | 9 + Shared/Enums/ELevel.cs | 8 + Shared/Enums/ERole.cs | 8 + Shared/Enums/EStudies.cs | 9 + Shared/IDataServices.cs | 44 +++ Shared/Shared.csproj | 9 + .../ControllerTests/AlumniControllerTest.cs | 130 +++++++ .../AlumuniRestrictedControllerTest.cs | 98 +++++ .../EvenementControllerTest.cs | 179 +++++++++ .../ExperienceControllerTest.cs | 186 +++++++++ .../FormationControllerTest.cs | 179 +++++++++ TestAPI/MapperTests/AlumniMappersTests.cs | 112 ++++++ TestAPI/MapperTests/EventMappersTests.cs | 62 +++ TestAPI/MapperTests/ExperienceMapperTests.cs | 63 +++ TestAPI/MapperTests/FormationMapperTests.cs | 61 +++ TestAPI/ServicesTests/AlumniServiceTests.cs | 101 +++++ TestAPI/ServicesTests/EventServicesTests.cs | 97 +++++ .../ServicesTests/ExperienceServicesTests.cs | 93 +++++ .../ServicesTests/FormationServiceTests.cs | 143 +++++++ TestAPI/TestAPI.csproj | 28 ++ TestConsoleApi/Program.cs | 93 +++++ TestConsoleApi/TestConsoleApi.csproj | 16 + UnitTestEF/Entities/AlumniTest.cs | 194 ++++++++++ UnitTestEF/Entities/EventTest.cs | 211 ++++++++++ UnitTestEF/Entities/ExperienceTest.cs | 150 +++++++ UnitTestEF/Entities/FormationTest.cs | 145 +++++++ UnitTestEF/GlobalUsings.cs | 1 + UnitTestEF/UnitTestEF.csproj | 24 ++ 85 files changed, 5148 insertions(+) create mode 100644 API_dotnet.sln create mode 100644 API_dotnet.sln.DotSettings.user create mode 100644 ConsoleTest/ConsoleTest.csproj create mode 100644 ConsoleTest/Program.cs create mode 100644 Infrastructure/AlumniDbContext.cs create mode 100644 Infrastructure/Base/EntityBase.cs create mode 100644 Infrastructure/Entities/EventEntity.cs create mode 100644 Infrastructure/Entities/ExperienceEntity.cs create mode 100644 Infrastructure/Entities/FormationEntity.cs create mode 100644 Infrastructure/Entities/User.cs create mode 100644 Infrastructure/Infrastructure.csproj create mode 100644 Infrastructure/Migrations/20240328220800_migV1.Designer.cs create mode 100644 Infrastructure/Migrations/20240328220800_migV1.cs create mode 100644 Infrastructure/Migrations/AlumniDbContextModelSnapshot.cs create mode 100644 Infrastructure/Stub/StubbedContext.cs create mode 100644 README.md create mode 100644 Schema_recap_API.png create mode 100644 Server/API_dotnet.csproj.user create mode 100644 Server/API_dotnet.http create mode 100644 Server/Controller/v1/AlumniRestrictedController.cs create mode 100644 Server/Controller/v1/AlumnisController.cs create mode 100644 Server/Controller/v1/EventsController.cs create mode 100644 Server/Controller/v1/ExperiencesController.cs create mode 100644 Server/Controller/v1/FormationsController.cs create mode 100644 Server/Dockerfile create mode 100644 Server/Dto/Request/RequestAlumniDto.cs create mode 100644 Server/Dto/Request/RequestEventDto.cs create mode 100644 Server/Dto/Request/RequestExperienceDto.cs create mode 100644 Server/Dto/Request/RequestFormationDto.cs create mode 100644 Server/Dto/Response/ResponseAlumniDto.cs create mode 100644 Server/Dto/Response/ResponseEventDto.cs create mode 100644 Server/Dto/Response/ResponseExperienceDto.cs create mode 100644 Server/Dto/Response/ResponseFormationDto.cs create mode 100644 Server/Dto/Response/ResponseRestrictedAlumniDto.cs create mode 100644 Server/FirstTest.db create mode 100644 Server/IServices/IAlumnisService.cs create mode 100644 Server/IServices/IEventsService.cs create mode 100644 Server/IServices/IExperiencesService.cs create mode 100644 Server/IServices/IFormationsService.cs create mode 100644 Server/Mappers/AlumnisMappers.cs create mode 100644 Server/Mappers/EventsMappers.cs create mode 100644 Server/Mappers/ExperiencesMappers.cs create mode 100644 Server/Mappers/FormationsMappers.cs create mode 100644 Server/Program.cs create mode 100644 Server/Properties/launchSettings.json create mode 100644 Server/Server.csproj create mode 100644 Server/Server.csproj.user create mode 100644 Server/Services/AlumniService.cs create mode 100644 Server/Services/EventServices.cs create mode 100644 Server/Services/ExperienceServices.cs create mode 100644 Server/Services/FormationServices.cs create mode 100644 Server/appsettings.Development.json create mode 100644 Server/appsettings.json create mode 100644 Shared/Criteria/AlumniOrderCriteria.cs create mode 100644 Shared/Criteria/EventOrderCriteria.cs create mode 100644 Shared/Criteria/ExperienceOrderCriteria.cs create mode 100644 Shared/Criteria/FormationOrderCriteria.cs create mode 100644 Shared/Enums/EContract.cs create mode 100644 Shared/Enums/ELevel.cs create mode 100644 Shared/Enums/ERole.cs create mode 100644 Shared/Enums/EStudies.cs create mode 100644 Shared/IDataServices.cs create mode 100644 Shared/Shared.csproj create mode 100644 TestAPI/ControllerTests/AlumniControllerTest.cs create mode 100644 TestAPI/ControllerTests/AlumuniRestrictedControllerTest.cs create mode 100644 TestAPI/ControllerTests/EvenementControllerTest.cs create mode 100644 TestAPI/ControllerTests/ExperienceControllerTest.cs create mode 100644 TestAPI/ControllerTests/FormationControllerTest.cs create mode 100644 TestAPI/MapperTests/AlumniMappersTests.cs create mode 100644 TestAPI/MapperTests/EventMappersTests.cs create mode 100644 TestAPI/MapperTests/ExperienceMapperTests.cs create mode 100644 TestAPI/MapperTests/FormationMapperTests.cs create mode 100644 TestAPI/ServicesTests/AlumniServiceTests.cs create mode 100644 TestAPI/ServicesTests/EventServicesTests.cs create mode 100644 TestAPI/ServicesTests/ExperienceServicesTests.cs create mode 100644 TestAPI/ServicesTests/FormationServiceTests.cs create mode 100644 TestAPI/TestAPI.csproj create mode 100644 TestConsoleApi/Program.cs create mode 100644 TestConsoleApi/TestConsoleApi.csproj create mode 100644 UnitTestEF/Entities/AlumniTest.cs create mode 100644 UnitTestEF/Entities/EventTest.cs create mode 100644 UnitTestEF/Entities/ExperienceTest.cs create mode 100644 UnitTestEF/Entities/FormationTest.cs create mode 100644 UnitTestEF/GlobalUsings.cs create mode 100644 UnitTestEF/UnitTestEF.csproj diff --git a/API_dotnet.sln b/API_dotnet.sln new file mode 100644 index 0000000..b642672 --- /dev/null +++ b/API_dotnet.sln @@ -0,0 +1,61 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34607.119 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure", "Infrastructure\Infrastructure.csproj", "{06E9AE9C-4329-41EF-BF95-168D38F1F6FE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{FF711AC2-DFCF-4C11-ABD1-69931E5C0D84}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{C07A8E83-FC00-4CDD-B74D-DB34F950E986}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestAPI", "TestAPI\TestAPI.csproj", "{8ECB7F8F-FCD4-4AA0-9F68-76A1A0944107}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleTest", "ConsoleTest\ConsoleTest.csproj", "{603E5564-6E8E-43BA-B260-FED22612E6EF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConsoleApi", "TestConsoleApi\TestConsoleApi.csproj", "{501CB464-8843-4500-AFB3-90C85658619C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestEF", "UnitTestEF\UnitTestEF.csproj", "{10655D92-BEAC-4BAB-AB82-65AF1DE7B60D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {06E9AE9C-4329-41EF-BF95-168D38F1F6FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {06E9AE9C-4329-41EF-BF95-168D38F1F6FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06E9AE9C-4329-41EF-BF95-168D38F1F6FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {06E9AE9C-4329-41EF-BF95-168D38F1F6FE}.Release|Any CPU.Build.0 = Release|Any CPU + {FF711AC2-DFCF-4C11-ABD1-69931E5C0D84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF711AC2-DFCF-4C11-ABD1-69931E5C0D84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF711AC2-DFCF-4C11-ABD1-69931E5C0D84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF711AC2-DFCF-4C11-ABD1-69931E5C0D84}.Release|Any CPU.Build.0 = Release|Any CPU + {C07A8E83-FC00-4CDD-B74D-DB34F950E986}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C07A8E83-FC00-4CDD-B74D-DB34F950E986}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C07A8E83-FC00-4CDD-B74D-DB34F950E986}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C07A8E83-FC00-4CDD-B74D-DB34F950E986}.Release|Any CPU.Build.0 = Release|Any CPU + {8ECB7F8F-FCD4-4AA0-9F68-76A1A0944107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8ECB7F8F-FCD4-4AA0-9F68-76A1A0944107}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8ECB7F8F-FCD4-4AA0-9F68-76A1A0944107}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8ECB7F8F-FCD4-4AA0-9F68-76A1A0944107}.Release|Any CPU.Build.0 = Release|Any CPU + {603E5564-6E8E-43BA-B260-FED22612E6EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {603E5564-6E8E-43BA-B260-FED22612E6EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {603E5564-6E8E-43BA-B260-FED22612E6EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {603E5564-6E8E-43BA-B260-FED22612E6EF}.Release|Any CPU.Build.0 = Release|Any CPU + {501CB464-8843-4500-AFB3-90C85658619C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {501CB464-8843-4500-AFB3-90C85658619C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {501CB464-8843-4500-AFB3-90C85658619C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {501CB464-8843-4500-AFB3-90C85658619C}.Release|Any CPU.Build.0 = Release|Any CPU + {10655D92-BEAC-4BAB-AB82-65AF1DE7B60D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10655D92-BEAC-4BAB-AB82-65AF1DE7B60D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10655D92-BEAC-4BAB-AB82-65AF1DE7B60D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10655D92-BEAC-4BAB-AB82-65AF1DE7B60D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E05D39E2-C0B7-4A72-B1CD-08C3B6C74097} + EndGlobalSection +EndGlobal diff --git a/API_dotnet.sln.DotSettings.user b/API_dotnet.sln.DotSettings.user new file mode 100644 index 0000000..dbe7ba1 --- /dev/null +++ b/API_dotnet.sln.DotSettings.user @@ -0,0 +1,4 @@ + + <SessionState ContinuousTestingMode="0" IsActive="True" Name="alumniTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Solution /> +</SessionState> \ No newline at end of file diff --git a/ConsoleTest/ConsoleTest.csproj b/ConsoleTest/ConsoleTest.csproj new file mode 100644 index 0000000..76eaf5a --- /dev/null +++ b/ConsoleTest/ConsoleTest.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + enable + Windows + + + + + + + + + + + diff --git a/ConsoleTest/Program.cs b/ConsoleTest/Program.cs new file mode 100644 index 0000000..47f7be6 --- /dev/null +++ b/ConsoleTest/Program.cs @@ -0,0 +1,366 @@ +// See https://aka.ms/new-console-template for more information + +using Infrastructure; +using Infrastructure.Entities; +using Infrastructure.Stub; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; + +var connection = new SqliteConnection("DataSource=:memory:"); +connection.Open(); +var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + +await using (var context = new StubbedContext(options)) +{ + await context.Database.EnsureCreatedAsync(); + Console.WriteLine("============Events============"); + //Display all events + var events = await context.Events.ToListAsync(); + Console.WriteLine("--Display of the Events: (Tolal:" + events.Count + ")"); + foreach (var eventEntity in events) Console.WriteLine(eventEntity); + + Console.WriteLine("--Create an event"); + //Create a new event + var evt = new EventEntity() + { + Title = "This is a title", + Description = "This is a description", + Date = DateTime.Now, + nbPlaces = 100 + }; + context.Events.Add(evt); + await context.SaveChangesAsync(); + + //verify if the event has been created + var getEvt = await context.Events.FirstOrDefaultAsync(e => e.Title == "This is a title"); + if( getEvt == null) + { + Console.WriteLine("Event not found (Creation failed)"); + } + else + { + Console.WriteLine("Event found (Creation success) :"); + Console.WriteLine(getEvt); + } + + //Update the event + Console.WriteLine("--Update event"); + getEvt.Title = "Changed title"; + await context.SaveChangesAsync(); + + //verify if the event has been updated + var getEvt2 = await context.Events.FirstOrDefaultAsync(e => e.Title == "Changed title"); + if( getEvt2 == null) + { + Console.WriteLine("Event not found (Update failed)"); + } + else + { + Console.WriteLine("Event found (Update success) :"); + Console.WriteLine(getEvt2); + } + + //Delete the event + Console.WriteLine("--Delete event"); + context.Events.Remove(getEvt2); + await context.SaveChangesAsync(); + + //verify if the event has been deleted + var getEvt3 = await context.Events.FirstOrDefaultAsync(e => e.Title == "Changed title"); + if( getEvt3 == null) + { + Console.WriteLine("Event not found (Deletion success)"); + } + else + { + Console.WriteLine("Event found (Deletion failed) :"); + Console.WriteLine(getEvt3); + } + + Console.WriteLine("\n============Alumnis============"); + //Display all alumnis + var alumnis = await context.Alumni.ToListAsync(); + Console.WriteLine("Diplay the Alumnis: (Tolal:" + alumnis.Count + ")"); + foreach (var alumniEntity in alumnis) Console.WriteLine(alumniEntity); + + Console.WriteLine("--Create an alumni"); + //Create a new alumni + var alumni = new User() + { + FirstName = "Leo", + LastName = "Tuaillon", + Email = "leo.tuaillon@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "ADMIN" + }; + context.Alumni.Add(alumni); + await context.SaveChangesAsync(); + + //verify if the alumni has been created + var getAlumni = await context.Alumni.FirstOrDefaultAsync(a => a.FirstName == "Leo"); + if( getAlumni == null) + { + Console.WriteLine("Alumni not found (Creation failed)"); + } + else + { + Console.WriteLine("Alumni found (Creation success) :"); + Console.WriteLine(getAlumni); + } + + //Update the alumni + Console.WriteLine("--Update alumni"); + getAlumni.FirstName = "Leo changed name"; + await context.SaveChangesAsync(); + + //verify if the alumni has been updated + var getAlumni2 = await context.Alumni.FirstOrDefaultAsync(a => a.FirstName == "Leo changed name"); + if( getAlumni2 == null) + { + Console.WriteLine("Alumni not found (Update failed)"); + } + else + { + Console.WriteLine("Alumni found (Update success) :"); + Console.WriteLine(getAlumni2); + } + + //Delete the alumni + Console.WriteLine("--Delete alumni"); + context.Alumni.Remove(getAlumni2); + await context.SaveChangesAsync(); + + //verify if the alumni has been deleted + var getAlumni3 = await context.Alumni.FirstOrDefaultAsync(a => a.FirstName == "Leo changed name"); + if( getAlumni3 == null) + { + Console.WriteLine("Alumni not found (Deletion success)"); + } + else + { + Console.WriteLine("Alumni found (Deletion failed) :"); + Console.WriteLine(getAlumni3); + } + + Console.WriteLine("\n============Experiences============"); + //Display all experiences + var experiences = await context.Experiences.ToListAsync(); + Console.WriteLine("Display the Experiences: (Tolal:" + experiences.Count + ")"); + foreach (var experienceEntity in experiences) Console.WriteLine(experienceEntity); + + Console.WriteLine("--Create an experience"); + //Create a new experience + var experience = new ExperienceEntity() + { + Title = "Ingénieur logiciel", + StartDate = DateTime.Now, + CompanyName = "Capgemini", + IsCurrent = true + }; + context.Experiences.Add(experience); + await context.SaveChangesAsync(); + + //verify if the experience has been created + var getExperience = await context.Experiences.FirstOrDefaultAsync(e => e.Title == "Ingénieur logiciel"); + if( getExperience == null) + { + Console.WriteLine("Experience not found (Creation failed)"); + } + else + { + Console.WriteLine("Experience found (Creation success) :"); + Console.WriteLine(getExperience); + } + + //Update the experience + Console.WriteLine("--Update experience"); + getExperience.Title = "Ingénieur logiciel changed"; + await context.SaveChangesAsync(); + + //verify if the experience has been updated + var getExperience2 = await context.Experiences.FirstOrDefaultAsync(e => e.Title == "Ingénieur logiciel changed"); + + if( getExperience2 == null) + { + Console.WriteLine("Experience not found (Update failed)"); + } + else + { + Console.WriteLine("Experience found (Update success) :"); + Console.WriteLine(getExperience2); + } + + //Delete the experience + Console.WriteLine("--Delete experience"); + context.Experiences.Remove(getExperience2); + await context.SaveChangesAsync(); + + //verify if the experience has been deleted + var getExperience3 = await context.Experiences.FirstOrDefaultAsync(e => e.Title == "Ingénieur logiciel changed"); + if( getExperience3 == null) + { + Console.WriteLine("Experience not found (Deletion success)"); + } + else + { + Console.WriteLine("Experience found (Deletion failed) :"); + Console.WriteLine(getExperience3); + } + + Console.WriteLine("\n============Formations============"); + //Display all formations + var formations = await context.Formations.ToListAsync(); + Console.WriteLine("Display the Formations: (Tolal:" + formations.Count + ")"); + foreach (var formationEntity in formations) Console.WriteLine(formationEntity); + + Console.WriteLine("--Create a formation"); + //Create a new formation + var formation = new FormationEntity() + { + SchoolName = "IUT Clermont-Ferrand", + Name = "BUT GEA", + StartDate = DateTime.Now, + IsCurrent = true + }; + context.Formations.Add(formation); + await context.SaveChangesAsync(); + + //verify if the formation has been created + var getFormation = await context.Formations.FirstOrDefaultAsync(f => f.Name == "BUT GEA"); + if( getFormation == null) + { + Console.WriteLine("Formation not found (Creation failed)"); + } + else + { + Console.WriteLine("Formation found (Creation success) :"); + Console.WriteLine(getFormation); + } + + //Update the formation + Console.WriteLine("--Update formation"); + getFormation.Name = "BUT Mesures Physiques"; + await context.SaveChangesAsync(); + + //verify if the formation has been updated + var getFormation2 = await context.Formations.FirstOrDefaultAsync(f => f.Name == "BUT Mesures Physiques"); + if( getFormation2 == null) + { + Console.WriteLine("Formation not found (Update failed)"); + } + else + { + Console.WriteLine("Formation found (Update success) :"); + Console.WriteLine(getFormation2); + } + + //Delete the formation + Console.WriteLine("--Delete formation"); + context.Formations.Remove(getFormation2); + await context.SaveChangesAsync(); + + //verify if the formation has been deleted + var getFormation3 = await context.Formations.FirstOrDefaultAsync(f => f.Name == "BUT Mesures Physiques"); + if( getFormation3 == null) + { + Console.WriteLine("Formation not found (Deletion success)"); + } + else + { + Console.WriteLine("Formation found (Deletion failed) :"); + Console.WriteLine(getFormation3); + } + + + Console.WriteLine("\nAlumni with their experiences, formations and events"); + var alumniDetails = await context.Alumni + .Include(a => a.Experiences) + .Include(a => a.Formations) + .Include(a => a.Events) + .FirstOrDefaultAsync( a => a.FirstName == "Test"); + + if (alumniDetails == null) + { + Console.WriteLine("Alumni not found"); + } + else + { + Console.WriteLine(alumniDetails); + } + + Console.WriteLine("Subscribe to an event"); + var eventToSubscribe = await context.Events.FirstOrDefaultAsync(e => e.Title == "Laser Game"); + var eventToSubscribe2 = await context.Events.FirstOrDefaultAsync(e => e.Title == "Afterwork Raclette"); + if (eventToSubscribe == null || eventToSubscribe2 == null) + { + Console.WriteLine("Event not found"); + } + else + { + alumniDetails.Events.Add(eventToSubscribe); + alumniDetails.Events.Add(eventToSubscribe2); + await context.SaveChangesAsync(); + Console.WriteLine(alumniDetails); + Console.WriteLine("\tEvents subscribed :"); + foreach (var eventEntity in alumniDetails.Events) + { + Console.WriteLine("\t"+eventEntity); + } + } + + Console.WriteLine("Unsubscribe to an event"); + var eventToUnsubscribe = await context.Events.FirstOrDefaultAsync(e => e.Title == "Laser Game"); + if (eventToUnsubscribe == null) + { + Console.WriteLine("Event not found"); + } + else + { + alumniDetails.Events.Remove(eventToUnsubscribe); + await context.SaveChangesAsync(); + Console.WriteLine(alumniDetails); + Console.WriteLine("\tEvents unsubscribed :"); + foreach (var eventEntity in alumniDetails.Events) + { + Console.WriteLine("\t" + eventEntity); + } + } + + Console.WriteLine("Add an experience and a formation to an alumni"); + var experienceToAdd = new ExperienceEntity() + { + Title = "Stage", + StartDate = DateTime.Now, + CompanyName = "Capgemini", + IsCurrent = true + }; + + var formationToAdd = new FormationEntity() + { + SchoolName = "IUT Clermont-Ferrand", + Name = "BUT GEA", + StartDate = DateTime.Now, + IsCurrent = true + }; + + alumniDetails.Experiences.Add(experienceToAdd); + alumniDetails.Formations.Add(formationToAdd); + await context.SaveChangesAsync(); + Console.WriteLine(alumniDetails); + Console.WriteLine("\tExperiences added :"); + foreach (var experienceEntity in alumniDetails.Experiences) + { + Console.WriteLine("\t" + experienceEntity); + } + Console.WriteLine("\tFormations added :"); + foreach (var formationEntity in alumniDetails.Formations) + { + Console.WriteLine("\t" + formationEntity); + } + +} + +connection.Close(); \ No newline at end of file diff --git a/Infrastructure/AlumniDbContext.cs b/Infrastructure/AlumniDbContext.cs new file mode 100644 index 0000000..53a45c3 --- /dev/null +++ b/Infrastructure/AlumniDbContext.cs @@ -0,0 +1,48 @@ +using Infrastructure.Entities; +using Microsoft.EntityFrameworkCore; + +namespace Infrastructure; + +public class AlumniDbContext : DbContext +{ + public virtual DbSet Alumni { get; set; } + public virtual DbSet Experiences { get; set; } + public virtual DbSet Formations { get; set; } + public virtual DbSet Events { get; set; } + public AlumniDbContext() + { + } + public AlumniDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnConfiguring(DbContextOptionsBuilder options) + { + if (!options.IsConfigured) + { + options.UseSqlite("Data Source=FirstTest.db"); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().Property(e => e.Title) + .IsRequired(); + + modelBuilder.Entity().Property(a => a.FirstName) + .IsRequired(); + + modelBuilder.Entity().Property(a => a.Email) + .IsRequired(); + + modelBuilder.Entity() + .Property(e => e.Title) + .IsRequired(); + + modelBuilder.Entity().Property(f => f.Name) + .IsRequired(); + + base.OnModelCreating(modelBuilder); + } +} \ No newline at end of file diff --git a/Infrastructure/Base/EntityBase.cs b/Infrastructure/Base/EntityBase.cs new file mode 100644 index 0000000..a0c62fd --- /dev/null +++ b/Infrastructure/Base/EntityBase.cs @@ -0,0 +1,8 @@ +using System.ComponentModel.DataAnnotations; + +namespace Infrastructure.Base; + +public abstract class EntityBase +{ + [Key] public string? Id { get; set; } = Guid.NewGuid().ToString(); +} \ No newline at end of file diff --git a/Infrastructure/Entities/EventEntity.cs b/Infrastructure/Entities/EventEntity.cs new file mode 100644 index 0000000..e69de29 diff --git a/Infrastructure/Entities/ExperienceEntity.cs b/Infrastructure/Entities/ExperienceEntity.cs new file mode 100644 index 0000000..e69de29 diff --git a/Infrastructure/Entities/FormationEntity.cs b/Infrastructure/Entities/FormationEntity.cs new file mode 100644 index 0000000..e69de29 diff --git a/Infrastructure/Entities/User.cs b/Infrastructure/Entities/User.cs new file mode 100644 index 0000000..c8e5659 --- /dev/null +++ b/Infrastructure/Entities/User.cs @@ -0,0 +1,51 @@ +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using Infrastructure.Base; + +namespace Infrastructure.Entities; + +public class User : EntityBase +{ + [Required] + [MaxLength(100)] + // Id is a field with a maximum length of 100 characters + public string Id { get; set; } + + [Required] + [MaxLength(200)] + // Title is a required field with a maximum length of 200 characters + public string FirstName { get; set; } + + [MaxLength(100)] + // Author is a field with a maximum length of 100 characters + public string LastName { get; set; } + + public int Age { get; set; } + + [MinLength(10)] + // Password is a field with a minimum length of 10 characters + public string Password { get; set; } + + public int Height { get; set; } + + public int Weight { get; set; } + + public int Sexe { get; set; } + + public string? WebSite { get; set; } + + public ICollection Experiences { get; set; } = new Collection(); + + public ICollection Formations { get; set; } = new Collection(); + + public ICollection Events { get; set; } = new Collection(); + + public override string ToString() + { + return $"\t------------Alumni Id : {Id} ------------- :" + + $"\n\tFirstname : {FirstName} Lastname : {LastName} Email : {Email} Role : {Role}\n\t" + + $"Experiences : {Experiences.Count} \t" + + $"Formations : {Formations.Count} \t Events : {Events.Count}"; + + } +} \ No newline at end of file diff --git a/Infrastructure/Infrastructure.csproj b/Infrastructure/Infrastructure.csproj new file mode 100644 index 0000000..541b460 --- /dev/null +++ b/Infrastructure/Infrastructure.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + $(MSBuildProjectDirectory) + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/Infrastructure/Migrations/20240328220800_migV1.Designer.cs b/Infrastructure/Migrations/20240328220800_migV1.Designer.cs new file mode 100644 index 0000000..7b522a8 --- /dev/null +++ b/Infrastructure/Migrations/20240328220800_migV1.Designer.cs @@ -0,0 +1,220 @@ +// +using System; +using Infrastructure; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Infrastructure.Migrations +{ + [DbContext(typeof(AlumniDbContext))] + [Migration("20240328220800_migV1")] + partial class migV1 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.1"); + + modelBuilder.Entity("AlumniEntityEventEntity", b => + { + b.Property("EventsId") + .HasColumnType("TEXT"); + + b.Property("ParticipantsId") + .HasColumnType("TEXT"); + + b.HasKey("EventsId", "ParticipantsId"); + + b.HasIndex("ParticipantsId"); + + b.ToTable("AlumniEntityEventEntity"); + }); + + modelBuilder.Entity("Infrastructure.Entities.AlumniEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("EntryYear") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Github") + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Linkedin") + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Role") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WebSite") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Alumni"); + }); + + modelBuilder.Entity("Infrastructure.Entities.EventEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("nbPlaces") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Events"); + }); + + modelBuilder.Entity("Infrastructure.Entities.ExperienceEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AlumniId") + .HasColumnType("TEXT"); + + b.Property("CompanyName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("IsCurrent") + .HasColumnType("INTEGER"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AlumniId"); + + b.ToTable("Experiences"); + }); + + modelBuilder.Entity("Infrastructure.Entities.FormationEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AlumniId") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("IsCurrent") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("SchoolName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AlumniId"); + + b.ToTable("Formations"); + }); + + modelBuilder.Entity("AlumniEntityEventEntity", b => + { + b.HasOne("Infrastructure.Entities.EventEntity", null) + .WithMany() + .HasForeignKey("EventsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Infrastructure.Entities.AlumniEntity", null) + .WithMany() + .HasForeignKey("ParticipantsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Infrastructure.Entities.ExperienceEntity", b => + { + b.HasOne("Infrastructure.Entities.AlumniEntity", "Alumni") + .WithMany("Experiences") + .HasForeignKey("AlumniId"); + + b.Navigation("Alumni"); + }); + + modelBuilder.Entity("Infrastructure.Entities.FormationEntity", b => + { + b.HasOne("Infrastructure.Entities.AlumniEntity", "Alumni") + .WithMany("Formations") + .HasForeignKey("AlumniId"); + + b.Navigation("Alumni"); + }); + + modelBuilder.Entity("Infrastructure.Entities.AlumniEntity", b => + { + b.Navigation("Experiences"); + + b.Navigation("Formations"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Infrastructure/Migrations/20240328220800_migV1.cs b/Infrastructure/Migrations/20240328220800_migV1.cs new file mode 100644 index 0000000..785a8e9 --- /dev/null +++ b/Infrastructure/Migrations/20240328220800_migV1.cs @@ -0,0 +1,152 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Infrastructure.Migrations +{ + /// + public partial class migV1 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Alumni", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + FirstName = table.Column(type: "TEXT", maxLength: 200, nullable: false), + LastName = table.Column(type: "TEXT", maxLength: 100, nullable: false), + Email = table.Column(type: "TEXT", maxLength: 100, nullable: false), + EntryYear = table.Column(type: "TEXT", nullable: false), + Password = table.Column(type: "TEXT", nullable: false), + Role = table.Column(type: "TEXT", nullable: false), + Linkedin = table.Column(type: "TEXT", nullable: true), + Github = table.Column(type: "TEXT", nullable: true), + WebSite = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Alumni", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Events", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Title = table.Column(type: "TEXT", maxLength: 128, nullable: false), + Description = table.Column(type: "TEXT", maxLength: 512, nullable: false), + Date = table.Column(type: "TEXT", nullable: false), + nbPlaces = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Events", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Experiences", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Title = table.Column(type: "TEXT", maxLength: 64, nullable: false), + StartDate = table.Column(type: "TEXT", nullable: false), + EndDate = table.Column(type: "TEXT", nullable: true), + CompanyName = table.Column(type: "TEXT", maxLength: 64, nullable: false), + IsCurrent = table.Column(type: "INTEGER", nullable: false), + AlumniId = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Experiences", x => x.Id); + table.ForeignKey( + name: "FK_Experiences_Alumni_AlumniId", + column: x => x.AlumniId, + principalTable: "Alumni", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Formations", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + SchoolName = table.Column(type: "TEXT", maxLength: 64, nullable: false), + Name = table.Column(type: "TEXT", maxLength: 64, nullable: false), + StartDate = table.Column(type: "TEXT", nullable: false), + EndDate = table.Column(type: "TEXT", nullable: true), + IsCurrent = table.Column(type: "INTEGER", nullable: false), + AlumniId = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Formations", x => x.Id); + table.ForeignKey( + name: "FK_Formations_Alumni_AlumniId", + column: x => x.AlumniId, + principalTable: "Alumni", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AlumniEntityEventEntity", + columns: table => new + { + EventsId = table.Column(type: "TEXT", nullable: false), + ParticipantsId = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AlumniEntityEventEntity", x => new { x.EventsId, x.ParticipantsId }); + table.ForeignKey( + name: "FK_AlumniEntityEventEntity_Alumni_ParticipantsId", + column: x => x.ParticipantsId, + principalTable: "Alumni", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AlumniEntityEventEntity_Events_EventsId", + column: x => x.EventsId, + principalTable: "Events", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AlumniEntityEventEntity_ParticipantsId", + table: "AlumniEntityEventEntity", + column: "ParticipantsId"); + + migrationBuilder.CreateIndex( + name: "IX_Experiences_AlumniId", + table: "Experiences", + column: "AlumniId"); + + migrationBuilder.CreateIndex( + name: "IX_Formations_AlumniId", + table: "Formations", + column: "AlumniId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AlumniEntityEventEntity"); + + migrationBuilder.DropTable( + name: "Experiences"); + + migrationBuilder.DropTable( + name: "Formations"); + + migrationBuilder.DropTable( + name: "Events"); + + migrationBuilder.DropTable( + name: "Alumni"); + } + } +} diff --git a/Infrastructure/Migrations/AlumniDbContextModelSnapshot.cs b/Infrastructure/Migrations/AlumniDbContextModelSnapshot.cs new file mode 100644 index 0000000..c14f539 --- /dev/null +++ b/Infrastructure/Migrations/AlumniDbContextModelSnapshot.cs @@ -0,0 +1,217 @@ +// +using System; +using Infrastructure; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Infrastructure.Migrations +{ + [DbContext(typeof(AlumniDbContext))] + partial class AlumniDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.1"); + + modelBuilder.Entity("AlumniEntityEventEntity", b => + { + b.Property("EventsId") + .HasColumnType("TEXT"); + + b.Property("ParticipantsId") + .HasColumnType("TEXT"); + + b.HasKey("EventsId", "ParticipantsId"); + + b.HasIndex("ParticipantsId"); + + b.ToTable("AlumniEntityEventEntity"); + }); + + modelBuilder.Entity("Infrastructure.Entities.AlumniEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("EntryYear") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Github") + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Linkedin") + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Role") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WebSite") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Alumni"); + }); + + modelBuilder.Entity("Infrastructure.Entities.EventEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("nbPlaces") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Events"); + }); + + modelBuilder.Entity("Infrastructure.Entities.ExperienceEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AlumniId") + .HasColumnType("TEXT"); + + b.Property("CompanyName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("IsCurrent") + .HasColumnType("INTEGER"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AlumniId"); + + b.ToTable("Experiences"); + }); + + modelBuilder.Entity("Infrastructure.Entities.FormationEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AlumniId") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("IsCurrent") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("SchoolName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AlumniId"); + + b.ToTable("Formations"); + }); + + modelBuilder.Entity("AlumniEntityEventEntity", b => + { + b.HasOne("Infrastructure.Entities.EventEntity", null) + .WithMany() + .HasForeignKey("EventsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Infrastructure.Entities.AlumniEntity", null) + .WithMany() + .HasForeignKey("ParticipantsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Infrastructure.Entities.ExperienceEntity", b => + { + b.HasOne("Infrastructure.Entities.AlumniEntity", "Alumni") + .WithMany("Experiences") + .HasForeignKey("AlumniId"); + + b.Navigation("Alumni"); + }); + + modelBuilder.Entity("Infrastructure.Entities.FormationEntity", b => + { + b.HasOne("Infrastructure.Entities.AlumniEntity", "Alumni") + .WithMany("Formations") + .HasForeignKey("AlumniId"); + + b.Navigation("Alumni"); + }); + + modelBuilder.Entity("Infrastructure.Entities.AlumniEntity", b => + { + b.Navigation("Experiences"); + + b.Navigation("Formations"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Infrastructure/Stub/StubbedContext.cs b/Infrastructure/Stub/StubbedContext.cs new file mode 100644 index 0000000..08ba847 --- /dev/null +++ b/Infrastructure/Stub/StubbedContext.cs @@ -0,0 +1,157 @@ +using Infrastructure.Entities; +using Microsoft.EntityFrameworkCore; + +namespace Infrastructure.Stub; + +public class StubbedContext : AlumniDbContext +{ + public StubbedContext(DbContextOptions options) : base(options) + { + } + + public StubbedContext(): this(new DbContextOptionsBuilder() + .UseSqlite("DataSource=:memory:") + .Options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + var eventEntities = new List( + [ + new EventEntity + { + Id = GenerateGuid().ToString(), + Title = "Laser Game", + Description = "Venez vous amuser et faire du networking lors d'une partie de Laser Game avec vos camarades de promo et d'anciens étudiants !", + Date = GenerateRandomDate(), + nbPlaces = GenerateRandomInt(1, 100) + }, + new EventEntity + { + Id = GenerateGuid().ToString(), + Title = "Afterwork Raclette", + Description = "Venez déguster de la raclette et boire un verre lors de notre afterwork recherche de stage et alternance !", + Date = GenerateRandomDate(), + nbPlaces = GenerateRandomInt(1, 100) + }, + new EventEntity + { + Id = GenerateGuid().ToString(), + Title = "Conférence : Développeur & IA ?", + Description = "Venez assister à une conférence qui vous permettra de découvrir comment l'IA doit être prise en compte dans le développement d'applications !", + Date = GenerateRandomDate(), + nbPlaces = GenerateRandomInt(1, 100) + } + ] + ); + + var alumniEntities = new List( + [ + new User + { + Id = GenerateGuid().ToString(), + FirstName = "Test", + LastName = "Test", + Email = "test@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "ADMIN" + }, + new User + { + Id = GenerateGuid().ToString(), + FirstName = "Test2", + LastName = "Test2", + Email = "test2@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "USER", + } + ] + ); + var experienceEntities = new List( + [ + new ExperienceEntity + { + Id = GenerateGuid().ToString(), + Title = "Data Scientist", + StartDate = GenerateRandomDate(), + CompanyName = "Michelin", + IsCurrent = GenerateRandomBool() + }, + new ExperienceEntity + { + Id = GenerateGuid().ToString(), + Title = "Développeur C# .NET", + StartDate = GenerateRandomDate(), + CompanyName = "CGI", + IsCurrent = GenerateRandomBool() + } + ] + ); + var formationEntities = new List( + + [ + new FormationEntity + { + Id = GenerateGuid().ToString(), + SchoolName = "IUT Clermont-Ferrand", + Name = "BUT Informatique", + StartDate = GenerateRandomDate(), + IsCurrent = GenerateRandomBool() + }, + new FormationEntity + { + Id = GenerateGuid().ToString(), + SchoolName = "Isima", + Name = "Ingénieur Informatique", + StartDate = GenerateRandomDate(), + IsCurrent = GenerateRandomBool() + } + ] + ); + + modelBuilder.Entity().HasData(experienceEntities); + modelBuilder.Entity().HasData(formationEntities); + modelBuilder.Entity().HasData(alumniEntities); + modelBuilder.Entity().HasData(eventEntities); + } + + + // Methods to generate random data to stub the database + public Guid GenerateGuid() + { + return Guid.NewGuid(); + } + + public string GenerateRandomString(int length) + { + var random = new Random(); + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Length)]).ToArray()); + } + + public int GenerateRandomInt(int min, int max) + { + var random = new Random(); + return random.Next(min, max); + } + + public DateTime GenerateRandomDate() + { + var random = new Random(); + var start = new DateTime(1995, 1, 1); + var range = (DateTime.Today - start).Days; + return start.AddDays(random.Next(range)); + } + + public bool GenerateRandomBool() + { + var random = new Random(); + return random.Next(0, 2) > 0; + } + +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..12f2a25 --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +
+

SAE Alica

+

Entity Framework - API dotnet

+
+ + +
+ + + +--- +  ![.NET](https://img.shields.io/badge/.NET-5C2D91?style=for-the-badge&logo=.net&logoColor=white) +  ![C#](https://img.shields.io/badge/C%23-239120?style=for-the-badge&logo=c-sharp&logoColor=white) +  ![NuGet](https://img.shields.io/badge/NuGet-004880?style=for-the-badge&logo=nuget&logoColor=white) +  ![Visual Studio](https://img.shields.io/badge/Visual%20Studio-5C2D91?style=for-the-badge&logo=visual-studio&logoColor=white) +  ![Git](https://img.shields.io/badge/Git-F05032?style=for-the-badge&logo=git&logoColor=white) + +
+ +# Table des matières +[Présentation](#présentation) | [Répartition du Git](#répartition-du-git) | [Prérequis](#prérequis-pour-le-projet-entity-framework) | [Getting Started](#premiers-pas) | [Fabriqué avec](#fabriqué-avec) | [Contributeurs](#contributeurs) | + + +## Présentation + +### Récapitulatif du Projet + +Ce repot représente le rendu en API et Entity Framework, dans le cadre de notre SAe Alica. +
+En ce qui concerne la notation, notre travaille se trouve sur la branche **dev** + +## Prérequis pour le projet Entity Framework + +* [Visual Studio](https://visualstudio.microsoft.com/) - Environnement de développement intégré (IDE) recommandé pour les projets .NET si vous êtes sur Window +* [Rider](https://www.jetbrains.com/fr-fr/rider/) - Environnement de développement intégré (IDE) recommandé pour les projets .NET si vous êtes sur MAC +* [Code First](https://codefirst.iut.uca.fr/) - Outil de versioning + +## Premiers Pas +#### Warning : Le développement se faire sur la branche **dev** +1. Cloner le dépôt Git : *git clone 'https://codefirst.iut.uca.fr/git/sae.alica/API_dotnet.git'* +2. Aller dans le dossier API_dotnet : *cd API_dotnet/* +3. Changer de branche afin d'avoir la dernière version du projet : *git checkout dev* +4. Verifier bien que vous êtes sur la branche dev : *git branch* +5. Lancer le projet avec votre IDE (Rider ou Visual Studio Code) +6. Lancer la solution +7. Profiter des fonctionnalités de l'API via swagger + + +## Fabriqué avec +* [Visual Studio](https://visualstudio.microsoft.com/) - Environnement de développement intégré (IDE) recommandé pour les projets .NET +* [C#](https://learn.microsoft.com/fr-fr/dotnet/csharp/) - Documentation C# +* [Entity Framework](https://learn.microsoft.com/fr-fr/ef/) - Documentation EF +* [CodeFirst](https://codefirst.iut.uca.fr/) - Gitea + + +## Contributeurs +* [Léo TUAILLON](https://codefirst.iut.uca.fr/git/leo.tuaillon) +* [Thomas MUZARD](https://codefirst.iut.uca.fr/git/thomas.muzard) \ No newline at end of file diff --git a/Schema_recap_API.png b/Schema_recap_API.png new file mode 100644 index 0000000000000000000000000000000000000000..5d1ebfc8d08fb9badd2f4fea08c66187e397d399 GIT binary patch literal 10529 zcmeHNX;_m-*N)Y?0=|~2?6k!q3bIH+WC^7xxUkhA5P^W2fb1X!fe?aKp$Zyhkwr+P zRH6_Gh9ztP6fBz%5C{eYM8p6gvL*pS;F~~erLW(Q?|QH6`}6uE*JS3IIdiuA%z4f; z*X(R8B{$1$hCm>aM~@sj0fDT;LLh4vH?9XGYc`)piJRaPmOnxAS`E4Z*O_Nn5*IrafS5(1ke%};xZ|EZoHUJDxS zZ_SlK6SYZpUOZ}5-?{-b?mtCC#a-$BGiyMTaw~HyXsWMB013cSO^c1$x`mN;~bT89&ZOXe_()ctUZCUYhtQN3yY zoEUd1Y8d-+`^6n=Xm(HNV8QO%zfnz# z%!lYQE`&9y1LcImMEoe@AKsx6WJuy@Y^ zo&0k(`{`mLY19KnMnkIWclbGFi^GBijGrAsdR1Hfn`F}r2v61L8v8olC*GBDDm6`K>Hwob6xAW?KB(eJh=V}3HlEiO!NuW(##zp*4y26S={v9UGA@}FFw0QBAJ z?CL)C2q3xj8t#d@{QRsDcGhaO&GWmmh%=Lvi;sU_?Ord{g+|y>O2Ad&v_yo{iPfC^ z*LV`+7Iz;(Ht)VMn}GIzbM@W|kTe?jk}A<*iR^aWM(c%Jv}H6!-QsTb*vN(v4looB zOxC*yjHxrf_A)>BheCfM!{w0CPN)K4l!LT5?UfWd*d)cVmcE`UMS2gWVH` z_i+r!fl2c)WhhA(guJRTtfa`vEr+VwLOh=MTfT`avM!;TViie8yExO|u!M$@QI_ zPJ7B(o;i5=b zo@s}XEr}m9iQEBAMu#Zhgv~Pzn%=~~7NsE7Ki`Rl>eN5PzAKqt%-v36y`f9oUkCpk~F<>^@1j2UCV|_fo}ULLt-T`)`ma6 z-f)!;=GD5tgQD%GS*@f+8bUKqd6d}m#8y<+C*{(XHLg<7w^Y4~A;J z#QVFE#AHrZ+-pfRq4r>Q+2KT)i|Pj^DFasw-+FbL*)I4PfYdios&9#x)zh`d)kofA zyVe8UAvm=sa+eEiAy=Pk8sGw=ayM>G9Y_LOo?t2?F9;3q`}oz6-+YO_GZT-cSk^3z zg6zeFSH-1-&i%d>l1>zaiiY{PXhw zGi#!PCo1!ldn;}J6v(e89FD_BhjqAh0jC4>ip&X^6&9O5X3_7ZDrc%K5W%H{T;)4f zfK2`MLIsXvNu$8ZnEKE6BJ6td-I$#2KpUQ8>HDQ;dHf$hQe|K|-aFsM#Xh!~}W6ybt`d3-*9376R<7L*|@{z%XwNk%en0S;0FyufdjXap5b2*C2c zjRV9-`~b3(CLwJV9S%xlA_oyGvUJrrvB?kv=BMKY=#S`+YK(j@MBvwh&@-(>`AAP0 zdl>P({H!&v7pPqq58~Xn_&i+o6oaG*jzCh(`Epv*>zUNZkEKqXdN8K1vfiS3X>#+ma+$WKsCkbG& zo*_}!FrOT}zGbg7!!N~+UqQQsVIDOt!`^sNkPTq*#67^kfv-@na7nj;8F+=$z%*NT zih1PY3CBZkjFsM+`y#7}>34Ax$ttAGC)r;u`4DjYc3~{bVe$*g0d!!iQ zU83)^YMo#}j>@j|Q03kOF)Fh8rH5O>%<0}hM%o9)IM2-Hp)SXZ*L!=|#TfTjVujP4 zxX~_NyXi^co_pi{RZEytC#&+oHP{9NuAS=oeL;wGOa265rmaL!x0#Iuwwu#QIje0SkQM3LIqpd5A-KuT zzx8m5o$*|4y4p2ml3n_ov~#$OoNQ524!o>;$&q+R zL*{-6r}jyyWY_9Ng3$YC_lXy!e_r(Oihz&rRV>0!Z^jGG&6^-boSGnH=?!dsm%DmT z)X0a6^Zl6(;n$zP+l-$~n!!}OczkD#({8C2KY-_7es+rWJ>5%A;9VfXpD(<$xYs|J zbhAjJ+At^(xFK9R?&&Gy7LG>-nS?(dq6^KwJ^V>iz;|=JtXt0AsngjjQleZSqae&{ zmxJZ=n$z6BW`5`Fbby02F^ShbC=@AYte82_57bGjsv_p5G{yCm;P>PGAVU;!7ShB` zY3=w$60Ix4dX>T9>?{JcJ$ZkbZXa8>ZG7@r-Kq6?kEF05uJGBpOC1#4!t5mY17eA; z;&6wVE&Ya_mM-V@$HMB&mo>caSMx%#wNUn+WfaffS0r|E)}MJueDjbv;e`TkV=`sR zQYU$3+;7h9_(&76x4W!E`Yn!uZ0UqWaI`QqWZuL9=)1ZItjUq`?{*t#1f`pBRv=00 zm(d~5kF6jR){7MQ{jSlFSCF_ZF1*U)x52YXk$Ms?J$;$BnAC~3-BB%?QqMnFMP~{y z+H(Z1UjF_B!mCiItD>l!JCl3*b$7%IPr89Nz&Ux7#p!+2XZ0M_@_;O4?pX1i^M%{q z*Nk0=AitnQU-D^+hA!F=T@+G2fac6wwC)tPM;+sP{9vPcmEh#?tkZor$+cZ~B(bAi zf|_*SVOS@Qo-4AqrCWuR%GO?5hT=?CdtD)Rb$dnLGEwL^)vuy`3RDSNoC`jAZ%6S& zzZHhEkc!B#>^>U)Cf;GbQyYYk6}~}EHBzv@AlC#zIJ+#l(J`jk9nVp$aCr8dSZ)we z#LCH{TpL?#5I#TiuFk?#g>v`yxN`vO?2-nfL&$HNY&%vZCl0M*m0KXBSy&^V_o(DB zhZgVbx~D-a94Jxi$`h4t&O;ruSIi0!y+uZeFD~zqfj~ zduavl#A&jHh4!fEj4u#itnxbJW9VD%QpfP^T@VM-g2Lc~eL#V@uV~sfI0E_q3`>c2Zp^=HmKAdSu3k9!{{nDhMvalfzO zmW*Xpq~p;AHq3UFg9!!wOS-N9lv8Y4!uRD|Pvp9+KCM4I#DTF;)$@m@L79x3c-Y^r zr9YKc|Go!aa5%(>(fDi2c~jZgWx|%JPsn(mU4~Gb5r=ZILWY(V@?Cj=XR{oON4Q;J zFpXuS$#>CI!h78WmU92b3lZrr9)*aN(YUOPLm~YwX&4rYkW`R1@;FdoIr!Gcfjrh4DX{JH+@Wi#KmXXDS$@KjdzRjK7MccFE$h?-C@@<_??))8 zDf{-U>kMgdFwwtg3vf}pUMwjV1p6Asu^qG<%IW$#NCSAyN702-N;u!t`nOD)~ zf0PZ|u3`hEQT5^Ut>YuVf)jo}^Du6e@BsfYHp&+Z3?Cx=b@J6a z?G%m78r*m0?$4&tX#H-L5p&}5y(wvd&1Mjn2#cI9iYZA$T!g6V5?ax%TXsu*g^%{T z(C~>3P*yrKb9``I3sw>UwO>m+HFc1Z6!%XypPf0am4vFZWv~| z$=){C%XE7Op-&2XCgp2V%)B03dc!r(X#7a*CrO+chQXFz5q6jpWnNzi4>x&4*h#7* zo*jlQDXh&3cjk_y+bZnpzA{!}S%Wcr^GTs)COR^$BEH)VeJpKGocAK|+f8^C^Jq-Q z-n@&raFNnvQ6>X3`3Ca`lGOd+zV52x?uQPUS=@0GQwRY@CnXfP3 zOEY}s1*@_|4F^kWRd_aoh=6~WL)G*y$@bmXQLVn5TilZMazzU6Ti(=viY>VgTwN9> zfz6pMdL$fRh`>3CK2zNu`P=Sja{-Aafdv&j0XghYh{!Tn&+r?kEpfHsApeNA8b{ym zU4&0*m;~Gv0868+xInw!qxW{NH`W2~3tlmLItn@LB2t%W*CmE%gvUR#5&0)qN-VBP zyn4y#;JX0k7b=gHK)U(uG#SuqA+z4d(w zldl}CUqzm*dS^QM6vH$=9@2wHI@k_pYz7Nx)GU3hq9-ohxt@rd%F`_u$OvElBHW4%GrV|l*TPk*HmHE}9TtQ0J zq-1;LAc}!rXL0LMvs_8?qXfAJ)S}7f>2Q81L6$)IK%Ppb=^ZQ>n>>_qoUdT%zKbRI z=+do6c)5+N`IqtP4N6OQCL-=THh(exEY@FMDFHqEbBhMXSTOL4$}W_QQ*|b7t7jfw z_fs*Hc?DD?^#@^*7$_tw^(5a3Rap(* z;RVp=TA03`A61>zxAB|8Z~V>e-P|U_uw9PvCXuNsf%+`NmZuR^_Q5SkYSCAxtH@m& zm-iMu+d7$a-h(xG@Hk;lxybT78ov8{Uv(3O<}5#HP)F4_ExDu|_@ zFC2r;Y^>Xx;gf-V6C=oSab+Hr=QkMkg3m`z@pOEmafQuDzixHNqD&8b}m@D!8ZnXE}WE%?6__phy%uQ9`c6 ze*u9|?$B*bjvElCD#G4{x-7Kz$Dpb2y+K)QKX~YwNT+ePzdK2AV`$^A?Ti*qq>yXm zirc;g1!)Wlhm5H`d*&=w8F-wN_*)#qj-L{eYOES9?f23m84S#v5D$=dUcM&Gw`QV1 z{Sh*DlAj!sLf&b9O@Ay41_r{_gvX7nn6a6M@mvkm5PZYD7elQotU=OcjuoC(&H#M3nzP)x zPg4;R-*@NZZNSI7;mk2Dt~OjN`YXSemLxG}cAwe!tc}mU@qalzW791Vb62;&4lH6+bf z`to%R5V^ktBNJ9AiWjXRL?^%gDF$x24Ge`AQ~L`Ck>xU{BJO|##7i7}OcG5{nm3VM==q^QQ&epzzP2y_Dz zsauPr@8e}I)Z@g=sU*=K^s0%Ty&gO!?mF%jf4m3tqF6GYZ~goycSe9VKVOdee247w leYyYjZlGwIVY;-ib + + + https + MinimalApiScaffolder + root/Common/Api + 650 + + \ No newline at end of file diff --git a/Server/API_dotnet.http b/Server/API_dotnet.http new file mode 100644 index 0000000..af17609 --- /dev/null +++ b/Server/API_dotnet.http @@ -0,0 +1,6 @@ +@API_dotnet_HostAddress = http://localhost:5166 + +GET {{API_dotnet_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Server/Controller/v1/AlumniRestrictedController.cs b/Server/Controller/v1/AlumniRestrictedController.cs new file mode 100644 index 0000000..ab7a72c --- /dev/null +++ b/Server/Controller/v1/AlumniRestrictedController.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNetCore.Mvc; +using Server.Dto.Response; +using Asp.Versioning; +using Server.IServices; +using Shared.Criteria; + +namespace Server.Controller.v1; + +[ApiController] +[ApiVersion("1.0")] +[Route("api/v{version:apiVersion}/alumni-restricted")] +public class AlumniRestrictedController : ControllerBase +{ + private readonly ILogger _logger; + private IAlumnisService _dataServices; + + public AlumniRestrictedController(ILogger logger, IAlumnisService dataServices) + { + _logger = logger; + _dataServices = dataServices; + } + + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [RequireHttps] + public async Task GetAlumniRestricted([FromQuery] string? lastname, [FromQuery] int page = 1, [FromQuery] int size = 5, + [FromQuery] AlumniOrderCriteria orderCriteria = AlumniOrderCriteria.None, [FromQuery] bool ascending = true) + { + var alumni = await _dataServices.GetAlumnisRestricted(lastname, page, size, orderCriteria, ascending); + if( alumni.Count == 0) return NoContent(); + return Ok(alumni.Alumnis); + } + + + [HttpGet("{id}")] + [ProducesResponseType(typeof(ResponseAlumniDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [RequireHttps] + public IActionResult GetAlumniRestrictedById(string id) + { + var alumni = _dataServices.GetAlumniRestrictedById(id); + return alumni.Result == null ? NotFound() : Ok(alumni.Result); + } +} \ No newline at end of file diff --git a/Server/Controller/v1/AlumnisController.cs b/Server/Controller/v1/AlumnisController.cs new file mode 100644 index 0000000..f7c7966 --- /dev/null +++ b/Server/Controller/v1/AlumnisController.cs @@ -0,0 +1,56 @@ +using Microsoft.AspNetCore.Mvc; +using Server.Dto.Request; +using Server.Dto.Response; +using Asp.Versioning; +using Server.IServices; +using Shared.Criteria; + +namespace Server.Controller.v1; + +[ApiController] +[ApiVersion("1.0")] +[Route("api/v{version:apiVersion}/[controller]")] +public class AlumnisController : ControllerBase +{ + private readonly ILogger _logger; + private IAlumnisService _dataServices; + + public AlumnisController(ILogger logger, IAlumnisService dataServices) + { + _logger = logger; + _dataServices = dataServices; + } + + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [RequireHttps] + public IActionResult GetAlumni([FromQuery] string? lastname, [FromQuery] int page = 1, [FromQuery] int size = 5, + [FromQuery] AlumniOrderCriteria orderCriteria = AlumniOrderCriteria.None, [FromQuery] bool ascending = true) + { + var alumni = _dataServices.GetAlumnis(lastname, page, size, orderCriteria, ascending); + return alumni.Result.Count == 0 ? NoContent() : Ok(alumni.Result.Alumnis); + } + + + [HttpPost()] + [ProducesResponseType(typeof(ResponseAlumniDto), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [RequireHttps] + public IActionResult CreateAlumni([FromBody] RequestAlumniDto alumniDto) + { + var alumni = _dataServices.CreateAlumni(alumniDto); + return alumni.Result == null ? BadRequest() : CreatedAtAction(nameof(CreateAlumni), alumni); + } + + [HttpGet("{id}")] + [ProducesResponseType(typeof(ResponseAlumniDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + + [RequireHttps] + public IActionResult GetAlumniById(string id) + { + var alumni = _dataServices.GetAlumniById(id); + return alumni.Result == null ? NotFound() : Ok(alumni); + } +} \ No newline at end of file diff --git a/Server/Controller/v1/EventsController.cs b/Server/Controller/v1/EventsController.cs new file mode 100644 index 0000000..a4fee54 --- /dev/null +++ b/Server/Controller/v1/EventsController.cs @@ -0,0 +1,85 @@ +using Microsoft.AspNetCore.Mvc; +using Server.Dto.Request; +using Server.Dto.Response; +using Asp.Versioning; +using Server.IServices; +using Shared.Criteria; + +namespace Server.Controller.v1; + +[ApiController] +[ApiVersion("1.0")] +[Route("api/v{version:apiVersion}/[controller]")] +public class EventsController : ControllerBase +{ + private readonly ILogger _logger; + private readonly IEventsService _dataServices; + + public EventsController(ILogger logger, IEventsService dataServices) + { + _logger = logger; + _dataServices = dataServices; + } + + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task GetEvents([FromQuery] string? title, [FromQuery] int page = 1, [FromQuery] int size = 5, + [FromQuery] EventOrderCriteria criteria = EventOrderCriteria.Date, [FromQuery] bool ascending = true) + { + var result = await _dataServices.GetEvents(title, page, size, criteria, ascending); + if (result.Count == 0) return NoContent(); + return Ok(result.Events); + } + + [HttpGet("{id}")] + [ProducesResponseType(typeof(ResponseEventDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [RequireHttps] + public IActionResult GetEventById(string id) + { + var evt = _dataServices.GetEventById(id); + return evt.Result == null ? NotFound() : Ok(evt.Result); + } + + [HttpPost] + [ProducesResponseType(typeof(ResponseEventDto), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [RequireHttps] + public IActionResult CreateEvent([FromBody] RequestEventDto eventDto) + { + var evenement = _dataServices.CreateEvent(eventDto); + return evenement.Result == null ? BadRequest() : CreatedAtAction(nameof(CreateEvent), evenement.Result); + } + + + [HttpPut("{id}")] + [ProducesResponseType(typeof(ResponseEventDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [RequireHttps] + public IActionResult UpdateEvent(string id, [FromBody] RequestEventDto evenement) + { + var eventSelected = _dataServices.UpdateEvent(id, evenement); + return eventSelected == Task.FromResult(null) ? BadRequest() : Ok(eventSelected.Result); + } + + [HttpDelete("{id}")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [RequireHttps] + public IActionResult DeleteEvent(string id) + { + return _dataServices.DeleteEvent(id).Result ? Ok() : NotFound(); + } + + [HttpGet("Alica/{id}")] + [ProducesResponseType(typeof(IEnumerable), 200)] + [RequireHttps] + public IActionResult GetEventsByAlumniId(string id) + { + //var evenement = _dataServices.GetData(); + //var evenementSelected = evenement.Result.Where(x => x.AlicaId == id).ToList(); + //return evenementSelected.Count() == 0 ? NoContent() : Ok(evenementSelected); + return Ok(); + } +} \ No newline at end of file diff --git a/Server/Controller/v1/ExperiencesController.cs b/Server/Controller/v1/ExperiencesController.cs new file mode 100644 index 0000000..37ef302 --- /dev/null +++ b/Server/Controller/v1/ExperiencesController.cs @@ -0,0 +1,90 @@ +using Microsoft.AspNetCore.Mvc; +using Server.Dto.Request; +using Server.Dto.Response; +using Asp.Versioning; +using Server.IServices; +using Shared.Criteria; + +namespace Server.Controller.v1; + +[ApiController] +[ApiVersion("1.0")] +[Route("api/v{version:apiVersion}/[controller]")] +public class ExperiencesController : ControllerBase +{ + private readonly ILogger _logger; + private readonly IExperiencesService _dataServices; + + public ExperiencesController(ILogger logger, IExperiencesService dataServices) + { + _logger = logger; + _dataServices = dataServices; + } + + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [RequireHttps] + public async Task GetExperiences([FromQuery] string? title, [FromQuery] int page = 1, [FromQuery] int size = 5, + [FromQuery] ExperienceOrderCriteria criteria = ExperienceOrderCriteria.StartDate, [FromQuery] bool ascending = true) + { + + var result = await _dataServices.GetExperiences(title, page, size, criteria, ascending); + if (result.Count == 0) return NoContent(); + return Ok(result.Experiences); + } + + [HttpGet("{id}")] + [ProducesResponseType(typeof(ResponseExperienceDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [RequireHttps] + public IActionResult GetExperienceById(string id) + { + var experience = _dataServices.GetExperienceById(id); + return experience.Result == null ? NotFound() : Ok(experience.Result); + + } + + [HttpPost] + [ProducesResponseType(typeof(ResponseExperienceDto), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [RequireHttps] + public IActionResult CreateExperience([FromBody] RequestExperienceDto experienceDto) + { + var experience = _dataServices.CreateExperience(experienceDto); + return experience.Result == null ? BadRequest() : CreatedAtAction(nameof(CreateExperience), experience.Result); + + } + + + [HttpPut("{id}")] + [ProducesResponseType(typeof(ResponseExperienceDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [RequireHttps] + public IActionResult UpdateExperience(string id, [FromBody] RequestExperienceDto experience) + { + var experienceSelected = _dataServices.UpdateExperience(id, experience); + return experienceSelected.Result == null ? BadRequest() : Ok(experienceSelected.Result); + + } + + [HttpDelete("{id}")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [RequireHttps] + public IActionResult DeleteExperience(string id) + { + return _dataServices.DeleteExperience(id).Result ? Ok() : NotFound(); + } + + [HttpGet("Alica/{id}")] + [ProducesResponseType(typeof(IEnumerable), 200)] + [RequireHttps] + public IActionResult GetExperiencesByAlumniId(string id) + { + //var experience = _dataServices.GetData(); + //var experienceSelected = experience.Result.Where(x => x.AlicaId == id).ToList(); + //return experienceSelected.Count() == 0 ? NoContent() : Ok(experienceSelected); + return Ok(); + } +} \ No newline at end of file diff --git a/Server/Controller/v1/FormationsController.cs b/Server/Controller/v1/FormationsController.cs new file mode 100644 index 0000000..6bbc0b3 --- /dev/null +++ b/Server/Controller/v1/FormationsController.cs @@ -0,0 +1,86 @@ +using Microsoft.AspNetCore.Mvc; +using Server.Dto.Request; +using Server.Dto.Response; +using Asp.Versioning; +using Server.IServices; +using Shared.Criteria; + +namespace Server.Controller.v1; + +[ApiController] +[ApiVersion("1.0")] +[Route("api/v{version:apiVersion}/[controller]")] +public class FormationsController : ControllerBase +{ + private readonly ILogger _logger; + private IFormationsService _dataServices; + + public FormationsController(ILogger logger, IFormationsService dataServices) + { + _logger = logger; + _dataServices = dataServices; + } + + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [RequireHttps] + public async Task GetFormations([FromQuery] string? name, [FromQuery] int page = 1, [FromQuery] int size = 5, + [FromQuery] FormationOrderCriteria criteria = FormationOrderCriteria.StartDate, [FromQuery] bool ascending = true) + { + var result = await _dataServices.GetFormations(name, page, size, criteria, ascending); + if (result.Count == 0) return NoContent(); + return Ok(result.Formations); + } + + [HttpGet("{id}")] + [ProducesResponseType(typeof(ResponseFormationDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [RequireHttps] + public IActionResult GetFormationById(string id) + { + var formation = _dataServices.GetFormationById(id); + return formation.Result == null ? NotFound() : Ok(formation.Result); + } + + [HttpPost] + [ProducesResponseType(typeof(ResponseFormationDto), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [RequireHttps] + public IActionResult CreateFormation([FromBody] RequestFormationDto experienceDto) + { + var formation = _dataServices.CreateFormation(experienceDto); + return formation.Result == null ? BadRequest() : CreatedAtAction(nameof(CreateFormation), formation.Result); + } + + + [HttpPut("{id}")] + [ProducesResponseType(typeof(ResponseFormationDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [RequireHttps] + public IActionResult UpdateFormation(string id, [FromBody] RequestFormationDto formation) + { + var formationSelected = _dataServices.UpdateFormation(id, formation); + return formationSelected.Result == null ? BadRequest() : Ok(formationSelected.Result); + } + + [HttpDelete("{id}")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [RequireHttps] + public IActionResult DeleteFormation(string id) + { + return _dataServices.DeleteFormation(id).Result ? Ok() : NotFound(); + } + + [HttpGet("Alica/{id}")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [RequireHttps] + public IActionResult GetFormationsByAlumniId(string id) + { + //var formation = _dataServices.GetData(); + //var formationSelected = formation.Result.Where(x => x.AlicaId == id).ToList(); + //return formationSelected.Count() == 0 ? NoContent() : Ok(formationSelected); + return Ok(); + } +} \ No newline at end of file diff --git a/Server/Dockerfile b/Server/Dockerfile new file mode 100644 index 0000000..18264a1 --- /dev/null +++ b/Server/Dockerfile @@ -0,0 +1,27 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER $APP_UID +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["Server/Server.csproj", "Server/"] +COPY ["Infrastructure/Infrastructure.csproj", "Infrastructure/"] +COPY ["Shared/Shared.csproj", "Shared/"] +COPY ["UnitTestEF/UnitTestEF.csproj", "UnitTestEF/"] +COPY ["TestAPI/TestAPI.csproj", "TestAPI/"] +RUN dotnet restore "Server/Server.csproj" +COPY . . +WORKDIR "/src/Server" +RUN dotnet build "Server.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "Server.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Server.dll"] diff --git a/Server/Dto/Request/RequestAlumniDto.cs b/Server/Dto/Request/RequestAlumniDto.cs new file mode 100644 index 0000000..b667698 --- /dev/null +++ b/Server/Dto/Request/RequestAlumniDto.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; + +namespace Server.Dto.Request; + +public class RequestAlumniDto +{ + [EmailAddress(ErrorMessage = "Invalid Email")] + [Required(ErrorMessage = "Email is required")] + public string Email { get; set; } + + [Required(ErrorMessage = "Password is required")] + public string Password { get; set; } + + [Required(ErrorMessage = "EntryYear is required")] + public string EntryYear { get; set; } + + [Required(ErrorMessage = "FirstName is required")] + public string FirstName { get; set; } + + [Required(ErrorMessage = "LastName is required")] + public string LastName { get; set; } + + public string? LinkedinUrl { get; set; } + + public string? GithubUrl { get; set; } + + public string? PortfolioUrl { get; set; } + + public string? ImageUrl { get; set; } +} \ No newline at end of file diff --git a/Server/Dto/Request/RequestEventDto.cs b/Server/Dto/Request/RequestEventDto.cs new file mode 100644 index 0000000..b2b2e4e --- /dev/null +++ b/Server/Dto/Request/RequestEventDto.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; + +namespace Server.Dto.Request; + +public class RequestEventDto +{ + [Required(ErrorMessage = "AlumniId is required")] + public string AlumniId { get; set; } + + [Required(ErrorMessage = "Title is required")] + public string Title { get; set; } + + [Required(ErrorMessage = "Description is required")] + public string Description { get; set; } + + [Required(ErrorMessage = "Date is required")] + public DateTime Date { get; set; } + + [Required(ErrorMessage = "NumberOfParticipants is required")] + public int nbMaxRegistrations { get; set; } + + public string? ImageUrl { get; set; } +} \ No newline at end of file diff --git a/Server/Dto/Request/RequestExperienceDto.cs b/Server/Dto/Request/RequestExperienceDto.cs new file mode 100644 index 0000000..63cfc26 --- /dev/null +++ b/Server/Dto/Request/RequestExperienceDto.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; + +namespace Server.Dto.Request; + +public class RequestExperienceDto +{ + [Required(ErrorMessage = "AlumniId is required")] + public string AlumniId { get; set; } + + [Required(ErrorMessage = "Title of post is required")] + public string Title { get; set; } + + [Required(ErrorMessage = "StartingDate is required")] + public DateTime StartingDate { get; set; } + + public DateTime? EndingDate { get; set; } + + [Required(ErrorMessage = "Company's name is required")] + public string CompanyName { get; set; } + + [Required(ErrorMessage = "CurrentFormation is required")] + public bool CurrentJob { get; set; } +} \ No newline at end of file diff --git a/Server/Dto/Request/RequestFormationDto.cs b/Server/Dto/Request/RequestFormationDto.cs new file mode 100644 index 0000000..cca9a2f --- /dev/null +++ b/Server/Dto/Request/RequestFormationDto.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; + +namespace Server.Dto.Request; + +public class RequestFormationDto +{ + [Required(ErrorMessage = "AlumniId is required")] + public string AlumniId { get; set; } + + [Required(ErrorMessage = "Name of formation is required")] + public string Name { get; set; } + + [Required(ErrorMessage = "StartingDate is required")] + public DateTime StartingDate { get; set; } + + public DateTime? EndingDate { get; set; } + + [Required(ErrorMessage = "School's name is required")] + public string SchoolName { get; set; } + + [Required(ErrorMessage = "CurrentFormation is required")] + public bool CurrentFormation { get; set; } +} \ No newline at end of file diff --git a/Server/Dto/Response/ResponseAlumniDto.cs b/Server/Dto/Response/ResponseAlumniDto.cs new file mode 100644 index 0000000..910d447 --- /dev/null +++ b/Server/Dto/Response/ResponseAlumniDto.cs @@ -0,0 +1,19 @@ +using Shared.Enums; + +namespace Server.Dto.Response; + +public class ResponseAlumniDto +{ + public string Id { get; set; } + public string Email { get; set; } + public ERole ERole { get; set; } + public string EntryYear { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string? LinkedinUrl { get; set; } + public string? GithubUrl { get; set; } + public string? PortfolioUrl { get; set; } + public string? ImageUrl { get; set; } + public IEnumerable Experiences { get; set; } = new List(); + public IEnumerable Formations { get; set; } = new List(); +} \ No newline at end of file diff --git a/Server/Dto/Response/ResponseEventDto.cs b/Server/Dto/Response/ResponseEventDto.cs new file mode 100644 index 0000000..9e64891 --- /dev/null +++ b/Server/Dto/Response/ResponseEventDto.cs @@ -0,0 +1,13 @@ +namespace Server.Dto.Response; + +public class ResponseEventDto +{ + public string Id { get; set; } + public string? AlumniId { get; set; } + public string Title { get; set; } + public string? ImageUrl { get; set; } + public string Description { get; set; } + public DateTime Date { get; set; } + public int nbMaxRegistrations { get; set; } + public int nbRegistrations { get; set; } +} \ No newline at end of file diff --git a/Server/Dto/Response/ResponseExperienceDto.cs b/Server/Dto/Response/ResponseExperienceDto.cs new file mode 100644 index 0000000..0da01f0 --- /dev/null +++ b/Server/Dto/Response/ResponseExperienceDto.cs @@ -0,0 +1,12 @@ +namespace Server.Dto.Response; + +public class ResponseExperienceDto +{ + public string Id { get; set; } + public string? AlumniId { get; set; } + public string Title { get; set; } + public DateTime StartingDate { get; set; } + public DateTime? EndingDate { get; set; } + public string CompanyName { get; set; } + public bool CurrentJob { get; set; } +} \ No newline at end of file diff --git a/Server/Dto/Response/ResponseFormationDto.cs b/Server/Dto/Response/ResponseFormationDto.cs new file mode 100644 index 0000000..1f9f4b5 --- /dev/null +++ b/Server/Dto/Response/ResponseFormationDto.cs @@ -0,0 +1,12 @@ +namespace Server.Dto.Response; + +public class ResponseFormationDto +{ + public string Id { get; set; } + public string? AlumniId { get; set; } + public string Name { get; set; } + public DateTime StartingDate { get; set; } + public DateTime? EndingDate { get; set; } + public string SchoolName { get; set; } + public bool CurrentFormation { get; set; } +} \ No newline at end of file diff --git a/Server/Dto/Response/ResponseRestrictedAlumniDto.cs b/Server/Dto/Response/ResponseRestrictedAlumniDto.cs new file mode 100644 index 0000000..86dff93 --- /dev/null +++ b/Server/Dto/Response/ResponseRestrictedAlumniDto.cs @@ -0,0 +1,10 @@ +namespace Server.Dto.Response; + +public class ResponseRestrictedAlumniDto +{ + public string Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string? LinkedinUrl { get; set; } + public string? ImageUrl { get; set; } +} \ No newline at end of file diff --git a/Server/FirstTest.db b/Server/FirstTest.db new file mode 100644 index 0000000000000000000000000000000000000000..41e1a6584cf228f9ed7c1ac46c69c48c479c25e8 GIT binary patch literal 65536 zcmeI)%}?8A9Kdm#mjpr~Y*J-K+QEcF7p))?$N+I@vtVdc8dws#_E1G8ajCVuP}^+f zumkO?oqOuPu*?3ONj>j0?LKM8J&E&T#D%(r)@s2qg6A8Eqco0fhIkbgD$#ldTRWQUS{W`N_9uRe9~{#?U2@TOy@%T!Du<| zYV}CB9J6Mg=`F`D)I;`K2=pmr$1A6Edl|BCr^o)*lc}E<=Y-ad{L7}JpEQh+BSVUB z^m+P49Zi!F1W?vU5KR~ z+=wXpjx2Q(*?!&-A1bQ)xzp}$hoM)~AvrStYGF32EG@~ePrDg5ylRJQF@GKnD+Z|( zNE+1}Gm#74V?5#Swo@-3d8RYt_A#!)z|t`E$z>SAA04 z$|~BvR=S$+uGes2gJZoT6WKT%Sw8`XNBSc^DECL)E$&A=mRgTRl>Mc!_LnqKH2WAA#x>%-Kvj>UvK}93f-<@*DUkQ z5g!UhU!dNL%>USEog6iE@njEPXR*{*k%)395sK68X*KN*JNokJWS8XiEzgtCy>_Pj zB!dgeeQ*sg;a<jF%S!H>&a?BAerv<>?~IeOcz$>)L{z5U7Zn$)|2UbxJeH%% z=BE6z(2Yv9s_i{6Pc6NZD)v3ocG}j($ifMK%tr1r$m+o<|1*{$=Lv@P$ZFTmYtBQ% zvV&P2OBE&}%9G8o)EwDLH9fL;Qhdgq>3qxuyn*{*`5I_I{1Q0*~0R#|0009KXN}x0U&-eea3Mqp@009ILKmY** z5I_I{1Q0+VAi(^8fP?}B5I_I{1Q0*~0R#|0009KXPJsFUu?r~!LI42-5I_I{1Q0*~ z0R#|0ARxf}e}IGn1Q0*~0R#|0009ILKmY**#!i6w|FH`x13~}+1Q0*~0R#|0009IL zKp-H%{C|Li0t661009ILKmY**5I_I{1jbH)`TwyCDFZ?P0R#|0009ILKmY**5I`Ux z!1w Alumnis)> GetAlumnisRestricted(string? lastname, int page, int size, AlumniOrderCriteria orderCriteria = AlumniOrderCriteria.None, bool ascending = true); + Task GetAlumniRestrictedById(string id); + Task GetAlumniById(string id); + Task<(long Count, IEnumerable Alumnis)> GetAlumnis + (string? lastname, int page, int size, AlumniOrderCriteria orderCriteria = AlumniOrderCriteria.None, + bool ascending = true); + + Task CreateAlumni(RequestAlumniDto alumni); +} \ No newline at end of file diff --git a/Server/IServices/IEventsService.cs b/Server/IServices/IEventsService.cs new file mode 100644 index 0000000..0d3a4b1 --- /dev/null +++ b/Server/IServices/IEventsService.cs @@ -0,0 +1,18 @@ +using Server.Dto.Request; +using Server.Dto.Response; +using Shared.Criteria; + +namespace Server.IServices; + +public interface IEventsService +{ + Task GetEventById(string id); + + Task<(long Count, IEnumerable Events)> GetEvents + (string? title, int page, int size, EventOrderCriteria orderCriteria = EventOrderCriteria.Date, + bool ascending = true); + + Task CreateEvent(RequestEventDto evt); + Task UpdateEvent(string id, RequestEventDto evt); + Task DeleteEvent(string id); +} diff --git a/Server/IServices/IExperiencesService.cs b/Server/IServices/IExperiencesService.cs new file mode 100644 index 0000000..2ae3f4f --- /dev/null +++ b/Server/IServices/IExperiencesService.cs @@ -0,0 +1,18 @@ +using Server.Dto.Request; +using Server.Dto.Response; +using Shared.Criteria; + +namespace Server.IServices; + +public interface IExperiencesService +{ + Task GetExperienceById(string id); + + Task<(long Count, IEnumerable Experiences)> GetExperiences + (string? title, int page, int size, + ExperienceOrderCriteria orderCriteria = ExperienceOrderCriteria.EndDate, bool ascending = true); + + Task CreateExperience(RequestExperienceDto experience); + Task UpdateExperience(string id, RequestExperienceDto experience); + Task DeleteExperience(string id); +} \ No newline at end of file diff --git a/Server/IServices/IFormationsService.cs b/Server/IServices/IFormationsService.cs new file mode 100644 index 0000000..48bb8b0 --- /dev/null +++ b/Server/IServices/IFormationsService.cs @@ -0,0 +1,17 @@ +using Server.Dto.Request; +using Server.Dto.Response; +using Shared.Criteria; + +namespace Server.IServices; + +public interface IFormationsService +{ + Task GetFormationById(string id); + + Task<(long Count, IEnumerable Formations)> GetFormations + (string? name, int page, int size, FormationOrderCriteria orderCriteria, bool ascending = true); + + Task CreateFormation(RequestFormationDto formation); + Task UpdateFormation(string id, RequestFormationDto formation); + Task DeleteFormation(string id); +} \ No newline at end of file diff --git a/Server/Mappers/AlumnisMappers.cs b/Server/Mappers/AlumnisMappers.cs new file mode 100644 index 0000000..b92c073 --- /dev/null +++ b/Server/Mappers/AlumnisMappers.cs @@ -0,0 +1,64 @@ +using Infrastructure.Entities; +using Server.Dto.Request; +using Server.Dto.Response; +using Shared.Enums; + +namespace Server.Mappers; + +public static class AlumnisMappers +{ + public static ResponseAlumniDto ToDto(this User alumni) + { + return new ResponseAlumniDto + { + Id = alumni.Id, + Email = alumni.Email, + ERole = alumni.Role.ToERole(), + EntryYear = alumni.EntryYear, + FirstName = alumni.FirstName, + LastName = alumni.LastName, + LinkedinUrl = alumni.Linkedin, + GithubUrl = alumni.Github, + PortfolioUrl = alumni.WebSite, + Experiences = alumni.Experiences.Select(e => e.ToDto()), + Formations = alumni.Formations.Select(f => f.ToDto()) + }; + } + + public static ResponseRestrictedAlumniDto ToDtoRestricted(this User alumni) + { + return new ResponseRestrictedAlumniDto + { + Id = alumni.Id, + FirstName = alumni.FirstName, + LastName = alumni.LastName, + LinkedinUrl = alumni.Linkedin + }; + } + + public static User ToEntity(this RequestAlumniDto alumni) + { + return new User + { + Email = alumni.Email, + Password = alumni.Password, + EntryYear = alumni.EntryYear, + FirstName = alumni.FirstName, + LastName = alumni.LastName, + Linkedin = alumni.LinkedinUrl, + Github = alumni.GithubUrl, + WebSite = alumni.PortfolioUrl, + Role = "USER" + }; + } + + public static ERole ToERole(this string role) + { + return role switch + { + "ADMIN" => ERole.ADMIN, + "MODERATOR" => ERole.MODERATOR, + "USER" => ERole.USER + }; + } +} \ No newline at end of file diff --git a/Server/Mappers/EventsMappers.cs b/Server/Mappers/EventsMappers.cs new file mode 100644 index 0000000..eb9fa6d --- /dev/null +++ b/Server/Mappers/EventsMappers.cs @@ -0,0 +1,32 @@ +using Infrastructure.Entities; +using Server.Dto.Request; +using Server.Dto.Response; + +namespace Server.Mappers; + +public static class EventsMappers +{ + public static ResponseEventDto ToDto(this EventEntity evt) + { + return new ResponseEventDto + { + Id = evt.Id, + Title = evt.Title, + Description = evt.Description, + Date = evt.Date, + nbMaxRegistrations = evt.nbPlaces, + nbRegistrations = evt.Participants.Count + }; + } + + public static EventEntity ToEntity(this RequestEventDto evt) + { + return new EventEntity + { + Title = evt.Title, + Description = evt.Description, + Date = evt.Date, + nbPlaces = evt.nbMaxRegistrations + }; + } +} \ No newline at end of file diff --git a/Server/Mappers/ExperiencesMappers.cs b/Server/Mappers/ExperiencesMappers.cs new file mode 100644 index 0000000..7e3cc49 --- /dev/null +++ b/Server/Mappers/ExperiencesMappers.cs @@ -0,0 +1,36 @@ +using Infrastructure.Entities; +using Server.Dto.Request; +using Server.Dto.Response; + +namespace Server.Mappers +{ + public static class ExperiencesMappers + { + public static ResponseExperienceDto ToDto(this ExperienceEntity exp) + { + return new ResponseExperienceDto + { + Id = exp.Id, + AlumniId = exp.AlumniId, + Title= exp.Title, + StartingDate = exp.StartDate, + EndingDate = exp.EndDate, + CompanyName = exp.CompanyName, + CurrentJob = exp.IsCurrent, + }; + } + + public static ExperienceEntity ToEntity(this RequestExperienceDto exp) + { + return new ExperienceEntity + { + AlumniId = exp.AlumniId, + Title = exp.Title, + StartDate = exp.StartingDate, + EndDate = exp.EndingDate, + CompanyName = exp.CompanyName, + IsCurrent = exp.CurrentJob, + }; + } + } +} diff --git a/Server/Mappers/FormationsMappers.cs b/Server/Mappers/FormationsMappers.cs new file mode 100644 index 0000000..660722a --- /dev/null +++ b/Server/Mappers/FormationsMappers.cs @@ -0,0 +1,35 @@ +using Infrastructure.Entities; +using Server.Dto.Request; +using Server.Dto.Response; + +namespace Server.Mappers +{ + public static class FormationsMappers + { + public static ResponseFormationDto ToDto(this FormationEntity form) + { + return new ResponseFormationDto + { + Id = form.Id, + AlumniId = form.AlumniId, + Name = form.Name, + StartingDate = form.StartDate, + EndingDate = form.EndDate, + SchoolName = form.SchoolName, + CurrentFormation = form.IsCurrent, + }; + } + + public static FormationEntity ToEntity(this RequestFormationDto form) + { + return new FormationEntity + { + SchoolName = form.SchoolName, + Name = form.Name, + StartDate = form.StartingDate, + EndDate = form.EndingDate, + IsCurrent = form.CurrentFormation + }; + } + } +} diff --git a/Server/Program.cs b/Server/Program.cs new file mode 100644 index 0000000..f54e2ef --- /dev/null +++ b/Server/Program.cs @@ -0,0 +1,56 @@ +using Infrastructure; +using Microsoft.EntityFrameworkCore; +using Server.IServices; +using Asp.Versioning; +using Server.Services; +using Microsoft.OpenApi.Models; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddControllers(); +builder.Services.AddDbContext(options => + options.UseSqlite("Data Source=FirstTest.db")); + +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +//allow us to have lowercase urls (/alica instead of /Alica) +builder.Services.AddRouting(options => options.LowercaseUrls = true); + +// Add API's versionning +builder.Services.AddApiVersioning(options => +{ + options.DefaultApiVersion = new ApiVersion(1, 0); + options.AssumeDefaultVersionWhenUnspecified = true; + options.ReportApiVersions = true; +}) +.AddApiExplorer(options => +{ + options.GroupNameFormat = "'v'VVV"; + options.SubstituteApiVersionInUrl = true; +}); + +builder.Services.AddSwaggerGen(c => + c.SwaggerDoc("v1", new OpenApiInfo { Title = "Alica API First Version", Version = "v1" }) +); +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +// app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); \ No newline at end of file diff --git a/Server/Properties/launchSettings.json b/Server/Properties/launchSettings.json new file mode 100644 index 0000000..e8afd30 --- /dev/null +++ b/Server/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:8364", + "sslPort": 44312 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5166", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7273;http://localhost:5166", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Server/Server.csproj b/Server/Server.csproj new file mode 100644 index 0000000..926b88a --- /dev/null +++ b/Server/Server.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + enable + enable + $(MSBuildProjectDirectory) + Linux + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + .dockerignore + + + + diff --git a/Server/Server.csproj.user b/Server/Server.csproj.user new file mode 100644 index 0000000..2c8f5c1 --- /dev/null +++ b/Server/Server.csproj.user @@ -0,0 +1,8 @@ + + + + https + ApiControllerEmptyScaffolder + root/Common/Api + + \ No newline at end of file diff --git a/Server/Services/AlumniService.cs b/Server/Services/AlumniService.cs new file mode 100644 index 0000000..c071b96 --- /dev/null +++ b/Server/Services/AlumniService.cs @@ -0,0 +1,83 @@ +using Infrastructure; +using Microsoft.EntityFrameworkCore; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; +using Server.Mappers; +using Shared.Criteria; + +namespace Server.Services; + +public class AlumniService(AlumniDbContext context) : IAlumnisService +{ + public Task<(long Count, IEnumerable Alumnis)> GetAlumnisRestricted(string? lastname, int page, int size, + AlumniOrderCriteria orderCriteria = AlumniOrderCriteria.None, bool ascending = true) + { + var query = context.Alumni.Skip((page-1) * size).Take(size); + if (lastname != null) + { + query = context.Alumni.Where(e => e.LastName.Contains(lastname)).Skip((page-1) * size).Take(size); + } + switch (orderCriteria) + { + case AlumniOrderCriteria.Name: + query = ascending ? query.OrderBy(e => e.LastName) : query.OrderByDescending(e => e.LastName); + break; + case AlumniOrderCriteria.None: + break; + } + var count = query.LongCount(); + return Task.FromResult((count, query.AsEnumerable().Select(e => e.ToDtoRestricted()))); + } + + public Task GetAlumniRestrictedById(string id) + { + var result = context.Alumni.FirstOrDefault(e => e.Id == id); + return Task.FromResult(result?.ToDtoRestricted()); + } + + public Task GetAlumniById(string id) + { + var result = context.Alumni + .Include(a => a.Experiences) + .Include(a => a.Formations) + .FirstOrDefault(e => e.Id == id); + return Task.FromResult(result?.ToDto()); + } + + public Task<(long Count, IEnumerable Alumnis)> GetAlumnis(string? lastname, int page, int size, + AlumniOrderCriteria orderCriteria = AlumniOrderCriteria.None, + bool ascending = true) + { + var query = context.Alumni + .Include(a => a.Experiences) + .Include(a => a.Formations) + .Skip((page-1) * size) + .Take(size); + if (lastname != null) + { + query = context.Alumni.Where(e => e.LastName.Contains(lastname)) + .Include(a => a.Experiences) + .Include(a => a.Formations) + .Skip((page-1) * size) + .Take(size); + } + switch (orderCriteria) + { + case AlumniOrderCriteria.Name: + query = ascending ? query.OrderBy(e => e.LastName) : query.OrderByDescending(e => e.LastName); + break; + case AlumniOrderCriteria.None: + break; + } + var count = query.LongCount(); + return Task.FromResult((count, query.AsEnumerable().Select(e => e.ToDto()))); + } + + public Task CreateAlumni(RequestAlumniDto alumni) + { + var result = context.Alumni.AddAsync(alumni.ToEntity()); + context.SaveChangesAsync(); + return Task.FromResult(result.Result?.Entity.ToDto()); + } +} \ No newline at end of file diff --git a/Server/Services/EventServices.cs b/Server/Services/EventServices.cs new file mode 100644 index 0000000..570959a --- /dev/null +++ b/Server/Services/EventServices.cs @@ -0,0 +1,73 @@ +using Infrastructure; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; +using Server.Mappers; +using Shared.Criteria; + +namespace Server.Services; + +/// +/// Opération CRUD des évènements +/// +/// TODO : manque subscribe subscribers unsubscribe et récupérer les inscription d'un alumni +public class EventServices(AlumniDbContext context) : IEventsService +{ + public Task GetEventById(string id) + { + var result = context.Events.FirstOrDefault(e => e.Id == id); + return Task.FromResult(result?.ToDto()); + } + + public Task<(long Count, IEnumerable Events)> GetEvents(string? title, int page, int size, + EventOrderCriteria orderCriteria = EventOrderCriteria.Date, bool ascending = true) + { + var query = context.Events.Skip((page-1) * size).Take(size); + if (title != null) + { + query = context.Events.Where(e => e.Title.Contains(title)).Skip((page-1) * size).Take(size); + } + switch (orderCriteria) + { + case EventOrderCriteria.Date: + query = ascending ? query.OrderBy(e => e.Date) : query.OrderByDescending(e => e.Date); + break; + case EventOrderCriteria.Title: + query = ascending ? query.OrderBy(e => e.Title) : query.OrderByDescending(e => e.Title); + break; + case EventOrderCriteria.NbPlaces: + query = ascending ? query.OrderBy(e => e.nbPlaces) : query.OrderByDescending(e => e.nbPlaces); + break; + } + var count = query.LongCount(); + return Task.FromResult((count, query.AsEnumerable().Select(e => e.ToDto()))); + } + + public Task CreateEvent(RequestEventDto evt) + { + var result = context.Events.AddAsync(evt.ToEntity()); + context.SaveChangesAsync(); + return Task.FromResult(result.Result.Entity.ToDto()); + } + + public Task UpdateEvent(string id, RequestEventDto evt) + { + var result = context.Events.FirstOrDefault(e => e.Id == id); + if (result == null) return Task.FromResult(null); + result.Title = evt.Title; + result.Description = evt.Description; + result.Date = evt.Date; + result.nbPlaces = evt.nbMaxRegistrations; + context.SaveChangesAsync(); + return Task.FromResult(result.ToDto()); + } + + public Task DeleteEvent(string id) + { + var result = context.Events.FirstOrDefault(e => e.Id == id); + if (result == null) return Task.FromResult(false); + context.Events.Remove(result); + context.SaveChangesAsync(); + return Task.FromResult(true); + } +} \ No newline at end of file diff --git a/Server/Services/ExperienceServices.cs b/Server/Services/ExperienceServices.cs new file mode 100644 index 0000000..5ef6e65 --- /dev/null +++ b/Server/Services/ExperienceServices.cs @@ -0,0 +1,82 @@ +using Infrastructure; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; +using Shared.Criteria; +using Server.Mappers; + +namespace Server.Services; + +public class ExperienceServices(AlumniDbContext context) : IExperiencesService +{ + public Task GetExperienceById(string id) + { + var result = context.Experiences.FirstOrDefault(exp => exp.Id == id); + return Task.FromResult(result?.ToDto()); + } + + public Task<(long Count, IEnumerable Experiences)> GetExperiences(string? title, int page, int size, + ExperienceOrderCriteria orderCriteria = ExperienceOrderCriteria.EndDate, bool ascending = true) + { + var query = context.Experiences + .Skip((page-1) * size) + .Take(size); + if (title != null) + { + query = context.Experiences + .Where(e => e.Title.Contains(title)) + .Skip((page-1) * size) + .Take(size); + } + switch (orderCriteria) + { + case ExperienceOrderCriteria.StartDate: + query = ascending ? query.OrderBy(e => e.StartDate) : query.OrderByDescending(e => e.StartDate); + break; + case ExperienceOrderCriteria.EndDate: + query = ascending ? query.OrderBy(e => e.EndDate) : query.OrderByDescending(e => e.EndDate); + break; + case ExperienceOrderCriteria.Title: + query = ascending ? query.OrderBy(e => e.Title) : query.OrderByDescending(e => e.Title); + break; + } + var count = query.LongCount(); + return Task.FromResult((count, query.AsEnumerable().Select(e => e.ToDto()))); + } + + public Task CreateExperience(RequestExperienceDto experience) + { + var result = context.Experiences.AddAsync(experience.ToEntity()); + var alica = context.Alumni.FirstOrDefault(a => a.Id == experience.AlumniId); + alica?.Experiences.Add(result.Result.Entity); + context.SaveChangesAsync(); + return Task.FromResult(result.Result.Entity.ToDto()); + } + + public Task UpdateExperience(string id, RequestExperienceDto experience) + { + var result = context.Experiences.FirstOrDefault(e => e.Id == id); + if (result == null) + { + return Task.FromResult(null); + } + result.Title = experience.Title; + result.StartDate = experience.StartingDate; + result.EndDate = experience.EndingDate; + result.CompanyName = experience.CompanyName; + result.IsCurrent = experience.CurrentJob; + + context.SaveChangesAsync(); + return Task.FromResult(result.ToDto()); + } + + public Task DeleteExperience(string id) + { + var result = context.Experiences.FirstOrDefault(e => e.Id == id); + if (result == null) + return Task.FromResult(false); + context.Experiences.Remove(result); + context.SaveChangesAsync(); + return Task.FromResult(true); + } +} \ No newline at end of file diff --git a/Server/Services/FormationServices.cs b/Server/Services/FormationServices.cs new file mode 100644 index 0000000..9b994b3 --- /dev/null +++ b/Server/Services/FormationServices.cs @@ -0,0 +1,79 @@ +using Infrastructure; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; +using Shared.Criteria; +using Server.Mappers; + +namespace Server.Services; + +public class FormationServices(AlumniDbContext context) : IFormationsService +{ + public Task GetFormationById(string id) + { + var result = context.Formations.FirstOrDefault(form => form.Id == id); + return Task.FromResult(result?.ToDto()); + } + + public Task<(long Count, IEnumerable Formations)> GetFormations(string? name, int page, int size, + FormationOrderCriteria orderCriteria = FormationOrderCriteria.EndDate, bool ascending = true) + { + var query = context.Formations.Skip((page-1) * size).Take(size); + if (name != null) + { + query = context.Formations.Where(e => e.Name.Contains(name)).Skip((page-1) * size).Take(size); + } + switch (orderCriteria) + { + case FormationOrderCriteria.StartDate: + query = ascending ? query.OrderBy(e => e.StartDate) : query.OrderByDescending(e => e.StartDate); + break; + case FormationOrderCriteria.EndDate: + query = ascending ? query.OrderBy(e => e.EndDate) : query.OrderByDescending(e => e.EndDate); + break; + case FormationOrderCriteria.Name: + query = ascending ? query.OrderBy(e => e.Name) : query.OrderByDescending(e => e.Name); + break; + case FormationOrderCriteria.SchoolName: + query = ascending ? query.OrderBy(e => e.SchoolName) : query.OrderByDescending(e => e.SchoolName); + break; + } + var count = query.LongCount(); + return Task.FromResult((count, query.AsEnumerable().Select(e => e.ToDto()))); + } + + public Task CreateFormation(RequestFormationDto formation) + { + var result = context.Formations.AddAsync(formation.ToEntity()); + var alica = context.Alumni.FirstOrDefault(a => a.Id == formation.AlumniId); + alica?.Formations.Add(result.Result.Entity); + context.SaveChangesAsync(); + return Task.FromResult(result.Result.Entity.ToDto()); + } + + public Task UpdateFormation(string id, RequestFormationDto formation) + { + var result = context.Formations.FirstOrDefault(e => e.Id == id); + if (result == null) + { + return Task.FromResult(null); + } + result.SchoolName = formation.SchoolName; + result.Name = formation.Name; + result.StartDate = formation.StartingDate; + result.EndDate = formation.EndingDate; + result.IsCurrent = formation.CurrentFormation; + + context.SaveChangesAsync(); + return Task.FromResult(result.ToDto()); + } + + public Task DeleteFormation(string id) + { + var result = context.Formations.FirstOrDefault(form => form.Id == id); + if (result == null) return Task.FromResult(false); + context.Formations.Remove(result); + context.SaveChangesAsync(); + return Task.FromResult(true); + } +} \ No newline at end of file diff --git a/Server/appsettings.Development.json b/Server/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Server/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Server/appsettings.json b/Server/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Server/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Shared/Criteria/AlumniOrderCriteria.cs b/Shared/Criteria/AlumniOrderCriteria.cs new file mode 100644 index 0000000..49381cc --- /dev/null +++ b/Shared/Criteria/AlumniOrderCriteria.cs @@ -0,0 +1,7 @@ +namespace Shared.Criteria; + +public enum AlumniOrderCriteria +{ + Name, + None +} \ No newline at end of file diff --git a/Shared/Criteria/EventOrderCriteria.cs b/Shared/Criteria/EventOrderCriteria.cs new file mode 100644 index 0000000..9c05e78 --- /dev/null +++ b/Shared/Criteria/EventOrderCriteria.cs @@ -0,0 +1,8 @@ +namespace Shared.Criteria; + +public enum EventOrderCriteria +{ + Title, + Date, + NbPlaces +} \ No newline at end of file diff --git a/Shared/Criteria/ExperienceOrderCriteria.cs b/Shared/Criteria/ExperienceOrderCriteria.cs new file mode 100644 index 0000000..f26b697 --- /dev/null +++ b/Shared/Criteria/ExperienceOrderCriteria.cs @@ -0,0 +1,8 @@ +namespace Shared.Criteria; + +public enum ExperienceOrderCriteria +{ + Title, + StartDate, + EndDate +} \ No newline at end of file diff --git a/Shared/Criteria/FormationOrderCriteria.cs b/Shared/Criteria/FormationOrderCriteria.cs new file mode 100644 index 0000000..2536803 --- /dev/null +++ b/Shared/Criteria/FormationOrderCriteria.cs @@ -0,0 +1,10 @@ +namespace Shared.Criteria; + +public enum FormationOrderCriteria +{ + Name, + StartDate, + EndDate, + SchoolName, + +} \ No newline at end of file diff --git a/Shared/Enums/EContract.cs b/Shared/Enums/EContract.cs new file mode 100644 index 0000000..54241b5 --- /dev/null +++ b/Shared/Enums/EContract.cs @@ -0,0 +1,9 @@ +namespace Shared.Enums; + +public enum EContract +{ + CDI, + CDD, + INTERNSHIP, + APPRENTICESHIP +} \ No newline at end of file diff --git a/Shared/Enums/ELevel.cs b/Shared/Enums/ELevel.cs new file mode 100644 index 0000000..a06763f --- /dev/null +++ b/Shared/Enums/ELevel.cs @@ -0,0 +1,8 @@ +namespace Shared.Enums; + +public enum ELevel +{ + JUNIOR, + SENIOR, + INDEFERENT +} \ No newline at end of file diff --git a/Shared/Enums/ERole.cs b/Shared/Enums/ERole.cs new file mode 100644 index 0000000..4a84ed2 --- /dev/null +++ b/Shared/Enums/ERole.cs @@ -0,0 +1,8 @@ +namespace Shared.Enums; + +public enum ERole +{ + ADMIN, + MODERATOR, + USER +} \ No newline at end of file diff --git a/Shared/Enums/EStudies.cs b/Shared/Enums/EStudies.cs new file mode 100644 index 0000000..73286b7 --- /dev/null +++ b/Shared/Enums/EStudies.cs @@ -0,0 +1,9 @@ +namespace Shared.Enums; + +public enum EStudies +{ + BAC_2, + BAC_3, + BAC_5, + INDIFERENT +} \ No newline at end of file diff --git a/Shared/IDataServices.cs b/Shared/IDataServices.cs new file mode 100644 index 0000000..e558fd9 --- /dev/null +++ b/Shared/IDataServices.cs @@ -0,0 +1,44 @@ +namespace Shared; + +/// +/// Interface d'objet générique contenant les méthodes CRUD +/// +/// Objet Générique +public interface IDataServices +{ + /// + /// Récupère toutes les données + /// + /// un Enumerable d'objet générique + /// TODO : Ne pas passer par un tuple + public Task> GetData(); + + /// + /// Récupère un objet en fonction de son identifiant + /// + /// identifiant + /// Un objet générique ou null si objet introuvable + public Task GetDataById(string id); + + /// + /// Ajout d'un objet + /// + /// information sur l'objet + /// L'objet créé + public Task CreateData(TObject data); + + /// + /// Modifie un objet en fonction de son id + /// + /// Information du nouvelle objet + /// identifiant de l'objet à modifier + /// L'objet modifié ou null si id incorrect + public Task UpdateData(TObject data, string id); + + /// + /// Supprime un objet en fonction de son identifiant + /// + /// identifiant + /// true si réussi sinon false + public Task DeleteObjectById(string id); +} \ No newline at end of file diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj new file mode 100644 index 0000000..3a63532 --- /dev/null +++ b/Shared/Shared.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/TestAPI/ControllerTests/AlumniControllerTest.cs b/TestAPI/ControllerTests/AlumniControllerTest.cs new file mode 100644 index 0000000..818d3eb --- /dev/null +++ b/TestAPI/ControllerTests/AlumniControllerTest.cs @@ -0,0 +1,130 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Moq; +using Server.Controller.v1; +using Server.Dto.Response; +using Server.IServices; +using Shared.Criteria; + +namespace TestAPI.ControllerTests +{ +public class AlumniControllerTest +{ + private readonly Mock> _loggerMock = new Mock>(); + private readonly Mock _alumnisServiceMock = new Mock(); + + [Fact] + public void GetAlumni_NoAlumni_ReturnsNoContent() + { + // Arrange + _alumnisServiceMock.Setup(service => service.GetAlumnis(null, 1, 5, AlumniOrderCriteria.None, true)) + .ReturnsAsync((0, Enumerable.Empty())); + + var controller = new AlumnisController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = controller.GetAlumni(null); + + // Assert + var actionResult = Assert.IsType(result); + } + + [Fact] + public void GetAlumni_AlumniExists_ReturnsOk() + { + // Arrange + var alumniList = new List + { + new ResponseAlumniDto { Id = "1", FirstName = "John", LastName = "Doe" } + }; + _alumnisServiceMock.Setup(service => service.GetAlumnis(null, 1, 5, AlumniOrderCriteria.None, true)) + .ReturnsAsync((alumniList.Count, alumniList)); + + var controller = new AlumnisController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = controller.GetAlumni(null); + + // Assert + var actionResult = Assert.IsType(result); + var returnValue = Assert.IsAssignableFrom>(actionResult.Value); + Assert.Single(returnValue); + } + + [Fact] + public void GetAlumniById_AlumniExists_ReturnsOk() + { + // Arrange + var alumniId = "1"; + var alumniDto = new ResponseAlumniDto { Id = alumniId }; + _alumnisServiceMock.Setup(service => service.GetAlumniById(alumniId)).ReturnsAsync(alumniDto); + + var controller = new AlumnisController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = controller.GetAlumniById(alumniId); + + // Assert + var actionResult = Assert.IsType(result); + var returnValue = Assert.IsType>(actionResult.Value); + Assert.Equal(alumniId, returnValue.Result.Id); + } + + [Fact] + public void GetAlumniById_AlumniDoesNotExist_ReturnsNotFound() + { + // Arrange + var alumniId = "1"; + _alumnisServiceMock.Setup(service => service.GetAlumniById(alumniId)).ReturnsAsync((ResponseAlumniDto)null); + + var controller = new AlumnisController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = controller.GetAlumniById(alumniId); + + // Assert + var actionResult = Assert.IsType(result); + } + + [Fact] + public void GetAlumni_ByLastName_NoAlumni_ReturnsNoContent() + { + // Arrange + var lastName = "Doe"; + _alumnisServiceMock.Setup(service => service.GetAlumnis(lastName, 1, 5, AlumniOrderCriteria.None, true)) + .ReturnsAsync((0, new List())); + + var controller = new AlumnisController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = controller.GetAlumni(lastName); + + // Assert + var actionResult = Assert.IsType(result); + } + + [Fact] + public void GetAlumni_ByLastName_AlumniExist_ReturnsOk() + { + // Arrange + var lastName = "Doe"; + var alumniList = new List + { + new ResponseAlumniDto { Id = "1", LastName = "Doe" } + }; + _alumnisServiceMock.Setup(service => service.GetAlumnis(lastName, 1, 5, AlumniOrderCriteria.None, true)) + .ReturnsAsync((alumniList.Count, alumniList)); + + var controller = new AlumnisController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = controller.GetAlumni(lastName); + + // Assert + var actionResult = Assert.IsType(result); + var returnValue = Assert.IsAssignableFrom>(actionResult.Value); + Assert.Single(returnValue); + } + } +} + diff --git a/TestAPI/ControllerTests/AlumuniRestrictedControllerTest.cs b/TestAPI/ControllerTests/AlumuniRestrictedControllerTest.cs new file mode 100644 index 0000000..570547f --- /dev/null +++ b/TestAPI/ControllerTests/AlumuniRestrictedControllerTest.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Xunit; +using Moq; +using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using Server.Dto.Response; +using Server.Controller.v1; +using Server.IServices; +using Shared.Criteria; +using System.Threading.Tasks; + +namespace TestAPI.ControllerTests +{ + public class AlumuniRestrictedControllerTest + { + private readonly Mock> _loggerMock = new Mock>(); + private readonly Mock _alumnisServiceMock = new Mock(); + + [Fact] + public async Task GetAlumniRestricted_NoAlumni_ReturnsNoContent() + { + // Arrange + var lastName = "Doe"; + _alumnisServiceMock.Setup(service => service.GetAlumnisRestricted(lastName, 1, 5, AlumniOrderCriteria.None, true)) + .ReturnsAsync((0L, new List())); + + var controller = new AlumniRestrictedController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = await controller.GetAlumniRestricted(lastName); + + // Assert + var actionResult = Assert.IsType(result); + } + + [Fact] + public async Task GetAlumniRestricted_AlumniExist_ReturnsOk() + { + // Arrange + var lastName = "Doe"; + var alumniList = new List + { + new ResponseRestrictedAlumniDto { Id = "1", LastName = "Doe" } + }; + _alumnisServiceMock.Setup(service => service.GetAlumnisRestricted(lastName, 1, 5, AlumniOrderCriteria.None, true)) + .ReturnsAsync((alumniList.Count, alumniList)); + + var controller = new AlumniRestrictedController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = await controller.GetAlumniRestricted(lastName); + + // Assert + var actionResult = Assert.IsType(result); + var returnValue = Assert.IsAssignableFrom>(actionResult.Value); + Assert.Single(returnValue); + } + + [Fact] + public void GetAlumniRestrictedById_AlumniExists_ReturnsOk() + { + // Arrange + var alumniId = "1"; + var alumniDto = new ResponseRestrictedAlumniDto { Id = alumniId }; + _alumnisServiceMock.Setup(service => service.GetAlumniRestrictedById(alumniId)).ReturnsAsync(alumniDto); + + var controller = new AlumniRestrictedController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = controller.GetAlumniRestrictedById(alumniId); + + // Assert + var actionResult = Assert.IsType(result); + var returnValue = Assert.IsType(actionResult.Value); + Assert.Equal(alumniId, returnValue.Id); + } + + [Fact] + public void GetAlumniRestrictedById_AlumniDoesNotExist_ReturnsNotFound() + { + // Arrange + var alumniId = "1"; + _alumnisServiceMock.Setup(service => service.GetAlumniRestrictedById(alumniId)).ReturnsAsync((ResponseRestrictedAlumniDto)null); + + var controller = new AlumniRestrictedController(_loggerMock.Object, _alumnisServiceMock.Object); + + // Act + var result = controller.GetAlumniRestrictedById(alumniId); + + // Assert + var actionResult = Assert.IsType(result); + } + } +} diff --git a/TestAPI/ControllerTests/EvenementControllerTest.cs b/TestAPI/ControllerTests/EvenementControllerTest.cs new file mode 100644 index 0000000..988c7e2 --- /dev/null +++ b/TestAPI/ControllerTests/EvenementControllerTest.cs @@ -0,0 +1,179 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Moq; +using Server.Controller.v1; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; +using Shared.Criteria; + +namespace TestAPI.ControllerTests +{ + public class EventTest + { + private readonly ILogger _loggerMock = Mock.Of>(); + private readonly Mock _servicesMock = new Mock(); + + [Fact] + public async Task GetEvents() + { + // Arrange + var expectedEvents = new List + { + new ResponseEventDto { Id = "1", Title = "Event 1" }, + new ResponseEventDto { Id = "2", Title = "Event 2" } + }; + _servicesMock.Setup(s => s.GetEvents(null, 0, 10, EventOrderCriteria.Date, true)) + .ReturnsAsync((expectedEvents.Count, expectedEvents)); + + var eventsController = new EventsController(_loggerMock, _servicesMock.Object); + + // Act + var result = await eventsController.GetEvents(null, 0, 10); + + // Assert + var okResult = Assert.IsType(result); + var eventList = Assert.IsAssignableFrom>(okResult.Value); + Assert.Equal(expectedEvents.Count, eventList.Count()); + } + + [Fact] + public async Task GetEventById_ValidId() + { + // Arrange + var expectedEvent = new ResponseEventDto { Id = "1", Title = "Event 1" }; + _servicesMock.Setup(s => s.GetEventById("1")).ReturnsAsync(expectedEvent); + + var eventsController = new EventsController(_loggerMock, _servicesMock.Object); + + // Act + var result = eventsController.GetEventById("1"); + + // Assert + var okResult = Assert.IsType(result); + var eventItem = Assert.IsType(okResult.Value); + Assert.Equal(expectedEvent.Id, eventItem.Id); + Assert.Equal(expectedEvent.Title, eventItem.Title); + } + + [Fact] + public async Task GetEventById_InvalidId() + { + // Arrange + _servicesMock.Setup(s => s.GetEventById("InvalidId")).ReturnsAsync((ResponseEventDto?)null); + + var eventsController = new EventsController(_loggerMock, _servicesMock.Object); + + // Act + var result = eventsController.GetEventById("InvalidId"); + + // Assert + Assert.IsType(result); + } + + [Fact] + public async Task CreateEvent() + { + // Arrange + var newEvent = new RequestEventDto + { + AlumniId = "A1", + Title = "New Event", + Description = "Description", + Date = DateTime.Now, + nbMaxRegistrations = 100 + }; + var expectedEvent = new ResponseEventDto { Id = "3", Title = "New Event" }; + _servicesMock.Setup(s => s.CreateEvent(newEvent)).ReturnsAsync(expectedEvent); + + var eventsController = new EventsController(_loggerMock, _servicesMock.Object); + + // Act + var result = eventsController.CreateEvent(newEvent); + + // Assert + var createdAtResult = Assert.IsType(result); + var createdEvent = Assert.IsType(createdAtResult.Value); + Assert.Equal(expectedEvent.Id, createdEvent.Id); + Assert.Equal(expectedEvent.Title, createdEvent.Title); + } + + [Fact] + public async Task UpdateEvent_ValidId() + { + // Arrange + var updatedEvent = new RequestEventDto + { + Title = "Updated Event", + Description = "Updated Description", + Date = DateTime.Now.AddDays(1), + nbMaxRegistrations = 200 + }; + var expectedEvent = new ResponseEventDto { Id = "1", Title = "Updated Event" }; + _servicesMock.Setup(s => s.UpdateEvent("1", updatedEvent)).ReturnsAsync(expectedEvent); + + var eventsController = new EventsController(_loggerMock, _servicesMock.Object); + + // Act + var result = eventsController.UpdateEvent("1", updatedEvent); + + // Assert + var okResult = Assert.IsType(result); + var updatedEventResult = Assert.IsType(okResult.Value); + Assert.Equal(expectedEvent.Id, updatedEventResult.Id); + Assert.Equal(expectedEvent.Title, updatedEventResult.Title); + } + + [Fact] + public async Task UpdateEvent_InvalidId() + { + // Arrange + var updatedEvent = new RequestEventDto + { + Title = "Updated Event", + Description = "Updated Description", + Date = DateTime.Now.AddDays(1), + nbMaxRegistrations = 200 + }; + _servicesMock.Setup(s => s.UpdateEvent("InvalidId", updatedEvent)).ReturnsAsync((ResponseEventDto?)null); + + var eventsController = new EventsController(_loggerMock, _servicesMock.Object); + + // Act + var result = eventsController.UpdateEvent("InvalidId", updatedEvent); + + // Assert + Assert.IsType(result); + } + + [Fact] + public async Task DeleteEvent_ValidId() + { + // Arrange + _servicesMock.Setup(s => s.DeleteEvent("1")).ReturnsAsync(true); + + var eventsController = new EventsController(_loggerMock, _servicesMock.Object); + + // Act + var result = eventsController.DeleteEvent("1"); + + // Assert + Assert.IsType(result); + } + + [Fact] + public async Task DeleteEvent_InvalidId() + { + // Arrange + _servicesMock.Setup(s => s.DeleteEvent("InvalidId")).ReturnsAsync(false); + + var eventsController = new EventsController(_loggerMock, _servicesMock.Object); + + // Act + var result = eventsController.DeleteEvent("InvalidId"); + + // Assert + Assert.IsType(result); + } + } +} diff --git a/TestAPI/ControllerTests/ExperienceControllerTest.cs b/TestAPI/ControllerTests/ExperienceControllerTest.cs new file mode 100644 index 0000000..335b4e2 --- /dev/null +++ b/TestAPI/ControllerTests/ExperienceControllerTest.cs @@ -0,0 +1,186 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Moq; +using Server.Controller.v1; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; +using Shared.Criteria; + +namespace TestAPI.ControllerTests +{ + public class ExperienceControllerTest + { + private readonly ILogger _loggerMock = Mock.Of>(); + private readonly Mock _servicesMock = new Mock(); + + [Fact] + public async Task GetExperiences() + { + // Arrange + var expectedExperiences = new List + { + new ResponseExperienceDto { Id = "1", Title = "Iut" }, + }; + _servicesMock.Setup(s => s.GetExperiences(null, 0, 10, ExperienceOrderCriteria.StartDate, true)) + .ReturnsAsync((expectedExperiences.Count, expectedExperiences)); + + var experiencesController = new ExperiencesController(_loggerMock, _servicesMock.Object); + + // Act + var result = await experiencesController.GetExperiences(null, 0, 10); + + // Assert + var okResult = Assert.IsType(result); + var experienceList = Assert.IsAssignableFrom>(okResult.Value); + Assert.Equal(expectedExperiences.Count, experienceList.Count()); + } + + [Fact] + public async Task GetExperienceById_ValidId() + { + // Arrange + var expectedExperience = new ResponseExperienceDto { Id = "1", Title = "Iut" }; + _servicesMock.Setup(s => s.GetExperienceById("1")).ReturnsAsync(expectedExperience); + + var experiencesController = new ExperiencesController(_loggerMock, _servicesMock.Object); + + // Act + var result = experiencesController.GetExperienceById("1"); + + // Assert + var okResult = Assert.IsType(result); + var experienceItem = Assert.IsType(okResult.Value); + Assert.Equal(expectedExperience.Id, experienceItem.Id); + Assert.Equal(expectedExperience.Title, experienceItem.Title); + } + + [Fact] + public async Task GetExperienceById_InvalidId() + { + // Arrange + _servicesMock.Setup(s => s.GetExperienceById("hgfyhgyjhu")).ReturnsAsync((ResponseExperienceDto?)null); + + // Act + var experiencesController = new ExperiencesController(_loggerMock, _servicesMock.Object); + + var result = experiencesController.GetExperienceById("hgfyhgyjhu"); + + // Assert + Assert.IsType(result); + } + + [Fact] + public async Task CreateExperience() + { + // Arrange + var newExperience = new RequestExperienceDto + { + AlumniId = "A1", + Title = "Junior Dev", + StartingDate = DateTime.Now.AddYears(-2), + CompanyName = "CGI", + CurrentJob = false + }; + var expectedExperience = new ResponseExperienceDto { Id = "4", Title = "Junior Dev" }; + _servicesMock.Setup(s => s.CreateExperience(newExperience)).ReturnsAsync(expectedExperience); + + var experiencesController = new ExperiencesController(_loggerMock, _servicesMock.Object); + + // Act + var result = experiencesController.CreateExperience(newExperience); + + // Assert + var createdAtResult = Assert.IsType(result); + var createdExperience = Assert.IsType(createdAtResult.Value); + Assert.Equal(expectedExperience.Id, createdExperience.Id); + Assert.Equal(expectedExperience.Title, createdExperience.Title); + } + + [Fact] + public async Task UpdateExperience_ValidId() + { + // Arrange + var updatedExperience = new RequestExperienceDto + { + Title = "Update Software Developer", + StartingDate = DateTime.Now.AddYears(-2), + EndingDate = DateTime.Now, + CompanyName = "TechCo", + CurrentJob = false, + AlumniId = "A1" + }; + var expectedExperience = new ResponseExperienceDto { Id = "1", Title = "Update Software Developer" }; + _servicesMock.Setup(s => s.UpdateExperience("1", updatedExperience)).ReturnsAsync(expectedExperience); + + var experiencesController = new ExperiencesController(_loggerMock, _servicesMock.Object); + + // Act + var result = experiencesController.UpdateExperience("1", updatedExperience); + + // Assert + var okResult = Assert.IsType(result); + var updatedExperienceResult = Assert.IsType(okResult.Value); + Assert.Equal(expectedExperience.Id, updatedExperienceResult.Id); + Assert.Equal(expectedExperience.Title, updatedExperienceResult.Title); + } + + [Fact] + public async Task UpdateExperience_InvalidId() + { + // Arrange + var updatedOffer = new RequestExperienceDto + { + Title = "Update Software Developer", + StartingDate = DateTime.Now.AddYears(-2), + EndingDate = DateTime.Now, + CompanyName = "TechCo", + CurrentJob = false, + AlumniId = "A1" + }; + _servicesMock.Setup(s => s.UpdateExperience("InvalidId", updatedOffer)).ReturnsAsync((ResponseExperienceDto?)null); + + // Act + var experiencesController = new ExperiencesController(_loggerMock, _servicesMock.Object); + + var result = experiencesController.UpdateExperience("InvalidId", updatedOffer); + + // Assert + var badRequestResult = Assert.IsType(result); + } + + [Fact] + public async Task DeleteExperience_ValidId() + { + // Arrange + _servicesMock.Setup(s => s.DeleteExperience("1")).ReturnsAsync(true); + + var experiencesController = new ExperiencesController(_loggerMock, _servicesMock.Object); + + // Act + var result = experiencesController.DeleteExperience("1"); + + // Assert + Assert.IsType(result); + } + + [Fact] + public async Task DeleteExperience_InvalidId() + { + // Arrange + _servicesMock.Setup(s => s.DeleteExperience("InvalidId")).ReturnsAsync(false); + + var experiencesController = new ExperiencesController(_loggerMock, _servicesMock.Object); + + // Act + var result = experiencesController.DeleteExperience("InvalidId"); + + // Assert + Assert.IsType(result); + } + + + + } +} + diff --git a/TestAPI/ControllerTests/FormationControllerTest.cs b/TestAPI/ControllerTests/FormationControllerTest.cs new file mode 100644 index 0000000..efe6d6c --- /dev/null +++ b/TestAPI/ControllerTests/FormationControllerTest.cs @@ -0,0 +1,179 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Moq; +using Server.Controller.v1; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; +using Shared.Criteria; + +namespace TestAPI.ControllerTests +{ + public class FormationControllerTest + { + private readonly ILogger _loggerMock = Mock.Of>(); + private readonly Mock _servicesMock = new Mock(); + + [Fact] + public async Task GetFormations() + { + // Arrange + var expectedFormations = new List + { + new ResponseFormationDto { Id = "1", Name = "Computer Science" }, + new ResponseFormationDto { Id = "2", Name = "Data Science" } + }; + _servicesMock.Setup(s => s.GetFormations(null, 0, 10, FormationOrderCriteria.StartDate, true)) + .ReturnsAsync((expectedFormations.Count, expectedFormations)); + + var formationsController = new FormationsController(_loggerMock, _servicesMock.Object); + + // Act + var result = await formationsController.GetFormations(null, 0, 10); + + // Assert + var okResult = Assert.IsType(result); + var formationList = Assert.IsAssignableFrom>(okResult.Value); + Assert.Equal(expectedFormations.Count, formationList.Count()); + } + + [Fact] + public async Task GetFormationById_ValidId() + { + // Arrange + var expectedFormation = new ResponseFormationDto { Id = "1", Name = "Computer Science" }; + _servicesMock.Setup(s => s.GetFormationById("1")).ReturnsAsync(expectedFormation); + + var formationsController = new FormationsController(_loggerMock, _servicesMock.Object); + + // Act + var result = formationsController.GetFormationById("1"); + + // Assert + var okResult = Assert.IsType(result); + var formationItem = Assert.IsType(okResult.Value); + Assert.Equal(expectedFormation.Id, formationItem.Id); + Assert.Equal(expectedFormation.Name, formationItem.Name); + } + + [Fact] + public async Task GetFormationById_InvalidId() + { + // Arrange + _servicesMock.Setup(s => s.GetFormationById("InvalidId")).ReturnsAsync((ResponseFormationDto)null); + + var formationsController = new FormationsController(_loggerMock, _servicesMock.Object); + + // Act + var result = formationsController.GetFormationById("InvalidId"); + + // Assert + Assert.IsType(result); + } + + [Fact] + public async Task CreateFormation() + { + // Arrange + var newFormation = new RequestFormationDto + { + AlumniId = "A1", + Name = "Software Engineering", + StartingDate = DateTime.Now.AddYears(-2), + SchoolName = "University XYZ", + CurrentFormation = true + }; + var expectedFormation = new ResponseFormationDto { Id = "3", Name = "Software Engineering" }; + _servicesMock.Setup(s => s.CreateFormation(newFormation)).ReturnsAsync(expectedFormation); + + var formationsController = new FormationsController(_loggerMock, _servicesMock.Object); + + // Act + var result = formationsController.CreateFormation(newFormation); + + // Assert + var createdAtResult = Assert.IsType(result); + var createdFormation = Assert.IsType(createdAtResult.Value); + Assert.Equal(expectedFormation.Id, createdFormation.Id); + Assert.Equal(expectedFormation.Name, createdFormation.Name); + } + + [Fact] + public async Task UpdateFormation_ValidId() + { + // Arrange + var updatedFormation = new RequestFormationDto + { + Name = "Updated Data Science", + StartingDate = DateTime.Now.AddYears(-2), + SchoolName = "University XYZ", + CurrentFormation = false + }; + var expectedFormation = new ResponseFormationDto { Id = "2", Name = "Updated Data Science" }; + _servicesMock.Setup(s => s.UpdateFormation("2", updatedFormation)).ReturnsAsync(expectedFormation); + + var formationsController = new FormationsController(_loggerMock, _servicesMock.Object); + + // Act + var result = formationsController.UpdateFormation("2", updatedFormation); + + // Assert + var okResult = Assert.IsType(result); + var updatedFormationResult = Assert.IsType(okResult.Value); + Assert.Equal(expectedFormation.Id, updatedFormationResult.Id); + Assert.Equal(expectedFormation.Name, updatedFormationResult.Name); + } + + [Fact] + public async Task UpdateFormation_InvalidId() + { + // Arrange + var updatedFormation = new RequestFormationDto + { + Name = "Updated Data Science", + StartingDate = DateTime.Now.AddYears(-2), + SchoolName = "University XYZ", + CurrentFormation = false + }; + _servicesMock.Setup(s => s.UpdateFormation("InvalidId", updatedFormation)).ReturnsAsync((ResponseFormationDto)null); + + var formationsController = new FormationsController(_loggerMock, _servicesMock.Object); + + // Act + var result = formationsController.UpdateFormation("InvalidId", updatedFormation); + + // Assert + Assert.IsType(result); + } + + [Fact] + public async Task DeleteFormation_ValidId() + { + // Arrange + _servicesMock.Setup(s => s.DeleteFormation("1")).ReturnsAsync(true); + + var formationsController = new FormationsController(_loggerMock, _servicesMock.Object); + + // Act + var result = formationsController.DeleteFormation("1"); + + // Assert + Assert.IsType(result); + } + + [Fact] + public async Task DeleteFormation_InvalidId() + { + // Arrange + _servicesMock.Setup(s => s.DeleteFormation("InvalidId")).ReturnsAsync(false); + + var formationsController = new FormationsController(_loggerMock, _servicesMock.Object); + + // Act + var result = formationsController.DeleteFormation("InvalidId"); + + // Assert + Assert.IsType(result); + } + } +} diff --git a/TestAPI/MapperTests/AlumniMappersTests.cs b/TestAPI/MapperTests/AlumniMappersTests.cs new file mode 100644 index 0000000..b610944 --- /dev/null +++ b/TestAPI/MapperTests/AlumniMappersTests.cs @@ -0,0 +1,112 @@ +using Server.Mappers; +using Server.Dto.Request; +using Infrastructure.Entities; +using Shared.Enums; + +namespace TestAPI.MapperTests +{ + public class AlumniMappersTests + { + [Fact] + public void ToDto_ConvertsAlumniEntityToResponseAlumniDto() + { + // Arrange + var alumniEntity = new User + { + Id = "1", + Email = "test@example.com", + Role = "USER", + EntryYear = "2020", + FirstName = "John", + LastName = "Doe", + Linkedin = "linkedin.com", + Github = "github.com", + WebSite = "portfolio.com", + Experiences = (ICollection)Enumerable.Empty(), + Formations = (ICollection)Enumerable.Empty() + }; + + // Act + var result = alumniEntity.ToDto(); + + // Assert + Assert.Equal(alumniEntity.Id, result.Id); + Assert.Equal(alumniEntity.Email, result.Email); + Assert.Equal(ERole.USER, result.ERole); + Assert.Equal(alumniEntity.EntryYear, result.EntryYear); + Assert.Equal(alumniEntity.FirstName, result.FirstName); + Assert.Equal(alumniEntity.LastName, result.LastName); + Assert.Equal(alumniEntity.Linkedin, result.LinkedinUrl); + Assert.Equal(alumniEntity.Github, result.GithubUrl); + Assert.Equal(alumniEntity.WebSite, result.PortfolioUrl); + Assert.Empty(result.Experiences); + Assert.Empty(result.Formations); + } + + [Fact] + public void ToDtoRestricted_ConvertsAlumniEntityToResponseRestrictedAlumniDto() + { + // Arrange + var alumniEntity = new User + { + Id = "1", + FirstName = "John", + LastName = "Doe", + Linkedin = "linkedin.com" + }; + + // Act + var result = alumniEntity.ToDtoRestricted(); + + // Assert + Assert.Equal(alumniEntity.Id, result.Id); + Assert.Equal(alumniEntity.FirstName, result.FirstName); + Assert.Equal(alumniEntity.LastName, result.LastName); + Assert.Equal(alumniEntity.Linkedin, result.LinkedinUrl); + } + + [Fact] + public void ToEntity_ConvertsRequestAlumniDtoToAlumniEntity() + { + // Arrange + var requestAlumniDto = new RequestAlumniDto + { + Email = "test@example.com", + Password = "password", + EntryYear = "2020", + FirstName = "John", + LastName = "Doe", + LinkedinUrl = "linkedin.com", + GithubUrl = "github.com", + PortfolioUrl = "portfolio.com" + }; + + // Act + var result = requestAlumniDto.ToEntity(); + + // Assert + Assert.Equal(requestAlumniDto.Email, result.Email); + Assert.Equal(requestAlumniDto.Password, result.Password); + Assert.Equal(requestAlumniDto.EntryYear, result.EntryYear); + Assert.Equal(requestAlumniDto.FirstName, result.FirstName); + Assert.Equal(requestAlumniDto.LastName, result.LastName); + Assert.Equal(requestAlumniDto.LinkedinUrl, result.Linkedin); + Assert.Equal(requestAlumniDto.GithubUrl, result.Github); + Assert.Equal(requestAlumniDto.PortfolioUrl, result.WebSite); + Assert.Equal("USER", result.Role); + } + + [Theory] + [InlineData("ADMIN", ERole.ADMIN)] + [InlineData("MODERATOR", ERole.MODERATOR)] + [InlineData("USER", ERole.USER)] + public void ToERole_ConvertsStringToERole(string role, ERole expectedRole) + { + // Act + var result = role.ToERole(); + + // Assert + Assert.Equal(expectedRole, result); + } + } +} diff --git a/TestAPI/MapperTests/EventMappersTests.cs b/TestAPI/MapperTests/EventMappersTests.cs new file mode 100644 index 0000000..1a1d75d --- /dev/null +++ b/TestAPI/MapperTests/EventMappersTests.cs @@ -0,0 +1,62 @@ +using Infrastructure.Entities; +using Server.Mappers; +using Server.Dto.Request; + + +namespace TestAPI.MapperTests +{ + public class EventMappersTests + { + [Fact] + public void ToDto_ConvertsEventEntityToResponseEventDto() + { + // Arrange + var eventEntity = new EventEntity + { + Id = "1", + Title = "Test Event", + Description = "Test Description", + Date = DateTime.UtcNow, + nbPlaces = 100, + Participants = new System.Collections.Generic.List + { + new User(), + new User() + } + }; + + // Act + var result = eventEntity.ToDto(); + + // Assert + Assert.Equal(eventEntity.Id, result.Id); + Assert.Equal(eventEntity.Title, result.Title); + Assert.Equal(eventEntity.Description, result.Description); + Assert.Equal(eventEntity.Date, result.Date); + Assert.Equal(eventEntity.nbPlaces, result.nbMaxRegistrations); + Assert.Equal(eventEntity.Participants.Count, result.nbRegistrations); + } + + [Fact] + public void ToEntity_ConvertsRequestEventDtoToEventEntity() + { + // Arrange + var requestEventDto = new RequestEventDto + { + Title = "Test Event", + Description = "Test Description", + Date = DateTime.UtcNow, + nbMaxRegistrations = 100 + }; + + // Act + var result = requestEventDto.ToEntity(); + + // Assert + Assert.Equal(requestEventDto.Title, result.Title); + Assert.Equal(requestEventDto.Description, result.Description); + Assert.Equal(requestEventDto.Date, result.Date); + Assert.Equal(requestEventDto.nbMaxRegistrations, result.nbPlaces); + } + } +} diff --git a/TestAPI/MapperTests/ExperienceMapperTests.cs b/TestAPI/MapperTests/ExperienceMapperTests.cs new file mode 100644 index 0000000..9728acb --- /dev/null +++ b/TestAPI/MapperTests/ExperienceMapperTests.cs @@ -0,0 +1,63 @@ +using Server.Mappers; +using Server.Dto.Request; +using Infrastructure.Entities; + +namespace TestAPI.MapperTests +{ + public class ExperienceMapperTests + { + [Fact] + public void ToDto_ConvertsExperienceEntityToResponseExperienceDto() + { + // Arrange + var experienceEntity = new ExperienceEntity + { + Id = "1", + AlumniId = "1", + Title = "Test Experience", + StartDate = DateTime.UtcNow, + EndDate = DateTime.UtcNow.AddYears(1), + CompanyName = "Test Company", + IsCurrent = false + }; + + // Act + var result = experienceEntity.ToDto(); + + // Assert + Assert.Equal(experienceEntity.Id, result.Id); + Assert.Equal(experienceEntity.AlumniId, result.AlumniId); + Assert.Equal(experienceEntity.Title, result.Title); + Assert.Equal(experienceEntity.StartDate, result.StartingDate); + Assert.Equal(experienceEntity.EndDate, result.EndingDate); + Assert.Equal(experienceEntity.CompanyName, result.CompanyName); + Assert.Equal(experienceEntity.IsCurrent, result.CurrentJob); + } + + [Fact] + public void ToEntity_ConvertsRequestExperienceDtoToExperienceEntity() + { + // Arrange + var requestExperienceDto = new RequestExperienceDto + { + AlumniId = "1", + Title = "Test Experience", + StartingDate = DateTime.UtcNow, + EndingDate = DateTime.UtcNow.AddYears(1), + CompanyName = "Test Company", + CurrentJob = false + }; + + // Act + var result = requestExperienceDto.ToEntity(); + + // Assert + Assert.Equal(requestExperienceDto.AlumniId, result.AlumniId); + Assert.Equal(requestExperienceDto.Title, result.Title); + Assert.Equal(requestExperienceDto.StartingDate, result.StartDate); + Assert.Equal(requestExperienceDto.EndingDate, result.EndDate); + Assert.Equal(requestExperienceDto.CompanyName, result.CompanyName); + Assert.Equal(requestExperienceDto.CurrentJob, result.IsCurrent); + } + } +} diff --git a/TestAPI/MapperTests/FormationMapperTests.cs b/TestAPI/MapperTests/FormationMapperTests.cs new file mode 100644 index 0000000..c418b4c --- /dev/null +++ b/TestAPI/MapperTests/FormationMapperTests.cs @@ -0,0 +1,61 @@ +using Infrastructure.Entities; +using Server.Dto.Request; +using Server.Mappers; + +namespace TestAPI.MapperTests +{ + public class FormationMapperTests + { + [Fact] + public void ToDto_ConvertsFormationEntityToResponseFormationDto() + { + // Arrange + var formationEntity = new FormationEntity + { + Id = "1", + AlumniId = "1", + Name = "Test Formation", + StartDate = DateTime.UtcNow, + EndDate = DateTime.UtcNow.AddYears(1), + SchoolName = "Test School", + IsCurrent = false + }; + + // Act + var result = formationEntity.ToDto(); + + // Assert + Assert.Equal(formationEntity.Id, result.Id); + Assert.Equal(formationEntity.AlumniId, result.AlumniId); + Assert.Equal(formationEntity.Name, result.Name); + Assert.Equal(formationEntity.StartDate, result.StartingDate); + Assert.Equal(formationEntity.EndDate, result.EndingDate); + Assert.Equal(formationEntity.SchoolName, result.SchoolName); + Assert.Equal(formationEntity.IsCurrent, result.CurrentFormation); + } + + [Fact] + public void ToEntity_ConvertsRequestFormationDtoToFormationEntity() + { + // Arrange + var requestFormationDto = new RequestFormationDto + { + Name = "Test Formation", + StartingDate = DateTime.UtcNow, + EndingDate = DateTime.UtcNow.AddYears(1), + SchoolName = "Test School", + CurrentFormation = false + }; + + // Act + var result = requestFormationDto.ToEntity(); + + // Assert + Assert.Equal(requestFormationDto.Name, result.Name); + Assert.Equal(requestFormationDto.StartingDate, result.StartDate); + Assert.Equal(requestFormationDto.EndingDate, result.EndDate); + Assert.Equal(requestFormationDto.SchoolName, result.SchoolName); + Assert.Equal(requestFormationDto.CurrentFormation, result.IsCurrent); + } + } +} diff --git a/TestAPI/ServicesTests/AlumniServiceTests.cs b/TestAPI/ServicesTests/AlumniServiceTests.cs new file mode 100644 index 0000000..e68aa23 --- /dev/null +++ b/TestAPI/ServicesTests/AlumniServiceTests.cs @@ -0,0 +1,101 @@ +using Xunit; +using Moq; +using System.Linq; +using System.Collections.Generic; +using Infrastructure; +using Infrastructure.Entities; +using Microsoft.EntityFrameworkCore; +using Server.Dto.Request; +using Server.Services; +using Shared.Criteria; + +public class AlumniServiceTests +{ + private readonly Mock _mockContext; + private readonly AlumniService _alumniService; + + public AlumniServiceTests() + { + var alumni = new List + { + new User { Id = "1", LastName = "Alumni1" }, + new User { Id = "2", LastName = "Alumni2" } + }.AsQueryable(); + + var mockSet = new Mock>(); + mockSet.As>().Setup(m => m.Provider).Returns(alumni.Provider); + mockSet.As>().Setup(m => m.Expression).Returns(alumni.Expression); + mockSet.As>().Setup(m => m.ElementType).Returns(alumni.ElementType); + mockSet.As>().Setup(m => m.GetEnumerator()).Returns(alumni.GetEnumerator()); + + _mockContext = new Mock(); + _mockContext.Setup(c => c.Alumni).Returns(mockSet.Object); + + _alumniService = new AlumniService(_mockContext.Object); + } + + [Fact] + public async Task GetAlumniById_ReturnsNull_WhenIdDoesNotExist() + { + var result = await _alumniService.GetAlumniById("3"); + Assert.Null(result); + } + + + [Fact] + public async Task GetAlumnis_ReturnsEmpty_WhenLastNameDoesNotExist() + { + var result = await _alumniService.GetAlumnis("Alumni3", 1, 1, AlumniOrderCriteria.Name, true); + Assert.Empty(result.Alumnis); + } + + + [Fact] + public async Task GetAlumnisRestricted_NoMatchingLastName_ReturnsEmpty() + { + // Arrange + string lastName = "NonExistingLastName"; + var page = 1; + var size = 5; + + // Act + var result = await _alumniService.GetAlumnisRestricted(lastName, page, size); + + // Assert + Assert.Empty(result.Alumnis); + } + + [Fact] + public async Task GetAlumnisRestricted_MatchingLastName_ReturnsAlumni() + { + // Arrange + string lastName = "Alumni1"; + var page = 1; + var size = 5; + + // Act + var result = await _alumniService.GetAlumnisRestricted(lastName, page, size); + + // Assert + Assert.NotEmpty(result.Alumnis); + Assert.Equal(1, result.Alumnis.Count()); + Assert.Equal("Alumni1", result.Alumnis.First().LastName); + } + + [Fact] + public async Task GetAlumnisRestricted_PaginationWorksCorrectly() + { + // Arrange + string lastName = null; + var page = 2; + var size = 1; + + // Act + var result = await _alumniService.GetAlumnisRestricted(lastName, page, size); + + // Assert + Assert.NotEmpty(result.Alumnis); + Assert.Single(result.Alumnis); + Assert.Equal("Alumni2", result.Alumnis.First().LastName); + } +} \ No newline at end of file diff --git a/TestAPI/ServicesTests/EventServicesTests.cs b/TestAPI/ServicesTests/EventServicesTests.cs new file mode 100644 index 0000000..5d34463 --- /dev/null +++ b/TestAPI/ServicesTests/EventServicesTests.cs @@ -0,0 +1,97 @@ +using Xunit; +using Moq; +using System.Linq; +using System.Collections.Generic; +using Infrastructure; +using Infrastructure.Entities; +using Microsoft.EntityFrameworkCore; +using Server.Dto.Request; +using Server.Services; +using Shared.Criteria; + +public class EventServicesTests +{ + private readonly Mock _mockContext; + private readonly EventServices _eventServices; + + public EventServicesTests() + { + var events = new List + { + new EventEntity { Id = "1", Title = "Event1", Description = "Description1", Date = DateTime.Now, nbPlaces = 100 }, + new EventEntity { Id = "2", Title = "Event2", Description = "Description2", Date = DateTime.Now.AddDays(1), nbPlaces = 200 } + }.AsQueryable(); + + var mockSet = new Mock>(); + mockSet.As>().Setup(m => m.Provider).Returns(events.Provider); + mockSet.As>().Setup(m => m.Expression).Returns(events.Expression); + mockSet.As>().Setup(m => m.ElementType).Returns(events.ElementType); + mockSet.As>().Setup(m => m.GetEnumerator()).Returns(events.GetEnumerator()); + + _mockContext = new Mock(); + _mockContext.Setup(c => c.Events).Returns(mockSet.Object); + + _eventServices = new EventServices(_mockContext.Object); + } + + [Fact] + public async Task GetEventById_ReturnsEvent_WhenIdExists() + { + var result = await _eventServices.GetEventById("1"); + Assert.NotNull(result); + Assert.Equal("1", result.Id); + } + + [Fact] + public async Task GetEventById_ReturnsNull_WhenIdDoesNotExist() + { + var result = await _eventServices.GetEventById("3"); + Assert.Null(result); + } + + [Fact] + public async Task GetEvents_ReturnsEvents_WhenTitleExists() + { + var result = await _eventServices.GetEvents("Event1", 1, 1, EventOrderCriteria.Date, true); + Assert.Single(result.Events); + Assert.Equal("Event1", result.Events.First().Title); + } + + [Fact] + public async Task GetEvents_ReturnsEmpty_WhenTitleDoesNotExist() + { + var result = await _eventServices.GetEvents("Event3", 1, 1, EventOrderCriteria.Date, true); + Assert.Empty(result.Events); + } + + [Fact] + public async Task UpdateEvent_ReturnsUpdatedEvent_WhenIdExists() + { + var eventDto = new RequestEventDto { Title = "UpdatedEvent", Description = "UpdatedDescription", Date = DateTime.Now, nbMaxRegistrations = 150 }; + var result = await _eventServices.UpdateEvent("1", eventDto); + Assert.NotNull(result); + Assert.Equal("UpdatedEvent", result.Title); + } + + [Fact] + public async Task UpdateEvent_ReturnsNull_WhenIdDoesNotExist() + { + var eventDto = new RequestEventDto { Title = "UpdatedEvent", Description = "UpdatedDescription", Date = DateTime.Now, nbMaxRegistrations = 150 }; + var result = await _eventServices.UpdateEvent("3", eventDto); + Assert.Null(result); + } + + [Fact] + public async Task DeleteEvent_ReturnsTrue_WhenIdExists() + { + var result = await _eventServices.DeleteEvent("1"); + Assert.True(result); + } + + [Fact] + public async Task DeleteEvent_ReturnsFalse_WhenIdDoesNotExist() + { + var result = await _eventServices.DeleteEvent("3"); + Assert.False(result); + } +} \ No newline at end of file diff --git a/TestAPI/ServicesTests/ExperienceServicesTests.cs b/TestAPI/ServicesTests/ExperienceServicesTests.cs new file mode 100644 index 0000000..0b6ace7 --- /dev/null +++ b/TestAPI/ServicesTests/ExperienceServicesTests.cs @@ -0,0 +1,93 @@ +using Moq; +using Infrastructure; +using Infrastructure.Entities; +using Microsoft.EntityFrameworkCore; +using Server.Dto.Request; +using Server.Services; + +public class ExperienceServicesTests +{ + private readonly Mock _mockContext; + private readonly ExperienceServices _experienceServices; + + public ExperienceServicesTests() + { + var experiences = new List + { + new ExperienceEntity { Id = "1", Title = "Experience1", CompanyName = "Company1", StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(30), IsCurrent = true }, + new ExperienceEntity { Id = "2", Title = "Experience2", CompanyName = "Company2", StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(30), IsCurrent = false } + }.AsQueryable(); + + var mockSet = new Mock>(); + mockSet.As>().Setup(m => m.Provider).Returns(experiences.Provider); + mockSet.As>().Setup(m => m.Expression).Returns(experiences.Expression); + mockSet.As>().Setup(m => m.ElementType).Returns(experiences.ElementType); + mockSet.As>().Setup(m => m.GetEnumerator()).Returns(experiences.GetEnumerator()); + + _mockContext = new Mock(); + _mockContext.Setup(c => c.Experiences).Returns(mockSet.Object); + + _experienceServices = new ExperienceServices(_mockContext.Object); + } + + [Fact] + public async Task GetExperienceById_ReturnsExperience_WhenIdExists() + { + var result = await _experienceServices.GetExperienceById("1"); + Assert.NotNull(result); + Assert.Equal("1", result.Id); + } + + [Fact] + public async Task GetExperienceById_ReturnsNull_WhenIdDoesNotExist() + { + var result = await _experienceServices.GetExperienceById("3"); + Assert.Null(result); + } + + [Fact] + public async Task GetExperiences_ReturnsExperiences_WhenTitleExists() + { + var result = await _experienceServices.GetExperiences("Experience1", 1, 1); + Assert.Single(result.Experiences); + Assert.Equal("Experience1", result.Experiences.First().Title); + } + + [Fact] + public async Task GetExperiences_ReturnsEmpty_WhenTitleDoesNotExist() + { + var result = await _experienceServices.GetExperiences("Experience3", 1, 1); + Assert.Empty(result.Experiences); + } + + [Fact] + public async Task UpdateExperience_ReturnsUpdatedExperience_WhenIdExists() + { + var experience = new RequestExperienceDto { Title = "UpdatedExperience", CompanyName = "UpdatedCompany", StartingDate = DateTime.Now, EndingDate = DateTime.Now.AddDays(30), CurrentJob = false }; + var result = await _experienceServices.UpdateExperience("1", experience); + Assert.NotNull(result); + Assert.Equal("UpdatedExperience", result.Title); + } + + [Fact] + public async Task UpdateExperience_ReturnsNull_WhenIdDoesNotExist() + { + var experience = new RequestExperienceDto { Title = "UpdatedExperience", CompanyName = "UpdatedCompany", StartingDate = DateTime.Now, EndingDate = DateTime.Now.AddDays(30), CurrentJob = false }; + var result = await _experienceServices.UpdateExperience("3", experience); + Assert.Null(result); + } + + [Fact] + public async Task DeleteExperience_ReturnsTrue_WhenIdExists() + { + var result = await _experienceServices.DeleteExperience("1"); + Assert.True(result); + } + + [Fact] + public async Task DeleteExperience_ReturnsFalse_WhenIdDoesNotExist() + { + var result = await _experienceServices.DeleteExperience("3"); + Assert.False(result); + } +} \ No newline at end of file diff --git a/TestAPI/ServicesTests/FormationServiceTests.cs b/TestAPI/ServicesTests/FormationServiceTests.cs new file mode 100644 index 0000000..950840f --- /dev/null +++ b/TestAPI/ServicesTests/FormationServiceTests.cs @@ -0,0 +1,143 @@ +using Moq; +using Infrastructure; +using Infrastructure.Entities; +using Microsoft.EntityFrameworkCore; +using Server.Dto.Request; +using Server.Services; + +public class FormationServicesTests +{ + private readonly Mock _mockContext; + private readonly FormationServices _formationServices; + + public FormationServicesTests() + { + var formations = new List + { + new FormationEntity { Id = "1", Name = "Formation1", SchoolName = "School1", StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(30), IsCurrent = true }, + new FormationEntity { Id = "2", Name = "Formation2", SchoolName = "School2", StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(30), IsCurrent = true } + }.AsQueryable(); + + var mockSet = new Mock>(); + mockSet.As>().Setup(m => m.Provider).Returns(formations.Provider); + mockSet.As>().Setup(m => m.Expression).Returns(formations.Expression); + mockSet.As>().Setup(m => m.ElementType).Returns(formations.ElementType); + mockSet.As>().Setup(m => m.GetEnumerator()).Returns(formations.GetEnumerator()); + + _mockContext = new Mock(); + _mockContext.Setup(c => c.Formations).Returns(mockSet.Object); + + _formationServices = new FormationServices(_mockContext.Object); + } + + [Fact] + public async Task GetFormationById_ReturnsFormation_WhenIdExists() + { + var result = await _formationServices.GetFormationById("1"); + Assert.NotNull(result); + Assert.Equal("1", result.Id); + } + + [Fact] + public async Task GetFormationById_ReturnsNull_WhenIdDoesNotExist() + { + var result = await _formationServices.GetFormationById("3"); + Assert.Null(result); + } + + [Fact] + public async Task GetFormations_ReturnsFormations_WhenNameExists() + { + var result = await _formationServices.GetFormations("Formation1", 1, 1); + Assert.Single(result.Formations); + Assert.Equal("Formation1", result.Formations.First().Name); + } + + [Fact] + public async Task GetFormations_ReturnsEmpty_WhenNameDoesNotExist() + { + var result = await _formationServices.GetFormations("Formation3", 1, 1); + Assert.Empty(result.Formations); + } + + [Fact] + public async Task UpdateFormation_ReturnsUpdatedFormation_WhenIdExists() + { + var formation = new RequestFormationDto { Name = "UpdatedFormation", SchoolName = "UpdatedSchool", StartingDate = DateTime.Now, EndingDate = DateTime.Now.AddDays(30), CurrentFormation = false }; + var result = await _formationServices.UpdateFormation("1", formation); + Assert.NotNull(result); + Assert.Equal("UpdatedFormation", result.Name); + } + + [Fact] + public async Task UpdateFormation_ReturnsNull_WhenIdDoesNotExist() + { + var formation = new RequestFormationDto { Name = "UpdatedFormation", SchoolName = "UpdatedSchool", StartingDate = DateTime.Now, EndingDate = DateTime.Now.AddDays(30), CurrentFormation = false }; + var result = await _formationServices.UpdateFormation("3", formation); + Assert.Null(result); + } + + [Fact] + public async Task DeleteFormation_ReturnsTrue_WhenIdExists() + { + var result = await _formationServices.DeleteFormation("1"); + Assert.True(result); + } + + [Fact] + public async Task DeleteFormation_ReturnsFalse_WhenIdDoesNotExist() + { + var result = await _formationServices.DeleteFormation("3"); + Assert.False(result); + } + + [Fact] + public async Task GetFormations_NoName_ReturnsFormations() + { + // Arrange + string name = null; + var page = 1; + var size = 5; + + // Act + var result = await _formationServices.GetFormations(name, page, size); + + // Assert + Assert.NotEmpty(result.Formations); + Assert.Equal(2, result.Formations.Count()); + } + + [Fact] + public async Task GetFormations_MatchingName_ReturnsFilteredFormations() + { + // Arrange + string name = "Formation1"; + var page = 1; + var size = 5; + + // Act + var result = await _formationServices.GetFormations(name, page, size); + + // Assert + Assert.Single(result.Formations); + Assert.Equal("Formation1", result.Formations.First().Name); + } + + [Fact] + public async Task GetFormations_PaginationWorksCorrectly() + { + // Arrange + string name = null; + var page = 2; + var size = 1; + + // Act + var result = await _formationServices.GetFormations(name, page, size); + + // Assert + Assert.NotEmpty(result.Formations); + Assert.Single(result.Formations); + Assert.Equal("Formation2", result.Formations.First().Name); + } + +} \ No newline at end of file diff --git a/TestAPI/TestAPI.csproj b/TestAPI/TestAPI.csproj new file mode 100644 index 0000000..32217dd --- /dev/null +++ b/TestAPI/TestAPI.csproj @@ -0,0 +1,28 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + + diff --git a/TestConsoleApi/Program.cs b/TestConsoleApi/Program.cs new file mode 100644 index 0000000..2a3b82d --- /dev/null +++ b/TestConsoleApi/Program.cs @@ -0,0 +1,93 @@ +using System; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Server.Dto.Request; +using Server.Dto.Response; + +class Program +{ + static async Task Main(string[] args) + { + string baseUrl = "https://localhost:7273/api/v1/"; + + HttpClient client = new HttpClient(); + client.BaseAddress = new Uri(baseUrl); + + // Création d'un nouvel élément + var newExperience = new RequestExperienceDto + { + AlumniId = "A1", + Title = "Junior Dev", + StartingDate = DateTime.Now.AddYears(-2), + CompanyName = "CGI", + CurrentJob = false + }; + + var json = JsonConvert.SerializeObject(newExperience); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + + var response = await client.PostAsync("experiences", content); + if (response.IsSuccessStatusCode) + { + var responseData = await response.Content.ReadAsStringAsync(); + var createdExperience = JsonConvert.DeserializeObject(responseData); + Console.WriteLine($"Expérience créée avec succès. ID : {createdExperience.Id}"); + } + else + { + Console.WriteLine($"Erreur lors de la création de l'expérience. Code : {response.StatusCode}"); + } + + // Lecture d'un élément par son ID + string experienceId = "123"; + response = await client.GetAsync($"experiences/{experienceId}"); + if (response.IsSuccessStatusCode) + { + var responseData = await response.Content.ReadAsStringAsync(); + var experience = JsonConvert.DeserializeObject(responseData); + Console.WriteLine($"Expérience récupérée avec succès : {experience.Title}"); + } + else + { + Console.WriteLine($"Erreur lors de la récupération de l'expérience. Code : {response.StatusCode}"); + } + + // Mise à jour d'un élément + var updatedExperience = new RequestExperienceDto + { + Title = "Senior Dev", + StartingDate = DateTime.Now.AddYears(-3), + CompanyName = "Microsoft", + CurrentJob = true, + AlumniId = "A1" + }; + + json = JsonConvert.SerializeObject(updatedExperience); + content = new StringContent(json, Encoding.UTF8, "application/json"); + + response = await client.PutAsync($"experiences/{experienceId}", content); + if (response.IsSuccessStatusCode) + { + var responseData = await response.Content.ReadAsStringAsync(); + var experience = JsonConvert.DeserializeObject(responseData); + Console.WriteLine($"Expérience mise à jour avec succès : {experience.Title}"); + } + else + { + Console.WriteLine($"Erreur lors de la mise à jour de l'expérience. Code : {response.StatusCode}"); + } + + // Suppression d'un élément + response = await client.DeleteAsync($"experiences/{experienceId}"); + if (response.IsSuccessStatusCode) + { + Console.WriteLine("Expérience supprimée avec succès."); + } + else + { + Console.WriteLine($"Erreur lors de la suppression de l'expérience. Code : {response.StatusCode}"); + } + } +} diff --git a/TestConsoleApi/TestConsoleApi.csproj b/TestConsoleApi/TestConsoleApi.csproj new file mode 100644 index 0000000..2fe15c3 --- /dev/null +++ b/TestConsoleApi/TestConsoleApi.csproj @@ -0,0 +1,16 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + diff --git a/UnitTestEF/Entities/AlumniTest.cs b/UnitTestEF/Entities/AlumniTest.cs new file mode 100644 index 0000000..ec34707 --- /dev/null +++ b/UnitTestEF/Entities/AlumniTest.cs @@ -0,0 +1,194 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; + +namespace UnitTestEF.Entities; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Infrastructure; +using Infrastructure.Entities; + +[TestClass] +public class AlumniTest +{ + [TestMethod] + public async Task AddAlumniTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + + var alumnis = new List( + [ + new User + { + Id = "1", + FirstName = "Test", + LastName = "Test", + Email = "test@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "ADMIN" + }, + new User + { + Id = "2", + FirstName = "Test2", + LastName = "Test2", + Email = "test2@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "USER", + } + ] + ); + + await context.Alumni.AddRangeAsync(alumnis); + await context.SaveChangesAsync(); + + Assert.AreEqual(2, await context.Alumni.CountAsync()); + + var inBaseAlumni = await context.Alumni.FirstOrDefaultAsync(a => a.Id == "1"); + Assert.IsNotNull(inBaseAlumni); + Assert.AreEqual("1", inBaseAlumni.Id); + Assert.AreEqual("Test", inBaseAlumni.FirstName); + Assert.AreEqual("Test", inBaseAlumni.LastName); + Assert.AreEqual("test@gmail.com", inBaseAlumni.Email); + Assert.AreEqual("2021", inBaseAlumni.EntryYear); + Assert.AreEqual("1234567890", inBaseAlumni.Password); + Assert.AreEqual("ADMIN", inBaseAlumni.Role); + + var inBaseAlumni2 = await context.Alumni.FirstOrDefaultAsync(a => a.Id == "2"); + Assert.IsNotNull(inBaseAlumni2); + Assert.AreEqual("2", inBaseAlumni2.Id); + Assert.AreEqual("Test2", inBaseAlumni2.FirstName); + Assert.AreEqual("Test2", inBaseAlumni2.LastName); + Assert.AreEqual("test2@gmail.com", inBaseAlumni2.Email); + Assert.AreEqual("2021", inBaseAlumni2.EntryYear); + Assert.AreEqual("1234567890", inBaseAlumni2.Password); + Assert.AreEqual("USER", inBaseAlumni2.Role); + } + } + + [TestMethod] + public async Task DeleteAlumniTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + + var alumni = new User + { + Id = "1", + FirstName = "Test", + LastName = "Test", + Email = "test@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "ADMIN" + }; + + await context.Alumni.AddAsync(alumni); + await context.SaveChangesAsync(); + + Assert.AreEqual(1, await context.Alumni.CountAsync()); + + var inBaseAlumni = await context.Alumni.FirstOrDefaultAsync(a => a.Id == "1"); + Assert.IsNotNull(inBaseAlumni); + + context.Alumni.Remove(alumni); + await context.SaveChangesAsync(); + + Assert.AreEqual(0, await context.Alumni.CountAsync()); + } + } + + [TestMethod] + public async Task UpdateAlumniTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + + var alumni = new User + { + Id = "1", + FirstName = "Test", + LastName = "Test", + Email = "test@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "ADMIN" + }; + + await context.Alumni.AddAsync(alumni); + await context.SaveChangesAsync(); + + Assert.AreEqual(1, await context.Alumni.CountAsync()); + + var inBaseAlumni = await context.Alumni.FirstOrDefaultAsync(a => a.Id == "1"); + Assert.IsNotNull(inBaseAlumni); + + inBaseAlumni.FirstName = "Test2"; + inBaseAlumni.LastName = "Test2"; + inBaseAlumni.Email = "test2@gmail.com"; + inBaseAlumni.EntryYear = "2022"; + inBaseAlumni.Password = "0987654321"; + inBaseAlumni.Role = "USER"; + + await context.SaveChangesAsync(); + + var alumniAfterUpdate = await context.Alumni.FirstOrDefaultAsync(a => a.Id == "1"); + Assert.IsNotNull(alumniAfterUpdate); + Assert.AreEqual("1", alumniAfterUpdate.Id); + Assert.AreEqual("Test2", alumniAfterUpdate.FirstName); + Assert.AreEqual("Test2", alumniAfterUpdate.LastName); + Assert.AreEqual("test2@gmail.com", alumniAfterUpdate.Email); + Assert.AreEqual("2022", alumniAfterUpdate.EntryYear); + Assert.AreEqual("0987654321", alumniAfterUpdate.Password); + Assert.AreEqual("USER", alumniAfterUpdate.Role); + } + } + + [TestMethod] + public void ToString_ReturnsCorrectFormat() + { + // Arrange + var alumni = new User + { + Id = "1", + FirstName = "Test", + LastName = "Test", + Email = "test@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "ADMIN", + Experiences = new List(), + Formations = new List(), + Events = new List() + }; + + // Act + var result = alumni.ToString(); + + // Assert + var expected = "\t------------Alumni Id : 1 ------------- :\n\tFirstname : Test Lastname : Test Email : test@gmail.com Role : ADMIN\n\tExperiences : 0 \tFormations : 0 \t Events : 0"; + Assert.AreEqual(expected, result); + } +} \ No newline at end of file diff --git a/UnitTestEF/Entities/EventTest.cs b/UnitTestEF/Entities/EventTest.cs new file mode 100644 index 0000000..1ba2e15 --- /dev/null +++ b/UnitTestEF/Entities/EventTest.cs @@ -0,0 +1,211 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; + +namespace UnitTestEF.Entities; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Infrastructure; +using Infrastructure.Entities; + +[TestClass] +public class EventTest +{ + [TestMethod] + public async Task AddEventTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + var newEvent = new EventEntity + { + Id = "1", + Title = "A Test Event", + Description = "A Test Description", + Date = new DateTime(2020, 9, 1), + nbPlaces = 50 + }; + await context.Events.AddAsync(newEvent); + await context.SaveChangesAsync(); + + Assert.AreEqual(1, await context.Events.CountAsync()); + + var inBaseEvent = await context.Events.FirstOrDefaultAsync(e => e.Id == "1"); + Assert.IsNotNull(inBaseEvent); + Assert.AreEqual("1", inBaseEvent.Id); + Assert.AreEqual("A Test Event", inBaseEvent.Title); + Assert.AreEqual("A Test Description", inBaseEvent.Description); + Assert.AreEqual(new DateTime(2020, 9, 1), inBaseEvent.Date); + Assert.AreEqual(50, inBaseEvent.nbPlaces); + } + } + + [TestMethod] + public async Task RemoveEventTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + var newEvent = new EventEntity + { + Id = "1", + Title = "A Test Event", + Description = "A Test Description", + Date = new DateTime(2020, 9, 1), + nbPlaces = 50 + }; + await context.Events.AddAsync(newEvent); + await context.SaveChangesAsync(); + + var inBaseEvent = await context.Events.FirstOrDefaultAsync(e => e.Id == "1"); + Assert.IsNotNull(inBaseEvent); + + context.Events.Remove(newEvent); + await context.SaveChangesAsync(); + + var eventAfterDelete = await context.Events.FirstOrDefaultAsync(e => e.Id == "1"); + Assert.IsNull(eventAfterDelete); + } + } + + [TestMethod] + public async Task UpdateEventTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + var newEvent = new EventEntity + { + Id = "1", + Title = "A Test Event", + Description = "A Test Description", + Date = new DateTime(2020, 9, 1), + nbPlaces = 50 + }; + await context.Events.AddAsync(newEvent); + await context.SaveChangesAsync(); + + var inBaseEvent = await context.Events.FirstOrDefaultAsync(e => e.Id == "1"); + Assert.IsNotNull(inBaseEvent); + + inBaseEvent.Title = "A New Title"; + inBaseEvent.Description = "A New Description"; + inBaseEvent.Date = new DateTime(2020, 9, 2); + inBaseEvent.nbPlaces = 100; + await context.SaveChangesAsync(); + + var eventAfterUpdate = await context.Events.FirstOrDefaultAsync(e => e.Id == "1"); + Assert.IsNotNull(eventAfterUpdate); + Assert.AreEqual("1", eventAfterUpdate.Id); + Assert.AreEqual("A New Title", eventAfterUpdate.Title); + Assert.AreEqual("A New Description", eventAfterUpdate.Description); + Assert.AreEqual(new DateTime(2020, 9, 2), eventAfterUpdate.Date); + Assert.AreEqual(100, eventAfterUpdate.nbPlaces); + } + } + + [TestMethod] + public async Task EventWithParticipantsTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + var newEvent = new EventEntity + { + Id = "1", + Title = "A Test Event", + Description = "A Test Description", + Date = new DateTime(2020, 9, 1), + nbPlaces = 50 + }; + await context.Events.AddAsync(newEvent); + await context.SaveChangesAsync(); + + var inBaseEvent = await context.Events.FirstOrDefaultAsync(e => e.Id == "1"); + Assert.IsNotNull(inBaseEvent); + + var participants = new List( + [ + new User + { + Id = "1", + FirstName = "Test", + LastName = "Test", + Email = "test@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "ADMIN" + }, + new User + { + Id = "2", + FirstName = "Test2", + LastName = "Test2", + Email = "test2@gmail.com", + EntryYear = "2021", + Password = "1234567890", + Role = "USER", + } + ] + ); + + foreach (var p in participants) + { + inBaseEvent.Participants.Add(p); + } + + await context.SaveChangesAsync(); + + var eventWithParticipants = await context.Events.Include(e => e.Participants).FirstOrDefaultAsync(e => e.Id == "1"); + Assert.IsNotNull(eventWithParticipants); + Assert.AreEqual(2, eventWithParticipants.Participants.Count); + + foreach (var p in eventWithParticipants.Participants) + { + Assert.IsTrue(participants.Contains(p)); + } + } + } + + [TestMethod] + public void ToString_ReturnsCorrectFormat() + { + // Arrange + var eventEntity = new EventEntity + { + Title = "Test Event", + Description = "This is a test event", + Date = new DateTime(2022, 1, 1), + nbPlaces = 100 + }; + + // Act + var result = eventEntity.ToString(); + + // Assert + var expected = "\tTitle: Test Event, Date: 01/01/2022 00:00:00, nbPlaces: 100"; + Assert.AreEqual(expected, result); + } +} \ No newline at end of file diff --git a/UnitTestEF/Entities/ExperienceTest.cs b/UnitTestEF/Entities/ExperienceTest.cs new file mode 100644 index 0000000..c635962 --- /dev/null +++ b/UnitTestEF/Entities/ExperienceTest.cs @@ -0,0 +1,150 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; + +namespace UnitTestEF.Entities; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Infrastructure; +using Infrastructure.Entities; + +[TestClass] +public class ExperienceTest +{ + [TestMethod] + public async Task AddFormationTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + var exp = new ExperienceEntity() + { + Id = "100", + Title = "Software Engineer", + CompanyName = "CGI", + StartDate = new DateTime(2020, 9, 1), + EndDate = new DateTime(2022, 6, 1), + IsCurrent = true + }; + await context.Experiences.AddAsync(exp); + await context.SaveChangesAsync(); + + var inBaseExp = await context.Experiences.FirstOrDefaultAsync(e => e.Id == "100"); + Assert.IsNotNull(inBaseExp); + Assert.AreEqual("100", inBaseExp.Id); + Assert.AreEqual("Software Engineer", inBaseExp.Title); + Assert.AreEqual("CGI", inBaseExp.CompanyName); + Assert.AreEqual(new DateTime(2020, 9, 1), inBaseExp.StartDate); + Assert.AreEqual(new DateTime(2022, 6, 1), inBaseExp.EndDate); + Assert.IsTrue(inBaseExp.IsCurrent); + } + } + + [TestMethod] + public async Task DeleteFormationTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + var exp = new ExperienceEntity() + { + Id = "100", + Title = "Software Engineer", + CompanyName = "CGI", + StartDate = new DateTime(2020, 9, 1), + EndDate = new DateTime(2022, 6, 1), + IsCurrent = true + }; + await context.Experiences.AddAsync(exp); + await context.SaveChangesAsync(); + + var inBaseExp = await context.Experiences.FirstOrDefaultAsync(e => e.Id == "100"); + Assert.IsNotNull(inBaseExp); + + context.Experiences.Remove(exp); + await context.SaveChangesAsync(); + + var inBaseExp2 = await context.Experiences.FirstOrDefaultAsync(e => e.Id == "100"); + Assert.IsNull(inBaseExp2); + } + } + + [TestMethod] + public async Task UpdateFormationTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + + var exp = new ExperienceEntity() + { + Id = "100", + Title = "Software Engineer", + CompanyName = "CGI", + StartDate = new DateTime(2020, 9, 1), + EndDate = new DateTime(2022, 6, 1), + IsCurrent = true + }; + + await context.Experiences.AddAsync(exp); + await context.SaveChangesAsync(); + + var inBaseExp = await context.Experiences.FirstOrDefaultAsync(e => e.Id == "100"); + Assert.IsNotNull(inBaseExp); + + inBaseExp.Title = "Software Engineer II"; + inBaseExp.CompanyName = "CGI II"; + inBaseExp.StartDate = new DateTime(2021, 9, 1); + inBaseExp.EndDate = new DateTime(2023, 6, 1); + inBaseExp.IsCurrent = false; + + await context.SaveChangesAsync(); + + var inBaseExp2 = await context.Experiences.FirstOrDefaultAsync(e => e.Id == "100"); + Assert.IsNotNull(inBaseExp2); + Assert.AreEqual("Software Engineer II", inBaseExp2.Title); + Assert.AreEqual("CGI II", inBaseExp2.CompanyName); + Assert.AreEqual(new DateTime(2021, 9, 1), inBaseExp2.StartDate); + Assert.AreEqual(new DateTime(2023, 6, 1), inBaseExp2.EndDate); + Assert.IsFalse(inBaseExp2.IsCurrent); + } + } + + [TestMethod] + public void ToString_ReturnsCorrectFormat() + { + // Arrange + var experience = new ExperienceEntity + { + Id = "100", + Title = "Software Engineer", + CompanyName = "CGI", + StartDate = new DateTime(2020, 9, 1), + EndDate = new DateTime(2022, 6, 1), + IsCurrent = true + }; + + // Act + var result = experience.ToString(); + + // Assert + var expected = "\tTitle: Software Engineer, Company: CGI, Start Date: 01/09/2020, End Date: 01/06/2022, Is Current: True"; + Assert.AreEqual(expected, result); + } +} \ No newline at end of file diff --git a/UnitTestEF/Entities/FormationTest.cs b/UnitTestEF/Entities/FormationTest.cs new file mode 100644 index 0000000..647e714 --- /dev/null +++ b/UnitTestEF/Entities/FormationTest.cs @@ -0,0 +1,145 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; + +namespace UnitTestEF.Entities; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Infrastructure; +using Infrastructure.Entities; + +[TestClass] +public class FormationTest +{ + [TestMethod] + public async Task AddFormationTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + var newFormation = new FormationEntity { + Id = "100", + SchoolName = "IUT", + Name = "BUT Informatique", + StartDate = new DateTime(2020, 9, 1), + EndDate = new DateTime(2022, 6, 1), + IsCurrent = true + }; + await context.Formations.AddAsync(newFormation); + await context.SaveChangesAsync(); + + var inBaseFormation = await context.Formations.FirstOrDefaultAsync(f => f.Id == "100"); + Assert.IsNotNull(inBaseFormation); + Assert.AreEqual("100", inBaseFormation.Id); + Assert.AreEqual("IUT", inBaseFormation.SchoolName); + Assert.AreEqual("BUT Informatique", inBaseFormation.Name); + Assert.AreEqual(new DateTime(2020, 9, 1), inBaseFormation.StartDate); + Assert.AreEqual(new DateTime(2022, 6, 1), inBaseFormation.EndDate); + Assert.IsTrue(inBaseFormation.IsCurrent); + + } + } + + [TestMethod] + public async Task DeleteFormationTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + var newFormation = new FormationEntity { + Id = "100", + SchoolName = "IUT", + Name = "BUT Informatique", + StartDate = new DateTime(2020, 9, 1), + EndDate = new DateTime(2022, 6, 1), + IsCurrent = true + }; + await context.Formations.AddAsync(newFormation); + await context.SaveChangesAsync(); + + var inBaseFormation = await context.Formations.FirstOrDefaultAsync(f => f.Id == "100"); + Assert.IsNotNull(inBaseFormation); + + context.Formations.Remove(newFormation); + await context.SaveChangesAsync(); + + var formationAfterDelete = await context.Formations.FirstOrDefaultAsync(f => f.Id == "100"); + Assert.IsNull(formationAfterDelete); + } + } + + [TestMethod] + public async Task UpdateFormationTest() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + using (var context = new AlumniDbContext(options)) + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + var newFormation = new FormationEntity { + Id = "100", + SchoolName = "IUT", + Name = "BUT Informatique", + StartDate = new DateTime(2020, 9, 1), + EndDate = new DateTime(2022, 6, 1), + IsCurrent = true + }; + await context.Formations.AddAsync(newFormation); + await context.SaveChangesAsync(); + + var inBaseFormation = await context.Formations.FirstOrDefaultAsync(f => f.Id == "100"); + Assert.IsNotNull(inBaseFormation); + + inBaseFormation.SchoolName = "IUT2"; + inBaseFormation.Name = "BUT Informatique2"; + inBaseFormation.StartDate = new DateTime(2020, 9, 2); + inBaseFormation.EndDate = new DateTime(2022, 6, 2); + inBaseFormation.IsCurrent = false; + await context.SaveChangesAsync(); + + var formationAfterUpdate = await context.Formations.FirstOrDefaultAsync(f => f.Id == "100"); + Assert.IsNotNull(formationAfterUpdate); + Assert.AreEqual("IUT2", formationAfterUpdate.SchoolName); + Assert.AreEqual("BUT Informatique2", formationAfterUpdate.Name); + Assert.AreEqual(new DateTime(2020, 9, 2), formationAfterUpdate.StartDate); + Assert.AreEqual(new DateTime(2022, 6, 2), formationAfterUpdate.EndDate); + Assert.IsFalse(formationAfterUpdate.IsCurrent); + } + } + + [TestMethod] + public void ToString_ReturnsCorrectFormat() + { + // Arrange + var formation = new FormationEntity + { + Id = "100", + SchoolName = "IUT", + Name = "BUT Informatique", + StartDate = new DateTime(2020, 9, 1), + EndDate = new DateTime(2022, 6, 1), + IsCurrent = true + }; + + // Act + var result = formation.ToString(); + + // Assert + var expected = "\tFormation : BUT Informatique \tSchool's name : IUT"; + Assert.AreEqual(expected, result); + } +} \ No newline at end of file diff --git a/UnitTestEF/GlobalUsings.cs b/UnitTestEF/GlobalUsings.cs new file mode 100644 index 0000000..ab67c7e --- /dev/null +++ b/UnitTestEF/GlobalUsings.cs @@ -0,0 +1 @@ +global using Microsoft.VisualStudio.TestTools.UnitTesting; \ No newline at end of file diff --git a/UnitTestEF/UnitTestEF.csproj b/UnitTestEF/UnitTestEF.csproj new file mode 100644 index 0000000..9714df6 --- /dev/null +++ b/UnitTestEF/UnitTestEF.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + + false + true + UnitTestEF + + + + + + + + + + + + + +