Files
Reactive-Resume/packages/api/src/features/documents/service.test.ts
T
Amruth Pillai 9a803305c8 fix: address verified v6 app findings
Fix authentication recovery, account imports, application tracking, resume
editing and exports, sharing, API contracts, provider selection, and private
local attachments. Preserve authored content during PDF pagination.

Update guides, generated OpenAPI output, and translation catalogs to match
verified behavior and documented constraints.

Validation: 1,019 tests passed; 12 database/OAuth integration tests skipped.
Ten affected package typechecks, production build, Biome, and package
boundaries passed.
2026-09-30 06:15:09 +02:00

97 lines
3.7 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const dbMock = vi.hoisted(() => ({ select: vi.fn(), update: vi.fn() }));
const resumeServiceMock = vi.hoisted(() => ({
getById: vi.fn(),
create: vi.fn(),
delete: vi.fn(),
setLocked: vi.fn(),
}));
const applicationServiceMock = vi.hoisted(() => ({ update: vi.fn() }));
vi.mock("@reactive-resume/db/client", () => ({ db: dbMock }));
vi.mock("../resume/service", () => ({ resumeService: resumeServiceMock }));
vi.mock("../cover-letters/service", () => ({ linkLetterApplication: vi.fn() }));
vi.mock("../applications/service", () => ({ applicationService: applicationServiceMock }));
const { documentsService } = await import("./service");
// `select().from().where()` resolving to `rows`.
const rows = (result: unknown[]) => ({ from: () => ({ where: () => Promise.resolve(result) }) });
const updates = () => {
const set = vi.fn((_changes: Record<string, unknown>) => ({
where: () => Promise.resolve(),
}));
dbMock.update.mockReturnValue({ set });
return set;
};
beforeEach(() => {
for (const mock of [
...Object.values(dbMock),
...Object.values(resumeServiceMock),
...Object.values(applicationServiceMock),
])
mock.mockReset();
});
describe("Trash", () => {
it("won't move a locked document, and keeps the resume's error code", async () => {
dbMock.select.mockReturnValueOnce(rows([{ isLocked: true, trashedAt: null }]));
await expect(documentsService.trash({ userId: "u1", type: "resume", id: "r1" })).rejects.toMatchObject({
code: "RESUME_LOCKED",
status: 403,
});
expect(dbMock.update).not.toHaveBeenCalled();
});
it("deletes for good only what is already in Trash", async () => {
dbMock.select.mockReturnValueOnce(rows([{ isLocked: false, trashedAt: null }]));
await expect(documentsService.purge({ userId: "u1", type: "resume", id: "r1" })).rejects.toMatchObject({
code: "BAD_REQUEST",
});
dbMock.select.mockReturnValueOnce(rows([{ isLocked: false, trashedAt: new Date() }]));
await documentsService.purge({ userId: "u1", type: "resume", id: "r1" });
expect(resumeServiceMock.delete).toHaveBeenCalledWith({ id: "r1", userId: "u1" });
});
});
describe("copyForJob", () => {
const source = {
name: "Product Designer — Lumen",
tags: ["design"],
data: { metadata: { page: { locale: "en-US" } } },
};
it("links the copy to the job, and gives the job the copy when it has no resume", async () => {
resumeServiceMock.getById.mockResolvedValueOnce(source);
dbMock.select.mockReturnValueOnce(rows([{ id: "a1", company: "Orbital", resumeId: null }]));
resumeServiceMock.create.mockResolvedValueOnce("copy");
const set = updates();
const id = await documentsService.copyForJob({ userId: "u1", resumeId: "r1", applicationId: "a1" });
expect(id).toBe("copy");
expect(resumeServiceMock.create).toHaveBeenCalledWith(
expect.objectContaining({ name: "Product Designer — Orbital", tags: ["design"] }),
);
expect(set).toHaveBeenCalledWith({ applicationId: "a1" });
expect(applicationServiceMock.update).toHaveBeenCalledWith({ userId: "u1", id: "a1", resumeId: "copy" });
});
it("leaves an application's existing resume alone", async () => {
resumeServiceMock.getById.mockResolvedValueOnce(source);
dbMock.select.mockReturnValueOnce(rows([{ id: "a1", company: "Orbital", resumeId: "base" }]));
resumeServiceMock.create.mockResolvedValueOnce("copy");
const set = updates();
await documentsService.copyForJob({ userId: "u1", resumeId: "r1", applicationId: "a1", name: "Mine" });
expect(resumeServiceMock.create).toHaveBeenCalledWith(expect.objectContaining({ name: "Mine" }));
expect(set).toHaveBeenCalledTimes(1);
expect(applicationServiceMock.update).not.toHaveBeenCalled();
});
});