import { describe, expect, it } from "vitest"; import type { MigrationTask } from "$lib/api/migrator"; import { migrationRows } from "./migrationRows"; const makeTask = ( id: string, jobs: { id: string; name: string; status: string; error?: string; repoDid?: string; }[] ): MigrationTask => ({ id, ownerDid: "did:plc:testuser", createdAt: "2026-09-15T10:00:00Z", jobs: jobs.map((j) => ({ id: j.id, name: j.name, knotDid: "did:plc:knot", sourceUrl: `https://github.com/test/${j.name}`, private: false, attempts: 1, status: j.status, error: j.error, repoDid: j.repoDid })) }) as MigrationTask; describe("migrationRows derivation", () => { it("empty tasks produce none", () => { expect(migrationRows([], [])).toEqual([]); expect(migrationRows()).toEqual([]); expect( migrationRows( [], [ { name: "idle-repo", migration: { status: "idle" } } ] ) ).toEqual([]); expect( migrationRows([], { 1: { name: "idle-repo", migration: { status: "idle" } } }) ).toEqual([]); }); it("tasks with no drafts produce rows (include an authorization_required job)", () => { const tasks: MigrationTask[] = [ makeTask("task-1", [ { id: "job-auth-req", name: "repo-needs-auth", status: "authorization_required", error: "credentials rejected" }, { id: "job-done", name: "repo-completed", status: "completed", repoDid: "did:plc:repo-done" } ]) ]; const rows = migrationRows(tasks, []); expect(rows).toHaveLength(2); const authRow = rows.find((r) => r.name === "repo-needs-auth"); expect(authRow).toBeDefined(); expect(authRow).toMatchObject({ id: "job-auth-req", name: "repo-needs-auth", migration: { status: "success", task: { taskId: "task-1", name: "repo-needs-auth" }, jobId: "job-auth-req", jobStatus: "authorization_required", jobError: "credentials rejected" } }); const doneRow = rows.find((r) => r.name === "repo-completed"); expect(doneRow).toBeDefined(); expect(doneRow).toMatchObject({ id: "job-done", name: "repo-completed", migration: { status: "success", task: { taskId: "task-1", name: "repo-completed" }, jobId: "job-done", jobStatus: "completed", repoDid: "did:plc:repo-done" } }); }); it("a job already covered by a draft produces exactly one row", () => { const tasks: MigrationTask[] = [ makeTask("task-1", [ { id: "job-1", name: "covered-repo", status: "cloning" }, { id: "job-2", name: "uncovered-repo", status: "queued" } ]) ]; const rowsWithJobId = migrationRows(tasks, [ { id: 101, name: "covered-repo", migration: { status: "success", task: { taskId: "task-1", name: "covered-repo" }, jobId: "job-1", jobStatus: "cloning" } } ]); expect(rowsWithJobId).toHaveLength(2); expect(rowsWithJobId.filter((r) => r.name === "covered-repo")).toHaveLength(1); expect(rowsWithJobId.filter((r) => r.name === "uncovered-repo")).toHaveLength(1); expect(rowsWithJobId.find((r) => r.name === "covered-repo")?.id).toBe(101); const rowsWithSubmitting = migrationRows(tasks, [ { id: 101, name: "covered-repo", migration: { status: "submitting" } } ]); expect(rowsWithSubmitting).toHaveLength(2); expect(rowsWithSubmitting.filter((r) => r.name === "covered-repo")).toHaveLength(1); expect(rowsWithSubmitting.find((r) => r.name === "covered-repo")?.migration.status).toBe( "submitting" ); const rowsWithRecord = migrationRows(tasks, { 101: { id: 101, name: "covered-repo", migration: { status: "success", task: { taskId: "task-1", name: "covered-repo" }, jobId: "job-1", jobStatus: "cloning" } } }); expect(rowsWithRecord).toHaveLength(2); expect(rowsWithRecord.filter((r) => r.name === "covered-repo")).toHaveLength(1); }); });