UNPKG

@seedts/testing

Version:

Testing utilities for SeedTS - Snapshot testing, deterministic seeding, and test helpers

198 lines 6.02 kB
"use strict"; /** * Test helper utilities for SeedTS */ Object.defineProperty(exports, "__esModule", { value: true }); exports.executeSeedsAsMap = executeSeedsAsMap; exports.assertSeedSuccess = assertSeedSuccess; exports.assertAllSeedsSuccess = assertAllSeedsSuccess; exports.getSeedByName = getSeedByName; exports.assertSeedCount = assertSeedCount; exports.assertSeedData = assertSeedData; exports.assertSeedDuration = assertSeedDuration; exports.createValidator = createValidator; exports.waitFor = waitFor; exports.deepEqual = deepEqual; /** * Execute seeds and return results by name for easy access * * @param executor Executor instance * @returns Map of seed results by name * * @example * ```typescript * const executor = new Executor([UsersSeed, PostsSeed]); * const results = await executeSeedsAsMap(executor); * * expect(results.get('users')).toBeDefined(); * expect(results.get('users')?.count).toBe(10); * ``` */ async function executeSeedsAsMap(executor) { const results = await executor.execute(); const map = new Map(); for (const result of results) { map.set(result.name, result); } return map; } /** * Assert that a seed executed successfully * * @param result Seed result * @throws Error if seed failed * * @example * ```typescript * const results = await executor.execute(); * assertSeedSuccess(results[0]); * ``` */ function assertSeedSuccess(result) { if (!result) { throw new Error('Seed result is undefined'); } if (!result.success || result.error) { throw new Error(`Seed "${result.name}" failed: ${result.error?.message || 'Unknown error'}`); } if (result.recordCount === 0) { throw new Error(`Seed "${result.name}" produced 0 records`); } } /** * Assert that all seeds executed successfully * * @param results Array of seed results * @throws Error if any seed failed */ function assertAllSeedsSuccess(results) { const failures = results.filter(r => !r.success || r.error); if (failures.length > 0) { const errors = failures.map(f => ` - ${f.name}: ${f.error?.message || 'Unknown error'}`).join('\n'); throw new Error(`${failures.length} seed(s) failed:\n${errors}`); } } /** * Get seed result by name * * @param results Array of seed results * @param name Seed name * @returns Seed result or undefined */ function getSeedByName(results, name) { return results.find(r => r.name === name); } /** * Assert that seed result exists and has expected count * * @param result Seed result * @param expectedCount Expected record count * @throws Error if count doesn't match */ function assertSeedCount(result, expectedCount) { assertSeedSuccess(result); if (result.recordCount !== expectedCount) { throw new Error(`Seed "${result.name}" expected ${expectedCount} records but got ${result.recordCount}`); } } /** * Assert that seed data matches predicate * * @param data Seed data array * @param seedName Seed name (for error messages) * @param predicate Function to test each record * @throws Error if any record fails predicate */ function assertSeedData(data, seedName, predicate, message) { const failedRecords = data.filter((record, index) => { try { return !predicate(record); } catch (error) { throw new Error(`Predicate error at index ${index}: ${error instanceof Error ? error.message : 'Unknown error'}`); } }); if (failedRecords.length > 0) { throw new Error(message || `${failedRecords.length} record(s) in seed "${seedName}" failed validation`); } } /** * Assert that seed completed within expected duration * * @param result Seed result * @param maxDuration Maximum duration in milliseconds * @throws Error if duration exceeds limit */ function assertSeedDuration(result, maxDuration) { if (result.duration > maxDuration) { throw new Error(`Seed "${result.name}" took ${result.duration}ms, expected < ${maxDuration}ms`); } } /** * Create a test data validator * * @example * ```typescript * const validateUser = createValidator<User>({ * email: (v) => typeof v === 'string' && v.includes('@'), * age: (v) => typeof v === 'number' && v >= 0 && v <= 150, * name: (v) => typeof v === 'string' && v.length > 0 * }); * * assertSeedData(usersResult, validateUser); * ``` */ function createValidator(rules) { return (record) => { for (const [key, validator] of Object.entries(rules)) { if (validator && !validator(record[key])) { throw new Error(`Validation failed for field "${key}"`); } } return true; }; } /** * Wait for a condition to be true with timeout * * @param condition Function that returns true when condition is met * @param timeout Timeout in milliseconds (default: 5000) * @param interval Check interval in milliseconds (default: 100) * @throws Error if timeout reached */ async function waitFor(condition, timeout = 5000, interval = 100) { const startTime = Date.now(); while (Date.now() - startTime < timeout) { if (await condition()) { return; } await new Promise(resolve => setTimeout(resolve, interval)); } throw new Error(`Timeout waiting for condition after ${timeout}ms`); } /** * Compare two objects deeply for equality * * @param a First object * @param b Second object * @returns True if objects are deeply equal */ function deepEqual(a, b) { if (a === b) return true; if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) { return false; } const keysA = Object.keys(a); const keysB = Object.keys(b); if (keysA.length !== keysB.length) return false; for (const key of keysA) { if (!keysB.includes(key) || !deepEqual(a[key], b[key])) { return false; } } return true; } //# sourceMappingURL=helpers.js.map