/** * General Test Helper Utilities * * This file provides general-purpose test utilities for the OAuth plugin tests. */ /** * Generate a random state parameter for testing */ export function generateTestState(): string { return 'test_state_' + Math.random().toString(36).substring(2, 15); } /** * Generate a random session ID for testing */ export function generateTestSessionId(): string { return 'test_session_' + Math.random().toString(36).substring(2, 15); } /** * Generate a random authorization code for testing */ export function generateTestAuthCode(): string { return 'test_code_' + Math.random().toString(36).substring(2, 15); } /** * Create a mock Express request object */ export function createMockRequest(overrides: any = {}): any { return { headers: {}, query: {}, params: {}, body: {}, method: 'GET', url: '/', ...overrides }; } /** * Create a mock Express response object */ export function createMockResponse(): any { const res: any = { statusCode: 200, headers: {}, body: null, redirectUrl: null, status(code: number) { res.statusCode = code; return res; }, json(data: any) { res.body = data; return res; }, send(data: any) { res.body = data; return res; }, redirect(url: string) { res.redirectUrl = url; res.statusCode = 302; return res; }, setHeader(name: string, value: string) { res.headers[name] = value; return res; }, getHeader(name: string) { return res.headers[name]; } }; return res; } /** * Wait for a specified number of milliseconds (for async testing) */ export function wait(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Assert that an error was thrown */ export async function expectToThrow(fn: () => Promise, expectedMessage?: string): Promise { try { await fn(); throw new Error('Expected function to throw but it did not'); } catch (error: any) { if (expectedMessage && !error.message.includes(expectedMessage)) { throw new Error(`Expected error message to include "${expectedMessage}" but got "${error.message}"`); } } } /** * Create a test user object */ export function createTestUser(overrides: any = {}): any { return { _id: 'user_' + Math.random().toString(36).substring(7), email: 'testuser@example.com', name: 'Test User', createdAt: new Date(), updatedAt: new Date(), ...overrides }; } /** * Create a test OAuth session object */ export function createTestOAuthSession(overrides: any = {}): any { return { sessionId: generateTestSessionId(), state: generateTestState(), provider: 'github', redirectUri: 'https://myapp.com/callback', createdAt: new Date(), ...overrides }; } /** * Create a test OAuth connection object */ export function createTestOAuthConnection(overrides: any = {}): any { return { userId: 'user_' + Math.random().toString(36).substring(7), provider: 'github', providerId: '12345678', accessToken: 'encrypted_access_token', scope: 'user:email', createdAt: new Date(), updatedAt: new Date(), ...overrides }; } /** * Parse a URL and return its components */ export function parseUrl(url: string): { pathname: string; query: Record; hash: string } { try { const urlObj = new URL(url); const query: Record = {}; urlObj.searchParams.forEach((value, key) => { query[key] = value; }); return { pathname: urlObj.pathname, query, hash: urlObj.hash.substring(1) // Remove leading # }; } catch (error) { return { pathname: '', query: {}, hash: '' }; } } /** * Extract token from URL (query param or hash fragment) */ export function extractTokenFromUrl(url: string): string | null { const parsed = parseUrl(url); // Check query parameter if (parsed.query.token) { return parsed.query.token; } // Check hash fragment if (parsed.hash) { const hashParams = new URLSearchParams(parsed.hash); return hashParams.get('token'); } return null; }