#
tokens: 12568/50000 24/24 files
lines: off (toggle) GitHub
raw markdown copy
# 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:
--------------------------------------------------------------------------------

```
node_modules

```

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

```
# Node.js
node_modules
npm-debug.log
yarn-debug.log
yarn-error.log

# TypeScript output
dist
build

# Version control
.git
.gitignore

# Docker
Dockerfile
docker-compose.yml
.dockerignore

# Environment variables
.env
.env.*

# IDE specific files
.idea
.vscode
*.swp
*.swo

# Logs
logs
*.log

# Test coverage
coverage
.nyc_output
```

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

```markdown
# MCP Frontend Testing Server

## Description

This MCP server provides tools for frontend testing, including:

- **Code Analysis**: Analyzes JavaScript/TypeScript code to determine appropriate testing strategies.
- **Test Generation**: Generates unit and component tests for Jest and Cypress.
- **Test Running**: Executes tests using Jest and Cypress and returns results.
- **Component Testing**: Provides a tool specifically for testing React components.

## Getting Started

### Installation

1.  **Clone the repository:**
    \`git clone <repository-url> mcp-frontend-testing\`
2.  **Navigate to the project directory:**
    \`cd mcp-frontend-testing\`
3.  **Install dependencies:**
    \`npm install\`

### Running the Server

#### HTTP Transport

\`\`\`bash
# Build the server
npm run build

# Start the server with HTTP transport
npm run start:http
\`\`\`

#### Stdio Transport

\`\`\`bash
# Build the server
npm run build

# Start the server with Stdio transport
npm run start:stdio
\`\`\`

## Usage

### Tools

-   **analyzeCode**: Analyzes code and returns analysis results.
    -   **Parameters**:
        -   \`code\` (string, required): The source code to analyze.
        -   \`language\` (enum, optional): Language of the code (\`javascript\` | \`typescript\` | \`jsx\` | \`tsx\`, default: \`javascript\`).
-   **generateTest**: Generates test code based on source code and framework.
    -   **Parameters**:
        -   \`code\` (string, required): The source code to generate tests for.
        -   \`framework\` (enum, required): Testing framework (\`jest\` | \`cypress\`).
        -   \`type\` (enum, required): Type of test (\`unit\` | \`component\` | \`e2e\`).
        -   \`language\` (enum, optional): Language of the code (\`javascript\` | \`typescript\` | \`jsx\` | \`tsx\`, default: \`javascript\`).
        -   \`description\` (string, optional): Description of the test case.
-   **runTest**: Runs tests and returns results.
    -   **Parameters**:
        -   \`sourceCode\` (string, required): The source code being tested.
        -   \`testCode\` (string, required): The test code to execute.
        -   \`framework\` (enum, required): Testing framework (\`jest\` | \`cypress\`).
        -   \`type\` (enum, required): Type of test (\`unit\` | \`component\` | \`e2e\`).
        -   \`config\` (record, optional): Configuration object for test execution.
-   **testReactComponent**: Runs component tests specifically for React components.
    -   **Parameters**:
        -   \`componentCode\` (string, required): The source code of the React component.
        -   \`testCode\` (string, optional): Test code for the component (auto-generated if not provided).
        -   \`framework\` (enum, optional): Testing framework (\`jest\` | \`cypress\`, default: \`jest\`).
        -   \`props\` (record, optional): Props to pass to the component during testing.
        -   \`autoGenerateTest\` (boolean, optional): Automatically generate test code if not provided (default: \`true\`).

### Resources

-   **templates**: Provides test templates.
    -   **URI**: \`templates://{framework}/{type}\`
    -   **Parameters**:
        -   \`framework\` (string, required): Testing framework (\`jest\` | \`cypress\`).
        -   \`type\` (string, required): Type of template (\`unit\` | \`component\`).
-   **docs**: Provides documentation for testing frameworks.
    -   **URI**: \`docs://{topic}\`
    -   **Parameters**:
        -   \`topic\` (string, required): Documentation topic (\`jest\` | \`cypress\` | \`react-testing-library\`).

## Deployment

### Docker

Build and run the server using Docker:

\`\`\`bash
docker build -t mcp-frontend-testing .
docker run -p 3000:3000 mcp-frontend-testing
\`\`\`

### Cloud

Deploy to cloud platforms like AWS Lambda, Google Cloud Run, or Azure Functions for serverless or containerized deployments.

---

**Note**: This server is designed to be used with an MCP client to enable LLMs to perform frontend testing tasks.
```

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

```
// Jest unit test template
describe('Unit test', () => {
  test('should work correctly', () => {
    // Arrange
    
    // Act
    
    // Assert
    expect(true).toBe(true);
  });
});
```

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

```yaml
version: '3.8'

services:
  mcp-frontend-testing:
    build:
      context: .
      dockerfile: Dockerfile
    image: mcp-frontend-testing
    container_name: mcp-frontend-testing
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    restart: unless-stopped
```

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

```
// Cypress component test template
import { mount } from '@cypress/react';
import Component from './Component';

describe('Component', () => {
  it('renders correctly', () => {
    // Arrange
    mount(<Component />);
    
    // Assert
    cy.contains(/example/i).should('be.visible');
  });
});
```

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

```typescript
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { createServer } from '../server.js';

export async function startStdioServer(): Promise<void> {
  const server = createServer();
  const transport = new StdioServerTransport();
  await server.connect(transport);
}
```

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

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "strict": true,
    "outDir": "dist",
    "sourceMap": true,
    "declaration": true,
    "jsx": "react-jsx",
    "lib": ["ES2022", "DOM"],
    "skipLibCheck": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}
```

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

```
// Jest React component test template
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Component from './Component';

describe('Component', () => {
  test('renders correctly', () => {
    // Arrange
    render(<Component />);
    
    // Assert
    expect(screen.getByText(/example/i)).toBeInTheDocument();
  });
});
```

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

```typescript
import { exec } from 'child_process';
import util from 'util';

const execPromise = util.promisify(exec);

// Execute a command and return stdout
export async function executeCommand(command: string, cwd: string): Promise<any> {
    return new Promise((resolve, reject) => {
        exec(command, { cwd }, (error, stdout, stderr) => {
            if (error) {
                reject(error);
            }
            resolve({ stdout, stderr });
        });
    });
}
```

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

```dockerfile
# Build stage
FROM node:20-alpine AS build

# Set working directory
WORKDIR /app

# Copy package files for dependency installation
COPY package.json package-lock.json ./

# Install dependencies
RUN npm ci

# Copy the rest of the application code
COPY . .

# Build the TypeScript application
RUN npm run build

# Production stage
FROM node:20-alpine AS production

# Set working directory
WORKDIR /app

# Copy package files
COPY package.json package-lock.json ./

# Install only production dependencies
RUN npm ci --production

# Copy built application from build stage
COPY --from=build /app/dist ./dist
COPY --from=build /app/templates ./templates

# Expose the HTTP port
EXPOSE 3000

# Set the default command to run the server with HTTP transport
CMD ["node", "dist/index.js", "--transport=http"]
```

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

```typescript
import { parseArgs } from 'node:util';
import { startHttpServer } from './transports/http.js';
import { startStdioServer } from './transports/stdio.js';

async function main() {
 // Parse command line arguments
  const { values } = parseArgs({
    options: {
      transport: {
        type: 'string',
        short: 't',
        default: 'stdio'
      },
      port: {
        type: 'string',
        short: 'p',
        default: '3000'
      }
    }
  });

  // Start server with appropriate transport
  const transport = values.transport;
  if (transport === 'stdio') {
    await startStdioServer();
  } else if (transport === 'http') {
    const port = parseInt(values.port);
    await startHttpServer(port);
    console.info(`HTTP server started on port ${port}`);
  } else {
    console.error(`Unknown transport: ${transport}`);
    process.exit(1);
  }
}

main().catch(err => {
  console.error('Error starting server:', err);
  process.exit(1);
});
```

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

```json
{
  "name": "mcp-frontend-testing",
  "version": "1.0.0",
  "description": "MCP server for frontend testing with Jest and Cypress",
  "main": "dist/index.js",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "start:http": "node dist/index.js --transport=http",
    "start:stdio": "node dist/index.js --transport=stdio",
    "dev": "ts-node-esm src/index.ts",
    "test": "jest"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "1.10.2",
    "@testing-library/jest-dom": "^6.1.5",
    "@testing-library/react": "16.3.0",
    "@testing-library/user-event": "^14.5.1",
    "cors": "^2.8.5",
    "cypress": "14.3.2",
    "esbuild": "0.25.3",
    "express": "5.0.1",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "react": "19.1.0",
    "react-dom": "19.1.0",
    "typescript": "5.8.3",
    "zod": "3.24.3"
  },
  "devDependencies": {
    "@types/cors": "^2.8.17",
    "@types/express": "5.0.1",
    "@types/jest": "^29.5.11",
    "@types/node": "22.13.11",
    "@types/react": "19.1.2",
    "@types/react-dom": "19.1.2",
    "ts-node": "^10.9.1"
  }
}

```

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

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

// Import resources
import { registerTemplateResources } from './resources/templates.js';
import { registerDocResources } from './resources/docs.js';

// Import tools
import { registerAnalyzerTool } from './tools/analyzer.js';
import { registerGeneratorTool } from './tools/generator.js';
import { registerRunnerTool } from './tools/runner.js';
import { registerComponentTesterTool } from './tools/component-tester.js';

// Import prompts
import { registerPrompts } from './prompts/index.js';

export function createServer(): McpServer {
  // Create MCP server
  const server = new McpServer({
    name: 'Frontend Testing Server',
    version: '1.0.0',
    description: 'MCP server for testing JavaScript/TypeScript code and React components'
  });

  // Register resources
  registerTemplateResources(server);
  registerDocResources(server);

  // Register tools
  registerAnalyzerTool(server);
  registerGeneratorTool(server);
  registerRunnerTool(server);
  registerComponentTesterTool(server);

  // Register prompts
  registerPrompts(server);

  return server;
}
```

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

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

export function registerPrompts(server: McpServer): void {
  // Simplified implementation to avoid TypeScript errors
  // These prompts will be used by the LLM to generate test code
  
  // Unit test prompt
  server.prompt(
    'create-unit-test',
    'Create a unit test for the given code',
    () => ({
      messages: [{
        role: 'user',
        content: {
          type: 'text',
          text: 'Please create a unit test for the provided code.',
        },
      }],
    })
  );

  // Component test prompt
  server.prompt(
    'create-component-test',
    'Create a test for a React component',
    () => ({
      messages: [{
        role: 'user',
        content: {
          type: 'text',
          text: 'Please create a test for this React component. Focus on testing the component\'s functionality, props, and user interactions.',
        },
      }],
    })
  );
  
  // Fix failing test prompt
  server.prompt(
    'fix-failing-test',
    'Fix a failing test',
    () => ({
      messages: [{
        role: 'user',
        content: {
          type: 'text',
          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.',
        },
      }],
    })
  );
}
```

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

```typescript
import express from 'express';
import cors from 'cors';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import { createServer } from '../server.js';

// Map to store active transports
const transports = new Map<string, SSEServerTransport>();

export async function startHttpServer(port: number): Promise<void> {
  const app = express();
  app.use(cors());
  app.use(express.json());

  // Health check endpoint
  app.get('/health', (req, res) => {
    res.json({ status: 'ok' });
  });

  // SSE endpoint
  app.get('/sse/:sessionId', async (req, res) => {
    const { sessionId } = req.params;
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');
    
    // Create server and transport
    const server = createServer();
    const transport = new SSEServerTransport('/messages', res);
    transports.set(sessionId, transport);
    
    // Connect the transport to the server
    await server.connect(transport);
    
    // Remove transport when connection closes
    req.on('close', () => {
      transports.delete(sessionId);
    });
  });

  // Message endpoint
  app.post('/messages/:sessionId', async (req, res) => {
    const { sessionId } = req.params;
    const transport = transports.get(sessionId);
    
    if (!transport) {
      res.status(404).json({ error: 'Session not found' });
      return;
    }
    
    await transport.handlePostMessage(req, res);
  });

  // Start server
  return new Promise((resolve) => {
    app.listen(port, () => {
      resolve();
    });
  });
}
```

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

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { setupTestEnvironment, executeTest, cleanupTestEnvironment } from '../utils/test-environment.js';
import crypto from 'crypto';
import path from 'path';
import os from 'os';
import { executeCommand } from '../utils/command-executor.js';

export { executeCommand };

export function registerRunnerTool(server: McpServer): void {
  server.tool(
    'runTest',
    {
      sourceCode: z.string(),
      testCode: z.string(),
      framework: z.enum(['jest', 'cypress']),
      type: z.enum(['unit', 'component', 'e2e']),
      config: z.record(z.any()).optional()
    },
    async ({ sourceCode, testCode, framework, type, config }) => {
      try {
        // Create temporary test environment
        const testId = crypto.randomUUID();
        const testDir = path.join(os.tmpdir(), 'mcp-test-server', testId);
        
        // Set up files
        await setupTestEnvironment(testDir, sourceCode, testCode, framework, type, config);
        
        // Install dependencies
        await executeCommand('npm install', testDir);

        try {
          // Run the test
          const results = await executeTest(testDir, framework, type);
          
          return {
            content: [{ 
              type: 'text', 
              text: JSON.stringify(results, null, 2)
            }]
          };
        } finally {
          // Clean up
          await cleanupTestEnvironment(testDir);
        }
      } catch (error) {
        return {
          isError: true,
          content: [{ 
            type: 'text', 
            text: `Error running test: ${String(error)}`
          }]
        };
      }
    }
  );
}
```

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

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { setupTestEnvironment, executeTest } from '../utils/test-environment.js';
import { generateTestCode } from './generator.js';
import { executeCommand } from '../utils/command-executor.js';
import crypto from 'crypto';
import path from 'path';
import os from 'os';
import { rm } from 'fs/promises';

export function registerComponentTesterTool(server: McpServer): void {
  server.tool(
    'testReactComponent',
    {
      componentCode: z.string(),
      testCode: z.string().optional(),
      framework: z.enum(['jest', 'cypress']).default('jest'),
      props: z.record(z.any()).optional(),
      autoGenerateTest: z.boolean().default(true)
    },
    async ({ componentCode, testCode, framework, props, autoGenerateTest }) => {
      try {
        // Determine language based on code
        const language = componentCode.includes('tsx') || componentCode.includes(':') ? 
          'tsx' : (componentCode.includes('jsx') ? 'jsx' : 'javascript');
        
        // Generate test if not provided
        let finalTestCode = testCode;
        if (!finalTestCode && autoGenerateTest) {
          finalTestCode = await generateTestCode(
            componentCode, 
            framework, 
            'component', 
            language
          );
        }
        
        if (!finalTestCode) {
          throw new Error('No test code provided or generated');
        }
        
        // Create temporary test environment
        const testId = crypto.randomUUID();
        const testDir = path.join(os.tmpdir(), 'mcp-test-server', testId);
        
        // Set up files for component testing
        await setupTestEnvironment(testDir, componentCode, finalTestCode, framework, 'component', props);
        
        // Install dependencies
        await executeCommand('npm install', testDir);
        
        try {
          // Run the test
          const results = await executeTest(testDir, framework, 'component');
          
          return {
            content: [{ 
              type: 'text', 
              text: JSON.stringify(results, null, 2),
            }],
          };
        } finally {
          // Clean up
          try {
            await rm(testDir, { recursive: true, force: true });
          } catch (error) {
            console.error('Error cleaning up test environment:', error);
          }
        }
      } catch (error) {
        return {
          isError: true,
          content: [{ 
            type: 'text', 
            text: `Error testing component: ${String(error)}`,
          }],
        };
      }
    }
  );
}
```

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

```typescript
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
import { readFile } from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';

// Get directory name
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const templatesDir = path.join(__dirname, '../../templates');

export function registerTemplateResources(server: McpServer): void {
  // Register template resources
  server.resource(
    'templates',
    new ResourceTemplate('templates://{framework}/{type}', { 
      list: async () => {
        return {
          resources: [
            {
              uri: 'templates://jest/component',
              name: 'Jest Component Test Template',
              mimeType: 'text/plain',
              description: 'Template for Jest React component tests'
            },
            {
              uri: 'templates://jest/unit',
              name: 'Jest Unit Test Template',
              mimeType: 'text/plain',
              description: 'Template for Jest unit tests'
            },
            {
              uri: 'templates://cypress/component',
              name: 'Cypress Component Test Template',
              mimeType: 'text/plain',
              description: 'Template for Cypress component tests'
            }
          ]
        };
      }
    }),
    async (uri, { framework, type }) => {
      try {
        // Try to load the template file
        const filePath = path.join(templatesDir, framework as string, `${type as string}.txt`);
        const content = await readFile(filePath, 'utf-8');
        
        return {
          contents: [{
            uri: uri.href,
            text: content
          }]
        };
      } catch (error) {
        // Fallback to hardcoded templates if file not found
        const templates: Record<string, Record<string, string>> = {
          jest: {
            unit: `
// Jest unit test template
describe('Unit test', () => {
  test('should work correctly', () => {
    // Arrange
    
    // Act
    
    // Assert
    expect(true).toBe(true);
  });
});`,
            component: `
// Jest React component test template
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Component from './Component';

describe('Component', () => {
  test('renders correctly', () => {
    // Arrange
    render(<Component />);
    
    // Assert
    expect(screen.getByText(/example/i)).toBeInTheDocument();
  });
});`,
          },
          cypress: {
            component: `
// Cypress component test template
import Component from './Component';

describe('Component', () => {
  it('renders correctly', () => {
    // Arrange
    cy.mount(<Component />);
    
    // Assert
    cy.contains(/example/i).should('be.visible');
  });
});`,
          }
        };
        
        const frameworkTemplates = templates[framework as keyof typeof templates];
        const templateContent = frameworkTemplates && (type as string) in frameworkTemplates
          ? frameworkTemplates[type as string]
          : "Template not found";
        
        return {
          contents: [{
            uri: uri.href,
            text: templateContent
          }]
        };
      }
    }
  );
  
  // Template index
  server.resource(
    'templates-index',
    'templates://',
    async (uri) => {
      return {
        contents: [{
          uri: uri.href,
          text: JSON.stringify({
            frameworks: [
              'jest',
              'cypress'
            ],
            types: [
              'unit',
              'component'
            ]
          }, null, 2)
        }]
      };
    }
  );
}
```

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

```typescript
// Default Jest configuration for different test types
export function getDefaultJestConfig(
  type: 'unit' | 'component' | 'e2e', 
  isTypeScript: boolean
): string {
  const baseConfig: any = {
    transform: {},
    testEnvironment: type === 'component' ? 'jsdom' : 'node',
    setupFilesAfterEnv: type === 'component' ? ['<rootDir>/setupTests.js'] : [],
    moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
    moduleDirectories: ['node_modules', '<rootDir>'],
  };
  
  if (isTypeScript) {
    baseConfig.transform = {'\\.(ts|tsx)$': 'ts-jest'};
    baseConfig.testRegex = '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$';
    baseConfig.moduleFileExtensions = ['ts', 'tsx', 'js', 'jsx', 'json', 'node'];
  } else {
    baseConfig.transform = {'\\.(js|jsx)$': 'babel-jest'};
    baseConfig.testRegex = '(/__tests__/.*|\\.(test|spec))\\.(js|jsx)$';
    baseConfig.moduleFileExtensions = ['js', 'jsx', 'json', 'node'];
  }
  
  return `export default ${JSON.stringify(baseConfig, null, 2)};`;
}

// Default Cypress configuration for different test types
export function getDefaultCypressConfig(
  type: 'unit' | 'component' | 'e2e', 
  isTypeScript: boolean
): string {
  let config;
  
  if (type === 'component') {
    config = {
      component: {
        devServer: {
          framework: 'react',
          bundler: 'vite',
        },
        specPattern: isTypeScript ? '**/*.cy.{js,jsx,ts,tsx}' : '**/*.cy.{js,jsx}',
      },
    };
  } else {
    config = {
      e2e: {
        setupNodeEvents(on: any, config: any) {
          return config;
        },
        specPattern: isTypeScript ? 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}' : 'cypress/e2e/**/*.cy.{js,jsx}',
      },
    };
  }
  
  return `import { defineConfig } from 'cypress'

export default defineConfig(${JSON.stringify(config, null, 2)})`;
}

// Generate component wrappers for testing with props
export function getComponentTestWrappers(
  componentName: string, 
  isTypeScript: boolean
): { wrapperCode: string, importStatement: string } {
  const importStatement = isTypeScript 
    ? `import React from 'react';`
    : `import React from 'react';`;
  
  const wrapperCode = isTypeScript
    ? `export const TestWrapper: React.FC = () => {
  return <${componentName} {...testProps} />;
};

export default TestWrapper;`
    : `export const TestWrapper = () => {
  return <${componentName} {...testProps} />;
};

export default TestWrapper;`;

  return { wrapperCode, importStatement };
}

// Get dependencies for package.json based on test configuration
export function getDependencies(
  framework: string,
  type: string,
  isTypeScript: boolean,
  isReact: boolean
): Record<string, string> {
  const dependencies: Record<string, string> = {
    // Common dependencies
    "jest": "^29.7.0",
  };

  // TypeScript dependencies
  if (isTypeScript) {
    dependencies["typescript"] = "^5.3.3";
    dependencies["ts-jest"] = "^29.1.1";
    dependencies["@types/jest"] = "^29.5.11";
  }

  // React dependencies
  if (isReact) {
    dependencies["react"] = "^18.2.0";
    dependencies["react-dom"] = "^18.2.0";
    
    if (isTypeScript) {
      dependencies["@types/react"] = "^18.2.42";
      dependencies["@types/react-dom"] = "^18.2.17";
    }
  }

  // Framework-specific dependencies
  if (framework === 'jest') {
    dependencies["jest-environment-jsdom"] = "^29.7.0";
    
    if (type === 'component' || isReact) {
      dependencies["@testing-library/react"] = "^14.1.2";
      dependencies["@testing-library/jest-dom"] = "^6.1.5";
      dependencies["@testing-library/user-event"] = "^14.5.1";
    }
  } else if (framework === 'cypress') {
    dependencies["cypress"] = "^13.6.1";
    
    if (type === 'component' || isReact) {
      dependencies["@cypress/react"] = "^7.0.3";
    }
  }

  // Build tools
  dependencies["esbuild"] = "^0.19.9";
  
  return dependencies;
}
```

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

```typescript
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';

export function registerDocResources(server: McpServer): void {
  server.resource(
    'docs',
    new ResourceTemplate('docs://{topic}', { 
      list: async () => {
        return {
          resources: [
            {
              uri: 'docs://jest',
              name: 'Jest Documentation',
              mimeType: 'text/plain',
              description: 'Documentation for Jest testing framework'
            },
            {
              uri: 'docs://cypress',
              name: 'Cypress Documentation',
              mimeType: 'text/plain',
              description: 'Documentation for Cypress testing framework'
            },
            {
              uri: 'docs://react-testing-library',
              name: 'React Testing Library Documentation',
              mimeType: 'text/plain',
              description: 'Documentation for React Testing Library'
            }
          ]
        };
      }
    }),
    async (uri, { topic }) => {
      const docs: Record<string, string> = {
        jest: `
# Jest Documentation

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.

## Key Features

- Zero config for most JavaScript projects
- Snapshots for tracking large objects
- Isolated test files to avoid sharing state
- Powerful mocking library

## Basic Example

\`\`\`javascript
// sum.js
function sum(a, b) {
  return a + b;
}
module.exports = sum;

// sum.test.js
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});
\`\`\`
`,
        cypress: `
# Cypress Documentation

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.

## Key Features

- Time Travel: Cypress takes snapshots as your tests run
- Debuggability: Debug directly from familiar tools like Chrome DevTools
- Automatic Waiting: Cypress automatically waits for commands and assertions
- Real-time Reloads: Test is automatically reloaded when you make changes

## Basic Example

\`\`\`javascript
describe('My First Test', () => {
  it('clicks the link "type"', () => {
    cy.visit('https://example.cypress.io')
    cy.contains('type').click()
    cy.url().should('include', '/commands/actions')
  })
})
\`\`\`
`,
        'react-testing-library': `
# React Testing Library Documentation

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.

## Key Features

- Works with actual DOM nodes
- Focuses on testing from the user perspective
- Encourages accessibility best practices
- Simple and intuitive API

## Basic Example

\`\`\`javascript
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import Component from './Component.js';

test('loads and displays greeting', async () => {
  // Arrange
  render(<Component />)
  
  // Act
  await userEvent.click(screen.getByText('Load Greeting'))
  
  // Assert
  expect(screen.getByRole('heading')).toHaveTextContent('hello there')
})
\`\`\`
`
      };

      return {
        contents: [{
          uri: uri.href,
          text: docs[topic as keyof typeof docs] || 'Documentation not found'
        }]
      };
    }
  );
  
  // Documentation index
  server.resource(
    'docs-index',
    'docs://',
    async (uri) => {
      return {
        contents: [{
          uri: uri.href,
          text: JSON.stringify({
            topics: [
              'jest',
              'cypress',
              'react-testing-library'
            ]
          }, null, 2)
        }]
      };
    }
  );
}

```

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

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';

export function registerAnalyzerTool(server: McpServer): void {
  server.tool(
    'analyzeCode',
    { 
      code: z.string(),
      language: z.enum(['javascript', 'typescript', 'jsx', 'tsx']).default('javascript')
    },
    async ({ code, language }) => {
      try {
        // Analyze code to determine what kind of tests would be appropriate
        const analysis = performCodeAnalysis(code, language);
        return {
          content: [{ 
            type: 'text', 
            text: JSON.stringify(analysis, null, 2),
          }],
        };
      } catch (error) {
        return {
          isError: true,
          content: [{ 
            type: 'text', 
            text: `Error analyzing code: ${String(error)}`,
          }],
        };
      }
    }
  );
}

// Helper function to analyze code
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function performCodeAnalysis(code: string, language: string): any {
  const analysisResult: any = {
    codeType: {},
    complexity: {},
    recommendations: {}
  };

  try {    
    // Determine if the code is a React component
    const isReactComponent = code.includes('import React') ||
                          code.includes('from "react"') ||
                          code.includes("from 'react'") ||
                          code.includes('extends Component') ||
                          code.includes('React.Component') ||
                          ((code.includes('export') && code.includes('return')) &&
                           (code.includes('JSX.') || code.includes('<div') || code.includes('<>')));

    // Check if it's a function or class
    const isClass = code.includes('class ') && code.includes('extends ');
    const isFunction = code.includes('function ') || code.includes('=>');
    
    // Check if it uses hooks
    const usesHooks = code.includes('useState') || 
                    code.includes('useEffect') || 
                    code.includes('useContext') ||
                    code.includes('useReducer') ||
                    code.includes('useCallback') ||
                    code.includes('useMemo');
    
    // Count imports to determine complexity
    const importMatches = code.match(/import .+ from .+/g);
    const imports = importMatches ? importMatches.length : 0;
    
    // Look for event handlers
    const hasEvents = code.includes('onClick') || 
                    code.includes('onChange') || 
                    code.includes('onSubmit') ||
                    code.includes('addEventListener');
    
    // Look for async operations
    const hasAsync = code.includes('async ') || 
                    code.includes('await ') || 
                    code.includes('Promise') ||
                    code.includes('.then(') ||
                    code.includes('fetch(');
    
    const recommendedTestTypes: string[] = [];
    if (isReactComponent) {
      recommendedTestTypes.push('component');
      if (hasEvents || hasAsync) {
        recommendedTestTypes.push('e2e');
      } else {
        recommendedTestTypes.push('unit');
      }
    } else {
      recommendedTestTypes.push('unit');
    }
  
    // Recommend testing frameworks
    const recommendedFrameworks: string[] = [];
    if (isReactComponent) {
      recommendedFrameworks.push('jest');
      if (hasEvents) {
        recommendedFrameworks.push('cypress');
      } else {
        recommendedFrameworks.push('jest');
      }
    } else {
      recommendedFrameworks.push('jest');
    }

    analysisResult.codeType = {
      isReactComponent,
      isClass,
      isFunction,
      usesHooks,
    };
    analysisResult.complexity = {
      imports,
      hasEvents,
      hasAsync
    };
    analysisResult.recommendations = {
      testTypes: recommendedTestTypes,
      frameworks: recommendedFrameworks,
      priority: hasAsync ? 'high' : 'medium'
    };
  } catch (error: any) {
    console.error(`Error during code analysis: ${error.message}`);
  }
  
  return analysisResult;
}
```

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

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { performCodeAnalysis } from './analyzer.js';

export function registerGeneratorTool(server: McpServer): void {
  server.tool(
    'generateTest',
    {
      code: z.string(),
      framework: z.enum(['jest', 'cypress']),
      type: z.enum(['unit', 'component', 'e2e']),
      language: z.enum(['javascript', 'typescript', 'jsx', 'tsx']).default('javascript'),
      description: z.string().optional()
    },
    async ({ code, framework, type, language, description }) => {
      try {
        const testCode = generateTestCode(code, framework, type, language, description);
        return {
          content: [{ 
            type: 'text', 
            text: testCode,
          }],
        };
      } catch (error) {
        return {
          isError: true,
          content: [{ 
            type: 'text', 
            text: `Error generating test: ${String(error)}`,
          }],
        };
      }
    }
  );
}

// Helper function to generate test code based on source code and parameters
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function generateTestCode(
  sourceCode: string, 
  framework: string,
  testType: string,
  language: string,
  description?: string
): string {
  // Analyze the code to better understand its structure
  const analysis = performCodeAnalysis(sourceCode, language);
  
  // Extract component or function name
  const nameMatch = sourceCode.match(/(?:function|class|const)\s+(\w+)/);
  const name = nameMatch ? nameMatch[1] : 'Component';
  
  // Generate appropriate import statements based on framework and test type
  let imports = '';
  let testCode = '';
  
  if (framework === 'jest') {
    if (testType === 'unit') {
      imports = `// Import the module to test\n${language.includes('typescript') ? `import { ${name} } from './${name}';` : `const ${name} = require('./${name}');`}`;
      testCode = `describe('${name}', () => {
  test('${description || 'should work correctly'}', () => {
    // Arrange
    ${(analysis as any)?.codeType?.isFunction ? `
    // Example test input
    const input = 'test';
    
    // Act
    const result = ${name}(input);
    
    // Assert
    expect(result).toBeDefined();` : `
    // Setup any required state
    
    // Act - perform the action
    
    // Assert - check the result
    expect(true).toBe(true);`}
  });
${(analysis as any)?.complexity?.hasAsync ? `
  test('handles async operations', async () => {
    // Arrange
    
    // Act
    const result = await ${name}();
    
    // Assert
    expect(result).toBeDefined();
  });` : ''}
});`;
    } else if (testType === 'component') {
      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}';`}`;
      testCode = `describe('${name}', () => {
  test('renders correctly', () => {
    // Arrange
    render(<${name} />);
    
    // Assert
    expect(screen.getByText(/content/i)).toBeInTheDocument();
  });
${(analysis as any).complexity?.hasEvents ? `
  test('handles user interaction', async () => {
    // Arrange
    render(<${name} />);
    
    // Act
    await userEvent.click(screen.getByRole('button'));
    
    // Assert
    expect(screen.getByText(/result/i)).toBeInTheDocument();
  });` : ''}
${(analysis as any)?.complexity?.hasAsync ? `
  test('loads data asynchronously', async () => {
    // Arrange
    render(<${name} />);
    
    // Act - wait for async operation
    await screen.findByText(/loaded/i);
    
    // Assert
    expect(screen.getByText(/loaded/i)).toBeInTheDocument();
  });` : ''}
});`;
    }
  } else if (framework === 'cypress') {
    if (testType === 'component') {
      imports = `${language.includes('typescript') ? `import { ${name} } from './${name}';` : `import  Component from './Component';`}`;
      testCode = `describe('${name}', () => {
  it('renders correctly', () => {
    // Arrange
    cy.mount(<${name} />);
    
    // Assert
    cy.contains(/content/i).should('be.visible');
  });
${(analysis as any)?.complexity?.hasEvents ? `
  it('handles user interaction', () => {
    // Arrange
    cy.mount(<${name} />);
    
    // Act
    cy.get('button').click();
    
    // Assert
    cy.contains(/result/i).should('be.visible');
  });` : ''}
${(analysis as any)?.complexity?.hasAsync ? `
  it('loads data asynchronously', () => {
    // Arrange
    cy.mount(<${name} />);
    
    // Assert - wait for async operation
    cy.contains(/loaded/i, { timeout: 10000 }).should('be.visible');
  });` : ''}
});`;
    } else if (testType === 'e2e') {
      imports = '// No imports needed for Cypress E2E tests';
      testCode = `describe('${name} E2E Test', () => {
  beforeEach(() => {
    // Visit the page containing the component
    cy.visit('/');
  });

  it('${description || 'works correctly'}', () => {
    // Assert the component is rendered
    cy.contains(/content/i).should('be.visible');
${(analysis as any)?.complexity?.hasEvents ? `
    // Act - interact with the component
    cy.get('button').click();
    
    // Assert the interaction worked
    cy.contains(/result/i).should('be.visible');` : ''}
${(analysis as any)?.complexity?.hasAsync ? `
    // Assert async data loads correctly
    cy.contains(/loaded/i, { timeout: 10000 }).should('be.visible');` : ''}
  });
});`;
    }
  }
  
  // Combine imports and test code
  return `${imports}\n${testCode}`;
}
```

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

```typescript
import { mkdir, writeFile, rm } from 'fs/promises';
import path from 'path';
import { exec } from 'child_process';
import util from 'util';
import { getDefaultJestConfig, getDefaultCypressConfig, getComponentTestWrappers, getDependencies } from './test-config.js';
import { executeCommand } from './command-executor.js';

const execPromise = util.promisify(exec);

// Set up a test environment with all necessary files
export async function setupTestEnvironment(
  testDir: string, 
  sourceCode: string, 
  testCode: string, 
  framework: 'jest' | 'cypress',
  type: 'unit' | 'component' | 'e2e',
  config?: Record<string, any>
): Promise<void> {
  // Create directory structure
  await mkdir(testDir, { recursive: true });
  
  // Determine file extensions
  const isTypeScript = sourceCode.includes('typescript') || 
                       sourceCode.includes('tsx') || 
                       sourceCode.includes(':') || 
                       sourceCode.includes('interface');
  const isReact = sourceCode.includes('React') || 
                 sourceCode.includes('react') || 
                 sourceCode.includes('JSX') || 
                 sourceCode.includes('<div') || 
                 sourceCode.includes('</');
  
  const sourceExt = isTypeScript 
    ? (isReact ? '.tsx' : '.ts') 
    : (isReact ? '.jsx' : '.js');
  
  const testExt = isTypeScript 
    ? (framework === 'jest' ? '.test.tsx' : '.cy.tsx') 
    : (framework === 'jest' ? '.test.jsx' : '.cy.jsx');
  
  // Extract component or function name
  const nameMatch = sourceCode.match(/(?:function|class|const)\s+(\w+)/);
  const name = nameMatch ? nameMatch[1] : 'Component';
  
  // Write source file
  await writeFile(path.join(testDir, `${name}${sourceExt}`), sourceCode);
  
  // Write test file
  await writeFile(path.join(testDir, `${name}${testExt}`), testCode);
  
  // Write configuration files
  if (framework === 'jest') {
    await writeFile(
      path.join(testDir, 'jest.config.js'),
      config?.jestConfig || getDefaultJestConfig(type, isTypeScript) as string
    );
    
    // Setup for React testing
    if (isReact) {
      await writeFile(
        path.join(testDir, 'setupTests.js'),
        `import '@testing-library/jest-dom';`
      );
    }
  } else if (framework === 'cypress') {
    await writeFile(
      path.join(testDir, 'cypress.config.js'),
      config?.cypressConfig || getDefaultCypressConfig(type, isTypeScript) as string
    );
    
    // Create cypress directory structure for e2e tests
    if (type === 'e2e') {
      await mkdir(path.join(testDir, 'cypress', 'e2e'), { recursive: true });
      await writeFile(
        path.join(testDir, 'cypress', 'e2e', `${name}.cy.js`),
        testCode
      );
    }
    
    // Setup for component testing
    if (type === 'component') {
      await mkdir(path.join(testDir, 'cypress', 'support'), { recursive: true });
      await writeFile(
        path.join(testDir, 'cypress', 'support', 'component.js'),
        `import { mount } from 'cypress/react18'
import './commands'
Cypress.Commands.add('mount', mount)`
      );
      
      await writeFile(
        path.join(testDir, 'cypress', 'support', 'commands.js'),
        `// Custom commands go here`
      );
    }
  }
  
  // Set up package.json
  await writeFile(
    path.join(testDir, 'package.json'),
    JSON.stringify({
      name: 'mcp-test',
      version: '1.0.0',
      type: 'module',
      dependencies: getDependencies(framework, type, isTypeScript, isReact),
      scripts: {
        test: framework === 'jest' ? 'jest' : 'cypress run'
      }
    }, null, 2)
  );
  
  // Create a basic index.html file for e2e tests
  if (framework === 'cypress' && type === 'e2e') {
    await writeFile(
      path.join(testDir, 'index.html'),
      `<!DOCTYPE html>
<html>
<head>
  <title>Test Page</title>
</head>
<body>
  <div id="root"></div>
  <script type="module" src="./index.js"></script>
</body>
</html>`
    );
    
    await writeFile(
      path.join(testDir, 'index.js'),
      `import React from 'react';
import ReactDOM from 'react-dom/client';
import ${name} from './${name}';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <${name} />
  </React.StrictMode>
);`
    );
  }
}

// Set up environment specifically for component testing
export async function setupComponentTestEnvironment(
  testDir: string,
  componentCode: string,
  testCode: string,
  framework: 'jest' | 'cypress',
  props?: Record<string, any>
): Promise<void> {
  // Determine if TypeScript
  const isTypeScript = componentCode.includes('typescript') || 
                       componentCode.includes('tsx') || 
                       componentCode.includes(':');
  
  // Create directory structure
  await mkdir(testDir, { recursive: true });
  
  // Extract component name
  const nameMatch = componentCode.match(/(?:function|class|const)\s+(\w+)/);
  const name = nameMatch ? nameMatch[1] : 'Component';
  
  // Determine file extensions
  const sourceExt = isTypeScript ? '.tsx' : '.jsx';
  const testExt = isTypeScript 
    ? (framework === 'jest' ? '.test.tsx' : '.cy.tsx') 
    : (framework === 'jest' ? '.test.jsx' : '.cy.jsx');
  
  // Write component file
  await writeFile(path.join(testDir, `${name}${sourceExt}`), componentCode);
  
  // Write test file
  await writeFile(path.join(testDir, `${name}${testExt}`), testCode);
  
  // Create props file if props provided
  if (props) {
    await writeFile(
      path.join(testDir, 'props.json'),
      JSON.stringify(props, null, 2)
    );
    
    // Create a wrapper component for the tests
    const { wrapperCode, importStatement } = getComponentTestWrappers(name, isTypeScript);
    
    await writeFile(
      path.join(testDir, `TestWrapper${sourceExt}`),
      `${importStatement}
import ${name} from './${name}';
import testProps from './props.json';

${wrapperCode}`
    );
  }
  
  // Set up configuration
  if (framework === 'jest') {
    await writeFile(
      path.join(testDir, 'jest.config.js'),
      getDefaultJestConfig('component', isTypeScript) as string
    );
    
    await writeFile(
      path.join(testDir, 'setupTests.js'),
      `import '@testing-library/jest-dom';`
    );
  } else {
    await writeFile(
      path.join(testDir, 'cypress.config.js'),
      getDefaultCypressConfig('component', isTypeScript) as string
    );
    
    await mkdir(path.join(testDir, 'cypress', 'support'), { recursive: true });
    await writeFile(
      path.join(testDir, 'cypress', 'support', 'component.js'),
      `import { mount } from 'cypress/react18'
import './commands'
Cypress.Commands.add('mount', mount)`
    );
    
    await writeFile(
      path.join(testDir, 'cypress', 'support', 'commands.js'),
      `// Custom commands go here`
    );
  }
  
  // Set up package.json
  await writeFile(
    path.join(testDir, 'package.json'),
    JSON.stringify({
      name: 'mcp-component-test',
      version: '1.0.0',
      type: 'module',
      dependencies: getDependencies(framework, 'component', isTypeScript, true),
      scripts: {
        test: framework === 'jest' ? 'jest' : 'cypress run-component'
      }
    }, null, 2)
  );
}

// Execute tests and return results
export async function executeTest(
  testDir: string,
  framework: 'jest' | 'cypress',
  type: 'unit' | 'component' | 'e2e'
): Promise<any> {
  // Change to test directory
  const cwd = process.cwd();
  process.chdir(testDir);
  
  try {
    // Install dependencies
    console.info('Installing dependencies...');
    await executeCommand('npm install --silent', testDir);
    
    // Run tests
    console.info(`Running ${framework} ${type} tests...`);
    let result;
    if (framework === 'jest') {
      result = await executeCommand('npx jest --json', testDir);
      return JSON.parse(result.stdout);
    } else if (framework === 'cypress') {
      if (type === 'component') {
        result = await executeCommand('npx cypress run-component --reporter json', testDir);
      } else {
        result = await executeCommand('npx cypress run --reporter json', testDir);
      }
      return result.stdout ? JSON.parse(result.stdout) : { success: false, error: result.stderr };
    }
  } catch (error) {
    console.error('Test execution error:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : String(error)
    };
  } finally {
    // Change back to original directory
    process.chdir(cwd);
  }
}

// Execute component tests
export async function executeComponentTest(
  testDir: string,
  framework: 'jest' | 'cypress'
): Promise<any> {
  return executeTest(testDir, framework, 'component');
}

// Clean up test environment
export async function cleanupTestEnvironment(testDir: string): Promise<void> {
  try {
    await rm(testDir, { recursive: true, force: true });
  } catch (error) {
    console.error('Error cleaning up test environment:', error);
  }
}
```