feat(routing): add ReleaseRoutes.DetailHref resolver; repoint release click sites and add /tracks/{id} redirect (P11 W2 §2)
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
using DeepDrftModels.DTOs;
|
||||
using DeepDrftModels.Enums;
|
||||
using DeepDrftPublic.Client.Common;
|
||||
|
||||
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).
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class ReleaseRoutesTests
|
||||
{
|
||||
[TestCase(ReleaseMedium.Cut, "/cuts/42")]
|
||||
[TestCase(ReleaseMedium.Session, "/sessions/42")]
|
||||
[TestCase(ReleaseMedium.Mix, "/mixes/42")]
|
||||
public void DetailHref_ResolvesEachMediumToItsDedicatedRoute(ReleaseMedium medium, string expected)
|
||||
{
|
||||
Assert.That(ReleaseRoutes.DetailHref(42, medium), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[TestCase(ReleaseMedium.Cut, "/cuts/7")]
|
||||
[TestCase(ReleaseMedium.Session, "/sessions/7")]
|
||||
[TestCase(ReleaseMedium.Mix, "/mixes/7")]
|
||||
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 };
|
||||
|
||||
Assert.That(ReleaseRoutes.DetailHref(release), Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetailHref_NonCutMediaNeverResolveToTheCutDefaultArm()
|
||||
{
|
||||
// The switch routes Cut via the default arm, so a new medium added without its own arm would
|
||||
// silently fall through to /cuts. This pins every non-Cut medium to a distinct, non-/cuts
|
||||
// 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);
|
||||
Assert.That(href, Does.Not.StartWith("/cuts/"),
|
||||
$"Medium {medium} fell through to the Cut default arm ('{href}') — it needs its own route.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user