From 57ce4c916b1ec76bd639213599377fc62a4c129d Mon Sep 17 00:00:00 2001 From: zysim <9867871+zysim@users.noreply.github.com> Date: Sun, 18 Aug 2024 12:06:52 +0800 Subject: [PATCH 01/11] Get leaderboard endpoint --- .../Controllers/LeaderboardsController.cs | 4 +--- .../Services/Impl/LeaderboardService.cs | 13 +++++-------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/LeaderboardBackend/Controllers/LeaderboardsController.cs b/LeaderboardBackend/Controllers/LeaderboardsController.cs index 55ec38bc..434f91c2 100644 --- a/LeaderboardBackend/Controllers/LeaderboardsController.cs +++ b/LeaderboardBackend/Controllers/LeaderboardsController.cs @@ -13,10 +13,8 @@ public class LeaderboardsController : ApiController { private readonly ILeaderboardService _leaderboardService; - public LeaderboardsController(ILeaderboardService leaderboardService) - { + public LeaderboardsController(ILeaderboardService leaderboardService) => _leaderboardService = leaderboardService; - } [AllowAnonymous] [HttpGet("api/leaderboard/{id:long}")] diff --git a/LeaderboardBackend/Services/Impl/LeaderboardService.cs b/LeaderboardBackend/Services/Impl/LeaderboardService.cs index 506a715b..1f702c89 100644 --- a/LeaderboardBackend/Services/Impl/LeaderboardService.cs +++ b/LeaderboardBackend/Services/Impl/LeaderboardService.cs @@ -12,17 +12,14 @@ public LeaderboardService(ApplicationContext applicationContext) _applicationContext = applicationContext; } - public async Task GetLeaderboard(long id) - { - return await _applicationContext.Leaderboards.FindAsync(id); - } + public async Task GetLeaderboard(long id) => + await _applicationContext.Leaderboards + .FirstOrDefaultAsync(board => board.Id == id); - public async Task GetLeaderboardBySlug(string slug) - { - return await _applicationContext.Leaderboards + public Task GetLeaderboardBySlug(string slug) => + _applicationContext.Leaderboards .AsNoTracking() .FirstOrDefaultAsync(x => x.Slug == slug); - } // FIXME: Paginate this public async Task> GetLeaderboards(long[]? ids = null) From d66ac751d89ec8d344dd77f8a3b341687719e4e8 Mon Sep 17 00:00:00 2001 From: zysim <9867871+zysim@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:07:52 +0800 Subject: [PATCH 02/11] Apply style rules to test file --- LeaderboardBackend.Test/Leaderboards.cs | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/LeaderboardBackend.Test/Leaderboards.cs b/LeaderboardBackend.Test/Leaderboards.cs index 79e75936..9640e301 100644 --- a/LeaderboardBackend.Test/Leaderboards.cs +++ b/LeaderboardBackend.Test/Leaderboards.cs @@ -35,24 +35,15 @@ public async Task OneTimeSetUp() } [OneTimeTearDown] - public void OneTimeTearDown() - { - _factory.Dispose(); - } + public void OneTimeTearDown() => _factory.Dispose(); [Test] - public void GetLeaderboard_NotFound() - { - RequestFailureException e = Assert.ThrowsAsync( - async () => - await _apiClient.Get( - $"/api/leaderboard/{long.MaxValue}", - new() - ) - )!; - - Assert.AreEqual(HttpStatusCode.NotFound, e.Response.StatusCode); - } + public void GetLeaderboard_NotFound() => _apiClient.Invoking(a => a.Get( + $"/api/leaderboard/{long.MaxValue}", + new() + )).Should() + .ThrowAsync() + .Where(e => e.Response.StatusCode == HttpStatusCode.NotFound); [Test] public async Task CreateLeaderboard_GetLeaderboard_OK() From 240699fa9d58bf0f47df1932299fc9822a5c479a Mon Sep 17 00:00:00 2001 From: zysim <9867871+zysim@users.noreply.github.com> Date: Fri, 6 Sep 2024 01:35:28 +0800 Subject: [PATCH 03/11] Address comments --- .../Services/ILeaderboardService.cs | 2 +- .../Services/Impl/LeaderboardService.cs | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/LeaderboardBackend/Services/ILeaderboardService.cs b/LeaderboardBackend/Services/ILeaderboardService.cs index bb8bc29b..3c491709 100644 --- a/LeaderboardBackend/Services/ILeaderboardService.cs +++ b/LeaderboardBackend/Services/ILeaderboardService.cs @@ -4,7 +4,7 @@ namespace LeaderboardBackend.Services; public interface ILeaderboardService { - Task GetLeaderboard(long id); + ValueTask GetLeaderboard(long id); Task GetLeaderboardBySlug(string slug); Task> GetLeaderboards(long[]? ids = null); Task CreateLeaderboard(Leaderboard leaderboard); diff --git a/LeaderboardBackend/Services/Impl/LeaderboardService.cs b/LeaderboardBackend/Services/Impl/LeaderboardService.cs index 1f702c89..9f55065f 100644 --- a/LeaderboardBackend/Services/Impl/LeaderboardService.cs +++ b/LeaderboardBackend/Services/Impl/LeaderboardService.cs @@ -3,18 +3,13 @@ namespace LeaderboardBackend.Services; -public class LeaderboardService : ILeaderboardService +public class LeaderboardService(ApplicationContext applicationContext) : ILeaderboardService { - private readonly ApplicationContext _applicationContext; + private readonly ApplicationContext _applicationContext = applicationContext; - public LeaderboardService(ApplicationContext applicationContext) - { - _applicationContext = applicationContext; - } - - public async Task GetLeaderboard(long id) => - await _applicationContext.Leaderboards - .FirstOrDefaultAsync(board => board.Id == id); + public ValueTask GetLeaderboard(long id) => + _applicationContext.Leaderboards + .FindAsync([id]); public Task GetLeaderboardBySlug(string slug) => _applicationContext.Leaderboards From 3223dde1432bc5dc0a095a054cc9baeb7ad00b1b Mon Sep 17 00:00:00 2001 From: zysim <9867871+zysim@users.noreply.github.com> Date: Fri, 6 Sep 2024 01:35:47 +0800 Subject: [PATCH 04/11] Use primary constructor for LeaderboardsController --- LeaderboardBackend/Controllers/LeaderboardsController.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/LeaderboardBackend/Controllers/LeaderboardsController.cs b/LeaderboardBackend/Controllers/LeaderboardsController.cs index 434f91c2..66dc1f49 100644 --- a/LeaderboardBackend/Controllers/LeaderboardsController.cs +++ b/LeaderboardBackend/Controllers/LeaderboardsController.cs @@ -9,12 +9,9 @@ namespace LeaderboardBackend.Controllers; -public class LeaderboardsController : ApiController +public class LeaderboardsController(ILeaderboardService leaderboardService) : ApiController { - private readonly ILeaderboardService _leaderboardService; - - public LeaderboardsController(ILeaderboardService leaderboardService) => - _leaderboardService = leaderboardService; + private readonly ILeaderboardService _leaderboardService = leaderboardService; [AllowAnonymous] [HttpGet("api/leaderboard/{id:long}")] From 9158304e8778ab17b1339949610cf3e821a472de Mon Sep 17 00:00:00 2001 From: Ted Wollman <25165500+TheTedder@users.noreply.github.com> Date: Thu, 5 Sep 2024 17:19:03 -0400 Subject: [PATCH 05/11] Use proper async assertions. --- LeaderboardBackend.Test/Leaderboards.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/LeaderboardBackend.Test/Leaderboards.cs b/LeaderboardBackend.Test/Leaderboards.cs index 9640e301..a69cdd3a 100644 --- a/LeaderboardBackend.Test/Leaderboards.cs +++ b/LeaderboardBackend.Test/Leaderboards.cs @@ -38,11 +38,12 @@ public async Task OneTimeSetUp() public void OneTimeTearDown() => _factory.Dispose(); [Test] - public void GetLeaderboard_NotFound() => _apiClient.Invoking(a => a.Get( - $"/api/leaderboard/{long.MaxValue}", - new() - )).Should() - .ThrowAsync() + public async Task GetLeaderboard_NotFound() => await FluentActions.Awaiting( + async () => await _apiClient.Get( + $"/api/leaderboards/{long.MaxValue}", + new() + ) + ).Should().ThrowAsync() .Where(e => e.Response.StatusCode == HttpStatusCode.NotFound); [Test] From e123df3422a1e0b81b54b99f6bd9c9da9e8da182 Mon Sep 17 00:00:00 2001 From: Ted Wollman <25165500+TheTedder@users.noreply.github.com> Date: Thu, 5 Sep 2024 17:20:13 -0400 Subject: [PATCH 06/11] Don't use a ValueTask for GetLeaderboard. --- .../Services/ILeaderboardService.cs | 2 +- .../Services/Impl/LeaderboardService.cs | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/LeaderboardBackend/Services/ILeaderboardService.cs b/LeaderboardBackend/Services/ILeaderboardService.cs index 3c491709..bb8bc29b 100644 --- a/LeaderboardBackend/Services/ILeaderboardService.cs +++ b/LeaderboardBackend/Services/ILeaderboardService.cs @@ -4,7 +4,7 @@ namespace LeaderboardBackend.Services; public interface ILeaderboardService { - ValueTask GetLeaderboard(long id); + Task GetLeaderboard(long id); Task GetLeaderboardBySlug(string slug); Task> GetLeaderboards(long[]? ids = null); Task CreateLeaderboard(Leaderboard leaderboard); diff --git a/LeaderboardBackend/Services/Impl/LeaderboardService.cs b/LeaderboardBackend/Services/Impl/LeaderboardService.cs index 9f55065f..4a0cf4d1 100644 --- a/LeaderboardBackend/Services/Impl/LeaderboardService.cs +++ b/LeaderboardBackend/Services/Impl/LeaderboardService.cs @@ -5,14 +5,11 @@ namespace LeaderboardBackend.Services; public class LeaderboardService(ApplicationContext applicationContext) : ILeaderboardService { - private readonly ApplicationContext _applicationContext = applicationContext; - - public ValueTask GetLeaderboard(long id) => - _applicationContext.Leaderboards - .FindAsync([id]); + public async Task GetLeaderboard(long id) => + await applicationContext.Leaderboards.FindAsync(id); public Task GetLeaderboardBySlug(string slug) => - _applicationContext.Leaderboards + applicationContext.Leaderboards .AsNoTracking() .FirstOrDefaultAsync(x => x.Slug == slug); @@ -21,11 +18,11 @@ public async Task> GetLeaderboards(long[]? ids = null) { if (ids is null) { - return await _applicationContext.Leaderboards.ToListAsync(); + return await applicationContext.Leaderboards.ToListAsync(); } else { - return await _applicationContext.Leaderboards + return await applicationContext.Leaderboards .Where(leaderboard => ids.Contains(leaderboard.Id)) .ToListAsync(); } @@ -33,7 +30,7 @@ public async Task> GetLeaderboards(long[]? ids = null) public async Task CreateLeaderboard(Leaderboard leaderboard) { - _applicationContext.Leaderboards.Add(leaderboard); - await _applicationContext.SaveChangesAsync(); + applicationContext.Leaderboards.Add(leaderboard); + await applicationContext.SaveChangesAsync(); } } From 8ba09c9d146b3bbf6bfb4e92e35c3b979baffe13 Mon Sep 17 00:00:00 2001 From: zysim <9867871+zysim@users.noreply.github.com> Date: Sat, 7 Sep 2024 12:39:38 +0800 Subject: [PATCH 07/11] Actually await async test --- LeaderboardBackend.Test/Leaderboards.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LeaderboardBackend.Test/Leaderboards.cs b/LeaderboardBackend.Test/Leaderboards.cs index a69cdd3a..d6d58277 100644 --- a/LeaderboardBackend.Test/Leaderboards.cs +++ b/LeaderboardBackend.Test/Leaderboards.cs @@ -40,7 +40,7 @@ public async Task OneTimeSetUp() [Test] public async Task GetLeaderboard_NotFound() => await FluentActions.Awaiting( async () => await _apiClient.Get( - $"/api/leaderboards/{long.MaxValue}", + $"/api/leaderboard/{long.MaxValue}", new() ) ).Should().ThrowAsync() From e25f03fa8a92b0ada825e0d33c727c481c43c17e Mon Sep 17 00:00:00 2001 From: zysim <9867871+zysim@users.noreply.github.com> Date: Sun, 8 Sep 2024 12:26:37 +0800 Subject: [PATCH 08/11] Remove unnecessary class field --- .../Controllers/LeaderboardsController.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/LeaderboardBackend/Controllers/LeaderboardsController.cs b/LeaderboardBackend/Controllers/LeaderboardsController.cs index 66dc1f49..91771228 100644 --- a/LeaderboardBackend/Controllers/LeaderboardsController.cs +++ b/LeaderboardBackend/Controllers/LeaderboardsController.cs @@ -11,8 +11,6 @@ namespace LeaderboardBackend.Controllers; public class LeaderboardsController(ILeaderboardService leaderboardService) : ApiController { - private readonly ILeaderboardService _leaderboardService = leaderboardService; - [AllowAnonymous] [HttpGet("api/leaderboard/{id:long}")] [SwaggerOperation("Gets a leaderboard by its ID.", OperationId = "getLeaderboard")] @@ -20,7 +18,7 @@ public class LeaderboardsController(ILeaderboardService leaderboardService) : Ap [SwaggerResponse(404)] public async Task> GetLeaderboard(long id) { - Leaderboard? leaderboard = await _leaderboardService.GetLeaderboard(id); + Leaderboard? leaderboard = await leaderboardService.GetLeaderboard(id); if (leaderboard == null) { @@ -37,7 +35,7 @@ public async Task> GetLeaderboard(long id) [SwaggerResponse(404)] public async Task> GetLeaderboardBySlug([FromQuery, SwaggerParameter(Required = true)] string slug) { - Leaderboard? leaderboard = await _leaderboardService.GetLeaderboardBySlug(slug); + Leaderboard? leaderboard = await leaderboardService.GetLeaderboardBySlug(slug); if (leaderboard == null) { @@ -55,7 +53,7 @@ public async Task>> GetLeaderboards( [FromQuery] long[] ids ) { - List result = await _leaderboardService.GetLeaderboards(ids); + List result = await leaderboardService.GetLeaderboards(ids); return Ok(result.Select(LeaderboardViewModel.MapFrom)); } @@ -72,7 +70,7 @@ [FromBody] CreateLeaderboardRequest request { Leaderboard leaderboard = new() { Name = request.Name, Slug = request.Slug, Info = request.Info }; - await _leaderboardService.CreateLeaderboard(leaderboard); + await leaderboardService.CreateLeaderboard(leaderboard); return CreatedAtAction( nameof(GetLeaderboard), From 534e70056f777ba8255314473ce7e09f167a0aca Mon Sep 17 00:00:00 2001 From: zysim <9867871+zysim@users.noreply.github.com> Date: Sun, 8 Sep 2024 12:27:16 +0800 Subject: [PATCH 09/11] Explicitly await within service method body --- LeaderboardBackend/Services/Impl/LeaderboardService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LeaderboardBackend/Services/Impl/LeaderboardService.cs b/LeaderboardBackend/Services/Impl/LeaderboardService.cs index 4a0cf4d1..0f08e020 100644 --- a/LeaderboardBackend/Services/Impl/LeaderboardService.cs +++ b/LeaderboardBackend/Services/Impl/LeaderboardService.cs @@ -8,8 +8,8 @@ public class LeaderboardService(ApplicationContext applicationContext) : ILeader public async Task GetLeaderboard(long id) => await applicationContext.Leaderboards.FindAsync(id); - public Task GetLeaderboardBySlug(string slug) => - applicationContext.Leaderboards + public async Task GetLeaderboardBySlug(string slug) => + await applicationContext.Leaderboards .AsNoTracking() .FirstOrDefaultAsync(x => x.Slug == slug); From 9296d24f0b8efcabe8c4fdfbcc0303753848fd90 Mon Sep 17 00:00:00 2001 From: zysim <9867871+zysim@users.noreply.github.com> Date: Mon, 9 Sep 2024 21:38:44 +0800 Subject: [PATCH 10/11] Convert statement lambdas in tests to expression lambdas --- LeaderboardBackend.Test/Categories.cs | 5 +---- LeaderboardBackend.Test/Runs.cs | 9 +++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/LeaderboardBackend.Test/Categories.cs b/LeaderboardBackend.Test/Categories.cs index 14c0054f..e42821a5 100644 --- a/LeaderboardBackend.Test/Categories.cs +++ b/LeaderboardBackend.Test/Categories.cs @@ -28,10 +28,7 @@ public async Task OneTimeSetUp() } [OneTimeTearDown] - public void OneTimeTearDown() - { - _factory.Dispose(); - } + public void OneTimeTearDown() => _factory.Dispose(); [Test] public static void GetCategory_NotFound() diff --git a/LeaderboardBackend.Test/Runs.cs b/LeaderboardBackend.Test/Runs.cs index 344faade..1e83dbe4 100644 --- a/LeaderboardBackend.Test/Runs.cs +++ b/LeaderboardBackend.Test/Runs.cs @@ -110,9 +110,10 @@ private static async Task CreateRun() ); } - private static async Task GetRun(Guid id) - { - return await _apiClient.Get($"/api/run/{id.ToUrlSafeBase64String()}", new() { Jwt = _jwt }); - } + private static async Task GetRun(Guid id) => + await _apiClient.Get( + $"/api/run/{id.ToUrlSafeBase64String()}", + new() { Jwt = _jwt } + ); } } From 016c12f4075929d26dd9a2efbfbe9bb89657f3a3 Mon Sep 17 00:00:00 2001 From: zysim <9867871+zysim@users.noreply.github.com> Date: Mon, 9 Sep 2024 21:51:03 +0800 Subject: [PATCH 11/11] Implement IDE suggestions for tests --- LeaderboardBackend.Test/Categories.cs | 21 +++++++++------------ LeaderboardBackend.Test/Runs.cs | 14 ++++++-------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/LeaderboardBackend.Test/Categories.cs b/LeaderboardBackend.Test/Categories.cs index e42821a5..9ed071d2 100644 --- a/LeaderboardBackend.Test/Categories.cs +++ b/LeaderboardBackend.Test/Categories.cs @@ -31,18 +31,15 @@ public async Task OneTimeSetUp() public void OneTimeTearDown() => _factory.Dispose(); [Test] - public static void GetCategory_NotFound() - { - RequestFailureException e = Assert.ThrowsAsync( - async () => - await _apiClient.Get( - $"/api/categories/69", - new() { Jwt = _jwt } - ) - )!; - - Assert.AreEqual(HttpStatusCode.NotFound, e.Response.StatusCode); - } + public static async Task GetCategory_NotFound() => + await _apiClient.Awaiting( + a => a.Get( + $"/api/cateogries/69", + new() { Jwt = _jwt } + ) + ).Should() + .ThrowAsync() + .Where(e => e.Response.StatusCode == HttpStatusCode.NotFound); [Test] public static async Task CreateCategory_GetCategory_OK() diff --git a/LeaderboardBackend.Test/Runs.cs b/LeaderboardBackend.Test/Runs.cs index 1e83dbe4..bb932262 100644 --- a/LeaderboardBackend.Test/Runs.cs +++ b/LeaderboardBackend.Test/Runs.cs @@ -74,8 +74,8 @@ public static async Task CreateRun_OK() RunViewModel retrieved = await GetRun(created.Id); - Assert.NotNull(created); - Assert.AreEqual(created.Id, retrieved.Id); + created.Should().NotBeNull(); + created.Id.Should().Be(retrieved.Id); } [Test] @@ -88,13 +88,12 @@ public static async Task GetCategory_OK() new() { Jwt = _jwt } ); - Assert.NotNull(category); - Assert.AreEqual(category.Id, _categoryId); + category.Should().NotBeNull(); + category.Id.Should().Be(_categoryId); } - private static async Task CreateRun() - { - return await _apiClient.Post( + private static async Task CreateRun() => + await _apiClient.Post( "/runs/create", new() { @@ -108,7 +107,6 @@ private static async Task CreateRun() Jwt = _jwt } ); - } private static async Task GetRun(Guid id) => await _apiClient.Get(