add TeamsController
continuous-integration/drone/push Build is passing Details

tests
maxime 1 year ago
parent 632ac19238
commit e8bdce981c

@ -1,13 +1,12 @@
using API.Validation;
using Microsoft.AspNetCore.Mvc;
namespace API;
namespace API.Context;
public static class AppHttpContext
public class HttpContextAccessor : IContextAccessor
{
public static int CurrentUserId(this ControllerBase b)
public int CurrentUserId(HttpContext ctx)
{
var idClaim = b.HttpContext
var idClaim = ctx
.User
.Claims
.First(c => c.Type == IdentityData.IdUserClaimName);

@ -0,0 +1,6 @@
namespace API.Context;
public interface IContextAccessor
{
public int CurrentUserId(HttpContext ctx);
}

@ -3,10 +3,10 @@ using Microsoft.AspNetCore.Mvc;
using Model;
using Services;
namespace API.Controllers;
namespace API.Controllers.Admin;
[ApiController]
public class TeamsController(ITeamService service) : ControllerBase
public class TeamsAdminController(ITeamService service) : ControllerBase
{
public record CountTeamsResponse(int Value);
@ -14,7 +14,7 @@ public class TeamsController(ITeamService service) : ControllerBase
[HttpGet("/admin/teams/count")]
public async Task<CountTeamsResponse> CountTeams()
{
return new CountTeamsResponse(await service.CountTeams());
return new CountTeamsResponse(await service.CountTotalTeams());
}
// [HttpGet("/admin/users/count")]

@ -3,13 +3,11 @@ using Microsoft.AspNetCore.Mvc;
using Model;
using Services;
namespace API.Controllers;
namespace API.Controllers.Admin;
[ApiController]
public class UsersController(IUserService service) : ControllerBase
public class UsersAdminController(IUserService service) : ControllerBase
{
private const string DefaultProfilePicture =
"https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png";
public record CountUsersResponse(int Value);
@ -54,7 +52,7 @@ public class UsersController(IUserService service) : ControllerBase
[HttpGet("/admin/users/{id:int}")]
public async Task<IActionResult> GetUser(
[Range(0, int.MaxValue, ErrorMessage = "Only positive number allowed")]
[Range(1, int.MaxValue, ErrorMessage = "Only positive number allowed")]
int id
)
{
@ -79,15 +77,16 @@ public class UsersController(IUserService service) : ControllerBase
[HttpPost("/admin/users")]
public Task<User> AddUser([FromBody] AddUserRequest req)
{
return service.CreateUser(req.Username, req.Email, req.Password, DefaultProfilePicture, req.IsAdmin);
return service.CreateUser(req.Username, req.Email, req.Password, UsersController.DefaultProfilePicture, req.IsAdmin);
}
public record RemoveUsersRequest(int[] Identifiers);
[HttpPost("/admin/users/remove-all")]
public async void RemoveUsers([FromBody] RemoveUsersRequest req)
public async Task<IActionResult> RemoveUsers([FromBody] RemoveUsersRequest req)
{
await service.RemoveUsers(req.Identifiers);
return Ok();
}
public record UpdateUserRequest(
@ -107,7 +106,7 @@ public class UsersController(IUserService service) : ControllerBase
{
try
{
await service.UpdateUser(new User(id, req.Username, req.Email, DefaultProfilePicture, req.IsAdmin));
await service.UpdateUser(new User(id, req.Username, req.Email, UsersController.DefaultProfilePicture, req.IsAdmin));
return Ok();
}
catch (ServiceException e)

@ -22,7 +22,8 @@ public class AuthenticationController(IUserService service, IConfiguration confi
[EmailAddress]
string Email,
[MaxLength(256, ErrorMessage = "Password is too wide")]
string Password);
string Password
);
private record AuthenticationResponse(String Token, DateTime ExpirationDate);

@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using API.Context;
using API.DTO;
using API.Validation;
using Microsoft.AspNetCore.Authorization;
@ -10,7 +11,7 @@ using Services;
namespace API.Controllers;
[ApiController]
public class TacticController(ITacticService service) : ControllerBase
public class TacticController(ITacticService service, IContextAccessor accessor) : ControllerBase
{
public record UpdateNameRequest(
[StringLength(50, MinimumLength = 1)]
@ -23,7 +24,7 @@ public class TacticController(ITacticService service) : ControllerBase
int tacticId,
[FromBody] UpdateNameRequest req)
{
var userId = this.CurrentUserId();
var userId = accessor.CurrentUserId(HttpContext);
if (!await service.HasAnyRights(userId, tacticId))
{
return Unauthorized();
@ -38,7 +39,7 @@ public class TacticController(ITacticService service) : ControllerBase
[Authorize]
public async Task<IActionResult> GetTacticInfo(int tacticId)
{
var userId = this.CurrentUserId();
var userId = accessor.CurrentUserId(HttpContext);
if (!await service.HasAnyRights(userId, tacticId))
{
return Unauthorized();
@ -54,7 +55,7 @@ public class TacticController(ITacticService service) : ControllerBase
[Authorize]
public async Task<IActionResult> GetTacticStepsRoot(int tacticId)
{
var userId = this.CurrentUserId();
var userId = accessor.CurrentUserId(HttpContext);
if (!await service.HasAnyRights(userId, tacticId))
{
return Unauthorized();
@ -78,7 +79,7 @@ public class TacticController(ITacticService service) : ControllerBase
[Authorize]
public async Task<CreateNewResponse> CreateNew([FromBody] CreateNewRequest req)
{
var userId = this.CurrentUserId();
var userId = accessor.CurrentUserId(HttpContext);
var courtType = req.CourtType switch
{
@ -107,7 +108,7 @@ public class TacticController(ITacticService service) : ControllerBase
[Authorize]
public async Task<IActionResult> GetStepContent(int tacticId, int stepId)
{
var userId = this.CurrentUserId();
var userId = accessor.CurrentUserId(HttpContext);
if (!await service.HasAnyRights(userId, tacticId))
{
@ -122,7 +123,7 @@ public class TacticController(ITacticService service) : ControllerBase
[Authorize]
public async Task<IActionResult> RemoveStepContent(int tacticId, int stepId)
{
var userId = this.CurrentUserId();
var userId = accessor.CurrentUserId(HttpContext);
if (!await service.HasAnyRights(userId, tacticId))
{
@ -140,7 +141,7 @@ public class TacticController(ITacticService service) : ControllerBase
[Authorize]
public async Task<IActionResult> SaveStepContent(int tacticId, int stepId, [FromBody] SaveStepContentRequest req)
{
var userId = this.CurrentUserId();
var userId = accessor.CurrentUserId(HttpContext);
if (!await service.HasAnyRights(userId, tacticId))
{

@ -0,0 +1,77 @@
using System.ComponentModel.DataAnnotations;
using API.Context;
using API.Validation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Model;
using Services;
namespace API.Controllers;
[ApiController]
[Authorize]
public class TeamsController(ITeamService service, IContextAccessor accessor) : ControllerBase
{
public record CreateTeamRequest(
[Name] string Name,
[Url] string Picture,
[RegularExpression("^#[0-9A-F]{6}$")] string FirstColor,
[RegularExpression("^#[0-9A-F]{6}$")] string SecondColor
);
[HttpPost("/teams")]
public async Task<IActionResult> CreateTeam([FromBody] CreateTeamRequest req)
{
var userId = accessor.CurrentUserId(HttpContext);
var team = await service.AddTeam(req.Name, req.Picture, req.FirstColor, req.SecondColor);
await service.AddMember(team.Id, userId, MemberRole.Coach);
return Ok(team);
}
[HttpGet("/teams/{teamId:int}/members")]
public IActionResult GetMembersOf(int teamId)
{
return Ok(service.GetMembersOf(teamId));
}
public record AddMemberRequest(
int UserId,
[AllowedValues("PLAYER", "COACH")] string Role
);
[HttpPost("/teams/{teamId:int}/members")]
public async Task<IActionResult> AddMember(int teamId, [FromBody] AddMemberRequest req)
{
if (!Enum.TryParse<MemberRole>(req.Role, true, out var role))
{
throw new Exception($"Unable to convert string input '{req.Role}' to a role enum variant.");
}
return Ok(await service.AddMember(teamId, req.UserId, role));
}
public record UpdateMemberRequest(
[AllowedValues("PLAYER", "COACH")] string Role
);
[HttpPut("/team/{teamId:int}/members/{userId:int}")]
public async Task<IActionResult> UpdateMember(int teamId, int userId, [FromBody] UpdateMemberRequest req)
{
if (!Enum.TryParse<MemberRole>(req.Role, true, out var role))
{
throw new Exception($"Unable to convert string input '{req.Role}' to a role enum variant.");
}
var updated = await service.UpdateMember(new Member(teamId, userId, role));
return updated ? Ok() : NotFound();
}
[HttpDelete("/team/{teamId:int}/members/{userId:int}")]
public async Task<IActionResult> RemoveMember(int teamId, int userId)
{
var removed = await service.RemoveMember(teamId, userId);
return removed ? Ok() : NotFound();
}
}

@ -1,19 +1,26 @@
using System.Runtime.CompilerServices;
using API.Context;
using API.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Model;
using Services;
[assembly: InternalsVisibleTo("UnitTests")]
namespace API.Controllers;
[ApiController]
public class UserController(IUserService users, ITeamService teams, ITacticService tactics) : ControllerBase
public class UsersController(IUserService users, ITeamService teams, ITacticService tactics, IContextAccessor accessor)
: ControllerBase
{
public const string DefaultProfilePicture =
"https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png";
[Authorize]
[HttpGet("/user")]
public async Task<User> GetUser()
{
var userId = this.CurrentUserId();
var userId = accessor.CurrentUserId(HttpContext);
return (await users.GetUser(userId))!;
}
@ -23,7 +30,7 @@ public class UserController(IUserService users, ITeamService teams, ITacticServi
[HttpGet("/user-data")]
public async Task<GetUserDataResponse> GetUserData()
{
var userId = this.CurrentUserId();
var userId = accessor.CurrentUserId(HttpContext);
var userTeams = await teams.ListTeamsOf(userId);
var userTactics = await tactics.ListTacticsOf(userId);
return new GetUserDataResponse(userTeams.ToArray(), userTactics.Select(t => t.ToDto()).ToArray());

@ -2,12 +2,14 @@ using System.Globalization;
using System.Net.Mime;
using System.Text;
using API.Auth;
using API.Context;
using API.Validation;
using DbServices;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Services;
using HttpContextAccessor = API.Context.HttpContextAccessor;
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
@ -17,7 +19,7 @@ var config = builder.Configuration;
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHttpLogging(o => {});
builder.Services.AddHttpLogging(o => { });
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options => options.InvalidModelStateResponseFactory = context =>
@ -55,6 +57,7 @@ builder.Services.AddDbContext<AppContext.AppContext>();
builder.Services.AddScoped<IUserService, DbUserService>();
builder.Services.AddScoped<ITeamService, DbTeamService>();
builder.Services.AddScoped<ITacticService, DbTacticService>();
builder.Services.AddScoped<IContextAccessor, HttpContextAccessor>();
var app = builder.Build();
@ -104,5 +107,4 @@ app.Use((context, next) =>
});
app.Run();

@ -14,7 +14,7 @@
"dotnetRunMessages": true,
"launchBrowser": false,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5254",
"applicationUrl": "http://+:5254",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}

@ -1,3 +1,6 @@
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("UnitTests")]
namespace API.Validation;
internal class IdentityData

@ -1,3 +1,5 @@
using Model;
namespace AppContext.Entities;
public class MemberEntity
@ -9,5 +11,5 @@ public class MemberEntity
public required int UserId { get; set; }
public UserEntity? User { get; set; }
public required string Role { get; set; }
public required MemberRole Role { get; set; }
}

@ -12,8 +12,4 @@ public class TacticEntity
public UserEntity? Owner { get; set; }
public CourtType Type { get; set; }
public required string JsonContent { get; set; }
public required int RootStepId { get; set; }
public TacticStepEntity RootStep { get; set; }
}

@ -7,9 +7,9 @@ public class TacticStepEntity
public int Id { get; set; }
public required int TacticId { get; set; }
public Tactic Tactic { get; set; }
public int TacticId { get; set; }
public TacticEntity Tactic { get; set; }
public required int? ParentId { get; set; }

@ -32,4 +32,9 @@ public static class EntitiesToModels
{
return new Team(entity.Id, entity.Name, entity.Picture, entity.MainColor, entity.SecondColor);
}
public static Member ToModel(this MemberEntity entity)
{
return new Member(entity.TeamId, entity.UserId, entity.Role);
}
}

@ -38,16 +38,14 @@ public class DbTacticService(AppContext.AppContext context) : ITacticService
Type = courtType
};
await context.Tactics.AddAsync(tacticEntity);
await context.SaveChangesAsync();
var stepEntity = new TacticStepEntity
{
ParentId = null,
TacticId = tacticEntity.Id,
JsonContent = "{\"components\": []}"
JsonContent = "{\"components\": []}",
Tactic = tacticEntity
};
await context.Tactics.AddAsync(tacticEntity);
await context.TacticSteps.AddAsync(stepEntity);
await context.SaveChangesAsync();

@ -42,7 +42,7 @@ public class DbTeamService(AppContext.AppContext context) : ITeamService
return await context.Teams.CountAsync(t => t.Name.ToLower().Contains(nameNeedle.ToLower()));
}
public async Task<int> CountTeams()
public async Task<int> CountTotalTeams()
{
return await context.Teams.CountAsync();
}
@ -82,4 +82,43 @@ public class DbTeamService(AppContext.AppContext context) : ITeamService
return await context.SaveChangesAsync() > 0;
}
public IEnumerable<Member> GetMembersOf(int teamId)
{
return context.Members.Where(m => m.TeamId == teamId)
.AsEnumerable()
.Select(e => e.ToModel());
}
public async Task<Member> AddMember(int teamId, int userId, MemberRole role)
{
await context.Members.AddAsync(new MemberEntity
{
TeamId = teamId,
UserId = userId,
Role = role
});
await context.SaveChangesAsync();
return new Member(teamId, userId, role);
}
public async Task<bool> UpdateMember(Member member)
{
var entity =
await context.Members.FirstOrDefaultAsync(e => e.TeamId == member.TeamId && e.UserId == member.UserId);
if (entity == null)
return false;
entity.Role = member.Role;
return await context.SaveChangesAsync() > 0;
}
public async Task<bool> RemoveMember(int teamId, int userId)
{
await context.Members
.Where(e => e.TeamId == teamId && e.UserId == userId)
.ExecuteDeleteAsync();
return await context.SaveChangesAsync() > 0;
}
}

@ -1,3 +1,5 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Model;
public enum CourtType

@ -0,0 +1,3 @@
namespace Model;
public record Member(int TeamId, int UserId, MemberRole Role);

@ -0,0 +1,7 @@
namespace Model;
public enum MemberRole
{
Player,
Coach
}

@ -8,10 +8,19 @@ public interface ITeamService
public Task<IEnumerable<Team>> ListTeams();
public Task<int> CountTeams();
public Task<int> CountTotalTeams();
public Task<Team> AddTeam(string name, string picture, string firstColor, string secondColor);
public Task RemoveTeams(params int[] teams);
public IEnumerable<Member> GetMembersOf(int teamId);
public Task<Member> AddMember(int teamId, int userId, MemberRole role);
public Task<bool> UpdateMember(Member member);
public Task<bool> RemoveMember(int teamId, int userId);
public Task<bool> UpdateTeam(Team team);
}

@ -1,5 +1,6 @@
using AppContext.Entities;
using Microsoft.EntityFrameworkCore;
using Model;
namespace StubContext;
@ -36,5 +37,24 @@ public class StubAppContext(DbContextOptions<AppContext> options) : AppContext(o
builder.Entity<MemberEntity>()
.HasKey("TeamId", "UserId");
builder.Entity<TacticEntity>()
.HasData(new TacticEntity()
{
Id = 1,
Name = "New tactic",
Type = CourtType.Plain,
CreationDate = new DateTime(2024, 5, 31),
OwnerId = 1,
});
builder.Entity<TacticStepEntity>()
.HasData(new TacticStepEntity
{
Id = 1,
JsonContent = "{}",
TacticId = 1,
ParentId = null
});
}
}

@ -0,0 +1,126 @@
using API.Controllers;
using API.Controllers.Admin;
using DbServices;
using FluentAssertions;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Model;
using StubContext;
namespace UnitTests;
public class AdminUserControllerTest
{
private static UsersAdminController GetUsersController()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var context = new StubAppContext(
new DbContextOptionsBuilder<AppContext.AppContext>()
.UseSqlite(connection)
.Options
);
context.Database.EnsureCreated();
var service = new DbUserService(context);
return new UsersAdminController(service);
}
[Fact]
public async void CountUsersTest()
{
var controller = GetUsersController();
(await controller.CountUsers()).Should().Be(new UsersAdminController.CountUsersResponse(5));
(await controller.CountUsers("a")).Should().BeEquivalentTo(new UsersAdminController.CountUsersResponse(3));
(await controller.CountUsers("")).Should().BeEquivalentTo(new UsersAdminController.CountUsersResponse(5));
(await controller.CountUsers("^ù$*")).Should().BeEquivalentTo(new UsersAdminController.CountUsersResponse(0));
}
[Fact]
public async void ListUsersTest()
{
var controller = GetUsersController();
(await controller.CountUsers()).Should().Be(new UsersAdminController.CountUsersResponse(5));
(await controller.ListUsers(0, 10, null)).Should().BeEquivalentTo(new List<User>
{
new(1, "maxime", "maxime@mail.com",
UsersController.DefaultProfilePicture, true),
new(2, "mael", "mael@mail.com",
UsersController.DefaultProfilePicture, true),
new(3, "yanis", "yanis@mail.com",
UsersController.DefaultProfilePicture, true),
new(4, "simon", "simon@mail.com",
UsersController.DefaultProfilePicture, true),
new(5, "vivien", "vivien@mail.com",
UsersController.DefaultProfilePicture, true),
});
(await controller.ListUsers(0, 10, "")).Should().BeEquivalentTo(new List<User>
{
new(1, "maxime", "maxime@mail.com",
UsersController.DefaultProfilePicture, true),
new(2, "mael", "mael@mail.com",
UsersController.DefaultProfilePicture, true),
new(3, "yanis", "yanis@mail.com",
UsersController.DefaultProfilePicture, true),
new(4, "simon", "simon@mail.com",
UsersController.DefaultProfilePicture, true),
new(5, "vivien", "vivien@mail.com",
UsersController.DefaultProfilePicture, true),
});
(await controller.ListUsers(0, 10, "a")).Should().BeEquivalentTo(new List<User>
{
new(1, "maxime", "maxime@mail.com",
UsersController.DefaultProfilePicture, true),
new(2, "mael", "mael@mail.com",
UsersController.DefaultProfilePicture, true),
new(3, "yanis", "yanis@mail.com",
UsersController.DefaultProfilePicture, true),
});
(await controller.ListUsers(0, 0, "")).Should().BeEquivalentTo(new List<User> { });
(await controller.ListUsers(0, 10, "^ù$*")).Should().BeEquivalentTo(new List<User> { });
}
[Fact]
public async void GetUserTest()
{
var controller = GetUsersController();
var response = await controller.GetUser(0);
response.Should().BeEquivalentTo(controller.NotFound());
response = await controller.GetUser(1);
response.Should().BeEquivalentTo(controller.Ok(new User(1, "maxime", "maxime@mail.com",
UsersController.DefaultProfilePicture, true)));
}
[Fact]
public async void AddUserTest()
{
var controller = GetUsersController();
var user = await controller.AddUser(new("Test", "TestPassword", "test@mail.com", true));
user.Should().BeEquivalentTo(new User(6, "Test", "test@mail.com", UsersController.DefaultProfilePicture, true));
}
[Fact]
public async void RemoveUsersTest()
{
var controller = GetUsersController();
var result = await controller.RemoveUsers(new([1, 4, 3, 5]));
result.Should().BeEquivalentTo(controller.Ok());
var remainingUsers = await controller.ListUsers(0, 10, null);
remainingUsers.Should().BeEquivalentTo(new User[] { new(2, "mael", "mael@mail.com",
UsersController.DefaultProfilePicture, true) });
}
[Fact]
public async void UpdateUserTest()
{
var controller = GetUsersController();
var result = await controller.UpdateUser(1, new("maxou", "maxou@mail.com", false));
result.Should().BeEquivalentTo(controller.Ok());
var userResult = await controller.GetUser(1);
userResult.Should().BeEquivalentTo(controller.Ok(new User(1, "maxou", "maxou@mail.com", UsersController.DefaultProfilePicture, false)));
}
}

@ -0,0 +1 @@
global using Xunit;

@ -0,0 +1,12 @@
using API.Context;
using Microsoft.AspNetCore.Http;
namespace UnitTests;
public class ManualContextAccessor(int userId) : IContextAccessor
{
public int CurrentUserId(HttpContext ctx)
{
return userId;
}
}

@ -0,0 +1,66 @@
using API.Controllers;
using API.DTO;
using AppContext.Entities;
using DbServices;
using FluentAssertions;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Model;
using StubContext;
namespace UnitTests;
public class TacticsControllerTest
{
private static (TacticController, AppContext.AppContext) GetController(int userId)
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var context = new StubAppContext(
new DbContextOptionsBuilder<AppContext.AppContext>()
.UseSqlite(connection)
.Options
);
context.Database.EnsureCreated();
var controller = new TacticController(
new DbTacticService(context),
new ManualContextAccessor(userId)
);
return (controller, context);
}
[Fact]
public async void UpdateName()
{
var (controller, context) = GetController(1);
var result = await controller.UpdateName(1, new("Stade de France"));
result.Should().BeEquivalentTo(controller.Ok());
var tactic = await context.Tactics.FindAsync(1);
tactic.Name.Should().BeEquivalentTo("Stade de France");
result = await controller.UpdateName(-1, new("Stade de France"));
result.Should().BeEquivalentTo(controller.Unauthorized());
}
[Fact]
public async void GetTacticInfoTest()
{
var (controller, context) = GetController(1);
var result = await controller.GetTacticInfo(1);
result.Should().BeEquivalentTo(controller.Ok(new Tactic(1, "New tactic", 1, CourtType.Plain, new DateTime(2024, 5, 31)).ToDto()));
result = await controller.GetTacticInfo(100);
result.Should().BeEquivalentTo(controller.Unauthorized());
}
[Fact]
public async void GetTacticStepsRoot()
{
var (controller, context) = GetController(1);
var result = await controller.GetTacticStepsRoot(1);
result.Should().BeEquivalentTo(controller.Ok(new TacticController.GetTacticStepsTreeResponse(new TacticStep(1, null, [], "{}").ToDto())));
}
}

@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="7.0.0-alpha.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="xunit" Version="2.4.2"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\API\API.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\API\API.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,49 @@
using API.Controllers;
using DbServices;
using FluentAssertions;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Model;
using StubContext;
namespace UnitTests;
public class UsersControllerTest
{
private static UsersController GetUserController(int userId)
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var context = new StubAppContext(
new DbContextOptionsBuilder<AppContext.AppContext>()
.UseSqlite(connection)
.Options
);
context.Database.EnsureCreated();
var controller = new UsersController(
new DbUserService(context),
new DbTeamService(context),
new DbTacticService(context),
new ManualContextAccessor(userId)
);
return controller;
}
[Fact]
public async void GetCurrentUserTest()
{
var controller = GetUserController(1);
var result = await controller.GetUser();
result.Should().BeEquivalentTo(new User(1, "maxime", "maxime@mail.com",
UsersController.DefaultProfilePicture, true));
}
[Fact]
public async void GetUserDataTest()
{
var controller = GetUserController(1);
var result = await controller.GetUserData();
result.Should().BeEquivalentTo(new UsersController.GetUserDataResponse([], []));
}
}

@ -4,8 +4,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppContext", "AppContext\AppContext.csproj", "{7E245DA5-0C5A-4933-9AF0-CA447F3BC159}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DTO", "DTO\DTO.csproj", "{7BE8B235-EF70-4C94-8938-5ABB5AEB08B1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StubContext", "StubContext\StubContext.csproj", "{420D507C-D51C-48D9-A819-72B08AEBD024}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "API", "API\API.csproj", "{B22FA426-EFF2-42E9-96BB-78F1C65E37CC}"
@ -16,6 +14,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DbServices", "DbServices\Db
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Converters", "Converters\Converters.csproj", "{465819A9-7158-4612-AC57-ED2C7A0F243E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{82A100BE-5610-4741-8F23-1CD653E8EFCD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -58,5 +58,9 @@ Global
{9C5EAD2F-FA50-43C2-BB86-1065ED661C52}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C5EAD2F-FA50-43C2-BB86-1065ED661C52}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C5EAD2F-FA50-43C2-BB86-1065ED661C52}.Release|Any CPU.Build.0 = Release|Any CPU
{82A100BE-5610-4741-8F23-1CD653E8EFCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{82A100BE-5610-4741-8F23-1CD653E8EFCD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{82A100BE-5610-4741-8F23-1CD653E8EFCD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{82A100BE-5610-4741-8F23-1CD653E8EFCD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

@ -1,18 +1,11 @@
kind: pipeline
type: docker
name: "CI and deploy on iqball.maxou.dev"
name: "CI, deploy server on iqball.maxou.dev, deploy doc on codehub"
steps:
- image: mcr.microsoft.com/dotnet/sdk:8.0
name: "CI"
commands:
- dotnet test
- image: plugins/docker
name: "build and push docker image"
depends_on:
- "CI"
settings:
dockerfile: ci/API.dockerfile
context: .

@ -0,0 +1,9 @@
{
"stryker-config":
{
"reporters": [
"progress",
"html"
]
}
}
Loading…
Cancel
Save