Jobber/orchestrator/src/shared/rxresume-schema.test.ts
Anas Syed 263ff8adcc fix CUID2 test
Added missing mock for validateAndRepairJson to prevent validation from blocking tests
2026-01-22 20:28:42 +00:00

153 lines
6.7 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { createId } from '@paralleldrive/cuid2';
import { idSchema, skillSchema, resumeDataSchema } from './rxresume-schema.js';
describe('RxResume Schema Validation', () => {
describe('idSchema (CUID2)', () => {
it('should accept valid CUID2 IDs generated by the library', () => {
// Generate real CUID2 IDs using the official library
const validIds = [
createId(),
createId(),
createId(),
];
validIds.forEach(id => {
const result = idSchema.safeParse(id);
expect(result.success, `ID "${id}" should be valid`).toBe(true);
});
});
it('should reject invalid IDs like "skill-0"', () => {
const invalidIds = [
'skill-0', // contains hyphen
'skill-1', // contains hyphen
'skill-123', // contains hyphen
'item_1', // contains underscore
'ABC123', // uppercase letters
'', // empty
];
invalidIds.forEach(id => {
const result = idSchema.safeParse(id);
expect(result.success, `ID "${id}" should be invalid`).toBe(false);
});
});
});
describe('skillSchema', () => {
it('should accept valid skill with CUID2 ID', () => {
const validSkill = {
id: createId(),
visible: true,
name: 'JavaScript',
description: '',
level: 3,
keywords: ['ES6', 'TypeScript'],
};
const result = skillSchema.safeParse(validSkill);
expect(result.success).toBe(true);
});
it('should reject skill with invalid ID format', () => {
const invalidSkill = {
id: 'skill-0', // Invalid CUID2
visible: true,
name: 'JavaScript',
description: '',
level: 3,
keywords: ['ES6'],
};
const result = skillSchema.safeParse(invalidSkill);
expect(result.success).toBe(false);
if (!result.success) {
expect(result.error.issues[0].path).toContain('id');
expect(result.error.issues[0].message).toContain('cuid2');
}
});
});
describe('resumeDataSchema', () => {
it('should reject resume with invalid skill IDs', () => {
const resumeWithInvalidIds = {
basics: {
name: 'John Doe',
headline: 'Developer',
email: 'john@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: [
{
id: 'skill-0', // Invalid!
visible: true,
name: 'JavaScript',
description: '',
level: 1,
keywords: [],
},
],
},
// Minimal required sections
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: '',
},
};
const result = resumeDataSchema.safeParse(resumeWithInvalidIds);
expect(result.success).toBe(false);
if (!result.success) {
// Should have error about the skill ID
const idError = result.error.issues.find(
issue => issue.path.join('.').includes('skills.items') && issue.path.includes('id')
);
expect(idError).toBeDefined();
}
});
});
});