From 60e7cf0762853be8f65da73ca89f03e40dee814c Mon Sep 17 00:00:00 2001 From: Lucas Delanier Date: Sat, 4 Mar 2023 19:08:37 +0100 Subject: [PATCH] unit test --- Sources/APILOL/APILOL.csproj | 7 +- Sources/APILOL/ConfigureSwaggerenOptions.cs | 40 ++++ .../{ => v1}/ChampionsController.cs | 7 +- .../Controllers/{ => v1}/RuneController.cs | 10 +- .../{ => v1}/RunePageController.cs | 10 +- .../Controllers/{ => v1}/SkinController.cs | 10 +- .../{ => v1}/WeatherForecastController.cs | 6 +- .../Controllers/v2/ChampionsController.cs | 181 +++++++++++++++++ .../APILOL/Controllers/v2/RuneController.cs | 178 +++++++++++++++++ .../Controllers/v2/RunePageController.cs | 183 ++++++++++++++++++ .../APILOL/Controllers/v2/SkinController.cs | 176 +++++++++++++++++ .../v2/WeatherForecastController.cs | 34 ++++ Sources/APILOL/Program.cs | 45 +++-- Sources/APILOL/SwaggerDefaultValues.cs | 40 ++++ Sources/TestUnitaire/UnitTestChampion.cs | 61 ++++-- 15 files changed, 941 insertions(+), 47 deletions(-) create mode 100644 Sources/APILOL/ConfigureSwaggerenOptions.cs rename Sources/APILOL/Controllers/{ => v1}/ChampionsController.cs (96%) rename Sources/APILOL/Controllers/{ => v1}/RuneController.cs (95%) rename Sources/APILOL/Controllers/{ => v1}/RunePageController.cs (95%) rename Sources/APILOL/Controllers/{ => v1}/SkinController.cs (95%) rename Sources/APILOL/Controllers/{ => v1}/WeatherForecastController.cs (86%) create mode 100644 Sources/APILOL/Controllers/v2/ChampionsController.cs create mode 100644 Sources/APILOL/Controllers/v2/RuneController.cs create mode 100644 Sources/APILOL/Controllers/v2/RunePageController.cs create mode 100644 Sources/APILOL/Controllers/v2/SkinController.cs create mode 100644 Sources/APILOL/Controllers/v2/WeatherForecastController.cs create mode 100644 Sources/APILOL/SwaggerDefaultValues.cs diff --git a/Sources/APILOL/APILOL.csproj b/Sources/APILOL/APILOL.csproj index ffe0ca3..4c081e5 100644 --- a/Sources/APILOL/APILOL.csproj +++ b/Sources/APILOL/APILOL.csproj @@ -9,6 +9,7 @@ + all @@ -16,7 +17,7 @@ - + @@ -25,8 +26,4 @@ - - - - diff --git a/Sources/APILOL/ConfigureSwaggerenOptions.cs b/Sources/APILOL/ConfigureSwaggerenOptions.cs new file mode 100644 index 0000000..7b7e9dd --- /dev/null +++ b/Sources/APILOL/ConfigureSwaggerenOptions.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace APILOL +{ + public class ConfigureSwaggerGenOptions : IConfigureOptions + { + private readonly IApiVersionDescriptionProvider _apiVersionDescriptionProvider; + + public ConfigureSwaggerGenOptions(IApiVersionDescriptionProvider apiVersionDescriptionProvider) + => _apiVersionDescriptionProvider = apiVersionDescriptionProvider; + + public void Configure(SwaggerGenOptions options) + { + foreach (var description in _apiVersionDescriptionProvider.ApiVersionDescriptions) + { + options.SwaggerDoc(description.GroupName, CreateOpenApiInfo(description)); + } + } + + private static OpenApiInfo CreateOpenApiInfo(ApiVersionDescription description) + { + var info = new OpenApiInfo() + { + Title = "LSE.Stocks.API", + Version = description.ApiVersion.ToString() + }; + + if (description.IsDeprecated) + { + info.Description += " (deprecated)"; + } + + return info; + } + } +} diff --git a/Sources/APILOL/Controllers/ChampionsController.cs b/Sources/APILOL/Controllers/v1/ChampionsController.cs similarity index 96% rename from Sources/APILOL/Controllers/ChampionsController.cs rename to Sources/APILOL/Controllers/v1/ChampionsController.cs index 5fd4043..1054419 100644 --- a/Sources/APILOL/Controllers/ChampionsController.cs +++ b/Sources/APILOL/Controllers/v1/ChampionsController.cs @@ -8,7 +8,7 @@ using System.Xml.Linq; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 -namespace APILOL.Controllers +namespace APILOL.Controllers.v1 { [ApiController] [Route("api/v{version:apiVersion}/[controller]")] @@ -30,6 +30,7 @@ namespace APILOL.Controllers // GET: api/ + [MapToApiVersion("1.0")] [HttpGet] public async Task Get([FromQuery] PageRequest request) { @@ -55,6 +56,7 @@ namespace APILOL.Controllers } // GET api//5 + [MapToApiVersion("1.0")] [HttpGet("{name}")] public async Task Get([FromQuery] PageRequest request,string name) { @@ -82,6 +84,7 @@ namespace APILOL.Controllers } // POST api/ + [MapToApiVersion("1.0")] [HttpPost] public async Task Post([FromBody] ChampionDTO championDTO) { @@ -105,6 +108,7 @@ namespace APILOL.Controllers } // PUT api//5 + [MapToApiVersion("1.0")] [HttpPut("{name}")] public async Task PutAsync(string name, [FromBody] ChampionDTO championDTO) { @@ -145,6 +149,7 @@ namespace APILOL.Controllers } // DELETE api//5 + [MapToApiVersion("1.0")] [HttpDelete("{name}")] public async Task Delete(string name) { diff --git a/Sources/APILOL/Controllers/RuneController.cs b/Sources/APILOL/Controllers/v1/RuneController.cs similarity index 95% rename from Sources/APILOL/Controllers/RuneController.cs rename to Sources/APILOL/Controllers/v1/RuneController.cs index f3a6fc0..7df9623 100644 --- a/Sources/APILOL/Controllers/RuneController.cs +++ b/Sources/APILOL/Controllers/v1/RuneController.cs @@ -7,10 +7,11 @@ using StubLib; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 -namespace APILOL.Controllers +namespace APILOL.Controllers.v1 { - [Route("api/[controller]")] [ApiController] + [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("1.0")] public class RuneController : ControllerBase { IRunesManager dataManager; @@ -27,6 +28,7 @@ namespace APILOL.Controllers // GET: api/ + [MapToApiVersion("1.0")] [HttpGet] public async Task Get([FromQuery] PageRequest request) { @@ -52,6 +54,7 @@ namespace APILOL.Controllers } // GET api//5 + [MapToApiVersion("1.0")] [HttpGet("{name}")] public async Task Get([FromQuery] PageRequest request, string name) { @@ -79,6 +82,7 @@ namespace APILOL.Controllers } // POST api/ + [MapToApiVersion("1.0")] [HttpPost] public async Task Post([FromBody] RuneDTO runeDTO) { @@ -102,6 +106,7 @@ namespace APILOL.Controllers } // PUT api//5 + [MapToApiVersion("1.0")] [HttpPut("{name}")] public async Task PutAsync(string name, [FromBody] RuneDTO runeDTO) { @@ -142,6 +147,7 @@ namespace APILOL.Controllers } // DELETE api//5 + [MapToApiVersion("1.0")] [HttpDelete("{name}")] public async Task Delete(string name) { diff --git a/Sources/APILOL/Controllers/RunePageController.cs b/Sources/APILOL/Controllers/v1/RunePageController.cs similarity index 95% rename from Sources/APILOL/Controllers/RunePageController.cs rename to Sources/APILOL/Controllers/v1/RunePageController.cs index 118ac50..c5f50e3 100644 --- a/Sources/APILOL/Controllers/RunePageController.cs +++ b/Sources/APILOL/Controllers/v1/RunePageController.cs @@ -7,10 +7,11 @@ using StubLib; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 -namespace APILOL.Controllers +namespace APILOL.Controllers.v1 { - [Route("api/[controller]")] [ApiController] + [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("1.0")] public class RunePageController : ControllerBase { IRunePagesManager dataManager; @@ -27,6 +28,7 @@ namespace APILOL.Controllers // GET: api/ + [MapToApiVersion("1.0")] [HttpGet] public async Task Get([FromQuery] PageRequest request) { @@ -52,6 +54,7 @@ namespace APILOL.Controllers } // GET api//5 + [MapToApiVersion("1.0")] [HttpGet("{name}")] public async Task Get([FromQuery] PageRequest request, string name) { @@ -79,6 +82,7 @@ namespace APILOL.Controllers } // POST api/ + [MapToApiVersion("1.0")] [HttpPost] public async Task Post([FromBody] RunePageDTO runePageDTO) { @@ -102,6 +106,7 @@ namespace APILOL.Controllers } // PUT api//5 + [MapToApiVersion("1.0")] [HttpPut("{name}")] public async Task PutAsync(string name, [FromBody] RunePageDTO runePageDTO) { @@ -142,6 +147,7 @@ namespace APILOL.Controllers } // DELETE api//5 + [MapToApiVersion("1.0")] [HttpDelete("{name}")] public async Task Delete(string name) { diff --git a/Sources/APILOL/Controllers/SkinController.cs b/Sources/APILOL/Controllers/v1/SkinController.cs similarity index 95% rename from Sources/APILOL/Controllers/SkinController.cs rename to Sources/APILOL/Controllers/v1/SkinController.cs index 00db4a3..88654aa 100644 --- a/Sources/APILOL/Controllers/SkinController.cs +++ b/Sources/APILOL/Controllers/v1/SkinController.cs @@ -4,10 +4,11 @@ using DTO; using Microsoft.AspNetCore.Mvc; using Model; -namespace APILOL.Controllers +namespace APILOL.Controllers.v1 { - [Route("api/[controller]")] [ApiController] + [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("1.0")] public class SkinController : ControllerBase { @@ -25,6 +26,7 @@ namespace APILOL.Controllers // GET: api/ + [MapToApiVersion("1.0")] [HttpGet] public async Task Get([FromQuery] PageRequest request) { @@ -50,6 +52,7 @@ namespace APILOL.Controllers } // GET api//5 + [MapToApiVersion("1.0")] [HttpGet("{name}")] public async Task Get([FromQuery] PageRequest request, string name) { @@ -77,6 +80,7 @@ namespace APILOL.Controllers } // POST api/ + [MapToApiVersion("1.0")] [HttpPost] public async Task Post([FromBody] SkinDTO skinDTO) { @@ -100,6 +104,7 @@ namespace APILOL.Controllers } // PUT api//5 + [MapToApiVersion("1.0")] [HttpPut("{name}")] public async Task PutAsync(string name, [FromBody] SkinDTO skinDTO) { @@ -140,6 +145,7 @@ namespace APILOL.Controllers } // DELETE api//5 + [MapToApiVersion("1.0")] [HttpDelete("{name}")] public async Task Delete(string name) { diff --git a/Sources/APILOL/Controllers/WeatherForecastController.cs b/Sources/APILOL/Controllers/v1/WeatherForecastController.cs similarity index 86% rename from Sources/APILOL/Controllers/WeatherForecastController.cs rename to Sources/APILOL/Controllers/v1/WeatherForecastController.cs index b250804..9ee38b0 100644 --- a/Sources/APILOL/Controllers/WeatherForecastController.cs +++ b/Sources/APILOL/Controllers/v1/WeatherForecastController.cs @@ -1,9 +1,10 @@ using Microsoft.AspNetCore.Mvc; -namespace APILOL.Controllers +namespace APILOL.Controllers.v1 { [ApiController] - [Route("[controller]")] + [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("1.0")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] @@ -19,6 +20,7 @@ namespace APILOL.Controllers } [HttpGet(Name = "GetWeatherForecast")] + [MapToApiVersion("1.0")] public IEnumerable Get() { return Enumerable.Range(1, 5).Select(index => new WeatherForecast diff --git a/Sources/APILOL/Controllers/v2/ChampionsController.cs b/Sources/APILOL/Controllers/v2/ChampionsController.cs new file mode 100644 index 0000000..be7e61d --- /dev/null +++ b/Sources/APILOL/Controllers/v2/ChampionsController.cs @@ -0,0 +1,181 @@ +using APILOL.Controllers.Request; +using APILOL.Mapper; +using DTO; +using Microsoft.AspNetCore.Mvc; +using Model; +using StubLib; +using System.Xml.Linq; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace APILOL.Controllers.v2 +{ + [ApiController] + [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("2.0")] + + public class ChampionsController : ControllerBase + { + IChampionsManager dataManager; + + private readonly ILogger _logger; + + public ChampionsController(IDataManager dataManager, ILogger logger) + { + this.dataManager = dataManager.ChampionsMgr; + this._logger = logger; + + } + + + + // GET: api/ + [MapToApiVersion("2.0")] + [HttpGet] + + public async Task Get([FromQuery] PageRequest request) + { + _logger.LogInformation("API call - [GET] - CHAMPION"); + try + { + + var total = await dataManager.GetNbItems(); + var champions = await dataManager.GetItems(request.offset, request.limit, request.orderingPropertyName, request.isDesc); + IEnumerable items = champions.Select(c => c.ToDto()); + if (items.Count() == 0) + { + _logger.LogInformation("No champion found."); + return NotFound("No champion found."); + } + return Ok(items); + } + catch(Exception error) + { + return BadRequest(error.Message); + } + + } + + // GET api//5 + [MapToApiVersion("2.0")] + [HttpGet("{name}")] + public async Task Get([FromQuery] PageRequest request,string name) + { + _logger.LogInformation("API call - [GET / NAME] - CHAMPION"); + try + { + if (dataManager.GetNbItemsByName(name) != null) + { + var champions = await dataManager.GetItemsByName(name, request.offset, request.limit, request.orderingPropertyName, request.isDesc); + IEnumerable items = champions.Select(c => c.ToDto()); + if (items.Count() == 0) + { + _logger.LogInformation("No champion found."); + return NotFound("No champion found."); + } + + return Ok(items); + } + return NotFound("No champion matching with this name."); + } + catch (Exception error) + { + return BadRequest(error.Message); + } + } + + // POST api/ + [MapToApiVersion("2.0")] + [HttpPost] + public async Task Post([FromBody] ChampionDTO championDTO) + { + _logger.LogInformation("API call - [POST] - CHAMPION"); + + try + { + if(await dataManager.GetNbItemsByName(championDTO.Name) == 0) + { + await dataManager.AddItem(championDTO.ToModel()); + return CreatedAtAction(nameof(Get), championDTO); + } + _logger.LogInformation("A champion already exist with this Name. ( Unique Name )"); + return BadRequest("A champion already exist with this Name. ( Unique Name )"); + } + catch (Exception error) + { + _logger.LogInformation("Error in the request"); + return BadRequest(error.Message); + } + } + + // PUT api//5 + [MapToApiVersion("2.0")] + [HttpPut("{name}")] + public async Task PutAsync(string name, [FromBody] ChampionDTO championDTO) + { + _logger.LogInformation("API call - [PUT / NAME] - CHAMPION"); + try + { + var champion = await dataManager + .GetItemsByName(name, 0, await dataManager.GetNbItems()); + Console.WriteLine(champion.First().Name) ; + var champion2 = await dataManager + .GetItemsByName(championDTO.Name, 0, await dataManager.GetNbItems()); + if (champion != null) + { + if(champion2.Count() == 0) + { + await dataManager.UpdateItem(champion.First(), championDTO.ToModel()); + return Ok(); + + } + _logger.LogInformation("champion already exist with this unique name."); + return BadRequest("champion already exist with this unique name."); + + } + else + { + _logger.LogInformation("champion not found."); + return NotFound("champion not found."); + } + await dataManager.UpdateItem(champion.First(), championDTO.ToModel()); + return Ok(); + + } + catch (Exception e) + { + return BadRequest(e.Message); + } + + } + + // DELETE api//5 + [MapToApiVersion("2.0")] + [HttpDelete("{name}")] + public async Task Delete(string name) + { + _logger.LogInformation("API call - [DELETE / NAME] - CHAMPION"); + try + { + var champion = await (dataManager.GetItemsByName(name, 0, await dataManager.GetNbItems())); + + if (champion.Count() != 0) + { + var championDto = champion.First().ToDto(); + await dataManager.DeleteItem(champion.First()); + return Ok(championDto); + } + else + { + _logger.LogInformation("No matching Champion with this name"); + return NotFound("No matching Champion with this name"); + } + + } + catch(Exception error) + { + return BadRequest(error); + } + } + } +} diff --git a/Sources/APILOL/Controllers/v2/RuneController.cs b/Sources/APILOL/Controllers/v2/RuneController.cs new file mode 100644 index 0000000..e40f51d --- /dev/null +++ b/Sources/APILOL/Controllers/v2/RuneController.cs @@ -0,0 +1,178 @@ +using APILOL.Controllers.Request; +using APILOL.Mapper; +using DTO; +using Microsoft.AspNetCore.Mvc; +using Model; +using StubLib; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace APILOL.Controllers.v2 +{ + [ApiController] + [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("2.0")] + public class RuneController : ControllerBase + { + IRunesManager dataManager; + + private readonly ILogger _logger; + + public RuneController(IDataManager dataManager, ILogger logger) + { + this.dataManager = dataManager.RunesMgr; + this._logger = logger; + + } + + + + // GET: api/ + [MapToApiVersion("2.0")] + [HttpGet] + public async Task Get([FromQuery] PageRequest request) + { + _logger.LogInformation("API call - [GET] - RUNE"); + try + { + + var total = await dataManager.GetNbItems(); + var runes = await dataManager.GetItems(request.offset, request.limit, request.orderingPropertyName, request.isDesc); + IEnumerable items = runes.Select(c => c.ToDto()); + if (items.Count() == 0) + { + _logger.LogInformation("No rune found."); + return NotFound("No rune found."); + } + return Ok(items); + } + catch (Exception error) + { + return BadRequest(error.Message); + } + + } + + // GET api//5 + [MapToApiVersion("2.0")] + [HttpGet("{name}")] + public async Task Get([FromQuery] PageRequest request, string name) + { + _logger.LogInformation("API call - [GET / NAME] - RUNE"); + try + { + if (dataManager.GetNbItemsByName(name) != null) + { + var runes = await dataManager.GetItemsByName(name, request.offset, request.limit, request.orderingPropertyName, request.isDesc); + IEnumerable items = runes.Select(c => c.ToDto()); + if (items.Count() == 0) + { + _logger.LogInformation("No rune found."); + return BadRequest("No rune found."); + } + + return Ok(items); + } + return NotFound("No rune matching with this name."); + } + catch (Exception error) + { + return BadRequest(error.Message); + } + } + + // POST api/ + [MapToApiVersion("2.0")] + [HttpPost] + public async Task Post([FromBody] RuneDTO runeDTO) + { + _logger.LogInformation("API call - [POST] - RUNE"); + + try + { + if (await dataManager.GetNbItemsByName(runeDTO.Name) == 0) + { + await dataManager.AddItem(runeDTO.ToModel()); + return CreatedAtAction(nameof(Get), runeDTO); + } + _logger.LogInformation("A rune already exist with this Name. ( Unique Name )"); + return BadRequest("A rune already exist with this Name. ( Unique Name )"); + } + catch (Exception error) + { + _logger.LogInformation("Error in the request"); + return BadRequest(error.Message); + } + } + + // PUT api//5 + [MapToApiVersion("2.0")] + [HttpPut("{name}")] + public async Task PutAsync(string name, [FromBody] RuneDTO runeDTO) + { + _logger.LogInformation("API call - [PUT / NAME] - RUNE"); + try + { + var rune = await dataManager + .GetItemsByName(name, 0, await dataManager.GetNbItems()); + Console.WriteLine(rune.First().Name); + var rune2 = await dataManager + .GetItemsByName(runeDTO.Name, 0, await dataManager.GetNbItems()); + if (rune != null) + { + if (rune2.Count() == 0) + { + await dataManager.UpdateItem(rune.First(), runeDTO.ToModel()); + return Ok(); + + } + _logger.LogInformation("rune already exist with this unique name."); + return BadRequest("rune already exist with this unique name."); + + } + else + { + _logger.LogInformation("rune not found."); + return NotFound("rune not found."); + } + await dataManager.UpdateItem(rune.First(), runeDTO.ToModel()); + return Ok(); + + } + catch (Exception e) + { + return BadRequest(e.Message); + } + + } + + // DELETE api//5 + [MapToApiVersion("2.0")] + [HttpDelete("{name}")] + public async Task Delete(string name) + { + _logger.LogInformation("API call - [DELETE / NAME] - RUNE"); + try + { + var rune = await (dataManager.GetItemsByName(name, 0, await dataManager.GetNbItems())); + + if (rune.Count() != 0) + { + var runeDto = rune.First().ToDto(); + await dataManager.DeleteItem(rune.First()); + return Ok(runeDto); + } + else + { + _logger.LogInformation("No matching rune with this name"); + return NotFound("No matching rune with this name"); + } + + } + catch (Exception error) + { + return BadRequest(error); + } + } + } +} diff --git a/Sources/APILOL/Controllers/v2/RunePageController.cs b/Sources/APILOL/Controllers/v2/RunePageController.cs new file mode 100644 index 0000000..038503b --- /dev/null +++ b/Sources/APILOL/Controllers/v2/RunePageController.cs @@ -0,0 +1,183 @@ +using APILOL.Controllers.Request; +using APILOL.Mapper; +using DTO; +using Microsoft.AspNetCore.Mvc; +using Model; +using StubLib; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace APILOL.Controllers.v2 +{ + [ApiController] + [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("2.0")] + public class RunePageController : ControllerBase + { + IRunePagesManager dataManager; + + private readonly ILogger _logger; + + public RunePageController(IDataManager dataManager, ILogger logger) + { + this.dataManager = dataManager.RunePagesMgr; + this._logger = logger; + + } + + + + // GET: api/ + [MapToApiVersion("2.0")] + [HttpGet] + public async Task Get([FromQuery] PageRequest request) + { + _logger.LogInformation("API call - [GET] - RUNEPAGE"); + try + { + + var total = await dataManager.GetNbItems(); + var runePages = await dataManager.GetItems(request.offset, request.limit, request.orderingPropertyName, request.isDesc); + IEnumerable items = runePages.Select(c => c.ToDto()); + if (items.Count() == 0) + { + _logger.LogInformation("No runePage found."); + return NotFound("No runePage found."); + } + return Ok(items); + } + catch (Exception error) + { + return BadRequest(error.Message); + } + + } + + // GET api//5 + [MapToApiVersion("2.0")] + [HttpGet("{name}")] + public async Task Get([FromQuery] PageRequest request, string name) + { + _logger.LogInformation("API call - [GET / NAME] - RUNEPAGE"); + try + { + if (dataManager.GetNbItemsByName(name) != null) + { + var runepages = await dataManager.GetItemsByName(name, request.offset, request.limit, request.orderingPropertyName, request.isDesc); + IEnumerable items = runepages.Select(c => c.ToDto()); + if (items.Count() == 0) + { + _logger.LogInformation("No runePage found."); + return NotFound("No runePage found."); + } + + return Ok(items); + } + return NotFound("No runePage matching with this name."); + } + catch (Exception error) + { + return BadRequest(error.Message); + } + } + + // POST api/ + [MapToApiVersion("2.0")] + [HttpPost] + public async Task Post([FromBody] RunePageDTO runePageDTO) + { + _logger.LogInformation("API call - [POST] - RUNEPAGE"); + + try + { + if (await dataManager.GetNbItemsByName(runePageDTO.Name) == 0) + { + await dataManager.AddItem(runePageDTO.ToModel()); + return CreatedAtAction(nameof(Get), runePageDTO); + } + _logger.LogInformation("A runePage already exist with this Name. ( Unique Name )"); + return BadRequest("A runePage already exist with this Name. ( Unique Name )"); + } + catch (Exception error) + { + _logger.LogInformation("Error in the request"); + return BadRequest(error.Message); + } + } + + // PUT api//5 + [MapToApiVersion("2.0")] + [HttpPut("{name}")] + public async Task PutAsync(string name, [FromBody] RunePageDTO runePageDTO) + { + _logger.LogInformation("API call - [PUT / NAME] - RUNEPAGE"); + try + { + var runePage = await dataManager + .GetItemsByName(name, 0, await dataManager.GetNbItems()); + Console.WriteLine(runePage.First().Name); + var runePage2 = await dataManager + .GetItemsByName(runePageDTO.Name, 0, await dataManager.GetNbItems()); + if (runePage != null) + { + if (runePage2.Count() == 0) + { + await dataManager.UpdateItem(runePage.First(), runePageDTO.ToModel()); + return Ok(); + + } + _logger.LogInformation("runePage already exist with this unique name."); + return BadRequest("runePage already exist with this unique name."); + + } + else + { + _logger.LogInformation("runePage not found."); + return NotFound("runePage not found."); + } + await dataManager.UpdateItem(runePage.First(), runePageDTO.ToModel()); + return Ok(); + + } + catch (Exception e) + { + return BadRequest(e.Message); + } + + } + + // DELETE api//5 + [MapToApiVersion("2.0")] + [HttpDelete("{name}")] + public async Task Delete(string name) + { + _logger.LogInformation("API call - [DELETE / NAME] - RUNEPAGE"); + try + { + var runePage = await (dataManager.GetItemsByName(name, 0, await dataManager.GetNbItems())); + + if (runePage.Count() != 0) + { + var runePageDto = runePage.First().ToDto(); + await dataManager.DeleteItem(runePage.First()); + return Ok(runePageDto); + } + else + { + _logger.LogInformation("No matching runePage with this name"); + return NotFound("No matching runePage with this name"); + } + + } + catch (Exception error) + { + return BadRequest(error); + } + } + } +} + +/* +var champion = new Champion(""); +var dto = ChampionMapper.ToDto(champion); +*/ \ No newline at end of file diff --git a/Sources/APILOL/Controllers/v2/SkinController.cs b/Sources/APILOL/Controllers/v2/SkinController.cs new file mode 100644 index 0000000..084c876 --- /dev/null +++ b/Sources/APILOL/Controllers/v2/SkinController.cs @@ -0,0 +1,176 @@ +using APILOL.Controllers.Request; +using APILOL.Mapper; +using DTO; +using Microsoft.AspNetCore.Mvc; +using Model; + +namespace APILOL.Controllers.v2 +{ + [ApiController] + [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("2.0")] + public class SkinController : ControllerBase + { + + ISkinsManager dataManager; + + private readonly ILogger _logger; + + public SkinController(IDataManager dataManager, ILogger logger) + { + this.dataManager = dataManager.SkinsMgr; + this._logger = logger; + + } + + + + // GET: api/ + [MapToApiVersion("2.0")] + [HttpGet] + public async Task Get([FromQuery] PageRequest request) + { + _logger.LogInformation("API call - [GET] - SKIN"); + try + { + + var total = await dataManager.GetNbItems(); + var skins = await dataManager.GetItems(request.offset, request.limit, request.orderingPropertyName, request.isDesc); + IEnumerable items = skins.Select(c => c.ToDto()); + if (items.Count() == 0) + { + _logger.LogInformation("No skin found."); + return NotFound("No skin found."); + } + return Ok(items); + } + catch (Exception error) + { + return BadRequest(error.Message); + } + + } + + // GET api//5 + [MapToApiVersion("2.0")] + [HttpGet("{name}")] + public async Task Get([FromQuery] PageRequest request, string name) + { + _logger.LogInformation("API call - [GET / NAME] - SKIN"); + try + { + if (dataManager.GetNbItemsByName(name) != null) + { + var skins = await dataManager.GetItemsByName(name, request.offset, request.limit, request.orderingPropertyName, request.isDesc); + IEnumerable items = skins.Select(c => c.ToDto()); + if (items.Count() == 0) + { + _logger.LogInformation("No Skin found."); + return NotFound("No Skin found."); + } + + return Ok(items); + } + return NotFound("No Skin matching with this name."); + } + catch (Exception error) + { + return BadRequest(error.Message); + } + } + + // POST api/ + [MapToApiVersion("2.0")] + [HttpPost] + public async Task Post([FromBody] SkinDTO skinDTO) + { + _logger.LogInformation("API call - [POST] - SKIN"); + + try + { + if (await dataManager.GetNbItemsByName(skinDTO.Name) == 0) + { + await dataManager.AddItem(skinDTO.ToModel()); + return CreatedAtAction(nameof(Get), skinDTO); + } + _logger.LogInformation("A Skin already exist with this Name. ( Unique Name )"); + return BadRequest("A Skin already exist with this Name. ( Unique Name )"); + } + catch (Exception error) + { + _logger.LogInformation("Error in the request"); + return BadRequest(error.Message); + } + } + + // PUT api//5 + [MapToApiVersion("2.0")] + [HttpPut("{name}")] + public async Task PutAsync(string name, [FromBody] SkinDTO skinDTO) + { + _logger.LogInformation("API call - [PUT / NAME] - SKIN"); + try + { + var skin = await dataManager + .GetItemsByName(name, 0, await dataManager.GetNbItems()); + Console.WriteLine(skin.First().Name); + var skin2 = await dataManager + .GetItemsByName(skinDTO.Name, 0, await dataManager.GetNbItems()); + if (skin != null) + { + if (skin2.Count() == 0) + { + await dataManager.UpdateItem(skin.First(), skinDTO.ToModel()); + return Ok(); + + } + _logger.LogInformation("Skin already exist with this unique name."); + return BadRequest("Skin already exist with this unique name."); + + } + else + { + _logger.LogInformation("Skin not found."); + return NotFound("Skin not found."); + } + await dataManager.UpdateItem(skin.First(), skinDTO.ToModel()); + return Ok(); + + } + catch (Exception e) + { + return BadRequest(e.Message); + } + + } + + // DELETE api//5 + [MapToApiVersion("2.0")] + [HttpDelete("{name}")] + public async Task Delete(string name) + { + _logger.LogInformation("API call - [DELETE / NAME] - SKIN"); + try + { + var skin = await (dataManager.GetItemsByName(name, 0, await dataManager.GetNbItems())); + + if (skin.Count() != 0) + { + var skinDto = skin.First().ToDto(); + await dataManager.DeleteItem(skin.First()); + return Ok(skinDto); + } + else + { + _logger.LogInformation("No matching skin with this name"); + return NotFound("No matching skin with this name"); + } + + } + catch (Exception error) + { + return BadRequest(error); + } + } + } +} diff --git a/Sources/APILOL/Controllers/v2/WeatherForecastController.cs b/Sources/APILOL/Controllers/v2/WeatherForecastController.cs new file mode 100644 index 0000000..202165d --- /dev/null +++ b/Sources/APILOL/Controllers/v2/WeatherForecastController.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Mvc; + +namespace APILOL.Controllers.v2 +{ + [ApiController] + [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("2.0")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + [MapToApiVersion("2.0")] + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} \ No newline at end of file diff --git a/Sources/APILOL/Program.cs b/Sources/APILOL/Program.cs index 82a752c..63b95a4 100644 --- a/Sources/APILOL/Program.cs +++ b/Sources/APILOL/Program.cs @@ -1,24 +1,51 @@ +using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.Versioning; -using Microsoft.Extensions.Options; using Model; using StubLib; var builder = WebApplication.CreateBuilder(args); -// Add services to the container. builder.Services.AddSingleton(); builder.Services.AddControllers(); -// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddApiVersioning(opt => +{ + opt.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0); + opt.AssumeDefaultVersionWhenUnspecified = true; + opt.ReportApiVersions = true; + opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(), + new HeaderApiVersionReader("x-api-version"), + new MediaTypeApiVersionReader("x-api-version")); +}); +builder.Services.AddVersionedApiExplorer(setup => +{ + setup.GroupNameFormat = "'v'VVV"; + setup.SubstituteApiVersionInUrl = true; +}); + builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); +// Configure the HTTP request pipeline. +var apiVersionDescriptionProvider = app.Services.GetRequiredService(); + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); - app.UseSwaggerUI(); + app.UseSwaggerUI(options => + { + foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions) + { + options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", + description.GroupName.ToUpperInvariant()); + } + }); } app.UseStaticFiles(); @@ -30,13 +57,3 @@ app.UseAuthorization(); app.MapControllers(); app.Run(); - -builder.Services.AddApiVersioning(opt => -{ - opt.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0); - opt.AssumeDefaultVersionWhenUnspecified = true; - opt.ReportApiVersions = true; - opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(), - new HeaderApiVersionReader("x-api-version"), - new MediaTypeApiVersionReader("x-api-version")); -}); diff --git a/Sources/APILOL/SwaggerDefaultValues.cs b/Sources/APILOL/SwaggerDefaultValues.cs new file mode 100644 index 0000000..cb04680 --- /dev/null +++ b/Sources/APILOL/SwaggerDefaultValues.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + + +namespace APILOL +{ + public class SwaggerDefaultValues : IOperationFilter + { + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + var apiDescription = context.ApiDescription; + + operation.Deprecated |= apiDescription.IsDeprecated(); + + if (operation.Parameters == null) + { + return; + } + + foreach (var parameter in operation.Parameters) + { + var description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name); + + if (parameter.Description is null) + { + parameter.Description = description.ModelMetadata?.Description; + } + + if (parameter.Schema.Default is null && description.DefaultValue is not null) + { + parameter.Schema.Default = new OpenApiString(description.DefaultValue.ToString()); + } + + parameter.Required |= description.IsRequired; + } + } + } +} diff --git a/Sources/TestUnitaire/UnitTestChampion.cs b/Sources/TestUnitaire/UnitTestChampion.cs index 512023b..f6c318b 100644 --- a/Sources/TestUnitaire/UnitTestChampion.cs +++ b/Sources/TestUnitaire/UnitTestChampion.cs @@ -1,11 +1,15 @@ using APILOL.Controllers; using APILOL.Controllers.Request; +using APILOL.Controllers.v1; +using APILOL.Controllers.v2; using APILOL.Mapper; using DTO; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging.Abstractions; +using Model; using StubLib; using System.Web.Http; +using ChampionsController = APILOL.Controllers.v1.ChampionsController; namespace TestUnitaire { @@ -23,8 +27,10 @@ namespace TestUnitaire [TestMethod] public async Task TestGet() { + //Act var champions = await controller.Get(new PageRequest()); + //Assert var resultObject = champions as OkObjectResult; Assert.IsNotNull(resultObject); @@ -34,41 +40,58 @@ namespace TestUnitaire Assert.AreEqual(resultType.Count(), await stub.ChampionsMgr.GetNbItems()); } + [TestMethod] - public void Get_OkResult_WhenChampExists() + public async Task TestPost() { - // Act - Task result = controller.Get(new PageRequest()); + //Arange + var champion = new ChampionDTO + { + Name = "Jinx", + Bio = "Awesome , great, fantastic Q", + }; - // Assert - Assert.IsInstanceOfType(result, typeof(OkResult)); + //Act + var championsResult = await controller.Post(champion); + + //Assert + var objectResult = championsResult as CreatedAtActionResult; + Assert.IsNotNull(objectResult); + + var champions = objectResult?.Value as ChampionDTO; + Assert.IsNotNull(champions); } [TestMethod] - public async Task TestPost() + public async Task TestDelete() { - /*var ChampionDtoToTest = new ChampionDTO { Bio= "This champion is a legendary Fox", Name="Foxane"}; + //Arange + string championName = "Aatrox"; - var champions = await controller.Post(ChampionDtoToTest); - var resultObject = champions as OkObjectResult; - Assert.IsNotNull(resultObject); - var resultType = resultObject?.Value as IEnumerable; - Assert.IsNotNull(resultType); + // Act + var result = await controller.Delete(championName); - Assert.AreEqual(resultType.Last(), stub.ChampionsMgr.GetItems(-1, await stub.ChampionsMgr.GetNbItems()));*/ + // Assert + Assert.IsInstanceOfType(result, typeof(OkObjectResult)); + Assert.IsTrue((await stub.ChampionsMgr.GetItemsByName(championName, 0, await stub.ChampionsMgr.GetNbItems())).Count() == 0); } - [TestMethod] - public void TestPut() + public async Task TestUpdate() { - } + //Arange + string championName = "Aatrox"; + var updatedChampion = new ChampionDTO {Name = "Bibouuu", Bio = "Updated Bio" }; - [TestMethod] - public void TestDelete() - { + + // Act + var result = await controller.PutAsync(championName, updatedChampion); + + // Assert + Assert.IsInstanceOfType(result, typeof(OkResult)); + Assert.IsNotNull(stub.ChampionsMgr.GetItemsByName("Bibouuu",0, await stub.ChampionsMgr.GetNbItems())); }