Cover shared zod schemas, extract traversal/refs/downloads, and tts filename/error handling. Document the test setup in the README and docs.
135 lines
3.2 KiB
TypeScript
135 lines
3.2 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
assetRefSchema,
|
|
extractedObjectSchema,
|
|
itemIdSchema,
|
|
searchQuerySchema,
|
|
searchResultSchema,
|
|
workshopItemSchema,
|
|
} from './schemas.js';
|
|
|
|
describe('itemIdSchema', () => {
|
|
it('accepts a run of digits', () => {
|
|
expect(itemIdSchema.parse('123456')).toBe('123456');
|
|
});
|
|
|
|
it('rejects empty strings', () => {
|
|
expect(itemIdSchema.safeParse('').success).toBe(false);
|
|
});
|
|
|
|
it('rejects non-numeric input', () => {
|
|
expect(itemIdSchema.safeParse('abc').success).toBe(false);
|
|
expect(itemIdSchema.safeParse('12a34').success).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('searchQuerySchema', () => {
|
|
it('coerces page to a number and defaults it', () => {
|
|
expect(searchQuerySchema.parse({ q: 'cards' })).toEqual({
|
|
q: 'cards',
|
|
page: 1,
|
|
});
|
|
expect(searchQuerySchema.parse({ q: 'cards', page: '3' })).toEqual({
|
|
q: 'cards',
|
|
page: 3,
|
|
});
|
|
});
|
|
|
|
it('rejects a missing or blank query', () => {
|
|
expect(searchQuerySchema.safeParse({}).success).toBe(false);
|
|
expect(searchQuerySchema.safeParse({ q: ' ' }).success).toBe(false);
|
|
});
|
|
|
|
it('rejects a non-positive page', () => {
|
|
expect(searchQuerySchema.safeParse({ q: 'cards', page: 0 }).success).toBe(
|
|
false,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('assetRefSchema', () => {
|
|
it('accepts a valid ref', () => {
|
|
const ref = {
|
|
kind: 'pdf',
|
|
url: 'https://example.com/doc.pdf',
|
|
ownerGuid: 'abc',
|
|
};
|
|
expect(assetRefSchema.parse(ref)).toEqual(ref);
|
|
});
|
|
|
|
it('rejects an invalid URL', () => {
|
|
expect(
|
|
assetRefSchema.safeParse({
|
|
kind: 'pdf',
|
|
url: 'not-a-url',
|
|
ownerGuid: 'abc',
|
|
}).success,
|
|
).toBe(false);
|
|
});
|
|
|
|
it('rejects an unknown kind', () => {
|
|
expect(
|
|
assetRefSchema.safeParse({
|
|
kind: 'video',
|
|
url: 'https://example.com/a.mp4',
|
|
ownerGuid: 'abc',
|
|
}).success,
|
|
).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('extractedObjectSchema', () => {
|
|
it('accepts a minimal object', () => {
|
|
const obj = {
|
|
guid: 'g1',
|
|
name: 'Card',
|
|
type: 'Card',
|
|
childrenGuids: [],
|
|
refs: [],
|
|
};
|
|
expect(extractedObjectSchema.parse(obj)).toEqual(obj);
|
|
});
|
|
|
|
it('accepts optional parentGuid', () => {
|
|
const obj = {
|
|
guid: 'g1',
|
|
name: 'Card',
|
|
type: 'Card',
|
|
parentGuid: 'g0',
|
|
childrenGuids: ['g2'],
|
|
refs: [],
|
|
};
|
|
expect(extractedObjectSchema.parse(obj).parentGuid).toBe('g0');
|
|
});
|
|
});
|
|
|
|
describe('workshopItemSchema', () => {
|
|
it('accepts a full item', () => {
|
|
const item = {
|
|
id: '1',
|
|
title: 'Deck',
|
|
author: 'someone',
|
|
previewImageUrl: 'https://example.com/p.png',
|
|
tags: ['card'],
|
|
timeCreated: 123,
|
|
};
|
|
expect(workshopItemSchema.parse(item)).toEqual(item);
|
|
});
|
|
|
|
it('accepts a minimal item', () => {
|
|
const item = {
|
|
id: '1',
|
|
title: 'Deck',
|
|
author: 'someone',
|
|
previewImageUrl: 'https://example.com/p.png',
|
|
};
|
|
expect(workshopItemSchema.parse(item)).toEqual(item);
|
|
});
|
|
});
|
|
|
|
describe('searchResultSchema', () => {
|
|
it('accepts an empty result set', () => {
|
|
const result = { items: [], page: 1, hasMore: false };
|
|
expect(searchResultSchema.parse(result)).toEqual(result);
|
|
});
|
|
}); |