UNPKG

ruch

Version:

Revolutionary React TypeScript CLI with hexagonal architecture & AI-powered development assistance. Create maintainable, scalable applications with domain-driven design and integrated AI tooling.

414 lines (350 loc) 10.4 kB
/** * MSW Templates for Mock Service Worker integration * Using MSW v2.x (2025 latest version) */ /** * Generate MSW setup configuration */ export const getMswSetupTemplate = (): string => { return `// MSW Setup Configuration // This file configures Mock Service Worker for the entire application import { setupWorker } from 'msw/browser'; import { setupServer } from 'msw/node'; import { handlers } from './handlers/index'; // Browser worker for development export const worker = setupWorker(...handlers); // Node server for testing export const server = setupServer(...handlers); // Setup for different environments export const setupMsw = async () => { if (typeof window !== 'undefined') { // Browser environment await worker.start({ onUnhandledRequest: 'bypass', serviceWorker: { url: '/mockServiceWorker.js' } }); } }; `; }; /** * Generate MSW browser configuration */ export const getMswBrowserTemplate = (): string => { return `// MSW Browser Worker Configuration // This file sets up MSW for browser/development environment import { setupWorker } from 'msw/browser'; import { handlers } from './handlers/index'; // Setup worker with all domain handlers export const worker = setupWorker(...handlers); // Start worker for development export const startMsw = async () => { if (process.env.NODE_ENV === 'development') { await worker.start({ onUnhandledRequest: 'bypass', serviceWorker: { url: '/mockServiceWorker.js' } }); console.log('🔧 MSW: Mock Service Worker started'); } }; `; }; /** * Generate MSW server configuration for Node.js/testing */ export const getMswServerTemplate = (): string => { return `// MSW Server Configuration // This file sets up MSW for Node.js/testing environment import { setupServer } from 'msw/node'; import { handlers } from './handlers/index'; // Setup server with all domain handlers export const server = setupServer(...handlers); // Server lifecycle for tests export const startMswServer = () => { server.listen({ onUnhandledRequest: 'warn' }); }; export const resetMswServer = () => { server.resetHandlers(); }; export const stopMswServer = () => { server.close(); }; `; }; /** * Generate handlers index file that exports all domain handlers */ export const getMswHandlersIndexTemplate = (domains: string[]): string => { const imports = domains.map(domain => `import { ${domain}Handlers } from './${domain}';` ).join('\n'); const exports = domains.map(domain => ` ...${domain}Handlers,` ).join('\n'); return `// MSW Handlers Index // This file aggregates all domain handlers for MSW ${imports} // Export all handlers for MSW setup export const handlers = [ ${exports} ]; `; }; /** * Generate MSW handlers template for a specific domain */ export const getMswHandlersTemplate = (domainName: string): string => { const capitalizedDomain = domainName.charAt(0).toUpperCase() + domainName.slice(1); return `// ${capitalizedDomain} Domain MSW Handlers // This file contains Mock Service Worker handlers for ${domainName} domain API endpoints import { http, HttpResponse } from 'msw'; import { mock${capitalizedDomain}Data } from '../../../domains/${domainName}/mocks/mockData'; const API_BASE = '/api/${domainName}'; export const ${domainName}Handlers = [ // GET /${domainName} - List all ${domainName} items http.get(\`\${API_BASE}\`, () => { return HttpResponse.json(mock${capitalizedDomain}Data.getAll()); }), // GET /${domainName}/:id - Get single ${domainName} item http.get(\`\${API_BASE}/:id\`, ({ params }) => { const { id } = params; const item = mock${capitalizedDomain}Data.getById(id as string); if (!item) { return new HttpResponse(null, { status: 404, statusText: '${capitalizedDomain} not found' }); } return HttpResponse.json(item); }), // POST /${domainName} - Create new ${domainName} item http.post(\`\${API_BASE}\`, async ({ request }) => { try { const newItem = await request.json(); const createdItem = mock${capitalizedDomain}Data.create(newItem); return HttpResponse.json(createdItem, { status: 201 }); } catch (error) { return new HttpResponse(null, { status: 400, statusText: 'Invalid ${domainName} data' }); } }), // PUT /${domainName}/:id - Update ${domainName} item http.put(\`\${API_BASE}/:id\`, async ({ params, request }) => { const { id } = params; try { const updates = await request.json(); const updatedItem = mock${capitalizedDomain}Data.update(id as string, updates); if (!updatedItem) { return new HttpResponse(null, { status: 404, statusText: '${capitalizedDomain} not found' }); } return HttpResponse.json(updatedItem); } catch (error) { return new HttpResponse(null, { status: 400, statusText: 'Invalid ${domainName} data' }); } }), // DELETE /${domainName}/:id - Delete ${domainName} item http.delete(\`\${API_BASE}/:id\`, ({ params }) => { const { id } = params; const deleted = mock${capitalizedDomain}Data.delete(id as string); if (!deleted) { return new HttpResponse(null, { status: 404, statusText: '${capitalizedDomain} not found' }); } return new HttpResponse(null, { status: 204 }); }), // Add more ${domainName}-specific endpoints here // Example: GET /${domainName}/:id/relationships // http.get(\`\${API_BASE}/:id/relationships\`, ({ params }) => { // const { id } = params; // const relationships = mock${capitalizedDomain}Data.getRelationships(id as string); // return HttpResponse.json(relationships); // }), ]; `; }; /** * Generate mock data template for a specific domain */ export const getMswMocksTemplate = (domainName: string): string => { const capitalizedDomain = domainName.charAt(0).toUpperCase() + domainName.slice(1); return `// ${capitalizedDomain} Domain Mock Data // This file contains mock data and utilities for ${domainName} domain testing /** * TODO: Replace this interface with your actual ${capitalizedDomain} entity * Import from: '../entities/${capitalizedDomain}' */ interface ${capitalizedDomain} { id: string; name: string; createdAt: string; updatedAt: string; // Add your domain-specific fields here } /** * Mock ${domainName} data store */ class Mock${capitalizedDomain}Data { private data: ${capitalizedDomain}[] = [ { id: '1', name: 'Sample ${capitalizedDomain} 1', createdAt: '2025-01-01T00:00:00Z', updatedAt: '2025-01-01T00:00:00Z', }, { id: '2', name: 'Sample ${capitalizedDomain} 2', createdAt: '2025-01-02T00:00:00Z', updatedAt: '2025-01-02T00:00:00Z', }, { id: '3', name: 'Sample ${capitalizedDomain} 3', createdAt: '2025-01-03T00:00:00Z', updatedAt: '2025-01-03T00:00:00Z', }, ]; /** * Get all ${domainName} items */ getAll(): ${capitalizedDomain}[] { return [...this.data]; } /** * Get ${domainName} item by ID */ getById(id: string): ${capitalizedDomain} | undefined { return this.data.find(item => item.id === id); } /** * Create new ${domainName} item */ create(item: Partial<${capitalizedDomain}>): ${capitalizedDomain} { const newItem: ${capitalizedDomain} = { id: Date.now().toString(), name: item.name || 'New ${capitalizedDomain}', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), ...item, }; this.data.push(newItem); return newItem; } /** * Update ${domainName} item */ update(id: string, updates: Partial<${capitalizedDomain}>): ${capitalizedDomain} | undefined { const index = this.data.findIndex(item => item.id === id); if (index === -1) { return undefined; } this.data[index] = { ...this.data[index], ...updates, updatedAt: new Date().toISOString(), }; return this.data[index]; } /** * Delete ${domainName} item */ delete(id: string): boolean { const index = this.data.findIndex(item => item.id === id); if (index === -1) { return false; } this.data.splice(index, 1); return true; } /** * Reset data to initial state (useful for tests) */ reset(): void { this.data = [ { id: '1', name: 'Sample ${capitalizedDomain} 1', createdAt: '2025-01-01T00:00:00Z', updatedAt: '2025-01-01T00:00:00Z', }, { id: '2', name: 'Sample ${capitalizedDomain} 2', createdAt: '2025-01-02T00:00:00Z', updatedAt: '2025-01-02T00:00:00Z', }, { id: '3', name: 'Sample ${capitalizedDomain} 3', createdAt: '2025-01-03T00:00:00Z', updatedAt: '2025-01-03T00:00:00Z', }, ]; } /** * Add custom methods for your domain-specific operations * Example: getByStatus, getByUser, etc. */ } // Export singleton instance export const mock${capitalizedDomain}Data = new Mock${capitalizedDomain}Data(); `; }; /** * Generate setupTests.ts configuration for MSW */ export const getMswSetupTestsTemplate = (): string => { return `// Global Test Setup with MSW // This file configures testing environment with Mock Service Worker import '@testing-library/jest-dom'; import { server } from './mocks/server'; // Enable MSW server before all tests beforeAll(() => { server.listen({ onUnhandledRequest: 'warn' }); }); // Reset handlers between tests to ensure test isolation afterEach(() => { server.resetHandlers(); }); // Close server after all tests afterAll(() => { server.close(); }); // Global test utilities global.ResizeObserver = class ResizeObserver { observe() {} unobserve() {} disconnect() {} }; // Mock console.error for cleaner test output const originalError = console.error; beforeAll(() => { console.error = (...args: any[]) => { if ( typeof args[0] === 'string' && args[0].includes('Warning: ReactDOM.render is deprecated') ) { return; } originalError.call(console, ...args); }; }); afterAll(() => { console.error = originalError; }); `; };