153 lines
6.7 KiB
TypeScript
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();
|
|
}
|
|
});
|
|
});
|
|
});
|