66 lines
3.6 KiB
C#
66 lines
3.6 KiB
C#
using System.Security.Claims;
|
|
using System.Text;
|
|
using JobTrackerApi.Controllers;
|
|
using JobTrackerApi.Data;
|
|
using JobTrackerApi.Models;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Xunit;
|
|
|
|
namespace JobTrackerApi.MariaDb.Tests;
|
|
|
|
public sealed class DashboardGeometryPersistenceTests
|
|
{
|
|
private const string Geometry = "{\"version\":2,\"revision\":0,\"widgets\":[{\"id\":\"attention\",\"visible\":false,\"size\":\"standard\",\"x\":4,\"y\":17,\"w\":8,\"h\":10}]}";
|
|
private static AuthController Controller(JobTrackerContext db, string body, string owner = "rd21-owner")
|
|
{
|
|
var http = new DefaultHttpContext { User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, owner) }, "test")) };
|
|
http.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body));
|
|
return new(new ConfigurationBuilder().Build(), null!, null!, null!, null!, null!, null!, null!, db)
|
|
{ ControllerContext = new() { HttpContext = http } };
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Geometry_is_durable_owner_scoped_and_stale_or_legacy_writes_preserve_other_preferences()
|
|
{
|
|
await using var database = await MariaDbDatabase.CreateAsync();
|
|
await using (var seed = database.Context())
|
|
{
|
|
seed.Users.AddRange(new ApplicationUser { Id = "rd21-owner", UserName = "geometry", UiLanguage = "nb-NO" }, new ApplicationUser { Id = "other", UserName = "untouched" });
|
|
await seed.SaveChangesAsync();
|
|
}
|
|
await using (var write = database.Context())
|
|
Assert.IsType<OkObjectResult>(await Controller(write, Geometry).UpdateDashboardPreference(default));
|
|
await using var verify = database.Context();
|
|
var owner = await verify.Users.AsNoTracking().SingleAsync(u => u.Id == "rd21-owner");
|
|
var saved = DashboardLayout.Read(owner.DashboardLayoutJson, owner.DashboardLayoutRevision);
|
|
Assert.Equal(1, saved.Revision);
|
|
Assert.Equal(new DashboardWidget("attention", false, "standard", 4, 17, 8, 10), Assert.Single(saved.Widgets));
|
|
Assert.Equal("nb-NO", owner.UiLanguage);
|
|
Assert.Null((await verify.Users.AsNoTracking().SingleAsync(u => u.Id == "other")).DashboardLayoutJson);
|
|
Assert.IsType<ConflictObjectResult>(await Controller(verify, Geometry).UpdateDashboardPreference(default));
|
|
Assert.IsType<ConflictObjectResult>(await Controller(verify, "{\"version\":1,\"revision\":1,\"widgets\":[]}").UpdateDashboardPreference(default));
|
|
Assert.Equal(owner.DashboardLayoutJson, (await verify.Users.AsNoTracking().SingleAsync(u => u.Id == owner.Id)).DashboardLayoutJson);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Concurrent_geometry_saves_have_one_winner_and_one_conflict()
|
|
{
|
|
await using var database = await MariaDbDatabase.CreateAsync();
|
|
await using (var seed = database.Context())
|
|
{
|
|
seed.Users.Add(new() { Id = "rd21-owner", UserName = "concurrent-geometry" });
|
|
await seed.SaveChangesAsync();
|
|
}
|
|
await using var first = database.Context();
|
|
await using var second = database.Context();
|
|
var results = await Task.WhenAll(Controller(first, Geometry).UpdateDashboardPreference(default), Controller(second, Geometry.Replace("\"h\":10", "\"h\":12")).UpdateDashboardPreference(default));
|
|
Assert.Single(results.OfType<OkObjectResult>());
|
|
Assert.Single(results.OfType<ConflictObjectResult>());
|
|
await using var readback = database.Context();
|
|
Assert.Equal(1, (await readback.Users.SingleAsync()).DashboardLayoutRevision);
|
|
}
|
|
}
|