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
text/typescript
/**
* 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;
});
`;
};