import fs from 'fs'; import path from 'path'; /** * Test utilities for scheduler testing */ export const testFixtures = { /** * Create a mock auth.json file with valid Instagram session */ createMockAuthFile: (filePath: string) => { const dir = path.dirname(filePath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } const mockAuth = { cookies: [ { name: 'sessionid', value: 'mock-session-' + Date.now(), domain: '.instagram.com', path: '/', expires: Math.floor(Date.now() / 1000) + 3600 * 24 * 30, httpOnly: true, secure: true, sameSite: 'Strict' }, { name: 'ig_did', value: 'mock-did-' + Date.now(), domain: '.instagram.com', path: '/', expires: Math.floor(Date.now() / 1000) + 3600 * 24 * 365, httpOnly: false, secure: true, sameSite: 'Strict' } ], origins: [ { origin: 'https://www.instagram.com', localStorage: [ { name: 'ig_nrcb', value: '1' } ] } ] }; fs.writeFileSync(filePath, JSON.stringify(mockAuth, null, 2)); return mockAuth; }, /** * Clean up mock auth files */ cleanupMockAuthFile: (filePath: string) => { if (fs.existsSync(filePath)) { fs.unlinkSync(filePath); } const dir = path.dirname(filePath); if (fs.existsSync(dir) && fs.readdirSync(dir).length === 0) { fs.rmdirSync(dir); } }, /** * Mock environment for scheduler testing */ setupEnv: (config: Record) => { const original: Record = {}; for (const [key, value] of Object.entries(config)) { original[key] = process.env[key]; if (value === undefined) { delete process.env[key]; } else { process.env[key] = value; } } return () => { // Restore original env for (const [key, value] of Object.entries(original)) { if (value === undefined) { delete process.env[key]; } else { process.env[key] = value; } } }; }, /** * Validate auth.json file structure */ validateAuthFile: (filePath: string): boolean => { try { const content = JSON.parse(fs.readFileSync(filePath, 'utf-8')); // Check required fields if (!Array.isArray(content.cookies)) return false; if (!Array.isArray(content.origins)) return false; // Check cookie structure for (const cookie of content.cookies) { if (!cookie.name || !cookie.value || !cookie.domain) { return false; } } return true; } catch { return false; } }, /** * Get mock browser context for testing */ createMockBrowserContext: () => { return { newPage: async () => ({ goto: async () => {}, waitForSelector: async () => {}, evaluate: async () => 'Home', close: async () => {}, screenshot: async () => Buffer.from('mock-image') }), storageState: async (options: { path: string }) => { const mockAuth = { cookies: [{ name: 'sessionid', value: 'refreshed', domain: '.instagram.com' }], origins: [] }; fs.writeFileSync(options.path, JSON.stringify(mockAuth, null, 2)); }, close: async () => {} }; } }; /** * Helper to create a spy for interval/timeout functions */ export const createTimerSpy = () => { let timers: NodeJS.Timeout[] = []; return { setInterval: (callback: () => void, ms: number) => { const timer = setInterval(callback, ms); timers.push(timer); return timer; }, cleanup: () => { timers.forEach((timer) => clearInterval(timer)); timers = []; } }; };