Skip to content

Commit 2aa5162

Browse files
✅ Add Last.fm fixture contract (#468)
1 parent 3a931ec commit 2aa5162

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

src/api/last-fm.spec.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { config } from "@anandchowdhary/cosmic";
2+
import LastFm from "@toplast/lastfm";
3+
import dayjs from "dayjs";
4+
import { readFileSync } from "fs";
5+
import { join } from "path";
6+
import { integrationConfig, write } from "../common";
7+
8+
jest.mock("@anandchowdhary/cosmic", () => ({
9+
config: jest.fn(),
10+
cosmicSync: jest.fn(),
11+
}));
12+
jest.mock("@toplast/lastfm", () => jest.fn());
13+
jest.mock("../common", () => ({
14+
integrationConfig: jest.fn(),
15+
write: jest.fn(),
16+
}));
17+
18+
const mockedConfig = config as jest.MockedFunction<typeof config>;
19+
const mockedLastFm = LastFm as unknown as jest.Mock;
20+
const mockedIntegrationConfig = integrationConfig as jest.MockedFunction<typeof integrationConfig>;
21+
const mockedWrite = write as jest.MockedFunction<typeof write>;
22+
const fixture = () => JSON.parse(readFileSync(join(__dirname, "..", "fixtures", "last-fm", "recent-tracks.json"), "utf8"));
23+
24+
describe("Last.fm history", () => {
25+
beforeEach(() => {
26+
jest.clearAllMocks();
27+
jest.useFakeTimers().setSystemTime(new Date("2026-09-07T12:00:00Z"));
28+
mockedConfig.mockImplementation((key: string) => {
29+
if (key === "lastfmApiKey") return "fixture-api-key";
30+
if (key === "lastfmUsername") return "fixture-user";
31+
return undefined;
32+
});
33+
mockedIntegrationConfig.mockImplementation((service: string, key: string) => service === "last-fm" && key === "history");
34+
});
35+
36+
afterEach(() => jest.useRealTimers());
37+
38+
test("requests a configured day and writes the provider response to the v2 history path", async () => {
39+
const getRecentTracks = jest.fn().mockResolvedValue(fixture());
40+
mockedLastFm.mockImplementation(() => ({ user: { getRecentTracks } }));
41+
const LastDotFm = require("./last-fm").default;
42+
const requestedDate = dayjs();
43+
const trackDate = dayjs(Number(fixture().recenttracks.track[0].date.uts) * 1000);
44+
45+
await new LastDotFm().update();
46+
47+
expect(mockedLastFm).toHaveBeenCalledWith("fixture-api-key");
48+
expect(getRecentTracks).toHaveBeenNthCalledWith(1, {
49+
limit: 50,
50+
page: 1,
51+
user: "fixture-user",
52+
from: requestedDate.startOf("day").unix(),
53+
to: requestedDate.endOf("day").unix(),
54+
});
55+
expect(mockedWrite).toHaveBeenCalledWith(
56+
`data/last-fm-music/daily/${trackDate.format("YYYY/MM/DD")}/listening-history.json`,
57+
JSON.stringify(fixture().recenttracks.track, null, 2)
58+
);
59+
});
60+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"recenttracks": {
3+
"track": [
4+
{
5+
"artist": { "#text": "Fixture Artist", "mbid": "" },
6+
"album": { "#text": "Fixture Album", "mbid": "" },
7+
"name": "Fixture Track",
8+
"date": { "uts": "1788775200", "#text": "07 Sep 2026, 10:00" },
9+
"url": "https://www.last.fm/music/Fixture+Artist/_/Fixture+Track"
10+
}
11+
]
12+
}
13+
}

0 commit comments

Comments
 (0)