#
tokens: 16932/50000 24/24 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .dockerignore
├── .gitignore
├── dist
│   ├── index.d.ts
│   ├── index.js
│   ├── index.js.map
│   ├── prompts
│   │   ├── index.d.ts
│   │   ├── index.js
│   │   └── index.js.map
│   ├── resources
│   │   ├── docs.d.ts
│   │   ├── docs.js
│   │   ├── docs.js.map
│   │   ├── templates.d.ts
│   │   ├── templates.js
│   │   └── templates.js.map
│   ├── server.d.ts
│   ├── server.js
│   ├── server.js.map
│   ├── tools
│   │   ├── analyzer.d.ts
│   │   ├── analyzer.js
│   │   ├── analyzer.js.map
│   │   ├── component-tester.d.ts
│   │   ├── component-tester.js
│   │   ├── component-tester.js.map
│   │   ├── generator.d.ts
│   │   ├── generator.js
│   │   ├── generator.js.map
│   │   ├── runner.d.ts
│   │   ├── runner.js
│   │   └── runner.js.map
│   ├── transports
│   │   ├── http.d.ts
│   │   ├── http.js
│   │   ├── http.js.map
│   │   ├── stdio.d.ts
│   │   ├── stdio.js
│   │   └── stdio.js.map
│   └── utils
│       ├── command-executor.d.ts
│       ├── command-executor.js
│       ├── command-executor.js.map
│       ├── test-config.d.ts
│       ├── test-config.js
│       ├── test-config.js.map
│       ├── test-environment.d.ts
│       ├── test-environment.js
│       └── test-environment.js.map
├── docker-compose.yml
├── Dockerfile
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── src
│   ├── index.ts
│   ├── prompts
│   │   └── index.ts
│   ├── resources
│   │   ├── docs.ts
│   │   └── templates.ts
│   ├── server.ts
│   ├── tools
│   │   ├── analyzer.ts
│   │   ├── component-tester.ts
│   │   ├── generator.ts
│   │   └── runner.ts
│   ├── transports
│   │   ├── http.ts
│   │   └── stdio.ts
│   └── utils
│       ├── command-executor.ts
│       ├── test-config.ts
│       └── test-environment.ts
├── templates
│   ├── cypress
│   │   └── component.txt
│   └── jest
│       ├── component.txt
│       └── unit.txt
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
1 | node_modules
2 | 
```

--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------

```
 1 | # Node.js
 2 | node_modules
 3 | npm-debug.log
 4 | yarn-debug.log
 5 | yarn-error.log
 6 | 
 7 | # TypeScript output
 8 | dist
 9 | build
10 | 
11 | # Version control
12 | .git
13 | .gitignore
14 | 
15 | # Docker
16 | Dockerfile
17 | docker-compose.yml
18 | .dockerignore
19 | 
20 | # Environment variables
21 | .env
22 | .env.*
23 | 
24 | # IDE specific files
25 | .idea
26 | .vscode
27 | *.swp
28 | *.swo
29 | 
30 | # Logs
31 | logs
32 | *.log
33 | 
34 | # Test coverage
35 | coverage
36 | .nyc_output
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | # MCP Frontend Testing Server
  2 | 
  3 | ## Description
  4 | 
  5 | This MCP server provides tools for frontend testing, including:
  6 | 
  7 | - **Code Analysis**: Analyzes JavaScript/TypeScript code to determine appropriate testing strategies.
  8 | - **Test Generation**: Generates unit and component tests for Jest and Cypress.
  9 | - **Test Running**: Executes tests using Jest and Cypress and returns results.
 10 | - **Component Testing**: Provides a tool specifically for testing React components.
 11 | 
 12 | ## Getting Started
 13 | 
 14 | ### Installation
 15 | 
 16 | 1.  **Clone the repository:**
 17 |     \`git clone <repository-url> mcp-frontend-testing\`
 18 | 2.  **Navigate to the project directory:**
 19 |     \`cd mcp-frontend-testing\`
 20 | 3.  **Install dependencies:**
 21 |     \`npm install\`
 22 | 
 23 | ### Running the Server
 24 | 
 25 | #### HTTP Transport
 26 | 
 27 | \`\`\`bash
 28 | # Build the server
 29 | npm run build
 30 | 
 31 | # Start the server with HTTP transport
 32 | npm run start:http
 33 | \`\`\`
 34 | 
 35 | #### Stdio Transport
 36 | 
 37 | \`\`\`bash
 38 | # Build the server
 39 | npm run build
 40 | 
 41 | # Start the server with Stdio transport
 42 | npm run start:stdio
 43 | \`\`\`
 44 | 
 45 | ## Usage
 46 | 
 47 | ### Tools
 48 | 
 49 | -   **analyzeCode**: Analyzes code and returns analysis results.
 50 |     -   **Parameters**:
 51 |         -   \`code\` (string, required): The source code to analyze.
 52 |         -   \`language\` (enum, optional): Language of the code (\`javascript\` | \`typescript\` | \`jsx\` | \`tsx\`, default: \`javascript\`).
 53 | -   **generateTest**: Generates test code based on source code and framework.
 54 |     -   **Parameters**:
 55 |         -   \`code\` (string, required): The source code to generate tests for.
 56 |         -   \`framework\` (enum, required): Testing framework (\`jest\` | \`cypress\`).
 57 |         -   \`type\` (enum, required): Type of test (\`unit\` | \`component\` | \`e2e\`).
 58 |         -   \`language\` (enum, optional): Language of the code (\`javascript\` | \`typescript\` | \`jsx\` | \`tsx\`, default: \`javascript\`).
 59 |         -   \`description\` (string, optional): Description of the test case.
 60 | -   **runTest**: Runs tests and returns results.
 61 |     -   **Parameters**:
 62 |         -   \`sourceCode\` (string, required): The source code being tested.
 63 |         -   \`testCode\` (string, required): The test code to execute.
 64 |         -   \`framework\` (enum, required): Testing framework (\`jest\` | \`cypress\`).
 65 |         -   \`type\` (enum, required): Type of test (\`unit\` | \`component\` | \`e2e\`).
 66 |         -   \`config\` (record, optional): Configuration object for test execution.
 67 | -   **testReactComponent**: Runs component tests specifically for React components.
 68 |     -   **Parameters**:
 69 |         -   \`componentCode\` (string, required): The source code of the React component.
 70 |         -   \`testCode\` (string, optional): Test code for the component (auto-generated if not provided).
 71 |         -   \`framework\` (enum, optional): Testing framework (\`jest\` | \`cypress\`, default: \`jest\`).
 72 |         -   \`props\` (record, optional): Props to pass to the component during testing.
 73 |         -   \`autoGenerateTest\` (boolean, optional): Automatically generate test code if not provided (default: \`true\`).
 74 | 
 75 | ### Resources
 76 | 
 77 | -   **templates**: Provides test templates.
 78 |     -   **URI**: \`templates://{framework}/{type}\`
 79 |     -   **Parameters**:
 80 |         -   \`framework\` (string, required): Testing framework (\`jest\` | \`cypress\`).
 81 |         -   \`type\` (string, required): Type of template (\`unit\` | \`component\`).
 82 | -   **docs**: Provides documentation for testing frameworks.
 83 |     -   **URI**: \`docs://{topic}\`
 84 |     -   **Parameters**:
 85 |         -   \`topic\` (string, required): Documentation topic (\`jest\` | \`cypress\` | \`react-testing-library\`).
 86 | 
 87 | ## Deployment
 88 | 
 89 | ### Docker
 90 | 
 91 | Build and run the server using Docker:
 92 | 
 93 | \`\`\`bash
 94 | docker build -t mcp-frontend-testing .
 95 | docker run -p 3000:3000 mcp-frontend-testing
 96 | \`\`\`
 97 | 
 98 | ### Cloud
 99 | 
100 | Deploy to cloud platforms like AWS Lambda, Google Cloud Run, or Azure Functions for serverless or containerized deployments.
101 | 
102 | ---
103 | 
104 | **Note**: This server is designed to be used with an MCP client to enable LLMs to perform frontend testing tasks.
```

--------------------------------------------------------------------------------
/templates/jest/unit.txt:
--------------------------------------------------------------------------------

```
 1 | // Jest unit test template
 2 | describe('Unit test', () => {
 3 |   test('should work correctly', () => {
 4 |     // Arrange
 5 |     
 6 |     // Act
 7 |     
 8 |     // Assert
 9 |     expect(true).toBe(true);
10 |   });
11 | });
```

--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------

```yaml
 1 | version: '3.8'
 2 | 
 3 | services:
 4 |   mcp-frontend-testing:
 5 |     build:
 6 |       context: .
 7 |       dockerfile: Dockerfile
 8 |     image: mcp-frontend-testing
 9 |     container_name: mcp-frontend-testing
10 |     ports:
11 |       - "3000:3000"
12 |     environment:
13 |       - NODE_ENV=production
14 |     restart: unless-stopped
```

--------------------------------------------------------------------------------
/templates/cypress/component.txt:
--------------------------------------------------------------------------------

```
 1 | // Cypress component test template
 2 | import { mount } from '@cypress/react';
 3 | import Component from './Component';
 4 | 
 5 | describe('Component', () => {
 6 |   it('renders correctly', () => {
 7 |     // Arrange
 8 |     mount(<Component />);
 9 |     
10 |     // Assert
11 |     cy.contains(/example/i).should('be.visible');
12 |   });
13 | });
```

--------------------------------------------------------------------------------
/src/transports/stdio.ts:
--------------------------------------------------------------------------------

```typescript
1 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2 | import { createServer } from '../server.js';
3 | 
4 | export async function startStdioServer(): Promise<void> {
5 |   const server = createServer();
6 |   const transport = new StdioServerTransport();
7 |   await server.connect(transport);
8 | }
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "module": "NodeNext",
 5 |     "moduleResolution": "NodeNext",
 6 |     "esModuleInterop": true,
 7 |     "strict": true,
 8 |     "outDir": "dist",
 9 |     "sourceMap": true,
10 |     "declaration": true,
11 |     "jsx": "react-jsx",
12 |     "lib": ["ES2022", "DOM"],
13 |     "skipLibCheck": true
14 |   },
15 |   "include": ["src/**/*"],
16 |   "exclude": ["node_modules", "dist"]
17 | }
```

--------------------------------------------------------------------------------
/templates/jest/component.txt:
--------------------------------------------------------------------------------

```
 1 | // Jest React component test template
 2 | import { render, screen } from '@testing-library/react';
 3 | import userEvent from '@testing-library/user-event';
 4 | import Component from './Component';
 5 | 
 6 | describe('Component', () => {
 7 |   test('renders correctly', () => {
 8 |     // Arrange
 9 |     render(<Component />);
10 |     
11 |     // Assert
12 |     expect(screen.getByText(/example/i)).toBeInTheDocument();
13 |   });
14 | });
```

--------------------------------------------------------------------------------
/src/utils/command-executor.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { exec } from 'child_process';
 2 | import util from 'util';
 3 | 
 4 | const execPromise = util.promisify(exec);
 5 | 
 6 | // Execute a command and return stdout
 7 | export async function executeCommand(command: string, cwd: string): Promise<any> {
 8 |     return new Promise((resolve, reject) => {
 9 |         exec(command, { cwd }, (error, stdout, stderr) => {
10 |             if (error) {
11 |                 reject(error);
12 |             }
13 |             resolve({ stdout, stderr });
14 |         });
15 |     });
16 | }
```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
 1 | # Build stage
 2 | FROM node:20-alpine AS build
 3 | 
 4 | # Set working directory
 5 | WORKDIR /app
 6 | 
 7 | # Copy package files for dependency installation
 8 | COPY package.json package-lock.json ./
 9 | 
10 | # Install dependencies
11 | RUN npm ci
12 | 
13 | # Copy the rest of the application code
14 | COPY . .
15 | 
16 | # Build the TypeScript application
17 | RUN npm run build
18 | 
19 | # Production stage
20 | FROM node:20-alpine AS production
21 | 
22 | # Set working directory
23 | WORKDIR /app
24 | 
25 | # Copy package files
26 | COPY package.json package-lock.json ./
27 | 
28 | # Install only production dependencies
29 | RUN npm ci --production
30 | 
31 | # Copy built application from build stage
32 | COPY --from=build /app/dist ./dist
33 | COPY --from=build /app/templates ./templates
34 | 
35 | # Expose the HTTP port
36 | EXPOSE 3000
37 | 
38 | # Set the default command to run the server with HTTP transport
39 | CMD ["node", "dist/index.js", "--transport=http"]
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { parseArgs } from 'node:util';
 2 | import { startHttpServer } from './transports/http.js';
 3 | import { startStdioServer } from './transports/stdio.js';
 4 | 
 5 | async function main() {
 6 |  // Parse command line arguments
 7 |   const { values } = parseArgs({
 8 |     options: {
 9 |       transport: {
10 |         type: 'string',
11 |         short: 't',
12 |         default: 'stdio'
13 |       },
14 |       port: {
15 |         type: 'string',
16 |         short: 'p',
17 |         default: '3000'
18 |       }
19 |     }
20 |   });
21 | 
22 |   // Start server with appropriate transport
23 |   const transport = values.transport;
24 |   if (transport === 'stdio') {
25 |     await startStdioServer();
26 |   } else if (transport === 'http') {
27 |     const port = parseInt(values.port);
28 |     await startHttpServer(port);
29 |     console.info(`HTTP server started on port ${port}`);
30 |   } else {
31 |     console.error(`Unknown transport: ${transport}`);
32 |     process.exit(1);
33 |   }
34 | }
35 | 
36 | main().catch(err => {
37 |   console.error('Error starting server:', err);
38 |   process.exit(1);
39 | });
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "mcp-frontend-testing",
 3 |   "version": "1.0.0",
 4 |   "description": "MCP server for frontend testing with Jest and Cypress",
 5 |   "main": "dist/index.js",
 6 |   "type": "module",
 7 |   "scripts": {
 8 |     "build": "tsc",
 9 |     "start": "node dist/index.js",
10 |     "start:http": "node dist/index.js --transport=http",
11 |     "start:stdio": "node dist/index.js --transport=stdio",
12 |     "dev": "ts-node-esm src/index.ts",
13 |     "test": "jest"
14 |   },
15 |   "dependencies": {
16 |     "@modelcontextprotocol/sdk": "1.10.2",
17 |     "@testing-library/jest-dom": "^6.1.5",
18 |     "@testing-library/react": "16.3.0",
19 |     "@testing-library/user-event": "^14.5.1",
20 |     "cors": "^2.8.5",
21 |     "cypress": "14.3.2",
22 |     "esbuild": "0.25.3",
23 |     "express": "5.0.1",
24 |     "jest": "^29.7.0",
25 |     "jest-environment-jsdom": "^29.7.0",
26 |     "react": "19.1.0",
27 |     "react-dom": "19.1.0",
28 |     "typescript": "5.8.3",
29 |     "zod": "3.24.3"
30 |   },
31 |   "devDependencies": {
32 |     "@types/cors": "^2.8.17",
33 |     "@types/express": "5.0.1",
34 |     "@types/jest": "^29.5.11",
35 |     "@types/node": "22.13.11",
36 |     "@types/react": "19.1.2",
37 |     "@types/react-dom": "19.1.2",
38 |     "ts-node": "^10.9.1"
39 |   }
40 | }
41 | 
```

--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
 2 | 
 3 | // Import resources
 4 | import { registerTemplateResources } from './resources/templates.js';
 5 | import { registerDocResources } from './resources/docs.js';
 6 | 
 7 | // Import tools
 8 | import { registerAnalyzerTool } from './tools/analyzer.js';
 9 | import { registerGeneratorTool } from './tools/generator.js';
10 | import { registerRunnerTool } from './tools/runner.js';
11 | import { registerComponentTesterTool } from './tools/component-tester.js';
12 | 
13 | // Import prompts
14 | import { registerPrompts } from './prompts/index.js';
15 | 
16 | export function createServer(): McpServer {
17 |   // Create MCP server
18 |   const server = new McpServer({
19 |     name: 'Frontend Testing Server',
20 |     version: '1.0.0',
21 |     description: 'MCP server for testing JavaScript/TypeScript code and React components'
22 |   });
23 | 
24 |   // Register resources
25 |   registerTemplateResources(server);
26 |   registerDocResources(server);
27 | 
28 |   // Register tools
29 |   registerAnalyzerTool(server);
30 |   registerGeneratorTool(server);
31 |   registerRunnerTool(server);
32 |   registerComponentTesterTool(server);
33 | 
34 |   // Register prompts
35 |   registerPrompts(server);
36 | 
37 |   return server;
38 | }
```

--------------------------------------------------------------------------------
/src/prompts/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
 2 | 
 3 | export function registerPrompts(server: McpServer): void {
 4 |   // Simplified implementation to avoid TypeScript errors
 5 |   // These prompts will be used by the LLM to generate test code
 6 |   
 7 |   // Unit test prompt
 8 |   server.prompt(
 9 |     'create-unit-test',
10 |     'Create a unit test for the given code',
11 |     () => ({
12 |       messages: [{
13 |         role: 'user',
14 |         content: {
15 |           type: 'text',
16 |           text: 'Please create a unit test for the provided code.',
17 |         },
18 |       }],
19 |     })
20 |   );
21 | 
22 |   // Component test prompt
23 |   server.prompt(
24 |     'create-component-test',
25 |     'Create a test for a React component',
26 |     () => ({
27 |       messages: [{
28 |         role: 'user',
29 |         content: {
30 |           type: 'text',
31 |           text: 'Please create a test for this React component. Focus on testing the component\'s functionality, props, and user interactions.',
32 |         },
33 |       }],
34 |     })
35 |   );
36 |   
37 |   // Fix failing test prompt
38 |   server.prompt(
39 |     'fix-failing-test',
40 |     'Fix a failing test',
41 |     () => ({
42 |       messages: [{
43 |         role: 'user',
44 |         content: {
45 |           type: 'text',
46 |           text: 'I have a test that\'s failing. Please help me fix it by explaining what\'s wrong and providing a fixed version of the test.',
47 |         },
48 |       }],
49 |     })
50 |   );
51 | }
```

--------------------------------------------------------------------------------
/src/transports/http.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import express from 'express';
 2 | import cors from 'cors';
 3 | import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
 4 | import { createServer } from '../server.js';
 5 | 
 6 | // Map to store active transports
 7 | const transports = new Map<string, SSEServerTransport>();
 8 | 
 9 | export async function startHttpServer(port: number): Promise<void> {
10 |   const app = express();
11 |   app.use(cors());
12 |   app.use(express.json());
13 | 
14 |   // Health check endpoint
15 |   app.get('/health', (req, res) => {
16 |     res.json({ status: 'ok' });
17 |   });
18 | 
19 |   // SSE endpoint
20 |   app.get('/sse/:sessionId', async (req, res) => {
21 |     const { sessionId } = req.params;
22 |     res.setHeader('Content-Type', 'text/event-stream');
23 |     res.setHeader('Cache-Control', 'no-cache');
24 |     res.setHeader('Connection', 'keep-alive');
25 |     
26 |     // Create server and transport
27 |     const server = createServer();
28 |     const transport = new SSEServerTransport('/messages', res);
29 |     transports.set(sessionId, transport);
30 |     
31 |     // Connect the transport to the server
32 |     await server.connect(transport);
33 |     
34 |     // Remove transport when connection closes
35 |     req.on('close', () => {
36 |       transports.delete(sessionId);
37 |     });
38 |   });
39 | 
40 |   // Message endpoint
41 |   app.post('/messages/:sessionId', async (req, res) => {
42 |     const { sessionId } = req.params;
43 |     const transport = transports.get(sessionId);
44 |     
45 |     if (!transport) {
46 |       res.status(404).json({ error: 'Session not found' });
47 |       return;
48 |     }
49 |     
50 |     await transport.handlePostMessage(req, res);
51 |   });
52 | 
53 |   // Start server
54 |   return new Promise((resolve) => {
55 |     app.listen(port, () => {
56 |       resolve();
57 |     });
58 |   });
59 | }
```

--------------------------------------------------------------------------------
/src/tools/runner.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
 2 | import { z } from 'zod';
 3 | import { setupTestEnvironment, executeTest, cleanupTestEnvironment } from '../utils/test-environment.js';
 4 | import crypto from 'crypto';
 5 | import path from 'path';
 6 | import os from 'os';
 7 | import { executeCommand } from '../utils/command-executor.js';
 8 | 
 9 | export { executeCommand };
10 | 
11 | export function registerRunnerTool(server: McpServer): void {
12 |   server.tool(
13 |     'runTest',
14 |     {
15 |       sourceCode: z.string(),
16 |       testCode: z.string(),
17 |       framework: z.enum(['jest', 'cypress']),
18 |       type: z.enum(['unit', 'component', 'e2e']),
19 |       config: z.record(z.any()).optional()
20 |     },
21 |     async ({ sourceCode, testCode, framework, type, config }) => {
22 |       try {
23 |         // Create temporary test environment
24 |         const testId = crypto.randomUUID();
25 |         const testDir = path.join(os.tmpdir(), 'mcp-test-server', testId);
26 |         
27 |         // Set up files
28 |         await setupTestEnvironment(testDir, sourceCode, testCode, framework, type, config);
29 |         
30 |         // Install dependencies
31 |         await executeCommand('npm install', testDir);
32 | 
33 |         try {
34 |           // Run the test
35 |           const results = await executeTest(testDir, framework, type);
36 |           
37 |           return {
38 |             content: [{ 
39 |               type: 'text', 
40 |               text: JSON.stringify(results, null, 2)
41 |             }]
42 |           };
43 |         } finally {
44 |           // Clean up
45 |           await cleanupTestEnvironment(testDir);
46 |         }
47 |       } catch (error) {
48 |         return {
49 |           isError: true,
50 |           content: [{ 
51 |             type: 'text', 
52 |             text: `Error running test: ${String(error)}`
53 |           }]
54 |         };
55 |       }
56 |     }
57 |   );
58 | }
```

--------------------------------------------------------------------------------
/src/tools/component-tester.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
 2 | import { z } from 'zod';
 3 | import { setupTestEnvironment, executeTest } from '../utils/test-environment.js';
 4 | import { generateTestCode } from './generator.js';
 5 | import { executeCommand } from '../utils/command-executor.js';
 6 | import crypto from 'crypto';
 7 | import path from 'path';
 8 | import os from 'os';
 9 | import { rm } from 'fs/promises';
10 | 
11 | export function registerComponentTesterTool(server: McpServer): void {
12 |   server.tool(
13 |     'testReactComponent',
14 |     {
15 |       componentCode: z.string(),
16 |       testCode: z.string().optional(),
17 |       framework: z.enum(['jest', 'cypress']).default('jest'),
18 |       props: z.record(z.any()).optional(),
19 |       autoGenerateTest: z.boolean().default(true)
20 |     },
21 |     async ({ componentCode, testCode, framework, props, autoGenerateTest }) => {
22 |       try {
23 |         // Determine language based on code
24 |         const language = componentCode.includes('tsx') || componentCode.includes(':') ? 
25 |           'tsx' : (componentCode.includes('jsx') ? 'jsx' : 'javascript');
26 |         
27 |         // Generate test if not provided
28 |         let finalTestCode = testCode;
29 |         if (!finalTestCode && autoGenerateTest) {
30 |           finalTestCode = await generateTestCode(
31 |             componentCode, 
32 |             framework, 
33 |             'component', 
34 |             language
35 |           );
36 |         }
37 |         
38 |         if (!finalTestCode) {
39 |           throw new Error('No test code provided or generated');
40 |         }
41 |         
42 |         // Create temporary test environment
43 |         const testId = crypto.randomUUID();
44 |         const testDir = path.join(os.tmpdir(), 'mcp-test-server', testId);
45 |         
46 |         // Set up files for component testing
47 |         await setupTestEnvironment(testDir, componentCode, finalTestCode, framework, 'component', props);
48 |         
49 |         // Install dependencies
50 |         await executeCommand('npm install', testDir);
51 |         
52 |         try {
53 |           // Run the test
54 |           const results = await executeTest(testDir, framework, 'component');
55 |           
56 |           return {
57 |             content: [{ 
58 |               type: 'text', 
59 |               text: JSON.stringify(results, null, 2),
60 |             }],
61 |           };
62 |         } finally {
63 |           // Clean up
64 |           try {
65 |             await rm(testDir, { recursive: true, force: true });
66 |           } catch (error) {
67 |             console.error('Error cleaning up test environment:', error);
68 |           }
69 |         }
70 |       } catch (error) {
71 |         return {
72 |           isError: true,
73 |           content: [{ 
74 |             type: 'text', 
75 |             text: `Error testing component: ${String(error)}`,
76 |           }],
77 |         };
78 |       }
79 |     }
80 |   );
81 | }
```

--------------------------------------------------------------------------------
/src/resources/templates.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
  2 | import { readFile } from 'fs/promises';
  3 | import path from 'path';
  4 | import { fileURLToPath } from 'url';
  5 | 
  6 | // Get directory name
  7 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
  8 | const templatesDir = path.join(__dirname, '../../templates');
  9 | 
 10 | export function registerTemplateResources(server: McpServer): void {
 11 |   // Register template resources
 12 |   server.resource(
 13 |     'templates',
 14 |     new ResourceTemplate('templates://{framework}/{type}', { 
 15 |       list: async () => {
 16 |         return {
 17 |           resources: [
 18 |             {
 19 |               uri: 'templates://jest/component',
 20 |               name: 'Jest Component Test Template',
 21 |               mimeType: 'text/plain',
 22 |               description: 'Template for Jest React component tests'
 23 |             },
 24 |             {
 25 |               uri: 'templates://jest/unit',
 26 |               name: 'Jest Unit Test Template',
 27 |               mimeType: 'text/plain',
 28 |               description: 'Template for Jest unit tests'
 29 |             },
 30 |             {
 31 |               uri: 'templates://cypress/component',
 32 |               name: 'Cypress Component Test Template',
 33 |               mimeType: 'text/plain',
 34 |               description: 'Template for Cypress component tests'
 35 |             }
 36 |           ]
 37 |         };
 38 |       }
 39 |     }),
 40 |     async (uri, { framework, type }) => {
 41 |       try {
 42 |         // Try to load the template file
 43 |         const filePath = path.join(templatesDir, framework as string, `${type as string}.txt`);
 44 |         const content = await readFile(filePath, 'utf-8');
 45 |         
 46 |         return {
 47 |           contents: [{
 48 |             uri: uri.href,
 49 |             text: content
 50 |           }]
 51 |         };
 52 |       } catch (error) {
 53 |         // Fallback to hardcoded templates if file not found
 54 |         const templates: Record<string, Record<string, string>> = {
 55 |           jest: {
 56 |             unit: `
 57 | // Jest unit test template
 58 | describe('Unit test', () => {
 59 |   test('should work correctly', () => {
 60 |     // Arrange
 61 |     
 62 |     // Act
 63 |     
 64 |     // Assert
 65 |     expect(true).toBe(true);
 66 |   });
 67 | });`,
 68 |             component: `
 69 | // Jest React component test template
 70 | import { render, screen } from '@testing-library/react';
 71 | import userEvent from '@testing-library/user-event';
 72 | import Component from './Component';
 73 | 
 74 | describe('Component', () => {
 75 |   test('renders correctly', () => {
 76 |     // Arrange
 77 |     render(<Component />);
 78 |     
 79 |     // Assert
 80 |     expect(screen.getByText(/example/i)).toBeInTheDocument();
 81 |   });
 82 | });`,
 83 |           },
 84 |           cypress: {
 85 |             component: `
 86 | // Cypress component test template
 87 | import Component from './Component';
 88 | 
 89 | describe('Component', () => {
 90 |   it('renders correctly', () => {
 91 |     // Arrange
 92 |     cy.mount(<Component />);
 93 |     
 94 |     // Assert
 95 |     cy.contains(/example/i).should('be.visible');
 96 |   });
 97 | });`,
 98 |           }
 99 |         };
100 |         
101 |         const frameworkTemplates = templates[framework as keyof typeof templates];
102 |         const templateContent = frameworkTemplates && (type as string) in frameworkTemplates
103 |           ? frameworkTemplates[type as string]
104 |           : "Template not found";
105 |         
106 |         return {
107 |           contents: [{
108 |             uri: uri.href,
109 |             text: templateContent
110 |           }]
111 |         };
112 |       }
113 |     }
114 |   );
115 |   
116 |   // Template index
117 |   server.resource(
118 |     'templates-index',
119 |     'templates://',
120 |     async (uri) => {
121 |       return {
122 |         contents: [{
123 |           uri: uri.href,
124 |           text: JSON.stringify({
125 |             frameworks: [
126 |               'jest',
127 |               'cypress'
128 |             ],
129 |             types: [
130 |               'unit',
131 |               'component'
132 |             ]
133 |           }, null, 2)
134 |         }]
135 |       };
136 |     }
137 |   );
138 | }
```

--------------------------------------------------------------------------------
/src/utils/test-config.ts:
--------------------------------------------------------------------------------

```typescript
  1 | // Default Jest configuration for different test types
  2 | export function getDefaultJestConfig(
  3 |   type: 'unit' | 'component' | 'e2e', 
  4 |   isTypeScript: boolean
  5 | ): string {
  6 |   const baseConfig: any = {
  7 |     transform: {},
  8 |     testEnvironment: type === 'component' ? 'jsdom' : 'node',
  9 |     setupFilesAfterEnv: type === 'component' ? ['<rootDir>/setupTests.js'] : [],
 10 |     moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
 11 |     moduleDirectories: ['node_modules', '<rootDir>'],
 12 |   };
 13 |   
 14 |   if (isTypeScript) {
 15 |     baseConfig.transform = {'\\.(ts|tsx)$': 'ts-jest'};
 16 |     baseConfig.testRegex = '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$';
 17 |     baseConfig.moduleFileExtensions = ['ts', 'tsx', 'js', 'jsx', 'json', 'node'];
 18 |   } else {
 19 |     baseConfig.transform = {'\\.(js|jsx)$': 'babel-jest'};
 20 |     baseConfig.testRegex = '(/__tests__/.*|\\.(test|spec))\\.(js|jsx)$';
 21 |     baseConfig.moduleFileExtensions = ['js', 'jsx', 'json', 'node'];
 22 |   }
 23 |   
 24 |   return `export default ${JSON.stringify(baseConfig, null, 2)};`;
 25 | }
 26 | 
 27 | // Default Cypress configuration for different test types
 28 | export function getDefaultCypressConfig(
 29 |   type: 'unit' | 'component' | 'e2e', 
 30 |   isTypeScript: boolean
 31 | ): string {
 32 |   let config;
 33 |   
 34 |   if (type === 'component') {
 35 |     config = {
 36 |       component: {
 37 |         devServer: {
 38 |           framework: 'react',
 39 |           bundler: 'vite',
 40 |         },
 41 |         specPattern: isTypeScript ? '**/*.cy.{js,jsx,ts,tsx}' : '**/*.cy.{js,jsx}',
 42 |       },
 43 |     };
 44 |   } else {
 45 |     config = {
 46 |       e2e: {
 47 |         setupNodeEvents(on: any, config: any) {
 48 |           return config;
 49 |         },
 50 |         specPattern: isTypeScript ? 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}' : 'cypress/e2e/**/*.cy.{js,jsx}',
 51 |       },
 52 |     };
 53 |   }
 54 |   
 55 |   return `import { defineConfig } from 'cypress'
 56 | 
 57 | export default defineConfig(${JSON.stringify(config, null, 2)})`;
 58 | }
 59 | 
 60 | // Generate component wrappers for testing with props
 61 | export function getComponentTestWrappers(
 62 |   componentName: string, 
 63 |   isTypeScript: boolean
 64 | ): { wrapperCode: string, importStatement: string } {
 65 |   const importStatement = isTypeScript 
 66 |     ? `import React from 'react';`
 67 |     : `import React from 'react';`;
 68 |   
 69 |   const wrapperCode = isTypeScript
 70 |     ? `export const TestWrapper: React.FC = () => {
 71 |   return <${componentName} {...testProps} />;
 72 | };
 73 | 
 74 | export default TestWrapper;`
 75 |     : `export const TestWrapper = () => {
 76 |   return <${componentName} {...testProps} />;
 77 | };
 78 | 
 79 | export default TestWrapper;`;
 80 | 
 81 |   return { wrapperCode, importStatement };
 82 | }
 83 | 
 84 | // Get dependencies for package.json based on test configuration
 85 | export function getDependencies(
 86 |   framework: string,
 87 |   type: string,
 88 |   isTypeScript: boolean,
 89 |   isReact: boolean
 90 | ): Record<string, string> {
 91 |   const dependencies: Record<string, string> = {
 92 |     // Common dependencies
 93 |     "jest": "^29.7.0",
 94 |   };
 95 | 
 96 |   // TypeScript dependencies
 97 |   if (isTypeScript) {
 98 |     dependencies["typescript"] = "^5.3.3";
 99 |     dependencies["ts-jest"] = "^29.1.1";
100 |     dependencies["@types/jest"] = "^29.5.11";
101 |   }
102 | 
103 |   // React dependencies
104 |   if (isReact) {
105 |     dependencies["react"] = "^18.2.0";
106 |     dependencies["react-dom"] = "^18.2.0";
107 |     
108 |     if (isTypeScript) {
109 |       dependencies["@types/react"] = "^18.2.42";
110 |       dependencies["@types/react-dom"] = "^18.2.17";
111 |     }
112 |   }
113 | 
114 |   // Framework-specific dependencies
115 |   if (framework === 'jest') {
116 |     dependencies["jest-environment-jsdom"] = "^29.7.0";
117 |     
118 |     if (type === 'component' || isReact) {
119 |       dependencies["@testing-library/react"] = "^14.1.2";
120 |       dependencies["@testing-library/jest-dom"] = "^6.1.5";
121 |       dependencies["@testing-library/user-event"] = "^14.5.1";
122 |     }
123 |   } else if (framework === 'cypress') {
124 |     dependencies["cypress"] = "^13.6.1";
125 |     
126 |     if (type === 'component' || isReact) {
127 |       dependencies["@cypress/react"] = "^7.0.3";
128 |     }
129 |   }
130 | 
131 |   // Build tools
132 |   dependencies["esbuild"] = "^0.19.9";
133 |   
134 |   return dependencies;
135 | }
```

--------------------------------------------------------------------------------
/src/resources/docs.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
  2 | 
  3 | export function registerDocResources(server: McpServer): void {
  4 |   server.resource(
  5 |     'docs',
  6 |     new ResourceTemplate('docs://{topic}', { 
  7 |       list: async () => {
  8 |         return {
  9 |           resources: [
 10 |             {
 11 |               uri: 'docs://jest',
 12 |               name: 'Jest Documentation',
 13 |               mimeType: 'text/plain',
 14 |               description: 'Documentation for Jest testing framework'
 15 |             },
 16 |             {
 17 |               uri: 'docs://cypress',
 18 |               name: 'Cypress Documentation',
 19 |               mimeType: 'text/plain',
 20 |               description: 'Documentation for Cypress testing framework'
 21 |             },
 22 |             {
 23 |               uri: 'docs://react-testing-library',
 24 |               name: 'React Testing Library Documentation',
 25 |               mimeType: 'text/plain',
 26 |               description: 'Documentation for React Testing Library'
 27 |             }
 28 |           ]
 29 |         };
 30 |       }
 31 |     }),
 32 |     async (uri, { topic }) => {
 33 |       const docs: Record<string, string> = {
 34 |         jest: `
 35 | # Jest Documentation
 36 | 
 37 | Jest is a JavaScript testing framework designed to ensure correctness of any JavaScript codebase. It allows you to write tests with an approachable, familiar and feature-rich API that gives you results quickly.
 38 | 
 39 | ## Key Features
 40 | 
 41 | - Zero config for most JavaScript projects
 42 | - Snapshots for tracking large objects
 43 | - Isolated test files to avoid sharing state
 44 | - Powerful mocking library
 45 | 
 46 | ## Basic Example
 47 | 
 48 | \`\`\`javascript
 49 | // sum.js
 50 | function sum(a, b) {
 51 |   return a + b;
 52 | }
 53 | module.exports = sum;
 54 | 
 55 | // sum.test.js
 56 | const sum = require('./sum');
 57 | test('adds 1 + 2 to equal 3', () => {
 58 |   expect(sum(1, 2)).toBe(3);
 59 | });
 60 | \`\`\`
 61 | `,
 62 |         cypress: `
 63 | # Cypress Documentation
 64 | 
 65 | Cypress is a next generation front end testing tool built for the modern web. It enables you to write faster, easier and more reliable tests.
 66 | 
 67 | ## Key Features
 68 | 
 69 | - Time Travel: Cypress takes snapshots as your tests run
 70 | - Debuggability: Debug directly from familiar tools like Chrome DevTools
 71 | - Automatic Waiting: Cypress automatically waits for commands and assertions
 72 | - Real-time Reloads: Test is automatically reloaded when you make changes
 73 | 
 74 | ## Basic Example
 75 | 
 76 | \`\`\`javascript
 77 | describe('My First Test', () => {
 78 |   it('clicks the link "type"', () => {
 79 |     cy.visit('https://example.cypress.io')
 80 |     cy.contains('type').click()
 81 |     cy.url().should('include', '/commands/actions')
 82 |   })
 83 | })
 84 | \`\`\`
 85 | `,
 86 |         'react-testing-library': `
 87 | # React Testing Library Documentation
 88 | 
 89 | React Testing Library is a very light-weight solution for testing React components. It provides light utility functions on top of react-dom and react-dom/test-utils, encouraging better testing practices.
 90 | 
 91 | ## Key Features
 92 | 
 93 | - Works with actual DOM nodes
 94 | - Focuses on testing from the user perspective
 95 | - Encourages accessibility best practices
 96 | - Simple and intuitive API
 97 | 
 98 | ## Basic Example
 99 | 
100 | \`\`\`javascript
101 | import { render, screen } from '@testing-library/react';
102 | import userEvent from '@testing-library/user-event';
103 | import '@testing-library/jest-dom';
104 | import Component from './Component.js';
105 | 
106 | test('loads and displays greeting', async () => {
107 |   // Arrange
108 |   render(<Component />)
109 |   
110 |   // Act
111 |   await userEvent.click(screen.getByText('Load Greeting'))
112 |   
113 |   // Assert
114 |   expect(screen.getByRole('heading')).toHaveTextContent('hello there')
115 | })
116 | \`\`\`
117 | `
118 |       };
119 | 
120 |       return {
121 |         contents: [{
122 |           uri: uri.href,
123 |           text: docs[topic as keyof typeof docs] || 'Documentation not found'
124 |         }]
125 |       };
126 |     }
127 |   );
128 |   
129 |   // Documentation index
130 |   server.resource(
131 |     'docs-index',
132 |     'docs://',
133 |     async (uri) => {
134 |       return {
135 |         contents: [{
136 |           uri: uri.href,
137 |           text: JSON.stringify({
138 |             topics: [
139 |               'jest',
140 |               'cypress',
141 |               'react-testing-library'
142 |             ]
143 |           }, null, 2)
144 |         }]
145 |       };
146 |     }
147 |   );
148 | }
149 | 
```

--------------------------------------------------------------------------------
/src/tools/analyzer.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
  2 | import { z } from 'zod';
  3 | 
  4 | export function registerAnalyzerTool(server: McpServer): void {
  5 |   server.tool(
  6 |     'analyzeCode',
  7 |     { 
  8 |       code: z.string(),
  9 |       language: z.enum(['javascript', 'typescript', 'jsx', 'tsx']).default('javascript')
 10 |     },
 11 |     async ({ code, language }) => {
 12 |       try {
 13 |         // Analyze code to determine what kind of tests would be appropriate
 14 |         const analysis = performCodeAnalysis(code, language);
 15 |         return {
 16 |           content: [{ 
 17 |             type: 'text', 
 18 |             text: JSON.stringify(analysis, null, 2),
 19 |           }],
 20 |         };
 21 |       } catch (error) {
 22 |         return {
 23 |           isError: true,
 24 |           content: [{ 
 25 |             type: 'text', 
 26 |             text: `Error analyzing code: ${String(error)}`,
 27 |           }],
 28 |         };
 29 |       }
 30 |     }
 31 |   );
 32 | }
 33 | 
 34 | // Helper function to analyze code
 35 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
 36 | export function performCodeAnalysis(code: string, language: string): any {
 37 |   const analysisResult: any = {
 38 |     codeType: {},
 39 |     complexity: {},
 40 |     recommendations: {}
 41 |   };
 42 | 
 43 |   try {    
 44 |     // Determine if the code is a React component
 45 |     const isReactComponent = code.includes('import React') ||
 46 |                           code.includes('from "react"') ||
 47 |                           code.includes("from 'react'") ||
 48 |                           code.includes('extends Component') ||
 49 |                           code.includes('React.Component') ||
 50 |                           ((code.includes('export') && code.includes('return')) &&
 51 |                            (code.includes('JSX.') || code.includes('<div') || code.includes('<>')));
 52 | 
 53 |     // Check if it's a function or class
 54 |     const isClass = code.includes('class ') && code.includes('extends ');
 55 |     const isFunction = code.includes('function ') || code.includes('=>');
 56 |     
 57 |     // Check if it uses hooks
 58 |     const usesHooks = code.includes('useState') || 
 59 |                     code.includes('useEffect') || 
 60 |                     code.includes('useContext') ||
 61 |                     code.includes('useReducer') ||
 62 |                     code.includes('useCallback') ||
 63 |                     code.includes('useMemo');
 64 |     
 65 |     // Count imports to determine complexity
 66 |     const importMatches = code.match(/import .+ from .+/g);
 67 |     const imports = importMatches ? importMatches.length : 0;
 68 |     
 69 |     // Look for event handlers
 70 |     const hasEvents = code.includes('onClick') || 
 71 |                     code.includes('onChange') || 
 72 |                     code.includes('onSubmit') ||
 73 |                     code.includes('addEventListener');
 74 |     
 75 |     // Look for async operations
 76 |     const hasAsync = code.includes('async ') || 
 77 |                     code.includes('await ') || 
 78 |                     code.includes('Promise') ||
 79 |                     code.includes('.then(') ||
 80 |                     code.includes('fetch(');
 81 |     
 82 |     const recommendedTestTypes: string[] = [];
 83 |     if (isReactComponent) {
 84 |       recommendedTestTypes.push('component');
 85 |       if (hasEvents || hasAsync) {
 86 |         recommendedTestTypes.push('e2e');
 87 |       } else {
 88 |         recommendedTestTypes.push('unit');
 89 |       }
 90 |     } else {
 91 |       recommendedTestTypes.push('unit');
 92 |     }
 93 |   
 94 |     // Recommend testing frameworks
 95 |     const recommendedFrameworks: string[] = [];
 96 |     if (isReactComponent) {
 97 |       recommendedFrameworks.push('jest');
 98 |       if (hasEvents) {
 99 |         recommendedFrameworks.push('cypress');
100 |       } else {
101 |         recommendedFrameworks.push('jest');
102 |       }
103 |     } else {
104 |       recommendedFrameworks.push('jest');
105 |     }
106 | 
107 |     analysisResult.codeType = {
108 |       isReactComponent,
109 |       isClass,
110 |       isFunction,
111 |       usesHooks,
112 |     };
113 |     analysisResult.complexity = {
114 |       imports,
115 |       hasEvents,
116 |       hasAsync
117 |     };
118 |     analysisResult.recommendations = {
119 |       testTypes: recommendedTestTypes,
120 |       frameworks: recommendedFrameworks,
121 |       priority: hasAsync ? 'high' : 'medium'
122 |     };
123 |   } catch (error: any) {
124 |     console.error(`Error during code analysis: ${error.message}`);
125 |   }
126 |   
127 |   return analysisResult;
128 | }
```

--------------------------------------------------------------------------------
/src/tools/generator.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
  2 | import { z } from 'zod';
  3 | import { performCodeAnalysis } from './analyzer.js';
  4 | 
  5 | export function registerGeneratorTool(server: McpServer): void {
  6 |   server.tool(
  7 |     'generateTest',
  8 |     {
  9 |       code: z.string(),
 10 |       framework: z.enum(['jest', 'cypress']),
 11 |       type: z.enum(['unit', 'component', 'e2e']),
 12 |       language: z.enum(['javascript', 'typescript', 'jsx', 'tsx']).default('javascript'),
 13 |       description: z.string().optional()
 14 |     },
 15 |     async ({ code, framework, type, language, description }) => {
 16 |       try {
 17 |         const testCode = generateTestCode(code, framework, type, language, description);
 18 |         return {
 19 |           content: [{ 
 20 |             type: 'text', 
 21 |             text: testCode,
 22 |           }],
 23 |         };
 24 |       } catch (error) {
 25 |         return {
 26 |           isError: true,
 27 |           content: [{ 
 28 |             type: 'text', 
 29 |             text: `Error generating test: ${String(error)}`,
 30 |           }],
 31 |         };
 32 |       }
 33 |     }
 34 |   );
 35 | }
 36 | 
 37 | // Helper function to generate test code based on source code and parameters
 38 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
 39 | export function generateTestCode(
 40 |   sourceCode: string, 
 41 |   framework: string,
 42 |   testType: string,
 43 |   language: string,
 44 |   description?: string
 45 | ): string {
 46 |   // Analyze the code to better understand its structure
 47 |   const analysis = performCodeAnalysis(sourceCode, language);
 48 |   
 49 |   // Extract component or function name
 50 |   const nameMatch = sourceCode.match(/(?:function|class|const)\s+(\w+)/);
 51 |   const name = nameMatch ? nameMatch[1] : 'Component';
 52 |   
 53 |   // Generate appropriate import statements based on framework and test type
 54 |   let imports = '';
 55 |   let testCode = '';
 56 |   
 57 |   if (framework === 'jest') {
 58 |     if (testType === 'unit') {
 59 |       imports = `// Import the module to test\n${language.includes('typescript') ? `import { ${name} } from './${name}';` : `const ${name} = require('./${name}');`}`;
 60 |       testCode = `describe('${name}', () => {
 61 |   test('${description || 'should work correctly'}', () => {
 62 |     // Arrange
 63 |     ${(analysis as any)?.codeType?.isFunction ? `
 64 |     // Example test input
 65 |     const input = 'test';
 66 |     
 67 |     // Act
 68 |     const result = ${name}(input);
 69 |     
 70 |     // Assert
 71 |     expect(result).toBeDefined();` : `
 72 |     // Setup any required state
 73 |     
 74 |     // Act - perform the action
 75 |     
 76 |     // Assert - check the result
 77 |     expect(true).toBe(true);`}
 78 |   });
 79 | ${(analysis as any)?.complexity?.hasAsync ? `
 80 |   test('handles async operations', async () => {
 81 |     // Arrange
 82 |     
 83 |     // Act
 84 |     const result = await ${name}();
 85 |     
 86 |     // Assert
 87 |     expect(result).toBeDefined();
 88 |   });` : ''}
 89 | });`;
 90 |     } else if (testType === 'component') {
 91 |       imports = `import { render, screen${(analysis as any)?.complexity?.hasEvents ? ', fireEvent' : ''} } from '@testing-library/react';\n${(analysis as any)?.complexity?.hasEvents ? `import userEvent from '@testing-library/user-event';` : ''}\n${language.includes('typescript') ? `import { ${name} } from './${name}';` : `import  { default as ${name} } from './${name}';`}`;
 92 |       testCode = `describe('${name}', () => {
 93 |   test('renders correctly', () => {
 94 |     // Arrange
 95 |     render(<${name} />);
 96 |     
 97 |     // Assert
 98 |     expect(screen.getByText(/content/i)).toBeInTheDocument();
 99 |   });
100 | ${(analysis as any).complexity?.hasEvents ? `
101 |   test('handles user interaction', async () => {
102 |     // Arrange
103 |     render(<${name} />);
104 |     
105 |     // Act
106 |     await userEvent.click(screen.getByRole('button'));
107 |     
108 |     // Assert
109 |     expect(screen.getByText(/result/i)).toBeInTheDocument();
110 |   });` : ''}
111 | ${(analysis as any)?.complexity?.hasAsync ? `
112 |   test('loads data asynchronously', async () => {
113 |     // Arrange
114 |     render(<${name} />);
115 |     
116 |     // Act - wait for async operation
117 |     await screen.findByText(/loaded/i);
118 |     
119 |     // Assert
120 |     expect(screen.getByText(/loaded/i)).toBeInTheDocument();
121 |   });` : ''}
122 | });`;
123 |     }
124 |   } else if (framework === 'cypress') {
125 |     if (testType === 'component') {
126 |       imports = `${language.includes('typescript') ? `import { ${name} } from './${name}';` : `import  Component from './Component';`}`;
127 |       testCode = `describe('${name}', () => {
128 |   it('renders correctly', () => {
129 |     // Arrange
130 |     cy.mount(<${name} />);
131 |     
132 |     // Assert
133 |     cy.contains(/content/i).should('be.visible');
134 |   });
135 | ${(analysis as any)?.complexity?.hasEvents ? `
136 |   it('handles user interaction', () => {
137 |     // Arrange
138 |     cy.mount(<${name} />);
139 |     
140 |     // Act
141 |     cy.get('button').click();
142 |     
143 |     // Assert
144 |     cy.contains(/result/i).should('be.visible');
145 |   });` : ''}
146 | ${(analysis as any)?.complexity?.hasAsync ? `
147 |   it('loads data asynchronously', () => {
148 |     // Arrange
149 |     cy.mount(<${name} />);
150 |     
151 |     // Assert - wait for async operation
152 |     cy.contains(/loaded/i, { timeout: 10000 }).should('be.visible');
153 |   });` : ''}
154 | });`;
155 |     } else if (testType === 'e2e') {
156 |       imports = '// No imports needed for Cypress E2E tests';
157 |       testCode = `describe('${name} E2E Test', () => {
158 |   beforeEach(() => {
159 |     // Visit the page containing the component
160 |     cy.visit('/');
161 |   });
162 | 
163 |   it('${description || 'works correctly'}', () => {
164 |     // Assert the component is rendered
165 |     cy.contains(/content/i).should('be.visible');
166 | ${(analysis as any)?.complexity?.hasEvents ? `
167 |     // Act - interact with the component
168 |     cy.get('button').click();
169 |     
170 |     // Assert the interaction worked
171 |     cy.contains(/result/i).should('be.visible');` : ''}
172 | ${(analysis as any)?.complexity?.hasAsync ? `
173 |     // Assert async data loads correctly
174 |     cy.contains(/loaded/i, { timeout: 10000 }).should('be.visible');` : ''}
175 |   });
176 | });`;
177 |     }
178 |   }
179 |   
180 |   // Combine imports and test code
181 |   return `${imports}\n${testCode}`;
182 | }
```

--------------------------------------------------------------------------------
/src/utils/test-environment.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { mkdir, writeFile, rm } from 'fs/promises';
  2 | import path from 'path';
  3 | import { exec } from 'child_process';
  4 | import util from 'util';
  5 | import { getDefaultJestConfig, getDefaultCypressConfig, getComponentTestWrappers, getDependencies } from './test-config.js';
  6 | import { executeCommand } from './command-executor.js';
  7 | 
  8 | const execPromise = util.promisify(exec);
  9 | 
 10 | // Set up a test environment with all necessary files
 11 | export async function setupTestEnvironment(
 12 |   testDir: string, 
 13 |   sourceCode: string, 
 14 |   testCode: string, 
 15 |   framework: 'jest' | 'cypress',
 16 |   type: 'unit' | 'component' | 'e2e',
 17 |   config?: Record<string, any>
 18 | ): Promise<void> {
 19 |   // Create directory structure
 20 |   await mkdir(testDir, { recursive: true });
 21 |   
 22 |   // Determine file extensions
 23 |   const isTypeScript = sourceCode.includes('typescript') || 
 24 |                        sourceCode.includes('tsx') || 
 25 |                        sourceCode.includes(':') || 
 26 |                        sourceCode.includes('interface');
 27 |   const isReact = sourceCode.includes('React') || 
 28 |                  sourceCode.includes('react') || 
 29 |                  sourceCode.includes('JSX') || 
 30 |                  sourceCode.includes('<div') || 
 31 |                  sourceCode.includes('</');
 32 |   
 33 |   const sourceExt = isTypeScript 
 34 |     ? (isReact ? '.tsx' : '.ts') 
 35 |     : (isReact ? '.jsx' : '.js');
 36 |   
 37 |   const testExt = isTypeScript 
 38 |     ? (framework === 'jest' ? '.test.tsx' : '.cy.tsx') 
 39 |     : (framework === 'jest' ? '.test.jsx' : '.cy.jsx');
 40 |   
 41 |   // Extract component or function name
 42 |   const nameMatch = sourceCode.match(/(?:function|class|const)\s+(\w+)/);
 43 |   const name = nameMatch ? nameMatch[1] : 'Component';
 44 |   
 45 |   // Write source file
 46 |   await writeFile(path.join(testDir, `${name}${sourceExt}`), sourceCode);
 47 |   
 48 |   // Write test file
 49 |   await writeFile(path.join(testDir, `${name}${testExt}`), testCode);
 50 |   
 51 |   // Write configuration files
 52 |   if (framework === 'jest') {
 53 |     await writeFile(
 54 |       path.join(testDir, 'jest.config.js'),
 55 |       config?.jestConfig || getDefaultJestConfig(type, isTypeScript) as string
 56 |     );
 57 |     
 58 |     // Setup for React testing
 59 |     if (isReact) {
 60 |       await writeFile(
 61 |         path.join(testDir, 'setupTests.js'),
 62 |         `import '@testing-library/jest-dom';`
 63 |       );
 64 |     }
 65 |   } else if (framework === 'cypress') {
 66 |     await writeFile(
 67 |       path.join(testDir, 'cypress.config.js'),
 68 |       config?.cypressConfig || getDefaultCypressConfig(type, isTypeScript) as string
 69 |     );
 70 |     
 71 |     // Create cypress directory structure for e2e tests
 72 |     if (type === 'e2e') {
 73 |       await mkdir(path.join(testDir, 'cypress', 'e2e'), { recursive: true });
 74 |       await writeFile(
 75 |         path.join(testDir, 'cypress', 'e2e', `${name}.cy.js`),
 76 |         testCode
 77 |       );
 78 |     }
 79 |     
 80 |     // Setup for component testing
 81 |     if (type === 'component') {
 82 |       await mkdir(path.join(testDir, 'cypress', 'support'), { recursive: true });
 83 |       await writeFile(
 84 |         path.join(testDir, 'cypress', 'support', 'component.js'),
 85 |         `import { mount } from 'cypress/react18'
 86 | import './commands'
 87 | Cypress.Commands.add('mount', mount)`
 88 |       );
 89 |       
 90 |       await writeFile(
 91 |         path.join(testDir, 'cypress', 'support', 'commands.js'),
 92 |         `// Custom commands go here`
 93 |       );
 94 |     }
 95 |   }
 96 |   
 97 |   // Set up package.json
 98 |   await writeFile(
 99 |     path.join(testDir, 'package.json'),
100 |     JSON.stringify({
101 |       name: 'mcp-test',
102 |       version: '1.0.0',
103 |       type: 'module',
104 |       dependencies: getDependencies(framework, type, isTypeScript, isReact),
105 |       scripts: {
106 |         test: framework === 'jest' ? 'jest' : 'cypress run'
107 |       }
108 |     }, null, 2)
109 |   );
110 |   
111 |   // Create a basic index.html file for e2e tests
112 |   if (framework === 'cypress' && type === 'e2e') {
113 |     await writeFile(
114 |       path.join(testDir, 'index.html'),
115 |       `<!DOCTYPE html>
116 | <html>
117 | <head>
118 |   <title>Test Page</title>
119 | </head>
120 | <body>
121 |   <div id="root"></div>
122 |   <script type="module" src="./index.js"></script>
123 | </body>
124 | </html>`
125 |     );
126 |     
127 |     await writeFile(
128 |       path.join(testDir, 'index.js'),
129 |       `import React from 'react';
130 | import ReactDOM from 'react-dom/client';
131 | import ${name} from './${name}';
132 | 
133 | ReactDOM.createRoot(document.getElementById('root')).render(
134 |   <React.StrictMode>
135 |     <${name} />
136 |   </React.StrictMode>
137 | );`
138 |     );
139 |   }
140 | }
141 | 
142 | // Set up environment specifically for component testing
143 | export async function setupComponentTestEnvironment(
144 |   testDir: string,
145 |   componentCode: string,
146 |   testCode: string,
147 |   framework: 'jest' | 'cypress',
148 |   props?: Record<string, any>
149 | ): Promise<void> {
150 |   // Determine if TypeScript
151 |   const isTypeScript = componentCode.includes('typescript') || 
152 |                        componentCode.includes('tsx') || 
153 |                        componentCode.includes(':');
154 |   
155 |   // Create directory structure
156 |   await mkdir(testDir, { recursive: true });
157 |   
158 |   // Extract component name
159 |   const nameMatch = componentCode.match(/(?:function|class|const)\s+(\w+)/);
160 |   const name = nameMatch ? nameMatch[1] : 'Component';
161 |   
162 |   // Determine file extensions
163 |   const sourceExt = isTypeScript ? '.tsx' : '.jsx';
164 |   const testExt = isTypeScript 
165 |     ? (framework === 'jest' ? '.test.tsx' : '.cy.tsx') 
166 |     : (framework === 'jest' ? '.test.jsx' : '.cy.jsx');
167 |   
168 |   // Write component file
169 |   await writeFile(path.join(testDir, `${name}${sourceExt}`), componentCode);
170 |   
171 |   // Write test file
172 |   await writeFile(path.join(testDir, `${name}${testExt}`), testCode);
173 |   
174 |   // Create props file if props provided
175 |   if (props) {
176 |     await writeFile(
177 |       path.join(testDir, 'props.json'),
178 |       JSON.stringify(props, null, 2)
179 |     );
180 |     
181 |     // Create a wrapper component for the tests
182 |     const { wrapperCode, importStatement } = getComponentTestWrappers(name, isTypeScript);
183 |     
184 |     await writeFile(
185 |       path.join(testDir, `TestWrapper${sourceExt}`),
186 |       `${importStatement}
187 | import ${name} from './${name}';
188 | import testProps from './props.json';
189 | 
190 | ${wrapperCode}`
191 |     );
192 |   }
193 |   
194 |   // Set up configuration
195 |   if (framework === 'jest') {
196 |     await writeFile(
197 |       path.join(testDir, 'jest.config.js'),
198 |       getDefaultJestConfig('component', isTypeScript) as string
199 |     );
200 |     
201 |     await writeFile(
202 |       path.join(testDir, 'setupTests.js'),
203 |       `import '@testing-library/jest-dom';`
204 |     );
205 |   } else {
206 |     await writeFile(
207 |       path.join(testDir, 'cypress.config.js'),
208 |       getDefaultCypressConfig('component', isTypeScript) as string
209 |     );
210 |     
211 |     await mkdir(path.join(testDir, 'cypress', 'support'), { recursive: true });
212 |     await writeFile(
213 |       path.join(testDir, 'cypress', 'support', 'component.js'),
214 |       `import { mount } from 'cypress/react18'
215 | import './commands'
216 | Cypress.Commands.add('mount', mount)`
217 |     );
218 |     
219 |     await writeFile(
220 |       path.join(testDir, 'cypress', 'support', 'commands.js'),
221 |       `// Custom commands go here`
222 |     );
223 |   }
224 |   
225 |   // Set up package.json
226 |   await writeFile(
227 |     path.join(testDir, 'package.json'),
228 |     JSON.stringify({
229 |       name: 'mcp-component-test',
230 |       version: '1.0.0',
231 |       type: 'module',
232 |       dependencies: getDependencies(framework, 'component', isTypeScript, true),
233 |       scripts: {
234 |         test: framework === 'jest' ? 'jest' : 'cypress run-component'
235 |       }
236 |     }, null, 2)
237 |   );
238 | }
239 | 
240 | // Execute tests and return results
241 | export async function executeTest(
242 |   testDir: string,
243 |   framework: 'jest' | 'cypress',
244 |   type: 'unit' | 'component' | 'e2e'
245 | ): Promise<any> {
246 |   // Change to test directory
247 |   const cwd = process.cwd();
248 |   process.chdir(testDir);
249 |   
250 |   try {
251 |     // Install dependencies
252 |     console.info('Installing dependencies...');
253 |     await executeCommand('npm install --silent', testDir);
254 |     
255 |     // Run tests
256 |     console.info(`Running ${framework} ${type} tests...`);
257 |     let result;
258 |     if (framework === 'jest') {
259 |       result = await executeCommand('npx jest --json', testDir);
260 |       return JSON.parse(result.stdout);
261 |     } else if (framework === 'cypress') {
262 |       if (type === 'component') {
263 |         result = await executeCommand('npx cypress run-component --reporter json', testDir);
264 |       } else {
265 |         result = await executeCommand('npx cypress run --reporter json', testDir);
266 |       }
267 |       return result.stdout ? JSON.parse(result.stdout) : { success: false, error: result.stderr };
268 |     }
269 |   } catch (error) {
270 |     console.error('Test execution error:', error);
271 |     return {
272 |       success: false,
273 |       error: error instanceof Error ? error.message : String(error)
274 |     };
275 |   } finally {
276 |     // Change back to original directory
277 |     process.chdir(cwd);
278 |   }
279 | }
280 | 
281 | // Execute component tests
282 | export async function executeComponentTest(
283 |   testDir: string,
284 |   framework: 'jest' | 'cypress'
285 | ): Promise<any> {
286 |   return executeTest(testDir, framework, 'component');
287 | }
288 | 
289 | // Clean up test environment
290 | export async function cleanupTestEnvironment(testDir: string): Promise<void> {
291 |   try {
292 |     await rm(testDir, { recursive: true, force: true });
293 |   } catch (error) {
294 |     console.error('Error cleaning up test environment:', error);
295 |   }
296 | }
```