This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206import { test, expect, beforeAll, afterAll, beforeEach, afterEach } from "bun:test";import { setupTestDb, teardownTestDb } from "db/test-utils";import * as dbschema from "db/schema";import type { BlobRef } from "db/schema";import { createRouter } from "../index";import { faker } from "@faker-js/faker";import { fakeDid, fakeCid, fakeTid, fakeBlobRef } from "shared/factories";import type { XRPCRouter } from "@atcute/xrpc-server";
let db: Awaited<ReturnType<typeof setupTestDb>>;let txDb: typeof db;let rollback: () => void;
beforeAll(async () => { db = await setupTestDb();});
afterAll(async () => { await teardownTestDb();});
beforeEach(async () => { await new Promise<void>((resolveSetup) => { let rejectTx: (err: Error) => void; db.transaction(async (tx) => { txDb = tx as unknown as typeof db; resolveSetup(); await new Promise<void>((_, reject) => { rejectTx = reject; }); }).catch(() => {}); rollback = () => rejectTx(new Error("rollback")); });});
afterEach(() => { rollback();});
const COLLECTION = "ca.ansxor.catnip.track";
async function insertTrack( db: typeof txDb, overrides?: { did?: `did:${string}:${string}`; rkey?: string; cid?: string; title?: string; audio?: BlobRef; artists?: { did?: string; name?: string }[]; },) { const did = overrides?.did ?? fakeDid(); const rkey = overrides?.rkey ?? fakeTid(); const uri = `at://${did}/${COLLECTION}/${rkey}`; const cid = overrides?.cid ?? fakeCid(); const title = overrides?.title ?? faker.music.songName(); const audio = overrides?.audio ?? fakeBlobRef();
await db.insert(dbschema.tracks).values({ uri, did, rkey, cid, title, createdAt: new Date(), audio, });
const artists = overrides?.artists ?? [{ did, name: faker.person.fullName() }]; for (let i = 0; i < artists.length; i++) { const a = artists[i]!; const [inserted] = await db .insert(dbschema.artists) .values({ did: a.did ?? null, name: a.name ?? null }) .onConflictDoNothing() .returning();
const artistId = inserted?.id ?? (await db.query.artists.findFirst({ where: (art, { eq }) => eq(art.did, a.did!), }))!.id;
await db.insert(dbschema.trackArtists).values({ trackUri: uri, artistId, position: i, }); }
return { uri, did, rkey, cid, title, audio };}
function makeRouter() { return createRouter(txDb);}
async function fetchTracks(router: XRPCRouter, uris: string[]) { const url = new URL("http://localhost/xrpc/ca.ansxor.catnip.getTracks"); for (const uri of uris) { url.searchParams.append("uris", uri); } return router.fetch(new Request(url, { method: "GET" }));}
async function fetchTracksByDid(router: XRPCRouter, did: string) { const url = new URL("http://localhost/xrpc/ca.ansxor.catnip.getTracksByDid"); url.searchParams.set("did", did); return router.fetch(new Request(url, { method: "GET" }));}
test("returns a track by URI", async () => { const title = faker.music.songName(); const artistName = faker.person.fullName(); const did = fakeDid(); const { uri } = await insertTrack(txDb, { did, title, artists: [{ did, name: artistName }], });
const router = makeRouter(); const response = await fetchTracks(router, [uri]); expect(response.status).toBe(200);
const data = await response.json(); expect(data.tracks).toHaveLength(1);
const track = data.tracks[0]; expect(track.title).toBe(title); expect(track.$type).toBe("ca.ansxor.catnip.track"); expect(track.artists).toHaveLength(1); expect(track.artists[0].did).toBe(did); expect(track.artists[0].name).toBe(artistName); expect(track.audio).toBeDefined();});
test("returns empty array for unknown URIs", async () => { const router = makeRouter(); const response = await fetchTracks(router, [ `at://${fakeDid()}/${COLLECTION}/${fakeTid()}`, ]); expect(response.status).toBe(200);
const data = await response.json(); expect(data.tracks).toHaveLength(0);});
test("returns multiple tracks", async () => { const { uri: uri1 } = await insertTrack(txDb, { title: "Track One" }); const { uri: uri2 } = await insertTrack(txDb, { title: "Track Two" });
const router = makeRouter(); const response = await fetchTracks(router, [uri1, uri2]); expect(response.status).toBe(200);
const data = await response.json(); expect(data.tracks).toHaveLength(2);
const titles = data.tracks.map((t: any) => t.title).sort(); expect(titles).toEqual(["Track One", "Track Two"]);});
// getTracksByDid tests
test("getTracksByDid returns tracks for a given DID", async () => { const did = fakeDid(); await insertTrack(txDb, { did, title: "DID Track 1" }); await insertTrack(txDb, { did, title: "DID Track 2" });
const router = makeRouter(); const response = await fetchTracksByDid(router, did); expect(response.status).toBe(200);
const data = await response.json(); expect(data.tracks).toHaveLength(2);
const titles = data.tracks.map((t: any) => t.title).sort(); expect(titles).toEqual(["DID Track 1", "DID Track 2"]);});
test("getTracksByDid returns empty array for unknown DID", async () => { const router = makeRouter(); const response = await fetchTracksByDid(router, fakeDid()); expect(response.status).toBe(200);
const data = await response.json(); expect(data.tracks).toHaveLength(0);});
test("getTracksByDid only returns tracks from the specified DID", async () => { const did1 = fakeDid(); const did2 = fakeDid(); await insertTrack(txDb, { did: did1, title: "User 1 Track" }); await insertTrack(txDb, { did: did2, title: "User 2 Track" });
const router = makeRouter(); const response = await fetchTracksByDid(router, did1); expect(response.status).toBe(200);
const data = await response.json(); expect(data.tracks).toHaveLength(1); expect(data.tracks[0].title).toBe("User 1 Track");});