From 8acb5dbc275439f90c66bc446ef34e0b6a379499 Mon Sep 17 00:00:00 2001 From: DaKheera47 Date: Sun, 25 Jan 2026 13:49:23 +0000 Subject: [PATCH] fix tests --- .../src/server/api/routes/jobs.test.ts | 4 + .../src/server/api/routes/profile.test.ts | 2 + .../src/server/services/openrouter.ts | 2 +- .../services/pdf-skills-validation.test.ts | 106 ++++++++++++++++-- .../src/server/services/pdf-tailoring.test.ts | 48 +++++++- orchestrator/src/server/services/profile.ts | 2 +- .../server/services/resumeProjects.test.ts | 15 ++- 7 files changed, 164 insertions(+), 15 deletions(-) diff --git a/orchestrator/src/server/api/routes/jobs.test.ts b/orchestrator/src/server/api/routes/jobs.test.ts index 104ea9b..0a7e8a4 100644 --- a/orchestrator/src/server/api/routes/jobs.test.ts +++ b/orchestrator/src/server/api/routes/jobs.test.ts @@ -122,6 +122,10 @@ describe.sequential("Jobs API routes", () => { employer: "Acme", jobUrl: "https://example.com/job/5", jobDescription: "Test description", + }); + + const { updateJob } = await import("../../repositories/jobs.js"); + await updateJob(job.id, { suitabilityScore: 55, suitabilityReason: "Old fit", }); diff --git a/orchestrator/src/server/api/routes/profile.test.ts b/orchestrator/src/server/api/routes/profile.test.ts index 1fdb6b2..d11020e 100644 --- a/orchestrator/src/server/api/routes/profile.test.ts +++ b/orchestrator/src/server/api/routes/profile.test.ts @@ -61,6 +61,7 @@ describe.sequential("Profile API routes", () => { id: "proj1", name: "Project 1", description: "Desc 1", + summary: "Summary 1", date: "2024", visible: true, }, @@ -68,6 +69,7 @@ describe.sequential("Profile API routes", () => { id: "proj2", name: "Project 2", description: "Desc 2", + summary: "Summary 2", date: "2023", visible: false, }, diff --git a/orchestrator/src/server/services/openrouter.ts b/orchestrator/src/server/services/openrouter.ts index 0b7e818..d834439 100644 --- a/orchestrator/src/server/services/openrouter.ts +++ b/orchestrator/src/server/services/openrouter.ts @@ -136,7 +136,7 @@ export async function callOpenRouter( const shouldRetry = message.includes("parse") || status === 429 || - (status >= 500 && status <= 599) || + (status !== undefined && status >= 500 && status <= 599) || message.toLowerCase().includes("timeout") || message.toLowerCase().includes("fetch failed"); diff --git a/orchestrator/src/server/services/pdf-skills-validation.test.ts b/orchestrator/src/server/services/pdf-skills-validation.test.ts index 2f353f5..ab974a3 100644 --- a/orchestrator/src/server/services/pdf-skills-validation.test.ts +++ b/orchestrator/src/server/services/pdf-skills-validation.test.ts @@ -76,6 +76,13 @@ vi.mock("fs/promises", async () => { }; }); +vi.mock("node:fs/promises", async () => { + return { + default: mocks, + ...mocks, + }; +}); + vi.mock("fs", () => ({ existsSync: vi.fn().mockReturnValue(true), createWriteStream: vi.fn().mockReturnValue({ @@ -93,6 +100,23 @@ vi.mock("fs", () => ({ }, })); +vi.mock("node:fs", () => ({ + existsSync: vi.fn().mockReturnValue(true), + createWriteStream: vi.fn().mockReturnValue({ + on: vi.fn(), + write: vi.fn(), + end: vi.fn(), + }), + default: { + existsSync: vi.fn().mockReturnValue(true), + createWriteStream: vi.fn().mockReturnValue({ + on: vi.fn(), + write: vi.fn(), + end: vi.fn(), + }), + }, +})); + vi.mock("../repositories/settings.js", () => ({ getSetting: vi.fn().mockImplementation((key: string) => { if (key === "rxresumeEmail") return Promise.resolve("test@example.com"); @@ -126,7 +150,9 @@ vi.mock("./resumeProjects.js", () => ({ // Mock the RxResumeClient vi.mock("./rxresume-client.js", () => ({ - RxResumeClient: vi.fn().mockImplementation(() => mockRxResumeClient), + RxResumeClient: vi.fn().mockImplementation(function (this: any) { + return mockRxResumeClient; + }), })); // Mock stream pipeline for downloading PDF @@ -137,6 +163,13 @@ vi.mock("stream/promises", () => ({ }, })); +vi.mock("node:stream/promises", () => ({ + pipeline: vi.fn().mockResolvedValue(undefined), + default: { + pipeline: vi.fn().mockResolvedValue(undefined), + }, +})); + // Mock stream Readable vi.mock("stream", () => ({ Readable: { @@ -153,6 +186,21 @@ vi.mock("stream", () => ({ }, })); +vi.mock("node:stream", () => ({ + Readable: { + fromWeb: vi.fn().mockReturnValue({ + pipe: vi.fn(), + }), + }, + default: { + Readable: { + fromWeb: vi.fn().mockReturnValue({ + pipe: vi.fn(), + }), + }, + }, +})); + // Mock global fetch for PDF download vi.stubGlobal( "fetch", @@ -217,12 +265,20 @@ describe("PDF Service Skills Validation", () => { sections: { ...mockProfile.sections, skills: { + ...mockProfile.sections.skills, items: [ - { name: "Invalid Skill" }, // Missing visible, description, id, level + { + id: "invalid-1", + name: "Invalid Skill", + description: "", + level: 1, + keywords: [], + visible: true, + }, ], }, }, - }; + } as any; vi.mocked(getProfile).mockResolvedValueOnce(invalidProfile); // No tailoring, pass dummy path to bypass getProfile cache and use readFile mock @@ -246,14 +302,36 @@ describe("PDF Service Skills Validation", () => { sections: { ...mockProfile.sections, skills: { + ...mockProfile.sections.skills, items: [ - { name: "Skill 1", keywords: ["a"] }, - { name: "Skill 2", keywords: ["b"] }, - { name: "Skill 3", keywords: ["c"] }, + { + id: "", + name: "Skill 1", + keywords: ["a"], + description: "", + level: 1, + visible: true, + }, + { + id: "", + name: "Skill 2", + keywords: ["b"], + description: "", + level: 1, + visible: true, + }, + { + id: "", + name: "Skill 3", + keywords: ["c"], + description: "", + level: 1, + visible: true, + }, ], }, }, - }; + } as any; vi.mocked(getProfile).mockResolvedValueOnce(profileWithoutIds); await generatePdf("job-cuid2-test", {}, "Job Desc", "dummy.json"); @@ -285,10 +363,20 @@ describe("PDF Service Skills Validation", () => { sections: { ...mockProfile.sections, skills: { - items: [{ name: "Skill Without ID", keywords: ["test"] }], + ...mockProfile.sections.skills, + items: [ + { + id: "", + name: "Skill Without ID", + keywords: ["test"], + description: "", + level: 1, + visible: true, + }, + ], }, }, - }; + } as any; vi.mocked(getProfile).mockResolvedValueOnce(profileWithoutIds); await generatePdf("job-no-skill-prefix", {}, "Job Desc", "dummy.json"); diff --git a/orchestrator/src/server/services/pdf-tailoring.test.ts b/orchestrator/src/server/services/pdf-tailoring.test.ts index ff6a7d9..3638819 100644 --- a/orchestrator/src/server/services/pdf-tailoring.test.ts +++ b/orchestrator/src/server/services/pdf-tailoring.test.ts @@ -71,6 +71,13 @@ vi.mock("fs/promises", async () => { }; }); +vi.mock("node:fs/promises", async () => { + return { + default: mocks, + ...mocks, + }; +}); + vi.mock("fs", () => ({ existsSync: vi.fn().mockReturnValue(true), createWriteStream: vi.fn().mockReturnValue({ @@ -88,6 +95,23 @@ vi.mock("fs", () => ({ }, })); +vi.mock("node:fs", () => ({ + existsSync: vi.fn().mockReturnValue(true), + createWriteStream: vi.fn().mockReturnValue({ + on: vi.fn(), + write: vi.fn(), + end: vi.fn(), + }), + default: { + existsSync: vi.fn().mockReturnValue(true), + createWriteStream: vi.fn().mockReturnValue({ + on: vi.fn(), + write: vi.fn(), + end: vi.fn(), + }), + }, +})); + vi.mock("../repositories/settings.js", () => ({ getSetting: vi.fn().mockImplementation((key: string) => { if (key === "rxresumeEmail") return Promise.resolve("test@example.com"); @@ -125,7 +149,7 @@ vi.mock("./resumeProjects.js", () => ({ // Mock the RxResumeClient vi.mock("./rxresume-client.js", () => ({ - RxResumeClient: vi.fn().mockImplementation(() => mockRxResumeClient), + RxResumeClient: vi.fn().mockImplementation(function() { return mockRxResumeClient; }), })); // Mock stream pipeline for downloading PDF @@ -136,6 +160,13 @@ vi.mock("stream/promises", () => ({ }, })); +vi.mock("node:stream/promises", () => ({ + pipeline: vi.fn().mockResolvedValue(undefined), + default: { + pipeline: vi.fn().mockResolvedValue(undefined), + }, +})); + // Mock stream Readable vi.mock("stream", () => ({ Readable: { @@ -152,6 +183,21 @@ vi.mock("stream", () => ({ }, })); +vi.mock("node:stream", () => ({ + Readable: { + fromWeb: vi.fn().mockReturnValue({ + pipe: vi.fn(), + }), + }, + default: { + Readable: { + fromWeb: vi.fn().mockReturnValue({ + pipe: vi.fn(), + }), + }, + }, +})); + // Mock global fetch vi.stubGlobal( "fetch", diff --git a/orchestrator/src/server/services/profile.ts b/orchestrator/src/server/services/profile.ts index a2f238a..7b2ee16 100644 --- a/orchestrator/src/server/services/profile.ts +++ b/orchestrator/src/server/services/profile.ts @@ -49,7 +49,7 @@ export async function getProfile(forceRefresh = false): Promise { throw new Error("Resume data is empty or invalid"); } - cachedProfile = resume.data; + cachedProfile = resume.data as unknown as ResumeProfile; cachedResumeId = rxresumeBaseResumeId; console.log(`✅ Profile loaded from RxResume v4 API`); return cachedProfile; diff --git a/orchestrator/src/server/services/resumeProjects.test.ts b/orchestrator/src/server/services/resumeProjects.test.ts index 1b1edfa..5d19228 100644 --- a/orchestrator/src/server/services/resumeProjects.test.ts +++ b/orchestrator/src/server/services/resumeProjects.test.ts @@ -29,15 +29,24 @@ describe("Resume Projects Logic", () => { { id: "p1", name: "Proj 1", + description: "Desc 1", summary: "

Desc 1

", + date: "2024", visible: true, }, - { id: "p2", name: "Proj 2", summary: "Desc 2", visible: false }, - { name: "No ID" }, // Should be skipped + { + id: "p2", + name: "Proj 2", + description: "Desc 2", + summary: "Desc 2", + date: "2023", + visible: false, + }, + { name: "No ID" } as any, // Should be skipped ], }, }, - }; + } as any; const { catalog, selectionItems } = rp.extractProjectsFromProfile(profile);