feat(documents): zod validators for folder CRUD
createFolderSchema, renameFolderSchema, moveFolderSchema, moveDocumentToFolderSchema. Names: 1–200 chars, non-whitespace. parentId/folderId nullable to allow root. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
28
src/lib/validators/document-folders.ts
Normal file
28
src/lib/validators/document-folders.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const folderName = z
|
||||
.string()
|
||||
.min(1, 'Folder name is required')
|
||||
.max(200, 'Folder name cannot exceed 200 characters')
|
||||
.refine((s) => s.trim().length > 0, 'Folder name cannot be only whitespace');
|
||||
|
||||
export const createFolderSchema = z.object({
|
||||
name: folderName,
|
||||
parentId: z.string().nullable(),
|
||||
});
|
||||
export type CreateFolderInput = z.infer<typeof createFolderSchema>;
|
||||
|
||||
export const renameFolderSchema = z.object({
|
||||
name: folderName,
|
||||
});
|
||||
export type RenameFolderInput = z.infer<typeof renameFolderSchema>;
|
||||
|
||||
export const moveFolderSchema = z.object({
|
||||
parentId: z.string().nullable(),
|
||||
});
|
||||
export type MoveFolderInput = z.infer<typeof moveFolderSchema>;
|
||||
|
||||
export const moveDocumentToFolderSchema = z.object({
|
||||
folderId: z.string().nullable(),
|
||||
});
|
||||
export type MoveDocumentToFolderInput = z.infer<typeof moveDocumentToFolderSchema>;
|
||||
42
tests/unit/document-folders-validators.test.ts
Normal file
42
tests/unit/document-folders-validators.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import {
|
||||
createFolderSchema,
|
||||
renameFolderSchema,
|
||||
moveFolderSchema,
|
||||
moveDocumentToFolderSchema,
|
||||
} from '@/lib/validators/document-folders';
|
||||
|
||||
describe('document-folder validators', () => {
|
||||
it('accepts a valid create payload', () => {
|
||||
expect(createFolderSchema.safeParse({ name: 'Deals', parentId: null }).success).toBe(true);
|
||||
expect(
|
||||
createFolderSchema.safeParse({ name: 'Q1', parentId: 'abc-123' }).success,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('rejects empty + over-long names', () => {
|
||||
expect(createFolderSchema.safeParse({ name: '', parentId: null }).success).toBe(false);
|
||||
expect(
|
||||
createFolderSchema.safeParse({ name: 'x'.repeat(201), parentId: null }).success,
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('rejects whitespace-only names', () => {
|
||||
expect(createFolderSchema.safeParse({ name: ' ', parentId: null }).success).toBe(false);
|
||||
});
|
||||
|
||||
it('rename schema requires only name', () => {
|
||||
expect(renameFolderSchema.safeParse({ name: 'New' }).success).toBe(true);
|
||||
expect(renameFolderSchema.safeParse({ name: '' }).success).toBe(false);
|
||||
});
|
||||
|
||||
it('move schema accepts null parentId', () => {
|
||||
expect(moveFolderSchema.safeParse({ parentId: null }).success).toBe(true);
|
||||
expect(moveFolderSchema.safeParse({ parentId: 'abc' }).success).toBe(true);
|
||||
});
|
||||
|
||||
it('moveDocumentToFolderSchema accepts null folderId', () => {
|
||||
expect(moveDocumentToFolderSchema.safeParse({ folderId: null }).success).toBe(true);
|
||||
expect(moveDocumentToFolderSchema.safeParse({ folderId: 'abc' }).success).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user