Skip to main content
Glama

MCP Frontend Testing Server

test-environment.ts8.92 kB
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); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/StudentOfJS/mcp-frontend-testing'

If you have feedback or need assistance with the MCP directory API, please join our Discord server