Same treatment as AlbumApplicationResponse, but Track is the cleaner
case: OwnerUserId (local-only) and ExternalId (external-only) are
both genuinely exclusive to one side, so the base carries neither and
is abstract — every real value is one of the two derived types.
TrackApplicationResponse (abstract, shared fields + FromEntity dispatch)
LocalTrackApplicationResponse (+ OwnerUserId)
ExternalTrackApplicationResponse (+ ExternalId)
Hit a real gotcha along the way: the response already had an explicit
Source property, which collides with the "source" discriminator STJ's
polymorphism support injects ("contains property 'source' that
conflicts with an existing metadata property name" — only surfaced at
runtime in the Api integration tests, not at build time). Fixed by
dropping the now-redundant explicit Source field entirely; the
discriminator already serializes the identical "Local"/"YouTube"
value under the same name, so the wire contract is unchanged. Updated
the two call sites that read .Source directly (TrackSearchItemResponse
and a playlist track filter that needed flatMap instead of
filter().map() to keep the narrowing across the chain).
52 lines
1.9 KiB
C#
52 lines
1.9 KiB
C#
using Musify.Application.Tests.TestSupport;
|
|
using Musify.Application.Tracks.Responses;
|
|
using Musify.Domain.Entities;
|
|
using Xunit;
|
|
|
|
namespace Musify.Application.Tests.Shared
|
|
{
|
|
public sealed class TrackApplicationResponseTests
|
|
{
|
|
[Fact]
|
|
public void FromEntity_LocalTrack_UsesOwnerNameAsArtist()
|
|
{
|
|
var owner = TestEntities.User(1, "The Owner");
|
|
var track = TestEntities.LocalTrack(owner);
|
|
|
|
var response = Assert.IsType<LocalTrackApplicationResponse>(TrackApplicationResponse.FromEntity(track, listensCount: 3));
|
|
|
|
Assert.Equal("The Owner", response.Artist);
|
|
Assert.Equal(owner.Id, response.OwnerUserId);
|
|
Assert.Equal(3, response.ListensCount);
|
|
}
|
|
|
|
[Fact]
|
|
public void FromEntity_ExternalTrackWithArtists_JoinsThemInPositionOrder()
|
|
{
|
|
var track = TestEntities.ExternalTrack();
|
|
var second = TestEntities.Artist("Second Artist", externalId: "second");
|
|
var first = TestEntities.Artist("First Artist", externalId: "first");
|
|
track.TrackArtists =
|
|
[
|
|
new TrackArtist { TrackId = track.Id, ArtistId = second.Id, Position = 1, Artist = second, Track = track },
|
|
new TrackArtist { TrackId = track.Id, ArtistId = first.Id, Position = 0, Artist = first, Track = track }
|
|
];
|
|
|
|
var response = Assert.IsType<ExternalTrackApplicationResponse>(TrackApplicationResponse.FromEntity(track, listensCount: 0));
|
|
|
|
Assert.Equal("First Artist, Second Artist", response.Artist);
|
|
Assert.Equal(track.ExternalId, response.ExternalId);
|
|
}
|
|
|
|
[Fact]
|
|
public void FromEntity_ExternalTrackWithNoArtists_HasNullArtist()
|
|
{
|
|
var track = TestEntities.ExternalTrack();
|
|
|
|
var response = TrackApplicationResponse.FromEntity(track, listensCount: 0);
|
|
|
|
Assert.Null(response.Artist);
|
|
}
|
|
}
|
|
}
|