Fixing everything, making the project structure ready for real code.
Signed-off-by: Cliff Hill <xlorep@darkhelm.org>
This commit is contained in:
133
frontend/src/test-setup.ts
Normal file
133
frontend/src/test-setup.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Automatic Zod validation setup for test runs
|
||||
* This file sets up global hooks that automatically validate all Zod schemas during testing
|
||||
*/
|
||||
|
||||
import { beforeAll, afterAll } from 'vitest';
|
||||
import { z } from 'zod';
|
||||
|
||||
// Store original Zod parse methods
|
||||
const originalParse = z.ZodType.prototype.parse;
|
||||
const originalSafeParse = z.ZodType.prototype.safeParse;
|
||||
|
||||
let validationCount = 0;
|
||||
let validationErrors: string[] = [];
|
||||
|
||||
/**
|
||||
* Enhanced parse method that logs validation attempts during tests
|
||||
* @param data - The data to validate against the schema
|
||||
* @returns The parsed and validated data
|
||||
*/
|
||||
function enhancedParse<T>(this: z.ZodType<T>, data: unknown): T {
|
||||
try {
|
||||
const result = originalParse.call(this, data);
|
||||
validationCount++;
|
||||
|
||||
// Log successful validations in test mode
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
console.log(`✅ Zod validation passed (${validationCount} total)`);
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
validationErrors.push(`Zod validation failed: ${error}`);
|
||||
|
||||
// Log failed validations in test mode
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
console.error(`❌ Zod validation failed:`, error);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhanced safeParse method that logs validation attempts during tests
|
||||
* @param data - The data to validate against the schema
|
||||
* @returns Safe parse result with success flag and data or error
|
||||
*/
|
||||
function enhancedSafeParse<T>(
|
||||
this: z.ZodType<T>,
|
||||
data: unknown
|
||||
): z.SafeParseReturnType<unknown, T> {
|
||||
const result = originalSafeParse.call(this, data);
|
||||
validationCount++;
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
if (result.success) {
|
||||
console.log(`✅ Zod safe validation passed (${validationCount} total)`);
|
||||
} else {
|
||||
console.warn(`⚠️ Zod safe validation failed but was handled gracefully`);
|
||||
validationErrors.push(`Zod safe validation failed: ${result.error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install automatic Zod validation hooks for testing
|
||||
*/
|
||||
export function installZodTestHooks(): void {
|
||||
// Replace Zod's parse methods with enhanced versions
|
||||
z.ZodType.prototype.parse = enhancedParse;
|
||||
z.ZodType.prototype.safeParse = enhancedSafeParse;
|
||||
|
||||
// Enable global auto-validation flag
|
||||
(globalThis as any).__AUTO_VALIDATE__ = true;
|
||||
|
||||
console.log('🛡️ Automatic Zod validation hooks installed for test run');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove automatic Zod validation hooks
|
||||
*/
|
||||
export function uninstallZodTestHooks(): void {
|
||||
// Restore original methods
|
||||
z.ZodType.prototype.parse = originalParse;
|
||||
z.ZodType.prototype.safeParse = originalSafeParse;
|
||||
|
||||
// Disable global auto-validation flag
|
||||
(globalThis as any).__AUTO_VALIDATE__ = false;
|
||||
|
||||
console.log('🔧 Zod validation hooks removed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get validation statistics for test reporting
|
||||
* @returns Object containing validation count and errors
|
||||
*/
|
||||
export function getValidationStats(): {
|
||||
count: number;
|
||||
errors: string[];
|
||||
} {
|
||||
return {
|
||||
count: validationCount,
|
||||
errors: [...validationErrors],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset validation statistics
|
||||
*/
|
||||
export function resetValidationStats(): void {
|
||||
validationCount = 0;
|
||||
validationErrors = [];
|
||||
}
|
||||
|
||||
// Automatic setup for Vitest
|
||||
beforeAll(() => {
|
||||
installZodTestHooks();
|
||||
resetValidationStats();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
const stats = getValidationStats();
|
||||
console.log(`📊 Test run completed with ${stats.count} Zod validations`);
|
||||
|
||||
if (stats.errors.length > 0) {
|
||||
console.warn(`⚠️ ${stats.errors.length} validation errors encountered during tests`);
|
||||
}
|
||||
|
||||
uninstallZodTestHooks();
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Hypermodern Zod validation setup - automatic runtime validation without explicit .parse() calls
|
||||
* Follows the same philosophy as typeguard for Python
|
||||
* Zod validation setup with automatic test hooks
|
||||
* Schemas are automatically validated during test runs via test-setup.ts
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
@@ -28,99 +28,3 @@ export const UserSchema = z.object({
|
||||
// Inferred types (no manual type definitions needed)
|
||||
export type Playlist = z.infer<typeof PlaylistSchema>;
|
||||
export type User = z.infer<typeof UserSchema>;
|
||||
|
||||
/**
|
||||
* Global schema registry for automatic validation
|
||||
*/
|
||||
class SchemaRegistry {
|
||||
private static schemas = new Map<string, z.ZodTypeAny>([
|
||||
['Playlist', PlaylistSchema as z.ZodTypeAny],
|
||||
['User', UserSchema as z.ZodTypeAny],
|
||||
]);
|
||||
|
||||
static register<T extends z.ZodTypeAny>(name: string, schema: T): void {
|
||||
this.schemas.set(name, schema as z.ZodTypeAny);
|
||||
}
|
||||
|
||||
static get(name: string): z.ZodTypeAny | undefined {
|
||||
return this.schemas.get(name);
|
||||
}
|
||||
|
||||
static validate<T>(typeName: string, data: unknown): T {
|
||||
const schema = this.schemas.get(typeName);
|
||||
if (!schema) {
|
||||
throw new Error(`No schema registered for type: ${typeName}`);
|
||||
}
|
||||
return schema.parse(data) as T;
|
||||
}
|
||||
|
||||
static safeValidate<T>(
|
||||
typeName: string,
|
||||
data: unknown
|
||||
): { success: true; data: T } | { success: false; error: z.ZodError } {
|
||||
const schema = this.schemas.get(typeName);
|
||||
if (!schema) {
|
||||
return {
|
||||
success: false,
|
||||
error: new z.ZodError([
|
||||
{
|
||||
code: 'custom',
|
||||
message: `No schema registered for type: ${typeName}`,
|
||||
path: [],
|
||||
},
|
||||
]),
|
||||
};
|
||||
}
|
||||
|
||||
const result = schema.safeParse(data);
|
||||
return result.success
|
||||
? { success: true, data: result.data as T }
|
||||
: { success: false, error: result.error };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic validation wrapper - works like typeguard for Python
|
||||
* In development/test: validates automatically
|
||||
* In production: can be stripped by build process
|
||||
*/
|
||||
export class AutoValidator {
|
||||
static validate<T>(typeName: string, data: unknown): T {
|
||||
// Check if auto-validation is enabled (development/test mode)
|
||||
if (typeof globalThis !== 'undefined' && (globalThis as any).__AUTO_VALIDATE__) {
|
||||
return SchemaRegistry.validate<T>(typeName, data);
|
||||
}
|
||||
|
||||
// In production, validation is skipped for performance
|
||||
return data as T;
|
||||
}
|
||||
|
||||
static safeValidate<T>(
|
||||
typeName: string,
|
||||
data: unknown
|
||||
): { success: true; data: T } | { success: false; error: z.ZodError } {
|
||||
if (typeof globalThis !== 'undefined' && (globalThis as any).__AUTO_VALIDATE__) {
|
||||
return SchemaRegistry.safeValidate<T>(typeName, data);
|
||||
}
|
||||
|
||||
// In production, assume data is valid
|
||||
return { success: true, data: data as T };
|
||||
}
|
||||
|
||||
static register<T extends z.ZodTypeAny>(name: string, schema: T): void {
|
||||
SchemaRegistry.register(name, schema);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable automatic validation in development/test environments
|
||||
declare global {
|
||||
var __AUTO_VALIDATE__: boolean;
|
||||
}
|
||||
|
||||
// Check environment and log status
|
||||
const isDev = typeof globalThis !== 'undefined' && (globalThis as any).__AUTO_VALIDATE__;
|
||||
if (isDev) {
|
||||
console.log('🛡️ Hypermodern Zod validation enabled (development/test mode)');
|
||||
} else {
|
||||
console.log('🏃♂️ Production mode - Zod validation optimized away');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user