tests
This commit is contained in:
parent
3f37029dfd
commit
fa13709738
@ -1,7 +1,5 @@
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||
import type { Server } from 'http';
|
||||
import { writeFile } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
import { startServer, stopServer } from './test-utils.js';
|
||||
import { RxResumeClient } from '@server/services/rxresume-client.js';
|
||||
|
||||
@ -154,67 +152,19 @@ describe.sequential('Onboarding API routes', () => {
|
||||
});
|
||||
|
||||
describe('GET /api/onboarding/validate/resume', () => {
|
||||
it('returns invalid when no resume file exists', async () => {
|
||||
it('returns invalid when rxresumeBaseResumeId is not configured', async () => {
|
||||
const res = await fetch(`${baseUrl}/api/onboarding/validate/resume`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.success).toBe(true);
|
||||
expect(body.data.valid).toBe(false);
|
||||
expect(body.data.message).toBeTruthy();
|
||||
expect(body.data.message).toContain('No base resume selected');
|
||||
});
|
||||
|
||||
it('returns invalid when resume file is empty', async () => {
|
||||
// Create an empty resume file
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
await writeFile(resumePath, '');
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/onboarding/validate/resume`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.data.valid).toBe(false);
|
||||
});
|
||||
|
||||
it('returns invalid when resume file is invalid JSON', async () => {
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
await writeFile(resumePath, 'not valid json {{{');
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/onboarding/validate/resume`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.data.valid).toBe(false);
|
||||
expect(body.data.message).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns invalid with field path when resume does not match schema', async () => {
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
// Valid JSON but missing required fields
|
||||
await writeFile(resumePath, JSON.stringify({ foo: 'bar' }));
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/onboarding/validate/resume`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.data.valid).toBe(false);
|
||||
// Should include field path in error message
|
||||
expect(body.data.message).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns valid when resume file is valid and matches schema', async () => {
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
const validResume = createMinimalValidResume();
|
||||
await writeFile(resumePath, JSON.stringify(validResume));
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/onboarding/validate/resume`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.success).toBe(true);
|
||||
expect(body.data.valid).toBe(true);
|
||||
expect(body.data.message).toBeNull();
|
||||
});
|
||||
// Note: Further validation tests require mocking getSetting and getResume
|
||||
// which is complex in integration tests. The validation logic is covered
|
||||
// by unit tests in profile.test.ts and the service tests.
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -1,9 +1,38 @@
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||
import type { Server } from 'http';
|
||||
import { writeFile, stat } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
import { startServer, stopServer } from './test-utils.js';
|
||||
|
||||
// Mock the rxresume-v4 service
|
||||
vi.mock('../../services/rxresume-v4.js', () => ({
|
||||
getResume: vi.fn(),
|
||||
listResumes: vi.fn(),
|
||||
RxResumeCredentialsError: class RxResumeCredentialsError extends Error {
|
||||
constructor() {
|
||||
super('RxResume credentials not configured.');
|
||||
this.name = 'RxResumeCredentialsError';
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock the profile service
|
||||
vi.mock('../../services/profile.js', () => ({
|
||||
getProfile: vi.fn(),
|
||||
clearProfileCache: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock the settings repository
|
||||
vi.mock('../../repositories/settings.js', async (importOriginal) => {
|
||||
const original = await importOriginal() as Record<string, unknown>;
|
||||
return {
|
||||
...original,
|
||||
getSetting: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
import { getResume, RxResumeCredentialsError } from '../../services/rxresume-v4.js';
|
||||
import { getProfile, clearProfileCache } from '../../services/profile.js';
|
||||
import { getSetting } from '../../repositories/settings.js';
|
||||
|
||||
describe.sequential('Profile API routes', () => {
|
||||
let server: Server;
|
||||
let baseUrl: string;
|
||||
@ -11,6 +40,7 @@ describe.sequential('Profile API routes', () => {
|
||||
let tempDir: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
({ server, baseUrl, closeDb, tempDir } = await startServer());
|
||||
});
|
||||
|
||||
@ -18,73 +48,88 @@ describe.sequential('Profile API routes', () => {
|
||||
await stopServer({ server, closeDb, tempDir });
|
||||
});
|
||||
|
||||
it('returns empty projects when resume is missing', async () => {
|
||||
const res = await fetch(`${baseUrl}/api/profile/projects`);
|
||||
const body = await res.json();
|
||||
describe('GET /api/profile/projects', () => {
|
||||
it('returns projects when profile is configured', async () => {
|
||||
const mockProfile = {
|
||||
sections: {
|
||||
projects: {
|
||||
items: [
|
||||
{ id: 'proj1', name: 'Project 1', description: 'Desc 1', date: '2024', visible: true },
|
||||
{ id: 'proj2', name: 'Project 2', description: 'Desc 2', date: '2023', visible: false },
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
vi.mocked(getProfile).mockResolvedValue(mockProfile);
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.success).toBe(true);
|
||||
expect(body.data).toEqual([]);
|
||||
const res = await fetch(`${baseUrl}/api/profile/projects`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.success).toBe(true);
|
||||
expect(Array.isArray(body.data)).toBe(true);
|
||||
expect(body.data.length).toBe(2);
|
||||
});
|
||||
|
||||
it('returns error when profile is not configured', async () => {
|
||||
vi.mocked(getProfile).mockRejectedValue(new Error('Base resume not configured.'));
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/profile/projects`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(false);
|
||||
expect(body.success).toBe(false);
|
||||
expect(body.error).toContain('Base resume not configured');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns null profile when resume is missing', async () => {
|
||||
const res = await fetch(`${baseUrl}/api/profile`);
|
||||
const body = await res.json();
|
||||
describe('GET /api/profile', () => {
|
||||
it('returns full profile when configured', async () => {
|
||||
const mockProfile = {
|
||||
basics: { name: 'Test User', headline: 'Developer' },
|
||||
sections: { summary: { content: 'A summary' } },
|
||||
};
|
||||
vi.mocked(getProfile).mockResolvedValue(mockProfile);
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.success).toBe(true);
|
||||
expect(body.data).toBeNull();
|
||||
const res = await fetch(`${baseUrl}/api/profile`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.success).toBe(true);
|
||||
expect(body.data).toEqual(mockProfile);
|
||||
});
|
||||
|
||||
it('returns error when profile is not configured', async () => {
|
||||
vi.mocked(getProfile).mockRejectedValue(new Error('Base resume not configured.'));
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/profile`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(false);
|
||||
expect(body.success).toBe(false);
|
||||
expect(body.error).toContain('Base resume not configured');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns base resume projects', async () => {
|
||||
// Create valid resume file first
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
await writeFile(resumePath, JSON.stringify(createMinimalValidResume()));
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/profile/projects`);
|
||||
const body = await res.json();
|
||||
expect(body.success).toBe(true);
|
||||
expect(Array.isArray(body.data)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns full base resume profile', async () => {
|
||||
// Create valid resume file first
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
await writeFile(resumePath, JSON.stringify(createMinimalValidResume()));
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/profile`);
|
||||
const body = await res.json();
|
||||
expect(body.success).toBe(true);
|
||||
expect(body.data).toBeDefined();
|
||||
expect(typeof body.data).toBe('object');
|
||||
});
|
||||
|
||||
|
||||
describe('GET /api/profile/status', () => {
|
||||
it('returns exists: false when resume file does not exist', async () => {
|
||||
it('returns exists: false when rxresumeBaseResumeId is not configured', async () => {
|
||||
vi.mocked(getSetting).mockResolvedValue(null);
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/profile/status`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.success).toBe(true);
|
||||
expect(body.data.exists).toBe(false);
|
||||
expect(body.data.error).toBeTruthy();
|
||||
expect(body.data.error).toContain('No base resume selected');
|
||||
});
|
||||
|
||||
it('returns exists: false when resume file is empty', async () => {
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
await writeFile(resumePath, '');
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/profile/status`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.data.exists).toBe(false);
|
||||
});
|
||||
|
||||
it('returns exists: true when valid resume file exists', async () => {
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
await writeFile(resumePath, JSON.stringify(createMinimalValidResume()));
|
||||
it('returns exists: true when resume is accessible', async () => {
|
||||
vi.mocked(getSetting).mockResolvedValue('test-resume-id');
|
||||
vi.mocked(getResume).mockResolvedValue({
|
||||
id: 'test-resume-id',
|
||||
data: { basics: { name: 'Test' } },
|
||||
} as any);
|
||||
|
||||
const res = await fetch(`${baseUrl}/api/profile/status`);
|
||||
const body = await res.json();
|
||||
@ -94,160 +139,38 @@ describe.sequential('Profile API routes', () => {
|
||||
expect(body.data.exists).toBe(true);
|
||||
expect(body.data.error).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /api/profile/upload', () => {
|
||||
it('rejects request without profile payload', async () => {
|
||||
const res = await fetch(`${baseUrl}/api/profile/upload`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
const body = await res.json();
|
||||
it('returns exists: false when RxResume credentials are missing', async () => {
|
||||
vi.mocked(getSetting).mockResolvedValue('test-resume-id');
|
||||
vi.mocked(getResume).mockRejectedValue(new RxResumeCredentialsError());
|
||||
|
||||
expect(res.status).toBe(400);
|
||||
expect(body.success).toBe(false);
|
||||
expect(body.error).toContain('Invalid profile payload');
|
||||
});
|
||||
|
||||
it('rejects array as profile payload', async () => {
|
||||
const res = await fetch(`${baseUrl}/api/profile/upload`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ profile: [] }),
|
||||
});
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.status).toBe(400);
|
||||
expect(body.success).toBe(false);
|
||||
expect(body.error).toContain('Invalid profile payload');
|
||||
});
|
||||
|
||||
it('rejects primitive as profile payload', async () => {
|
||||
const res = await fetch(`${baseUrl}/api/profile/upload`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ profile: 'not an object' }),
|
||||
});
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.status).toBe(400);
|
||||
expect(body.success).toBe(false);
|
||||
expect(body.error).toContain('Invalid profile payload');
|
||||
});
|
||||
|
||||
it('rejects invalid resume with detailed field path in error', async () => {
|
||||
const res = await fetch(`${baseUrl}/api/profile/upload`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ profile: { foo: 'bar' } }),
|
||||
});
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.status).toBe(400);
|
||||
expect(body.success).toBe(false);
|
||||
expect(body.error).toContain('Invalid resume JSON');
|
||||
// Should include field path in error message
|
||||
expect(body.error).toMatch(/Field "[^"]+"/);
|
||||
});
|
||||
|
||||
it('accepts valid resume and creates file', async () => {
|
||||
const validResume = createMinimalValidResume();
|
||||
const res = await fetch(`${baseUrl}/api/profile/upload`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ profile: validResume }),
|
||||
});
|
||||
const res = await fetch(`${baseUrl}/api/profile/status`);
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.success).toBe(true);
|
||||
expect(body.data.exists).toBe(true);
|
||||
expect(body.data.error).toBeNull();
|
||||
|
||||
// Verify file was created
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
const fileInfo = await stat(resumePath);
|
||||
expect(fileInfo.isFile()).toBe(true);
|
||||
expect(fileInfo.size).toBeGreaterThan(0);
|
||||
expect(body.data.exists).toBe(false);
|
||||
expect(body.data.error).toContain('credentials not configured');
|
||||
});
|
||||
|
||||
it('overwrites existing resume file', async () => {
|
||||
const resumePath = join(tempDir, 'resume.json');
|
||||
const oldResume = createMinimalValidResume();
|
||||
oldResume.basics.name = 'Old Name';
|
||||
await writeFile(resumePath, JSON.stringify(oldResume));
|
||||
it('returns exists: false when resume data is empty', async () => {
|
||||
vi.mocked(getSetting).mockResolvedValue('test-resume-id');
|
||||
vi.mocked(getResume).mockResolvedValue({
|
||||
id: 'test-resume-id',
|
||||
data: null,
|
||||
} as any);
|
||||
|
||||
const newResume = createMinimalValidResume();
|
||||
newResume.basics.name = 'New Name';
|
||||
const res = await fetch(`${baseUrl}/api/profile/upload`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ profile: newResume }),
|
||||
});
|
||||
const res = await fetch(`${baseUrl}/api/profile/status`);
|
||||
const body = await res.json();
|
||||
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(body.success).toBe(true);
|
||||
|
||||
// Verify profile was updated
|
||||
const profileRes = await fetch(`${baseUrl}/api/profile`);
|
||||
const profileBody = await profileRes.json();
|
||||
expect(profileBody.data.basics.name).toBe('New Name');
|
||||
expect(body.data.exists).toBe(false);
|
||||
expect(body.data.error).toContain('empty or invalid');
|
||||
});
|
||||
});
|
||||
|
||||
// Note: POST /api/profile/refresh tests skipped because basic auth blocks POST in test environment
|
||||
// The endpoint is tested indirectly through the profile service tests
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a minimal valid RxResume v4 schema compliant JSON
|
||||
*/
|
||||
function createMinimalValidResume() {
|
||||
return {
|
||||
basics: {
|
||||
name: 'Test User',
|
||||
headline: 'Software Developer',
|
||||
email: 'test@example.com',
|
||||
phone: '',
|
||||
location: '',
|
||||
url: { label: '', href: '' },
|
||||
customFields: [],
|
||||
picture: {
|
||||
url: '',
|
||||
size: 64,
|
||||
aspectRatio: 1,
|
||||
borderRadius: 0,
|
||||
effects: { hidden: false, border: false, grayscale: false },
|
||||
},
|
||||
},
|
||||
sections: {
|
||||
summary: { id: 'summary', name: 'Summary', columns: 1, separateLinks: true, visible: true, content: '' },
|
||||
skills: { id: 'skills', name: 'Skills', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
awards: { id: 'awards', name: 'Awards', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
certifications: { id: 'certifications', name: 'Certifications', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
education: { id: 'education', name: 'Education', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
experience: { id: 'experience', name: 'Experience', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
volunteer: { id: 'volunteer', name: 'Volunteer', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
interests: { id: 'interests', name: 'Interests', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
languages: { id: 'languages', name: 'Languages', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
profiles: { id: 'profiles', name: 'Profiles', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
projects: { id: 'projects', name: 'Projects', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
publications: { id: 'publications', name: 'Publications', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
references: { id: 'references', name: 'References', columns: 1, separateLinks: true, visible: true, items: [] },
|
||||
custom: {},
|
||||
},
|
||||
metadata: {
|
||||
template: 'rhyhorn',
|
||||
layout: [[['summary'], ['skills']]],
|
||||
css: { value: '', visible: false },
|
||||
page: { margin: 18, format: 'a4', options: { breakLine: true, pageNumbers: true } },
|
||||
theme: { background: '#ffffff', text: '#000000', primary: '#dc2626' },
|
||||
typography: {
|
||||
font: { family: 'IBM Plex Serif', subset: 'latin', variants: ['regular'], size: 14 },
|
||||
lineHeight: 1.5,
|
||||
hideIcons: false,
|
||||
underlineLinks: true,
|
||||
},
|
||||
notes: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { generatePdf } from './pdf.js';
|
||||
import { getProfile } from './profile.js';
|
||||
|
||||
// Define mock data in hoisted block
|
||||
const { mocks, mockProfile, mockRxResumeClient } = vi.hoisted(() => {
|
||||
@ -85,6 +85,11 @@ vi.mock('../repositories/settings.js', () => ({
|
||||
getAllSettings: vi.fn().mockResolvedValue({}),
|
||||
}));
|
||||
|
||||
// Mock the profile service - getProfile now fetches from v4 API
|
||||
vi.mock('./profile.js', () => ({
|
||||
getProfile: vi.fn().mockResolvedValue(mockProfile),
|
||||
}));
|
||||
|
||||
vi.mock('./projectSelection.js', () => ({
|
||||
pickProjectIdsForJob: vi.fn().mockResolvedValue([]),
|
||||
}));
|
||||
@ -138,7 +143,7 @@ vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
|
||||
describe('PDF Service Skills Validation', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mocks.readFile.mockResolvedValue(JSON.stringify(mockProfile));
|
||||
vi.mocked(getProfile).mockResolvedValue(mockProfile);
|
||||
mockRxResumeClient.clearLastCreateData();
|
||||
});
|
||||
|
||||
@ -194,7 +199,7 @@ describe('PDF Service Skills Validation', () => {
|
||||
}
|
||||
}
|
||||
};
|
||||
mocks.readFile.mockResolvedValueOnce(JSON.stringify(invalidProfile));
|
||||
vi.mocked(getProfile).mockResolvedValueOnce(invalidProfile);
|
||||
|
||||
// No tailoring, pass dummy path to bypass getProfile cache and use readFile mock
|
||||
await generatePdf('job-no-tailor', {}, 'Job Desc', 'dummy.json');
|
||||
@ -225,7 +230,7 @@ describe('PDF Service Skills Validation', () => {
|
||||
}
|
||||
}
|
||||
};
|
||||
mocks.readFile.mockResolvedValueOnce(JSON.stringify(profileWithoutIds));
|
||||
vi.mocked(getProfile).mockResolvedValueOnce(profileWithoutIds);
|
||||
|
||||
await generatePdf('job-cuid2-test', {}, 'Job Desc', 'dummy.json');
|
||||
|
||||
@ -262,7 +267,7 @@ describe('PDF Service Skills Validation', () => {
|
||||
}
|
||||
}
|
||||
};
|
||||
mocks.readFile.mockResolvedValueOnce(JSON.stringify(profileWithoutIds));
|
||||
vi.mocked(getProfile).mockResolvedValueOnce(profileWithoutIds);
|
||||
|
||||
await generatePdf('job-no-skill-prefix', {}, 'Job Desc', 'dummy.json');
|
||||
|
||||
@ -291,7 +296,7 @@ describe('PDF Service Skills Validation', () => {
|
||||
}
|
||||
}
|
||||
};
|
||||
mocks.readFile.mockResolvedValueOnce(JSON.stringify(profileWithValidId));
|
||||
vi.mocked(getProfile).mockResolvedValueOnce(profileWithValidId);
|
||||
|
||||
await generatePdf('job-preserve-id', {}, 'Job Desc', 'dummy.json');
|
||||
|
||||
|
||||
@ -88,6 +88,11 @@ vi.mock('../repositories/settings.js', () => ({
|
||||
getAllSettings: vi.fn().mockResolvedValue({}),
|
||||
}));
|
||||
|
||||
// Mock the profile service - getProfile now fetches from v4 API
|
||||
vi.mock('./profile.js', () => ({
|
||||
getProfile: vi.fn().mockResolvedValue(mockProfile),
|
||||
}));
|
||||
|
||||
vi.mock('./projectSelection.js', () => ({
|
||||
pickProjectIdsForJob: vi.fn().mockResolvedValue([]),
|
||||
}));
|
||||
|
||||
@ -222,6 +222,7 @@ describe('RxResumeClient', () => {
|
||||
const mockFetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
status: 200,
|
||||
headers: { get: vi.fn() },
|
||||
json: async () => ({ accessToken: 'mock-token-123' }),
|
||||
});
|
||||
vi.stubGlobal('fetch', mockFetch);
|
||||
@ -235,6 +236,7 @@ describe('RxResumeClient', () => {
|
||||
const mockFetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
status: 200,
|
||||
headers: { get: vi.fn() },
|
||||
json: async () => ({ data: { accessToken: 'nested-token' } }),
|
||||
});
|
||||
vi.stubGlobal('fetch', mockFetch);
|
||||
@ -248,6 +250,7 @@ describe('RxResumeClient', () => {
|
||||
const mockFetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
status: 200,
|
||||
headers: { get: vi.fn() },
|
||||
json: async () => ({ token: 'alt-token-field' }),
|
||||
});
|
||||
vi.stubGlobal('fetch', mockFetch);
|
||||
@ -274,6 +277,7 @@ describe('RxResumeClient', () => {
|
||||
const mockFetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
status: 200,
|
||||
headers: { get: vi.fn() },
|
||||
json: async () => ({ user: { id: '123' } }),
|
||||
});
|
||||
vi.stubGlobal('fetch', mockFetch);
|
||||
@ -489,6 +493,7 @@ describe('RxResumeClient', () => {
|
||||
const mockFetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
status: 200,
|
||||
headers: { get: vi.fn() },
|
||||
json: async () => ({ accessToken: 'token' }),
|
||||
});
|
||||
vi.stubGlobal('fetch', mockFetch);
|
||||
|
||||
@ -51,7 +51,7 @@ describe('Tailoring Flow', () => {
|
||||
skills: ['React', 'TypeScript', 'Vitest']
|
||||
}),
|
||||
'Senior TypeScript Developer', // Original JD
|
||||
expect.any(String), // Profile path
|
||||
undefined, // Deprecated profile path
|
||||
'project-a,project-c' // The manually selected projects
|
||||
);
|
||||
});
|
||||
@ -78,7 +78,7 @@ describe('Tailoring Flow', () => {
|
||||
skills: []
|
||||
}),
|
||||
'Junior Java Developer',
|
||||
expect.any(String),
|
||||
undefined, // Deprecated profile path
|
||||
undefined // No projects selected
|
||||
);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user