90dc-core 1.16.18 → 1.16.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -64,7 +64,7 @@ export declare const TEST_UUIDS: {
|
|
|
64
64
|
/** Coach user UUID #3 */
|
|
65
65
|
readonly COACH_3: "c3333333-c333-4c33-8c33-c33333333333";
|
|
66
66
|
/** Head coach UUID */
|
|
67
|
-
readonly HEAD_COACH: "hc111111-
|
|
67
|
+
readonly HEAD_COACH: "hc111111-1111-4111-8111-111111111111";
|
|
68
68
|
/** Client user UUID #1 */
|
|
69
69
|
readonly CLIENT_1: "cccccccc-cccc-4ccc-8ccc-cccccccccccc";
|
|
70
70
|
/** Client user UUID #2 */
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
/** Coach user UUID #1 */ COACH_1: 'c1111111-c111-4c11-8c11-c11111111111',
|
|
48
48
|
/** Coach user UUID #2 */ COACH_2: 'c2222222-c222-4c22-8c22-c22222222222',
|
|
49
49
|
/** Coach user UUID #3 */ COACH_3: 'c3333333-c333-4c33-8c33-c33333333333',
|
|
50
|
-
/** Head coach UUID */ HEAD_COACH: 'hc111111-
|
|
50
|
+
/** Head coach UUID */ HEAD_COACH: 'hc111111-1111-4111-8111-111111111111',
|
|
51
51
|
/** Client user UUID #1 */ CLIENT_1: 'cccccccc-cccc-4ccc-8ccc-cccccccccccc',
|
|
52
52
|
/** Client user UUID #2 */ CLIENT_2: 'dddddddd-dddd-4ddd-8ddd-dddddddddddd',
|
|
53
53
|
/** Client user UUID #3 */ CLIENT_3: 'eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/testing/testFixtures.ts"],"sourcesContent":["/**\n * Test Fixtures and Utilities\n *\n * Centralized test data generators and helpers for consistent, type-safe testing\n * across all 90dc projects.\n *\n * @module testFixtures\n *\n * Key Principles:\n * - Industry-standard UUID v4 format (RFC 4122)\n * - Complete, realistic mock data with proper TypeScript types\n * - Reusable and composable fixtures\n * - Deterministic test data for reproducible tests\n * - No magic strings or fake IDs\n *\n * @example\n * ```typescript\n * import { TEST_UUIDS, createTestUser, freezeTime } from '90dc-core';\n *\n * const user = createTestUser({\n * userUuid: TEST_UUIDS.USER_1,\n * role: 'coach'\n * });\n * ```\n */\n\nimport type { UserTypes } from '../models/UserInterfaces.js';\n\n/**\n * Pre-generated valid UUID v4 identifiers for deterministic testing.\n *\n * These UUIDs follow RFC 4122 format and are safe to use across all tests.\n * Using predefined UUIDs ensures test reproducibility and makes debugging easier.\n *\n * @example\n * ```typescript\n * const coachUuid = TEST_UUIDS.COACH_1;\n * const clientUuid = TEST_UUIDS.CLIENT_1;\n * ```\n */\nexport const TEST_UUIDS = {\n /** Generic user UUID #1 */\n USER_1: '11111111-1111-4111-8111-111111111111',\n /** Generic user UUID #2 */\n USER_2: '22222222-2222-4222-8222-222222222222',\n /** Generic user UUID #3 */\n USER_3: '33333333-3333-4333-8333-333333333333',\n /** Generic user UUID #4 */\n USER_4: '44444444-4444-4444-8444-444444444444',\n /** Generic user UUID #5 */\n USER_5: '55555555-5555-4555-8555-555555555555',\n /** Generic user UUID #6 */\n USER_6: '66666666-6666-4666-8666-666666666666',\n /** Generic user UUID #7 */\n USER_7: '77777777-7777-4777-8777-777777777777',\n /** Generic user UUID #8 */\n USER_8: '88888888-8888-4888-8888-888888888888',\n /** Generic user UUID #9 */\n USER_9: '99999999-9999-4999-8999-999999999999',\n /** Generic user UUID #10 */\n USER_10: 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa',\n\n /** Coach user UUID #1 */\n COACH_1: 'c1111111-c111-4c11-8c11-c11111111111',\n /** Coach user UUID #2 */\n COACH_2: 'c2222222-c222-4c22-8c22-c22222222222',\n /** Coach user UUID #3 */\n COACH_3: 'c3333333-c333-4c33-8c33-c33333333333',\n\n /** Head coach UUID */\n HEAD_COACH: 'hc111111-hc11-4hc1-8hc1-hc1111111111',\n\n /** Client user UUID #1 */\n CLIENT_1: 'cccccccc-cccc-4ccc-8ccc-cccccccccccc',\n /** Client user UUID #2 */\n CLIENT_2: 'dddddddd-dddd-4ddd-8ddd-dddddddddddd',\n /** Client user UUID #3 */\n CLIENT_3: 'eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee',\n\n /** Finance role user UUID */\n FINANCE: 'ffffffff-ffff-4fff-8fff-ffffffffffff',\n\n /** Admin user UUID */\n ADMIN: 'adadadad-adad-4dad-8dad-adadadadadad',\n\n /** Super admin user UUID */\n SUPER_ADMIN: 'aaaaaaaa-0000-4000-8000-000000000000',\n} as const;\n\n/**\n * UUID validation regex (RFC 4122 v4)\n * @internal\n */\nconst UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/**\n * Validates if a string is a valid UUID v4\n *\n * @param value - String to validate\n * @returns True if valid UUID v4, false otherwise\n *\n * @example\n * ```typescript\n * isValidUUID('11111111-1111-4111-8111-111111111111'); // true\n * isValidUUID('invalid-uuid'); // false\n * ```\n */\nexport function isValidUUID(value: string): boolean {\n return UUID_V4_REGEX.test(value);\n}\n\n/**\n * Generates a unique email address for testing to avoid collisions.\n *\n * Format: `{prefix}-{timestamp}-{random}@{domain}`\n *\n * @param prefix - Email prefix (default: 'test')\n * @param domain - Email domain (default: 'test.com')\n * @returns Unique email address\n *\n * @example\n * ```typescript\n * generateTestEmail('coach'); // 'coach-1234567890-abc12@test.com'\n * generateTestEmail('user', 'example.com'); // 'user-1234567890-xyz98@example.com'\n * ```\n */\nexport function generateTestEmail(\n prefix: string = 'test',\n domain: string = 'test.com',\n): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).slice(2, 7);\n return `${prefix}-${timestamp}-${random}@${domain}`;\n}\n\n/**\n * Creates a complete mock user with sensible defaults and type safety.\n *\n * All fields are properly typed and provide realistic test data.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete UserTypes object\n *\n * @example\n * ```typescript\n * const user = createTestUser({\n * userUuid: TEST_UUIDS.USER_1,\n * role: 'coach',\n * email: 'coach@test.com'\n * });\n * ```\n */\nexport function createTestUser(overrides?: Partial<UserTypes>): UserTypes {\n return {\n userUuid: TEST_UUIDS.USER_1,\n email: generateTestEmail('user'),\n firstName: 'Test',\n lastName: 'User',\n role: 'user',\n avatar: '1',\n isSubscriptionActive: true,\n ...overrides,\n };\n}\n\n/**\n * Creates a mock coach user with coach-specific defaults.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete coach UserTypes object\n *\n * @example\n * ```typescript\n * const coach = createTestCoach({\n * userUuid: TEST_UUIDS.COACH_1,\n * firstName: 'John',\n * lastName: 'Coach'\n * });\n * ```\n */\nexport function createTestCoach(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.COACH_1,\n role: 'coach',\n email: generateTestEmail('coach'),\n firstName: 'Coach',\n lastName: 'Test',\n ...overrides,\n });\n}\n\n/**\n * Creates a mock head coach user.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete head coach UserTypes object\n */\nexport function createTestHeadCoach(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.HEAD_COACH,\n role: 'head-coach',\n email: generateTestEmail('head-coach'),\n firstName: 'Head',\n lastName: 'Coach',\n ...overrides,\n });\n}\n\n/**\n * Creates a mock finance user.\n *\n * Typically used for Richard (finance role) in financial tracking tests.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete finance UserTypes object\n */\nexport function createTestFinanceUser(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.FINANCE,\n role: 'finance',\n email: generateTestEmail('finance'),\n firstName: 'Richard',\n lastName: 'Finance',\n ...overrides,\n });\n}\n\n/**\n * Creates a mock admin user.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete admin UserTypes object\n */\nexport function createTestAdmin(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.ADMIN,\n role: 'admin',\n email: generateTestEmail('admin'),\n firstName: 'Admin',\n lastName: 'User',\n ...overrides,\n });\n}\n\n/**\n * Creates a mock client user (regular user role).\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete client UserTypes object\n */\nexport function createTestClient(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.CLIENT_1,\n role: 'user',\n email: generateTestEmail('client'),\n firstName: 'Client',\n lastName: 'User',\n ...overrides,\n });\n}\n\n/**\n * Fixed date constants for deterministic testing.\n *\n * Using consistent dates across tests ensures reproducible behavior\n * and easier debugging of time-dependent logic.\n */\nexport const TEST_DATES = {\n /** Fixed date for deterministic tests: 2026-03-01 10:00:00 UTC */\n FIXED_DATE: new Date('2026-03-01T10:00:00.000Z'),\n\n /** Start of month: 2026-03-01 00:00:00 UTC */\n MONTH_START: new Date('2026-03-01T00:00:00.000Z'),\n\n /** End of month: 2026-03-31 23:59:59 UTC */\n MONTH_END: new Date('2026-03-31T23:59:59.999Z'),\n\n /** Yesterday relative to FIXED_DATE */\n YESTERDAY: new Date('2026-02-28T10:00:00.000Z'),\n\n /** Tomorrow relative to FIXED_DATE */\n TOMORROW: new Date('2026-03-02T10:00:00.000Z'),\n\n /** One week ago relative to FIXED_DATE */\n WEEK_AGO: new Date('2026-02-22T10:00:00.000Z'),\n\n /** One week from now relative to FIXED_DATE */\n WEEK_AHEAD: new Date('2026-03-08T10:00:00.000Z'),\n} as const;\n\n/**\n * Common test data patterns and constants.\n */\nexport const TEST_DATA = {\n /**\n * Valid month format strings (YYYY-MM) for financial tracking\n */\n MONTHS: {\n CURRENT: '2026-03',\n PREVIOUS: '2026-02',\n NEXT: '2026-04',\n JANUARY: '2026-01',\n DECEMBER: '2025-12',\n },\n\n /**\n * Common test email domains\n */\n EMAIL_DOMAINS: ['test.com', 'example.com', 'test.org', 'example.org'] as const,\n\n /**\n * Sample notes for testing note-taking features\n */\n SAMPLE_NOTES: [\n 'Client is making great progress with consistency',\n 'Needs additional support with nutrition planning',\n 'Struggling with morning routine, discussed strategies',\n 'Excellent workout form, ready to increase weight',\n 'Discussed goal adjustments for next quarter',\n ] as const,\n\n /**\n * Common HTTP status codes for testing\n */\n HTTP_STATUS: {\n OK: 200,\n CREATED: 201,\n NO_CONTENT: 204,\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n CONFLICT: 409,\n INTERNAL_SERVER_ERROR: 500,\n } as const,\n} as const;\n\n/**\n * Waits for all pending promises to resolve.\n *\n * Useful for testing async operations that may have multiple\n * promise chains.\n *\n * @returns Promise that resolves when all pending promises complete\n *\n * @example\n * ```typescript\n * await flushPromises();\n * expect(mockCallback).toHaveBeenCalled();\n * ```\n */\nexport async function flushPromises(): Promise<void> {\n return new Promise((resolve) => setImmediate(resolve));\n}\n\n/**\n * Waits for a specific amount of time.\n *\n * @param ms - Milliseconds to wait\n * @returns Promise that resolves after the specified time\n *\n * @example\n * ```typescript\n * await wait(1000); // Wait 1 second\n * ```\n */\nexport async function wait(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Original Date class reference for restoring after time mocking\n * @internal\n */\nlet originalDate: typeof Date;\n\n/**\n * Freezes time to a specific date for deterministic testing.\n *\n * This function mocks the global Date object to always return\n * the specified date. Useful for testing time-dependent logic.\n *\n * **Important:** Call the returned cleanup function to restore\n * normal Date behavior after your test.\n *\n * @param date - Date to freeze time to (default: TEST_DATES.FIXED_DATE)\n * @returns Cleanup function to restore original Date behavior\n *\n * @example\n * ```typescript\n * const cleanup = freezeTime(new Date('2026-03-01'));\n * const now = new Date(); // Always returns 2026-03-01\n * cleanup(); // Restore normal behavior\n * ```\n */\nexport function freezeTime(date: Date = TEST_DATES.FIXED_DATE): () => void {\n originalDate = Date;\n const frozenTime = new Date(date).getTime();\n\n // Intentionally mocking global Date for testing purposes\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (global as any).Date = class MockDate extends originalDate {\n constructor(...args: unknown[]) {\n if (args.length === 0) {\n super(frozenTime);\n } else {\n super(...(args as [number | string]));\n }\n }\n\n static override now(): number {\n return frozenTime;\n }\n };\n\n // Preserve static methods\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (global as any).Date.UTC = originalDate.UTC;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (global as any).Date.parse = originalDate.parse;\n\n return () => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (global as any).Date = originalDate;\n };\n}\n\n/**\n * Custom assertion helpers for common test scenarios.\n *\n * These assertions provide better error messages and type safety\n * compared to basic Jest assertions.\n */\nexport const testAssertions = {\n /**\n * Asserts that a value is a valid UUID v4 (RFC 4122).\n *\n * @param value - String to validate\n * @param message - Optional custom error message\n * @throws Error if value is not a valid UUID v4\n *\n * @example\n * ```typescript\n * testAssertions.assertValidUUID('11111111-1111-4111-8111-111111111111');\n * ```\n */\n assertValidUUID(value: string, message?: string): void {\n if (!isValidUUID(value)) {\n throw new Error(\n message || `Expected valid UUID v4, got: ${value}`,\n );\n }\n },\n\n /**\n * Asserts that a date is within a specified range (inclusive).\n *\n * @param date - Date to check\n * @param start - Start of valid range\n * @param end - End of valid range\n * @param message - Optional custom error message\n * @throws Error if date is outside range\n */\n assertDateInRange(\n date: Date,\n start: Date,\n end: Date,\n message?: string,\n ): void {\n if (date < start || date > end) {\n throw new Error(\n message ||\n `Date ${date.toISOString()} not in range ${start.toISOString()} to ${end.toISOString()}`,\n );\n }\n },\n\n /**\n * Asserts that an array has a specific length.\n *\n * @param array - Array to check\n * @param expectedLength - Expected length\n * @param message - Optional custom error message\n * @throws Error if array length doesn't match\n */\n assertLength<T>(\n array: readonly T[],\n expectedLength: number,\n message?: string,\n ): void {\n if (array.length !== expectedLength) {\n throw new Error(\n message ||\n `Expected array length ${expectedLength}, got ${array.length}`,\n );\n }\n },\n\n /**\n * Asserts that a value is truthy.\n *\n * @param value - Value to check\n * @param message - Optional custom error message\n * @throws Error if value is falsy\n */\n assertTruthy(value: unknown, message?: string): asserts value {\n if (!value) {\n throw new Error(message || `Expected truthy value, got: ${value}`);\n }\n },\n\n /**\n * Asserts that a value is falsy.\n *\n * @param value - Value to check\n * @param message - Optional custom error message\n * @throws Error if value is truthy\n */\n assertFalsy(value: unknown, message?: string): void {\n if (value) {\n throw new Error(message || `Expected falsy value, got: ${value}`);\n }\n },\n\n /**\n * Asserts that two dates are equal (within 1 second tolerance).\n *\n * @param actual - Actual date\n * @param expected - Expected date\n * @param message - Optional custom error message\n * @throws Error if dates are not equal within tolerance\n */\n assertDateEquals(\n actual: Date,\n expected: Date,\n message?: string,\n ): void {\n const tolerance = 1000; // 1 second\n const diff = Math.abs(actual.getTime() - expected.getTime());\n if (diff > tolerance) {\n throw new Error(\n message ||\n `Dates are not equal. Expected: ${expected.toISOString()}, Got: ${actual.toISOString()}`,\n );\n }\n },\n};\n\n/**\n * Standard response builders for common API response patterns.\n *\n * These helpers ensure consistent response shapes across tests.\n */\nexport const mockResponses = {\n /**\n * Creates a success response object.\n *\n * @param data - Response data\n * @returns Success response object\n *\n * @example\n * ```typescript\n * const response = mockResponses.success({ id: 1, name: 'Test' });\n * // { success: true, data: { id: 1, name: 'Test' } }\n * ```\n */\n success<T>(data: T): { success: true; data: T } {\n return { success: true, data };\n },\n\n /**\n * Creates an error response object.\n *\n * @param message - Error message\n * @param code - Optional error code\n * @returns Error response object\n *\n * @example\n * ```typescript\n * const response = mockResponses.error('Not found', 'NOT_FOUND');\n * // { success: false, error: 'Not found', code: 'NOT_FOUND' }\n * ```\n */\n error(\n message: string,\n code?: string,\n ): { success: false; error: string; code?: string } {\n return code\n ? { success: false, error: message, code }\n : { success: false, error: message };\n },\n\n /**\n * Creates a paginated response object.\n *\n * @param items - Array of items for current page\n * @param total - Total number of items across all pages\n * @param page - Current page number (1-indexed)\n * @param limit - Items per page\n * @returns Paginated response object\n *\n * @example\n * ```typescript\n * const response = mockResponses.paginated([item1, item2], 100, 1, 10);\n * // {\n * // items: [item1, item2],\n * // total: 100,\n * // page: 1,\n * // limit: 10,\n * // hasMore: true\n * // }\n * ```\n */\n paginated<T>(\n items: T[],\n total: number,\n page: number = 1,\n limit: number = 10,\n ): {\n items: T[];\n total: number;\n page: number;\n limit: number;\n hasMore: boolean;\n totalPages: number;\n } {\n return {\n items,\n total,\n page,\n limit,\n hasMore: page * limit < total,\n totalPages: Math.ceil(total / limit),\n };\n },\n};\n\n/**\n * Type guard to check if a value is a non-null object.\n *\n * @param value - Value to check\n * @returns True if value is a non-null object\n */\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Type guard to check if a value is an array.\n *\n * @param value - Value to check\n * @returns True if value is an array\n */\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n"],"names":["TEST_UUIDS","USER_1","USER_2","USER_3","USER_4","USER_5","USER_6","USER_7","USER_8","USER_9","USER_10","COACH_1","COACH_2","COACH_3","HEAD_COACH","CLIENT_1","CLIENT_2","CLIENT_3","FINANCE","ADMIN","SUPER_ADMIN","UUID_V4_REGEX","isValidUUID","value","test","generateTestEmail","prefix","domain","timestamp","Date","now","random","Math","toString","slice","createTestUser","overrides","userUuid","email","firstName","lastName","role","avatar","isSubscriptionActive","createTestCoach","createTestHeadCoach","createTestFinanceUser","createTestAdmin","createTestClient","TEST_DATES","FIXED_DATE","MONTH_START","MONTH_END","YESTERDAY","TOMORROW","WEEK_AGO","WEEK_AHEAD","TEST_DATA","MONTHS","CURRENT","PREVIOUS","NEXT","JANUARY","DECEMBER","EMAIL_DOMAINS","SAMPLE_NOTES","HTTP_STATUS","OK","CREATED","NO_CONTENT","BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","INTERNAL_SERVER_ERROR","flushPromises","Promise","resolve","setImmediate","wait","ms","setTimeout","originalDate","freezeTime","date","frozenTime","getTime","global","MockDate","args","length","UTC","parse","testAssertions","assertValidUUID","message","Error","assertDateInRange","start","end","toISOString","assertLength","array","expectedLength","assertTruthy","assertFalsy","assertDateEquals","actual","expected","tolerance","diff","abs","mockResponses","success","data","error","code","paginated","items","total","page","limit","hasMore","totalPages","ceil","isObject","Array","isArray"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/testing/testFixtures.ts"],"sourcesContent":["/**\n * Test Fixtures and Utilities\n *\n * Centralized test data generators and helpers for consistent, type-safe testing\n * across all 90dc projects.\n *\n * @module testFixtures\n *\n * Key Principles:\n * - Industry-standard UUID v4 format (RFC 4122)\n * - Complete, realistic mock data with proper TypeScript types\n * - Reusable and composable fixtures\n * - Deterministic test data for reproducible tests\n * - No magic strings or fake IDs\n *\n * @example\n * ```typescript\n * import { TEST_UUIDS, createTestUser, freezeTime } from '90dc-core';\n *\n * const user = createTestUser({\n * userUuid: TEST_UUIDS.USER_1,\n * role: 'coach'\n * });\n * ```\n */\n\nimport type { UserTypes } from '../models/UserInterfaces.js';\n\n/**\n * Pre-generated valid UUID v4 identifiers for deterministic testing.\n *\n * These UUIDs follow RFC 4122 format and are safe to use across all tests.\n * Using predefined UUIDs ensures test reproducibility and makes debugging easier.\n *\n * @example\n * ```typescript\n * const coachUuid = TEST_UUIDS.COACH_1;\n * const clientUuid = TEST_UUIDS.CLIENT_1;\n * ```\n */\nexport const TEST_UUIDS = {\n /** Generic user UUID #1 */\n USER_1: '11111111-1111-4111-8111-111111111111',\n /** Generic user UUID #2 */\n USER_2: '22222222-2222-4222-8222-222222222222',\n /** Generic user UUID #3 */\n USER_3: '33333333-3333-4333-8333-333333333333',\n /** Generic user UUID #4 */\n USER_4: '44444444-4444-4444-8444-444444444444',\n /** Generic user UUID #5 */\n USER_5: '55555555-5555-4555-8555-555555555555',\n /** Generic user UUID #6 */\n USER_6: '66666666-6666-4666-8666-666666666666',\n /** Generic user UUID #7 */\n USER_7: '77777777-7777-4777-8777-777777777777',\n /** Generic user UUID #8 */\n USER_8: '88888888-8888-4888-8888-888888888888',\n /** Generic user UUID #9 */\n USER_9: '99999999-9999-4999-8999-999999999999',\n /** Generic user UUID #10 */\n USER_10: 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa',\n\n /** Coach user UUID #1 */\n COACH_1: 'c1111111-c111-4c11-8c11-c11111111111',\n /** Coach user UUID #2 */\n COACH_2: 'c2222222-c222-4c22-8c22-c22222222222',\n /** Coach user UUID #3 */\n COACH_3: 'c3333333-c333-4c33-8c33-c33333333333',\n\n /** Head coach UUID */\n HEAD_COACH: 'hc111111-1111-4111-8111-111111111111',\n\n /** Client user UUID #1 */\n CLIENT_1: 'cccccccc-cccc-4ccc-8ccc-cccccccccccc',\n /** Client user UUID #2 */\n CLIENT_2: 'dddddddd-dddd-4ddd-8ddd-dddddddddddd',\n /** Client user UUID #3 */\n CLIENT_3: 'eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee',\n\n /** Finance role user UUID */\n FINANCE: 'ffffffff-ffff-4fff-8fff-ffffffffffff',\n\n /** Admin user UUID */\n ADMIN: 'adadadad-adad-4dad-8dad-adadadadadad',\n\n /** Super admin user UUID */\n SUPER_ADMIN: 'aaaaaaaa-0000-4000-8000-000000000000',\n} as const;\n\n/**\n * UUID validation regex (RFC 4122 v4)\n * @internal\n */\nconst UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/**\n * Validates if a string is a valid UUID v4\n *\n * @param value - String to validate\n * @returns True if valid UUID v4, false otherwise\n *\n * @example\n * ```typescript\n * isValidUUID('11111111-1111-4111-8111-111111111111'); // true\n * isValidUUID('invalid-uuid'); // false\n * ```\n */\nexport function isValidUUID(value: string): boolean {\n return UUID_V4_REGEX.test(value);\n}\n\n/**\n * Generates a unique email address for testing to avoid collisions.\n *\n * Format: `{prefix}-{timestamp}-{random}@{domain}`\n *\n * @param prefix - Email prefix (default: 'test')\n * @param domain - Email domain (default: 'test.com')\n * @returns Unique email address\n *\n * @example\n * ```typescript\n * generateTestEmail('coach'); // 'coach-1234567890-abc12@test.com'\n * generateTestEmail('user', 'example.com'); // 'user-1234567890-xyz98@example.com'\n * ```\n */\nexport function generateTestEmail(\n prefix: string = 'test',\n domain: string = 'test.com',\n): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).slice(2, 7);\n return `${prefix}-${timestamp}-${random}@${domain}`;\n}\n\n/**\n * Creates a complete mock user with sensible defaults and type safety.\n *\n * All fields are properly typed and provide realistic test data.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete UserTypes object\n *\n * @example\n * ```typescript\n * const user = createTestUser({\n * userUuid: TEST_UUIDS.USER_1,\n * role: 'coach',\n * email: 'coach@test.com'\n * });\n * ```\n */\nexport function createTestUser(overrides?: Partial<UserTypes>): UserTypes {\n return {\n userUuid: TEST_UUIDS.USER_1,\n email: generateTestEmail('user'),\n firstName: 'Test',\n lastName: 'User',\n role: 'user',\n avatar: '1',\n isSubscriptionActive: true,\n ...overrides,\n };\n}\n\n/**\n * Creates a mock coach user with coach-specific defaults.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete coach UserTypes object\n *\n * @example\n * ```typescript\n * const coach = createTestCoach({\n * userUuid: TEST_UUIDS.COACH_1,\n * firstName: 'John',\n * lastName: 'Coach'\n * });\n * ```\n */\nexport function createTestCoach(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.COACH_1,\n role: 'coach',\n email: generateTestEmail('coach'),\n firstName: 'Coach',\n lastName: 'Test',\n ...overrides,\n });\n}\n\n/**\n * Creates a mock head coach user.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete head coach UserTypes object\n */\nexport function createTestHeadCoach(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.HEAD_COACH,\n role: 'head-coach',\n email: generateTestEmail('head-coach'),\n firstName: 'Head',\n lastName: 'Coach',\n ...overrides,\n });\n}\n\n/**\n * Creates a mock finance user.\n *\n * Typically used for Richard (finance role) in financial tracking tests.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete finance UserTypes object\n */\nexport function createTestFinanceUser(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.FINANCE,\n role: 'finance',\n email: generateTestEmail('finance'),\n firstName: 'Richard',\n lastName: 'Finance',\n ...overrides,\n });\n}\n\n/**\n * Creates a mock admin user.\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete admin UserTypes object\n */\nexport function createTestAdmin(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.ADMIN,\n role: 'admin',\n email: generateTestEmail('admin'),\n firstName: 'Admin',\n lastName: 'User',\n ...overrides,\n });\n}\n\n/**\n * Creates a mock client user (regular user role).\n *\n * @param overrides - Partial user properties to override defaults\n * @returns Complete client UserTypes object\n */\nexport function createTestClient(overrides?: Partial<UserTypes>): UserTypes {\n return createTestUser({\n userUuid: TEST_UUIDS.CLIENT_1,\n role: 'user',\n email: generateTestEmail('client'),\n firstName: 'Client',\n lastName: 'User',\n ...overrides,\n });\n}\n\n/**\n * Fixed date constants for deterministic testing.\n *\n * Using consistent dates across tests ensures reproducible behavior\n * and easier debugging of time-dependent logic.\n */\nexport const TEST_DATES = {\n /** Fixed date for deterministic tests: 2026-03-01 10:00:00 UTC */\n FIXED_DATE: new Date('2026-03-01T10:00:00.000Z'),\n\n /** Start of month: 2026-03-01 00:00:00 UTC */\n MONTH_START: new Date('2026-03-01T00:00:00.000Z'),\n\n /** End of month: 2026-03-31 23:59:59 UTC */\n MONTH_END: new Date('2026-03-31T23:59:59.999Z'),\n\n /** Yesterday relative to FIXED_DATE */\n YESTERDAY: new Date('2026-02-28T10:00:00.000Z'),\n\n /** Tomorrow relative to FIXED_DATE */\n TOMORROW: new Date('2026-03-02T10:00:00.000Z'),\n\n /** One week ago relative to FIXED_DATE */\n WEEK_AGO: new Date('2026-02-22T10:00:00.000Z'),\n\n /** One week from now relative to FIXED_DATE */\n WEEK_AHEAD: new Date('2026-03-08T10:00:00.000Z'),\n} as const;\n\n/**\n * Common test data patterns and constants.\n */\nexport const TEST_DATA = {\n /**\n * Valid month format strings (YYYY-MM) for financial tracking\n */\n MONTHS: {\n CURRENT: '2026-03',\n PREVIOUS: '2026-02',\n NEXT: '2026-04',\n JANUARY: '2026-01',\n DECEMBER: '2025-12',\n },\n\n /**\n * Common test email domains\n */\n EMAIL_DOMAINS: ['test.com', 'example.com', 'test.org', 'example.org'] as const,\n\n /**\n * Sample notes for testing note-taking features\n */\n SAMPLE_NOTES: [\n 'Client is making great progress with consistency',\n 'Needs additional support with nutrition planning',\n 'Struggling with morning routine, discussed strategies',\n 'Excellent workout form, ready to increase weight',\n 'Discussed goal adjustments for next quarter',\n ] as const,\n\n /**\n * Common HTTP status codes for testing\n */\n HTTP_STATUS: {\n OK: 200,\n CREATED: 201,\n NO_CONTENT: 204,\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n CONFLICT: 409,\n INTERNAL_SERVER_ERROR: 500,\n } as const,\n} as const;\n\n/**\n * Waits for all pending promises to resolve.\n *\n * Useful for testing async operations that may have multiple\n * promise chains.\n *\n * @returns Promise that resolves when all pending promises complete\n *\n * @example\n * ```typescript\n * await flushPromises();\n * expect(mockCallback).toHaveBeenCalled();\n * ```\n */\nexport async function flushPromises(): Promise<void> {\n return new Promise((resolve) => setImmediate(resolve));\n}\n\n/**\n * Waits for a specific amount of time.\n *\n * @param ms - Milliseconds to wait\n * @returns Promise that resolves after the specified time\n *\n * @example\n * ```typescript\n * await wait(1000); // Wait 1 second\n * ```\n */\nexport async function wait(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Original Date class reference for restoring after time mocking\n * @internal\n */\nlet originalDate: typeof Date;\n\n/**\n * Freezes time to a specific date for deterministic testing.\n *\n * This function mocks the global Date object to always return\n * the specified date. Useful for testing time-dependent logic.\n *\n * **Important:** Call the returned cleanup function to restore\n * normal Date behavior after your test.\n *\n * @param date - Date to freeze time to (default: TEST_DATES.FIXED_DATE)\n * @returns Cleanup function to restore original Date behavior\n *\n * @example\n * ```typescript\n * const cleanup = freezeTime(new Date('2026-03-01'));\n * const now = new Date(); // Always returns 2026-03-01\n * cleanup(); // Restore normal behavior\n * ```\n */\nexport function freezeTime(date: Date = TEST_DATES.FIXED_DATE): () => void {\n originalDate = Date;\n const frozenTime = new Date(date).getTime();\n\n // Intentionally mocking global Date for testing purposes\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (global as any).Date = class MockDate extends originalDate {\n constructor(...args: unknown[]) {\n if (args.length === 0) {\n super(frozenTime);\n } else {\n super(...(args as [number | string]));\n }\n }\n\n static override now(): number {\n return frozenTime;\n }\n };\n\n // Preserve static methods\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (global as any).Date.UTC = originalDate.UTC;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (global as any).Date.parse = originalDate.parse;\n\n return () => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (global as any).Date = originalDate;\n };\n}\n\n/**\n * Custom assertion helpers for common test scenarios.\n *\n * These assertions provide better error messages and type safety\n * compared to basic Jest assertions.\n */\nexport const testAssertions = {\n /**\n * Asserts that a value is a valid UUID v4 (RFC 4122).\n *\n * @param value - String to validate\n * @param message - Optional custom error message\n * @throws Error if value is not a valid UUID v4\n *\n * @example\n * ```typescript\n * testAssertions.assertValidUUID('11111111-1111-4111-8111-111111111111');\n * ```\n */\n assertValidUUID(value: string, message?: string): void {\n if (!isValidUUID(value)) {\n throw new Error(\n message || `Expected valid UUID v4, got: ${value}`,\n );\n }\n },\n\n /**\n * Asserts that a date is within a specified range (inclusive).\n *\n * @param date - Date to check\n * @param start - Start of valid range\n * @param end - End of valid range\n * @param message - Optional custom error message\n * @throws Error if date is outside range\n */\n assertDateInRange(\n date: Date,\n start: Date,\n end: Date,\n message?: string,\n ): void {\n if (date < start || date > end) {\n throw new Error(\n message ||\n `Date ${date.toISOString()} not in range ${start.toISOString()} to ${end.toISOString()}`,\n );\n }\n },\n\n /**\n * Asserts that an array has a specific length.\n *\n * @param array - Array to check\n * @param expectedLength - Expected length\n * @param message - Optional custom error message\n * @throws Error if array length doesn't match\n */\n assertLength<T>(\n array: readonly T[],\n expectedLength: number,\n message?: string,\n ): void {\n if (array.length !== expectedLength) {\n throw new Error(\n message ||\n `Expected array length ${expectedLength}, got ${array.length}`,\n );\n }\n },\n\n /**\n * Asserts that a value is truthy.\n *\n * @param value - Value to check\n * @param message - Optional custom error message\n * @throws Error if value is falsy\n */\n assertTruthy(value: unknown, message?: string): asserts value {\n if (!value) {\n throw new Error(message || `Expected truthy value, got: ${value}`);\n }\n },\n\n /**\n * Asserts that a value is falsy.\n *\n * @param value - Value to check\n * @param message - Optional custom error message\n * @throws Error if value is truthy\n */\n assertFalsy(value: unknown, message?: string): void {\n if (value) {\n throw new Error(message || `Expected falsy value, got: ${value}`);\n }\n },\n\n /**\n * Asserts that two dates are equal (within 1 second tolerance).\n *\n * @param actual - Actual date\n * @param expected - Expected date\n * @param message - Optional custom error message\n * @throws Error if dates are not equal within tolerance\n */\n assertDateEquals(\n actual: Date,\n expected: Date,\n message?: string,\n ): void {\n const tolerance = 1000; // 1 second\n const diff = Math.abs(actual.getTime() - expected.getTime());\n if (diff > tolerance) {\n throw new Error(\n message ||\n `Dates are not equal. Expected: ${expected.toISOString()}, Got: ${actual.toISOString()}`,\n );\n }\n },\n};\n\n/**\n * Standard response builders for common API response patterns.\n *\n * These helpers ensure consistent response shapes across tests.\n */\nexport const mockResponses = {\n /**\n * Creates a success response object.\n *\n * @param data - Response data\n * @returns Success response object\n *\n * @example\n * ```typescript\n * const response = mockResponses.success({ id: 1, name: 'Test' });\n * // { success: true, data: { id: 1, name: 'Test' } }\n * ```\n */\n success<T>(data: T): { success: true; data: T } {\n return { success: true, data };\n },\n\n /**\n * Creates an error response object.\n *\n * @param message - Error message\n * @param code - Optional error code\n * @returns Error response object\n *\n * @example\n * ```typescript\n * const response = mockResponses.error('Not found', 'NOT_FOUND');\n * // { success: false, error: 'Not found', code: 'NOT_FOUND' }\n * ```\n */\n error(\n message: string,\n code?: string,\n ): { success: false; error: string; code?: string } {\n return code\n ? { success: false, error: message, code }\n : { success: false, error: message };\n },\n\n /**\n * Creates a paginated response object.\n *\n * @param items - Array of items for current page\n * @param total - Total number of items across all pages\n * @param page - Current page number (1-indexed)\n * @param limit - Items per page\n * @returns Paginated response object\n *\n * @example\n * ```typescript\n * const response = mockResponses.paginated([item1, item2], 100, 1, 10);\n * // {\n * // items: [item1, item2],\n * // total: 100,\n * // page: 1,\n * // limit: 10,\n * // hasMore: true\n * // }\n * ```\n */\n paginated<T>(\n items: T[],\n total: number,\n page: number = 1,\n limit: number = 10,\n ): {\n items: T[];\n total: number;\n page: number;\n limit: number;\n hasMore: boolean;\n totalPages: number;\n } {\n return {\n items,\n total,\n page,\n limit,\n hasMore: page * limit < total,\n totalPages: Math.ceil(total / limit),\n };\n },\n};\n\n/**\n * Type guard to check if a value is a non-null object.\n *\n * @param value - Value to check\n * @returns True if value is a non-null object\n */\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Type guard to check if a value is an array.\n *\n * @param value - Value to check\n * @returns True if value is an array\n */\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n"],"names":["TEST_UUIDS","USER_1","USER_2","USER_3","USER_4","USER_5","USER_6","USER_7","USER_8","USER_9","USER_10","COACH_1","COACH_2","COACH_3","HEAD_COACH","CLIENT_1","CLIENT_2","CLIENT_3","FINANCE","ADMIN","SUPER_ADMIN","UUID_V4_REGEX","isValidUUID","value","test","generateTestEmail","prefix","domain","timestamp","Date","now","random","Math","toString","slice","createTestUser","overrides","userUuid","email","firstName","lastName","role","avatar","isSubscriptionActive","createTestCoach","createTestHeadCoach","createTestFinanceUser","createTestAdmin","createTestClient","TEST_DATES","FIXED_DATE","MONTH_START","MONTH_END","YESTERDAY","TOMORROW","WEEK_AGO","WEEK_AHEAD","TEST_DATA","MONTHS","CURRENT","PREVIOUS","NEXT","JANUARY","DECEMBER","EMAIL_DOMAINS","SAMPLE_NOTES","HTTP_STATUS","OK","CREATED","NO_CONTENT","BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","INTERNAL_SERVER_ERROR","flushPromises","Promise","resolve","setImmediate","wait","ms","setTimeout","originalDate","freezeTime","date","frozenTime","getTime","global","MockDate","args","length","UTC","parse","testAssertions","assertValidUUID","message","Error","assertDateInRange","start","end","toISOString","assertLength","array","expectedLength","assertTruthy","assertFalsy","assertDateEquals","actual","expected","tolerance","diff","abs","mockResponses","success","data","error","code","paginated","items","total","page","limit","hasMore","totalPages","ceil","isObject","Array","isArray"],"mappings":"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"}
|