Skip to main content
Glama
StudentOfJS

MCP Frontend Testing Server

generateTest

Create automated tests for frontend code using Jest or Cypress frameworks. Supports unit, component, and end-to-end testing in JavaScript, TypeScript, JSX, and TSX.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeYes
descriptionNo
frameworkYes
languageNojavascript
typeYes

Implementation Reference

  • Handler function for the 'generateTest' tool. It calls the generateTestCode helper with provided parameters and returns the generated test code in MCP format, or an error if generation fails.
    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)}`,
          }],
        };
      }
    }
  • Input schema for the 'generateTest' tool using Zod, validating code snippet, testing framework, test type, language, and optional description.
    {
      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()
    },
  • The server.tool call that registers the 'generateTest' tool, including its schema and handler implementation.
    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)}`,
            }],
          };
        }
      }
    );
  • Primary helper function that implements the test generation logic. Analyzes source code, extracts name, generates imports and test suites tailored to framework (Jest/Cypress) and type (unit/component/e2e), incorporating analysis results.
    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}`;
    }
  • Supporting helper function called by generateTestCode to statically analyze the source code, detecting React components, functions, hooks, events, async operations, and providing test recommendations.
    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;
    }
Install Server

Other Tools

Related Tools

Latest Blog Posts

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