import { describe, expect, it, beforeAll } from "vitest"; import { appRouter } from "./routers"; import type { TrpcContext } from "./_core/context"; import * as db from "./db"; type AuthenticatedUser = NonNullable; function createAuthContext(): TrpcContext { const user: AuthenticatedUser = { id: 1, openId: "test-user", email: "test@example.com", name: "Test User", loginMethod: "manus", role: "user", createdAt: new Date(), updatedAt: new Date(), lastSignedIn: new Date(), }; const ctx: TrpcContext = { user, req: { protocol: "https", headers: {}, } as TrpcContext["req"], res: { clearCookie: () => {}, } as TrpcContext["res"], }; return ctx; } describe("tracks router", () => { let testTrackId: number; beforeAll(async () => { // Initialize demo training tracks const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); await caller.tracks.initDemo(); }); it("should initialize demo training tracks", async () => { const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); const result = await caller.tracks.initDemo(); expect(result.count).toBeGreaterThan(0); const trainingTracks = await db.getTrainingTracks(); expect(trainingTracks.length).toBeGreaterThan(0); }); it("should upload a track successfully", async () => { const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); // Create a small mock audio file (base64 encoded) const mockAudioData = Buffer.from("mock audio content").toString("base64"); const result = await caller.tracks.upload({ title: "Test AI Track", artist: "Test Artist", fileData: mockAudioData, mimeType: "audio/mpeg", fileName: "test.mp3", }); expect(result.trackId).toBeDefined(); expect(result.fileUrl).toBeDefined(); testTrackId = result.trackId; }); it("should list user tracks", async () => { const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); const tracks = await caller.tracks.list(); expect(Array.isArray(tracks)).toBe(true); expect(tracks.length).toBeGreaterThan(0); }); it("should get track details with stems and attributions", async () => { const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); // Wait a bit for async processing to start await new Promise(resolve => setTimeout(resolve, 2000)); const result = await caller.tracks.get({ id: testTrackId }); expect(result.track).toBeDefined(); expect(result.track.id).toBe(testTrackId); expect(result.track.title).toBe("Test AI Track"); expect(result.stems).toBeDefined(); expect(result.attributions).toBeDefined(); expect(result.jobs).toBeDefined(); }); it("should get attribution results for a track", async () => { const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); // Wait for processing to complete (async processing takes ~3 seconds) await new Promise(resolve => setTimeout(resolve, 4000)); const attributions = await caller.attribution.getResults({ trackId: testTrackId }); expect(Array.isArray(attributions)).toBe(true); // Should have attribution results if training tracks exist if (attributions.length > 0) { const attr = attributions[0]; expect(attr?.score).toBeGreaterThan(0); expect(attr?.score).toBeLessThanOrEqual(1); expect(attr?.method).toBeDefined(); } }, 10000); it("should throw error for non-existent track", async () => { const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); await expect(caller.tracks.get({ id: 999999 })).rejects.toThrow("Track not found"); }); });