Ability to heart and star tracks whilst playing

Ability to heart and star tracks whilst playing
This commit is contained in:
Simon J
2021-10-07 15:57:09 +11:00
committed by GitHub
parent a02b8c1ecd
commit 8f3d2bddf7
28 changed files with 1739 additions and 861 deletions

View File

@@ -151,6 +151,7 @@ export function aTrack(fields: Partial<Track> = {}): Track {
const id = uuid();
const artist = anArtist();
const genre = fields.genre || randomGenre();
const rating = { love: false, stars: Math.floor(Math.random() * 5) };
return {
id,
name: `Track ${id}`,
@@ -163,9 +164,10 @@ export function aTrack(fields: Partial<Track> = {}): Track {
anAlbum({ artistId: artist.id, artistName: artist.name, genre })
),
coverArt: `coverArt:${uuid()}`,
rating,
...fields,
};
}
};
export function anAlbum(fields: Partial<Album> = {}): Album {
const id = uuid();

View File

@@ -175,8 +175,8 @@ describe("InMemoryMusicService", () => {
describe("fetching tracks for an album", () => {
it("should return only tracks on that album", async () => {
expect(await musicLibrary.tracks(artist1Album1.id)).toEqual([
track1,
track2,
{ ...track1, rating: { love: false, stars: 0 } },
{ ...track2, rating: { love: false, stars: 0 } },
]);
});
});
@@ -192,7 +192,7 @@ describe("InMemoryMusicService", () => {
describe("fetching a single track", () => {
describe("when it exists", () => {
it("should return the track", async () => {
expect(await musicLibrary.track(track3.id)).toEqual(track3);
expect(await musicLibrary.track(track3.id)).toEqual({ ...track3, rating: { love: false, stars: 0 } },);
});
});
});
@@ -221,7 +221,10 @@ describe("InMemoryMusicService", () => {
],
});
const artist2 = anArtist({ name: "artist2", albums: [artist2_album1] });
const artist3 = anArtist({ name: "artist3", albums: [artist3_album1, artist3_album2] });
const artist3 = anArtist({
name: "artist3",
albums: [artist3_album1, artist3_album2],
});
const artistWithNoAlbums = anArtist({ albums: [] });
const allAlbums = [artist1, artist2, artist3, artistWithNoAlbums].flatMap(
@@ -258,7 +261,7 @@ describe("InMemoryMusicService", () => {
});
expect(albums.total).toEqual(totalAlbumCount);
expect(albums.results.length).toEqual(3)
expect(albums.results.length).toEqual(3);
// cannot really assert the results and they will change every time
});
});
@@ -282,9 +285,9 @@ describe("InMemoryMusicService", () => {
albumToAlbumSummary(artist1_album3),
albumToAlbumSummary(artist1_album4),
albumToAlbumSummary(artist1_album5),
albumToAlbumSummary(artist2_album1),
albumToAlbumSummary(artist3_album1),
albumToAlbumSummary(artist3_album2),
],
@@ -302,13 +305,11 @@ describe("InMemoryMusicService", () => {
type: "alphabeticalByName",
})
).toEqual({
results:
_.sortBy(allAlbums, 'name').map(albumToAlbumSummary),
results: _.sortBy(allAlbums, "name").map(albumToAlbumSummary),
total: totalAlbumCount,
});
});
});
});
describe("fetching a page", () => {

View File

@@ -22,6 +22,7 @@ import {
albumToAlbumSummary,
Track,
Genre,
Rating,
} from "../src/music_service";
export class InMemoryMusicService implements MusicService {
@@ -75,9 +76,11 @@ export class InMemoryMusicService implements MusicService {
switch (q.type) {
case "alphabeticalByArtist":
return artist2Album;
case "alphabeticalByName":
return artist2Album.sort((a, b) => a.album.name.localeCompare(b.album.name));
case "byGenre":
case "alphabeticalByName":
return artist2Album.sort((a, b) =>
a.album.name.localeCompare(b.album.name)
);
case "byGenre":
return artist2Album.filter(
(it) => it.album.genre?.id === q.genre
);
@@ -107,18 +110,21 @@ export class InMemoryMusicService implements MusicService {
A.map((it) => O.fromNullable(it.genre)),
A.compact,
A.uniq(fromEquals((x, y) => x.id === y.id)),
A.sort(
fromCompare<Genre>((x, y) => ordString.compare(x.id, y.id))
)
A.sort(fromCompare<Genre>((x, y) => ordString.compare(x.id, y.id)))
)
),
tracks: (albumId: string) =>
Promise.resolve(this.tracks.filter((it) => it.album.id === albumId)),
Promise.resolve(
this.tracks
.filter((it) => it.album.id === albumId)
.map((it) => ({ ...it, rating: { love: false, stars: 0 } }))
),
rate: (_: string, _2: Rating) => Promise.resolve(false),
track: (trackId: string) =>
pipe(
this.tracks.find((it) => it.id === trackId),
O.fromNullable,
O.map((it) => Promise.resolve(it)),
O.map((it) => Promise.resolve({ ...it, rating: { love: false, stars: 0 } })),
O.getOrElse(() =>
Promise.reject(`Failed to find track with id ${trackId}`)
)
@@ -139,10 +145,14 @@ export class InMemoryMusicService implements MusicService {
playlists: async () => Promise.resolve([]),
playlist: async (id: string) =>
Promise.reject(`No playlist with id ${id}`),
createPlaylist: async (_: string) => Promise.reject("Unsupported operation"),
deletePlaylist: async (_: string) => Promise.reject("Unsupported operation"),
addToPlaylist: async (_: string) => Promise.reject("Unsupported operation"),
removeFromPlaylist: async (_: string, _2: number[]) => Promise.reject("Unsupported operation"),
createPlaylist: async (_: string) =>
Promise.reject("Unsupported operation"),
deletePlaylist: async (_: string) =>
Promise.reject("Unsupported operation"),
addToPlaylist: async (_: string) =>
Promise.reject("Unsupported operation"),
removeFromPlaylist: async (_: string, _2: number[]) =>
Promise.reject("Unsupported operation"),
similarSongs: async (_: string) => Promise.resolve([]),
topSongs: async (_: string) => Promise.resolve([]),
});

View File

@@ -1668,7 +1668,7 @@ describe("server", () => {
"playlists",
"genres",
"random",
"starred",
"heart",
"recentlyAdded",
"recentlyPlayed",
"mostPlayed",

View File

@@ -24,8 +24,11 @@ import {
iconArtURI,
playlistAlbumArtURL,
sonosifyMimeType,
ratingAsInt,
ratingFromInt,
} from "../src/smapi";
import { keys as i8nKeys } from '../src/i8n';
import {
aService,
getAppLinkMessage,
@@ -54,6 +57,32 @@ import { iconForGenre } from "../src/icon";
const parseXML = (value: string) => new DOMParserImpl().parseFromString(value);
describe("rating to and from ints", () => {
describe("ratingAsInt", () => {
[
{ rating: { love: false, stars: 0 }, expectedValue: 100 },
{ rating: { love: true, stars: 0 }, expectedValue: 101 },
{ rating: { love: false, stars: 1 }, expectedValue: 110 },
{ rating: { love: true, stars: 1 }, expectedValue: 111 },
{ rating: { love: false, stars: 2 }, expectedValue: 120 },
{ rating: { love: true, stars: 2 }, expectedValue: 121 },
{ rating: { love: false, stars: 3 }, expectedValue: 130 },
{ rating: { love: true, stars: 3 }, expectedValue: 131 },
{ rating: { love: false, stars: 4 }, expectedValue: 140 },
{ rating: { love: true, stars: 4 }, expectedValue: 141 },
{ rating: { love: false, stars: 5 }, expectedValue: 150 },
{ rating: { love: true, stars: 5 }, expectedValue: 151 },
].forEach(({ rating, expectedValue }) => {
it(`should map ${JSON.stringify(rating)} to a ${expectedValue} and back`, () => {
const actualValue = ratingAsInt(rating);
expect(actualValue).toEqual(expectedValue);
expect(ratingFromInt(actualValue)).toEqual(rating);
});
});
});
});
describe("service config", () => {
const bonobWithNoContextPath = url("http://localhost:1234");
const bonobWithContextPath = url("http://localhost:5678/some-context-path");
@@ -72,18 +101,18 @@ describe("service config", () => {
pathname: PRESENTATION_MAP_ROUTE,
});
async function fetchStringsXml() {
const res = await request(server).get(stringsUrl.path()).send();
expect(res.status).toEqual(200);
// removing the sonos xml ns as makes xpath queries with xpath-ts painful
return parseXML(
res.text.replace('xmlns="http://sonos.com/sonosapi"', "")
);
}
describe(STRINGS_ROUTE, () => {
async function fetchStringsXml() {
const res = await request(server).get(stringsUrl.path()).send();
expect(res.status).toEqual(200);
// removing the sonos xml ns as makes xpath queries with xpath-ts painful
return parseXML(
res.text.replace('xmlns="http://sonos.com/sonosapi"', "")
);
}
it("should return xml for the strings", async () => {
const xml = await fetchStringsXml();
@@ -120,15 +149,17 @@ describe("service config", () => {
});
describe(PRESENTATION_MAP_ROUTE, () => {
it("should have an ArtWorkSizeMap for all sizes recommended by sonos", async () => {
async function presentationMapXml() {
const res = await request(server).get(presentationUrl.path()).send();
expect(res.status).toEqual(200);
// removing the sonos xml ns as makes xpath queries with xpath-ts painful
const xml = parseXML(
return parseXML(
res.text.replace('xmlns="http://sonos.com/sonosapi"', "")
);
}
it("should have an ArtWorkSizeMap for all sizes recommended by sonos", async () => {
const xml = await presentationMapXml();
const imageSizeMap = (size: string) =>
xpath.select(
@@ -142,14 +173,7 @@ describe("service config", () => {
});
it("should have an BrowseIconSizeMap for all sizes recommended by sonos", async () => {
const res = await request(server).get(presentationUrl.path()).send();
expect(res.status).toEqual(200);
// removing the sonos xml ns as makes xpath queries with xpath-ts painful
const xml = parseXML(
res.text.replace('xmlns="http://sonos.com/sonosapi"', "")
);
const xml = await presentationMapXml();
const imageSizeMap = (size: string) =>
xpath.select(
@@ -161,6 +185,64 @@ describe("service config", () => {
expect(imageSizeMap(size)).toEqual(`/size/${size}`);
});
});
describe("NowPlayingRatings", () => {
it("should have Matches with propname = rating", async () => {
const xml = await presentationMapXml();
const matchElements = xpath.select(
`/Presentation/PresentationMap[@type="NowPlayingRatings"]/Match`,
xml
) as Element[];
expect(matchElements.length).toBe(12);
matchElements.forEach((match) => {
expect(match.getAttributeNode("propname")?.value).toEqual(
"rating"
);
});
});
it("should have Rating stringIds that are in strings.xml", async () => {
const xml = await presentationMapXml();
const ratingElements = xpath.select(
`/Presentation/PresentationMap[@type="NowPlayingRatings"]/Match/Ratings/Rating`,
xml
) as Element[];
expect(ratingElements.length).toBeGreaterThan(1);
ratingElements.forEach((rating) => {
const OnSuccessStringId =
rating.getAttributeNode("OnSuccessStringId")!.value;
const StringId = rating.getAttributeNode("StringId")!.value;
expect(i8nKeys()).toContain(OnSuccessStringId);
expect(i8nKeys()).toContain(StringId);
});
});
it("should have Rating Ids that are valid ratings as ints", async () => {
const xml = await presentationMapXml();
const ratingElements = xpath.select(
`/Presentation/PresentationMap[@type="NowPlayingRatings"]/Match/Ratings/Rating`,
xml
) as Element[];
expect(ratingElements.length).toBeGreaterThan(1);
ratingElements.forEach((ratingElement) => {
const rating = ratingFromInt(Math.abs(Number.parseInt(ratingElement.getAttributeNode("Id")!.value)))
expect(rating.love).toBeDefined();
expect(rating.stars).toBeGreaterThanOrEqual(0);
expect(rating.stars).toBeLessThanOrEqual(5);
});
});
});
});
});
});
@@ -264,13 +346,17 @@ describe("track", () => {
genre: { id: "genre101", name: "some genre" },
}),
artist: anArtist({ name: "great artist", id: uuid() }),
coverArt:"coverArt:887766"
coverArt: "coverArt:887766",
rating: {
love: true,
stars: 5
}
});
expect(track(bonobUrl, someTrack)).toEqual({
itemType: "track",
id: `track:${someTrack.id}`,
mimeType: 'audio/flac',
mimeType: "audio/flac",
title: someTrack.name,
trackMetadata: {
@@ -286,6 +372,14 @@ describe("track", () => {
genreId: someTrack.album.genre?.id,
trackNumber: someTrack.number,
},
dynamic: {
property: [
{
name: "rating",
value: `${ratingAsInt(someTrack.rating)}`,
},
],
},
});
});
});
@@ -328,7 +422,10 @@ describe("playlistAlbumArtURL", () => {
it("should return question mark icon", () => {
const bonobUrl = url("http://localhost:1234/context-path?search=yes");
const playlist = aPlaylist({
entries: [aTrack({ coverArt: undefined }), aTrack({ coverArt: undefined })],
entries: [
aTrack({ coverArt: undefined }),
aTrack({ coverArt: undefined }),
],
});
expect(playlistAlbumArtURL(bonobUrl, playlist).href()).toEqual(
@@ -403,7 +500,9 @@ describe("playlistAlbumArtURL", () => {
});
describe("defaultAlbumArtURI", () => {
const bonobUrl = new URLBuilder("http://bonob.example.com:8080/context?search=yes");
const bonobUrl = new URLBuilder(
"http://bonob.example.com:8080/context?search=yes"
);
describe("when there is an album coverArt", () => {
it("should use it in the image url", () => {
@@ -421,10 +520,7 @@ describe("defaultAlbumArtURI", () => {
describe("when there is no album coverArt", () => {
it("should return a vinly icon image", () => {
expect(
defaultAlbumArtURI(
bonobUrl,
anAlbum({ coverArt: undefined })
).href()
defaultAlbumArtURI(bonobUrl, anAlbum({ coverArt: undefined })).href()
).toEqual(
"http://bonob.example.com:8080/context/icon/vinyl/size/legacy?search=yes"
);
@@ -473,6 +569,7 @@ describe("api", () => {
removeFromPlaylist: jest.fn(),
scrobble: jest.fn(),
nowPlaying: jest.fn(),
rate: jest.fn(),
};
const accessTokens = {
mint: jest.fn(),
@@ -868,6 +965,18 @@ describe("api", () => {
albumArtURI: iconArtURI(bonobUrl, "albums").href(),
itemType: "albumList",
},
{
id: "randomAlbums",
title: "Random",
albumArtURI: iconArtURI(bonobUrl, "random").href(),
itemType: "albumList",
},
{
id: "favouriteAlbums",
title: "Favourites",
albumArtURI: iconArtURI(bonobUrl, "heart").href(),
itemType: "albumList",
},
{
id: "playlists",
title: "Playlists",
@@ -885,18 +994,6 @@ describe("api", () => {
albumArtURI: iconArtURI(bonobUrl, "genres").href(),
itemType: "container",
},
{
id: "randomAlbums",
title: "Random",
albumArtURI: iconArtURI(bonobUrl, "random").href(),
itemType: "albumList",
},
{
id: "starredAlbums",
title: "Starred",
albumArtURI: iconArtURI(bonobUrl, "starred").href(),
itemType: "albumList",
},
{
id: "recentlyAdded",
title: "Recently added",
@@ -955,6 +1052,18 @@ describe("api", () => {
albumArtURI: iconArtURI(bonobUrl, "albums").href(),
itemType: "albumList",
},
{
id: "randomAlbums",
title: "Willekeurig",
albumArtURI: iconArtURI(bonobUrl, "random").href(),
itemType: "albumList",
},
{
id: "favouriteAlbums",
title: "Favorieten",
albumArtURI: iconArtURI(bonobUrl, "heart").href(),
itemType: "albumList",
},
{
id: "playlists",
title: "Afspeellijsten",
@@ -972,18 +1081,6 @@ describe("api", () => {
albumArtURI: iconArtURI(bonobUrl, "genres").href(),
itemType: "container",
},
{
id: "randomAlbums",
title: "Willekeurig",
albumArtURI: iconArtURI(bonobUrl, "random").href(),
itemType: "albumList",
},
{
id: "starredAlbums",
title: "Favorieten",
albumArtURI: iconArtURI(bonobUrl, "starred").href(),
itemType: "albumList",
},
{
id: "recentlyAdded",
title: "Onlangs toegevoegd",
@@ -1568,7 +1665,7 @@ describe("api", () => {
});
});
describe("asking for starred albums", () => {
describe("asking for favourite albums", () => {
const albums = [rock2, rock1, pop2];
beforeEach(() => {
@@ -1585,7 +1682,7 @@ describe("api", () => {
};
const result = await ws.getMetadataAsync({
id: "starredAlbums",
id: "favouriteAlbums",
...paging,
});
@@ -2325,42 +2422,90 @@ describe("api", () => {
});
describe("asking for a track", () => {
it("should return the track", async () => {
const track = aTrack();
describe("that has a love", () => {
it("should return the track", async () => {
const track = aTrack();
musicLibrary.track.mockResolvedValue(track);
musicLibrary.track.mockResolvedValue(track);
const root = await ws.getExtendedMetadataAsync({
id: `track:${track.id}`,
});
const root = await ws.getExtendedMetadataAsync({
id: `track:${track.id}`,
});
expect(root[0]).toEqual({
getExtendedMetadataResult: {
mediaMetadata: {
id: `track:${track.id}`,
itemType: "track",
title: track.name,
mimeType: track.mimeType,
trackMetadata: {
artistId: `artist:${track.artist.id}`,
artist: track.artist.name,
albumId: `album:${track.album.id}`,
albumArtist: track.artist.name,
albumArtistId: `artist:${track.artist.id}`,
album: track.album.name,
genre: track.genre?.name,
genreId: track.genre?.id,
duration: track.duration,
albumArtURI: defaultAlbumArtURI(
bonobUrlWithAccessToken,
track
).href(),
trackNumber: track.number,
expect(root[0]).toEqual({
getExtendedMetadataResult: {
mediaMetadata: {
id: `track:${track.id}`,
itemType: "track",
title: track.name,
mimeType: track.mimeType,
trackMetadata: {
artistId: `artist:${track.artist.id}`,
artist: track.artist.name,
albumId: `album:${track.album.id}`,
albumArtist: track.artist.name,
albumArtistId: `artist:${track.artist.id}`,
album: track.album.name,
genre: track.genre?.name,
genreId: track.genre?.id,
duration: track.duration,
albumArtURI: defaultAlbumArtURI(
bonobUrlWithAccessToken,
track
).href(),
trackNumber: track.number,
},
dynamic: {
property: [{ name: "rating", value: `${ratingAsInt(track.rating)}` }],
},
},
},
},
});
expect(musicLibrary.track).toHaveBeenCalledWith(track.id);
});
});
describe("that does not have a love", () => {
it("should return the track", async () => {
const track = aTrack();
musicLibrary.track.mockResolvedValue(track);
const root = await ws.getExtendedMetadataAsync({
id: `track:${track.id}`,
});
expect(root[0]).toEqual({
getExtendedMetadataResult: {
mediaMetadata: {
id: `track:${track.id}`,
itemType: "track",
title: track.name,
mimeType: track.mimeType,
trackMetadata: {
artistId: `artist:${track.artist.id}`,
artist: track.artist.name,
albumId: `album:${track.album.id}`,
albumArtist: track.artist.name,
albumArtistId: `artist:${track.artist.id}`,
album: track.album.name,
genre: track.genre?.name,
genreId: track.genre?.id,
duration: track.duration,
albumArtURI: defaultAlbumArtURI(
bonobUrlWithAccessToken,
track
).href(),
trackNumber: track.number,
},
dynamic: {
property: [{ name: "rating", value: `${ratingAsInt(track.rating)}` }],
},
},
},
});
expect(musicLibrary.track).toHaveBeenCalledWith(track.id);
});
expect(musicLibrary.track).toHaveBeenCalledWith(track.id);
});
});
@@ -2471,7 +2616,7 @@ describe("api", () => {
getMediaURIResult: bonobUrl
.append({
pathname: `/stream/track/${trackId}`,
searchParams: { "bat": accessToken }
searchParams: { bat: accessToken },
})
.href(),
});
@@ -2788,6 +2933,64 @@ describe("api", () => {
});
});
describe("rateItem", () => {
let ws: Client;
beforeEach(async () => {
musicService.login.mockResolvedValue(musicLibrary);
accessTokens.mint.mockReturnValue(accessToken);
ws = await createClientAsync(`${service.uri}?wsdl`, {
endpoint: service.uri,
httpClient: supersoap(server),
});
ws.addSoapHeader({ credentials: someCredentials(authToken) });
});
describe("rating a track with a positive rating value", () => {
const trackId = "123";
const ratingIntValue = 31;
it("should give the track a love", async () => {
musicLibrary.rate.mockResolvedValue(true);
const result = await ws.rateItemAsync({
id: `track:${trackId}`,
rating: ratingIntValue,
});
expect(result[0]).toEqual({
rateItemResult: { shouldSkip: false },
});
expect(musicService.login).toHaveBeenCalledWith(authToken);
expect(accessTokens.mint).toHaveBeenCalledWith(authToken);
expect(musicLibrary.rate).toHaveBeenCalledWith(trackId, ratingFromInt(ratingIntValue));
});
});
describe("rating a track with a negative rating value", () => {
const trackId = "123";
const ratingIntValue = -20;
it("should give the track a love", async () => {
musicLibrary.rate.mockResolvedValue(true);
const result = await ws.rateItemAsync({
id: `track:${trackId}`,
rating: ratingIntValue,
});
expect(result[0]).toEqual({
rateItemResult: { shouldSkip: false },
});
expect(musicService.login).toHaveBeenCalledWith(authToken);
expect(accessTokens.mint).toHaveBeenCalledWith(authToken);
expect(musicLibrary.rate).toHaveBeenCalledWith(trackId, ratingFromInt(Math.abs(ratingIntValue)));
});
});
});
describe("setPlayedSeconds", () => {
let ws: Client;
@@ -2812,7 +3015,7 @@ describe("api", () => {
}: {
trackId: string;
secondsPlayed: number;
shouldMarkNowPlaying: boolean,
shouldMarkNowPlaying: boolean;
}) {
it("should scrobble", async () => {
musicLibrary.scrobble.mockResolvedValue(true);
@@ -2827,7 +3030,7 @@ describe("api", () => {
expect(accessTokens.mint).toHaveBeenCalledWith(authToken);
expect(musicLibrary.track).toHaveBeenCalledWith(trackId);
expect(musicLibrary.scrobble).toHaveBeenCalledWith(trackId);
if(shouldMarkNowPlaying) {
if (shouldMarkNowPlaying) {
expect(musicLibrary.nowPlaying).toHaveBeenCalledWith(trackId);
} else {
expect(musicLibrary.nowPlaying).not.toHaveBeenCalled();
@@ -2842,7 +3045,7 @@ describe("api", () => {
}: {
trackId: string;
secondsPlayed: number;
shouldMarkNowPlaying: boolean,
shouldMarkNowPlaying: boolean;
}) {
it("should scrobble", async () => {
const result = await ws.setPlayedSecondsAsync({
@@ -2855,7 +3058,7 @@ describe("api", () => {
expect(accessTokens.mint).toHaveBeenCalledWith(authToken);
expect(musicLibrary.track).toHaveBeenCalledWith(trackId);
expect(musicLibrary.scrobble).not.toHaveBeenCalled();
if(shouldMarkNowPlaying) {
if (shouldMarkNowPlaying) {
expect(musicLibrary.nowPlaying).toHaveBeenCalledWith(trackId);
} else {
expect(musicLibrary.nowPlaying).not.toHaveBeenCalled();
@@ -2871,23 +3074,43 @@ describe("api", () => {
});
describe("when the seconds played is 30 seconds", () => {
itShouldScroble({ trackId, secondsPlayed: 30, shouldMarkNowPlaying: true });
itShouldScroble({
trackId,
secondsPlayed: 30,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is > 30 seconds", () => {
itShouldScroble({ trackId, secondsPlayed: 90, shouldMarkNowPlaying: true });
itShouldScroble({
trackId,
secondsPlayed: 90,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is < 30 seconds", () => {
itShouldNotScroble({ trackId, secondsPlayed: 29, shouldMarkNowPlaying: true });
itShouldNotScroble({
trackId,
secondsPlayed: 29,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is 1 seconds", () => {
itShouldNotScroble({ trackId, secondsPlayed: 1, shouldMarkNowPlaying: true });
itShouldNotScroble({
trackId,
secondsPlayed: 1,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is 0 seconds", () => {
itShouldNotScroble({ trackId, secondsPlayed: 0, shouldMarkNowPlaying: false });
itShouldNotScroble({
trackId,
secondsPlayed: 0,
shouldMarkNowPlaying: false,
});
});
});
@@ -2899,23 +3122,43 @@ describe("api", () => {
});
describe("when the seconds played is 30 seconds", () => {
itShouldScroble({ trackId, secondsPlayed: 30, shouldMarkNowPlaying: true });
itShouldScroble({
trackId,
secondsPlayed: 30,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is > 30 seconds", () => {
itShouldScroble({ trackId, secondsPlayed: 90, shouldMarkNowPlaying: true });
itShouldScroble({
trackId,
secondsPlayed: 90,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is < 30 seconds", () => {
itShouldNotScroble({ trackId, secondsPlayed: 29, shouldMarkNowPlaying: true });
itShouldNotScroble({
trackId,
secondsPlayed: 29,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is 1 seconds", () => {
itShouldNotScroble({ trackId, secondsPlayed: 1, shouldMarkNowPlaying: true });
itShouldNotScroble({
trackId,
secondsPlayed: 1,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is 0 seconds", () => {
itShouldNotScroble({ trackId, secondsPlayed: 0, shouldMarkNowPlaying: false });
itShouldNotScroble({
trackId,
secondsPlayed: 0,
shouldMarkNowPlaying: false,
});
});
});
@@ -2927,27 +3170,51 @@ describe("api", () => {
});
describe("when the seconds played is 29 seconds", () => {
itShouldScroble({ trackId, secondsPlayed: 30, shouldMarkNowPlaying: true });
itShouldScroble({
trackId,
secondsPlayed: 30,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is > 29 seconds", () => {
itShouldScroble({ trackId, secondsPlayed: 30, shouldMarkNowPlaying: true });
itShouldScroble({
trackId,
secondsPlayed: 30,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is 10 seconds", () => {
itShouldScroble({ trackId, secondsPlayed: 10, shouldMarkNowPlaying: true });
itShouldScroble({
trackId,
secondsPlayed: 10,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is < 10 seconds", () => {
itShouldNotScroble({ trackId, secondsPlayed: 9, shouldMarkNowPlaying: true });
itShouldNotScroble({
trackId,
secondsPlayed: 9,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is 1 seconds", () => {
itShouldNotScroble({ trackId, secondsPlayed: 1, shouldMarkNowPlaying: true });
itShouldNotScroble({
trackId,
secondsPlayed: 1,
shouldMarkNowPlaying: true,
});
});
describe("when the seconds played is 0 seconds", () => {
itShouldNotScroble({ trackId, secondsPlayed: 0, shouldMarkNowPlaying: false });
itShouldNotScroble({
trackId,
secondsPlayed: 0,
shouldMarkNowPlaying: false,
});
});
});
});

File diff suppressed because it is too large Load Diff