Skip to content

Commit

Permalink
Get Leaderboard Endpoint (leaderboardsgg#232)
Browse files Browse the repository at this point in the history
* Get leaderboard endpoint

* Apply style rules to test file

* Address comments

* Use primary constructor for LeaderboardsController

* Use proper async assertions.

* Don't use a ValueTask for GetLeaderboard.

* Actually await async test

* Remove unnecessary class field

* Explicitly await within service method body

* Convert statement lambdas in tests to expression lambdas

* Implement IDE suggestions for tests

---------

Co-authored-by: Ted Wollman <[email protected]>
  • Loading branch information
zysim and TheTedder authored Sep 9, 2024
1 parent d8633f9 commit 4c5bedf
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 76 deletions.
26 changes: 10 additions & 16 deletions LeaderboardBackend.Test/Categories.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,18 @@ public async Task OneTimeSetUp()
}

[OneTimeTearDown]
public void OneTimeTearDown()
{
_factory.Dispose();
}
public void OneTimeTearDown() => _factory.Dispose();

[Test]
public static void GetCategory_NotFound()
{
RequestFailureException e = Assert.ThrowsAsync<RequestFailureException>(
async () =>
await _apiClient.Get<CategoryViewModel>(
$"/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<CategoryViewModel>(
$"/api/cateogries/69",
new() { Jwt = _jwt }
)
).Should()
.ThrowAsync<RequestFailureException>()
.Where(e => e.Response.StatusCode == HttpStatusCode.NotFound);

[Test]
public static async Task CreateCategory_GetCategory_OK()
Expand Down
24 changes: 8 additions & 16 deletions LeaderboardBackend.Test/Leaderboards.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,16 @@ public async Task OneTimeSetUp()
}

[OneTimeTearDown]
public void OneTimeTearDown()
{
_factory.Dispose();
}
public void OneTimeTearDown() => _factory.Dispose();

[Test]
public void GetLeaderboard_NotFound()
{
RequestFailureException e = Assert.ThrowsAsync<RequestFailureException>(
async () =>
await _apiClient.Get<LeaderboardViewModel>(
$"/api/leaderboard/{long.MaxValue}",
new()
)
)!;

Assert.AreEqual(HttpStatusCode.NotFound, e.Response.StatusCode);
}
public async Task GetLeaderboard_NotFound() => await FluentActions.Awaiting(
async () => await _apiClient.Get<LeaderboardViewModel>(
$"/api/leaderboard/{long.MaxValue}",
new()
)
).Should().ThrowAsync<RequestFailureException>()
.Where(e => e.Response.StatusCode == HttpStatusCode.NotFound);

[Test]
public async Task CreateLeaderboard_GetLeaderboard_OK()
Expand Down
23 changes: 11 additions & 12 deletions LeaderboardBackend.Test/Runs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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<RunViewModel> CreateRun()
{
return await _apiClient.Post<RunViewModel>(
private static async Task<RunViewModel> CreateRun() =>
await _apiClient.Post<RunViewModel>(
"/runs/create",
new()
{
Expand All @@ -108,11 +107,11 @@ private static async Task<RunViewModel> CreateRun()
Jwt = _jwt
}
);
}

private static async Task<RunViewModel> GetRun(Guid id)
{
return await _apiClient.Get<RunViewModel>($"/api/run/{id.ToUrlSafeBase64String()}", new() { Jwt = _jwt });
}
private static async Task<RunViewModel> GetRun(Guid id) =>
await _apiClient.Get<RunViewModel>(
$"/api/run/{id.ToUrlSafeBase64String()}",
new() { Jwt = _jwt }
);
}
}
17 changes: 5 additions & 12 deletions LeaderboardBackend/Controllers/LeaderboardsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,16 @@

namespace LeaderboardBackend.Controllers;

public class LeaderboardsController : ApiController
public class LeaderboardsController(ILeaderboardService leaderboardService) : ApiController
{
private readonly ILeaderboardService _leaderboardService;

public LeaderboardsController(ILeaderboardService leaderboardService)
{
_leaderboardService = leaderboardService;
}

[AllowAnonymous]
[HttpGet("api/leaderboard/{id:long}")]
[SwaggerOperation("Gets a leaderboard by its ID.", OperationId = "getLeaderboard")]
[SwaggerResponse(200)]
[SwaggerResponse(404)]
public async Task<ActionResult<LeaderboardViewModel>> GetLeaderboard(long id)
{
Leaderboard? leaderboard = await _leaderboardService.GetLeaderboard(id);
Leaderboard? leaderboard = await leaderboardService.GetLeaderboard(id);

if (leaderboard == null)
{
Expand All @@ -42,7 +35,7 @@ public async Task<ActionResult<LeaderboardViewModel>> GetLeaderboard(long id)
[SwaggerResponse(404)]
public async Task<ActionResult<LeaderboardViewModel>> GetLeaderboardBySlug([FromQuery, SwaggerParameter(Required = true)] string slug)
{
Leaderboard? leaderboard = await _leaderboardService.GetLeaderboardBySlug(slug);
Leaderboard? leaderboard = await leaderboardService.GetLeaderboardBySlug(slug);

if (leaderboard == null)
{
Expand All @@ -60,7 +53,7 @@ public async Task<ActionResult<List<LeaderboardViewModel>>> GetLeaderboards(
[FromQuery] long[] ids
)
{
List<Leaderboard> result = await _leaderboardService.GetLeaderboards(ids);
List<Leaderboard> result = await leaderboardService.GetLeaderboards(ids);
return Ok(result.Select(LeaderboardViewModel.MapFrom));
}

Expand All @@ -77,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),
Expand Down
29 changes: 9 additions & 20 deletions LeaderboardBackend/Services/Impl/LeaderboardService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,34 @@

namespace LeaderboardBackend.Services;

public class LeaderboardService : ILeaderboardService
public class LeaderboardService(ApplicationContext applicationContext) : ILeaderboardService
{
private readonly ApplicationContext _applicationContext;
public async Task<Leaderboard?> GetLeaderboard(long id) =>
await applicationContext.Leaderboards.FindAsync(id);

public LeaderboardService(ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
}

public async Task<Leaderboard?> GetLeaderboard(long id)
{
return await _applicationContext.Leaderboards.FindAsync(id);
}

public async Task<Leaderboard?> GetLeaderboardBySlug(string slug)
{
return await _applicationContext.Leaderboards
public async Task<Leaderboard?> GetLeaderboardBySlug(string slug) =>
await applicationContext.Leaderboards
.AsNoTracking()
.FirstOrDefaultAsync(x => x.Slug == slug);
}

// FIXME: Paginate this
public async Task<List<Leaderboard>> 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();
}
}

public async Task CreateLeaderboard(Leaderboard leaderboard)
{
_applicationContext.Leaderboards.Add(leaderboard);
await _applicationContext.SaveChangesAsync();
applicationContext.Leaderboards.Add(leaderboard);
await applicationContext.SaveChangesAsync();
}
}

0 comments on commit 4c5bedf

Please sign in to comment.