feat(release): front int PK with app-minted GUID EntryKey on the public addressing surface (P11 W5, 11.H)

This commit is contained in:
daniel-c-harvey
2026-06-16 17:11:55 -04:00
parent fe28573b68
commit f07d29cdcf
37 changed files with 627 additions and 160 deletions
+19 -15
View File
@@ -6,31 +6,35 @@ namespace DeepDrftTests;
/// <summary>
/// The medium→detail-route table is the single source of truth for release navigation (Phase 11
/// §2): Archive cards, AlbumsView cards, the player-bar title, and the /tracks/{id} redirect page
/// all resolve through <see cref="ReleaseRoutes.DetailHref(long, ReleaseMedium)"/>. These tests pin
/// each medium to its dedicated route and confirm the DTO overload (the call shape used everywhere
/// but the redirect page) agrees with the primitive overload (the shape the redirect page uses
/// after fetching the release by id).
/// §2, §3e): Archive cards, AlbumsView cards, the player-bar title, and the /tracks/{entryKey}
/// redirect page all resolve through <see cref="ReleaseRoutes.DetailHref(string, ReleaseMedium)"/>.
/// The route now carries the release's opaque public EntryKey (a GUID string), never the int PK.
/// These tests pin each medium to its dedicated route and confirm the DTO overload (the call shape
/// used everywhere but the redirect page) agrees with the primitive overload (the shape the redirect
/// page uses after fetching the release by EntryKey).
/// </summary>
[TestFixture]
public class ReleaseRoutesTests
{
[TestCase(ReleaseMedium.Cut, "/cuts/42")]
[TestCase(ReleaseMedium.Session, "/sessions/42")]
[TestCase(ReleaseMedium.Mix, "/mixes/42")]
private const string Key = "9f8a3c2e-key";
[TestCase(ReleaseMedium.Cut, "/cuts/9f8a3c2e-key")]
[TestCase(ReleaseMedium.Session, "/sessions/9f8a3c2e-key")]
[TestCase(ReleaseMedium.Mix, "/mixes/9f8a3c2e-key")]
public void DetailHref_ResolvesEachMediumToItsDedicatedRoute(ReleaseMedium medium, string expected)
{
Assert.That(ReleaseRoutes.DetailHref(42, medium), Is.EqualTo(expected));
Assert.That(ReleaseRoutes.DetailHref(Key, medium), Is.EqualTo(expected));
}
[TestCase(ReleaseMedium.Cut, "/cuts/7")]
[TestCase(ReleaseMedium.Session, "/sessions/7")]
[TestCase(ReleaseMedium.Mix, "/mixes/7")]
[TestCase(ReleaseMedium.Cut, "/cuts/9f8a3c2e-key")]
[TestCase(ReleaseMedium.Session, "/sessions/9f8a3c2e-key")]
[TestCase(ReleaseMedium.Mix, "/mixes/9f8a3c2e-key")]
public void DetailHref_DtoOverload_AgreesWithPrimitiveOverload(ReleaseMedium medium, string expected)
{
// The redirect page resolves a fetched ReleaseDto through this overload; every other call
// site does too. It must produce the same route as the (id, medium) primitive.
var release = new ReleaseDto { Id = 7, Medium = medium };
// site does too. It must read EntryKey and produce the same route as the (entryKey, medium)
// primitive — a regression to release.Id here would re-expose the transparent int (§3e).
var release = new ReleaseDto { EntryKey = Key, Medium = medium };
Assert.That(ReleaseRoutes.DetailHref(release), Is.EqualTo(expected));
}
@@ -43,7 +47,7 @@ public class ReleaseRoutesTests
// route — a fourth medium lacking a route arm fails here rather than mis-routing to /cuts.
foreach (var medium in Enum.GetValues<ReleaseMedium>().Where(m => m != ReleaseMedium.Cut))
{
var href = ReleaseRoutes.DetailHref(1, medium);
var href = ReleaseRoutes.DetailHref(Key, medium);
Assert.That(href, Does.Not.StartWith("/cuts/"),
$"Medium {medium} fell through to the Cut default arm ('{href}') — it needs its own route.");
}