vineguard-mcp-server-standalone
Version:
VineGuard MCP Server v2.1 - Intelligent QA Workflow System with advanced test generation for Jest/RTL, Cypress, and Playwright. Features smart project analysis, progressive testing strategies, and comprehensive quality patterns for React/Vue/Angular proje
550 lines (461 loc) • 17.3 kB
JavaScript
/**
* Cypress E2E test generator
* Supports user flows, API testing, and visual testing patterns
*/
export class CypressGenerator {
/**
* Generate Cypress test based on test type
*/
static generateTest(options) {
const { testType } = options;
switch (testType) {
case 'user-flow':
return this.generateUserFlowTest(options);
case 'api':
return this.generateApiTest(options);
case 'smoke':
return this.generateSmokeTest(options);
case 'visual':
return this.generateVisualTest(options);
case 'accessibility':
return this.generateAccessibilityTest(options);
default:
return this.generateBasicTest(options);
}
}
/**
* Generate comprehensive user flow test
*/
static generateUserFlowTest(options) {
const { featureName, hasAuth = false, hasApi = false, baseUrl = 'http://localhost:3000' } = options;
return `describe('${featureName} - User Flow', () => {
beforeEach(() => {
// Setup before each test
cy.visit('${baseUrl}');
${hasAuth ? `
// Setup authentication
cy.login('test@example.com', 'password123');` : ''}
${hasApi ? `
// Setup API interceptors
cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('getUsers');
cy.intercept('POST', '/api/users', { statusCode: 201, body: { success: true } }).as('createUser');` : ''}
// Set viewport for consistent testing
cy.viewport(1280, 720);
});
afterEach(() => {
// Cleanup after each test
${hasAuth ? `cy.logout();` : ''}
// Clear any stored data
cy.clearAllLocalStorage();
cy.clearAllSessionStorage();
});
describe('Happy Path', () => {
it('should complete the main user journey successfully', () => {
// Step 1: Navigate to feature
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
cy.url().should('include', '/${featureName.toLowerCase()}');
// Step 2: Verify page loads correctly
cy.get('[data-testid="${featureName.toLowerCase()}-page"]').should('be.visible');
cy.get('h1').should('contain.text', '${featureName}');
${hasApi ? `
// Wait for API calls to complete
cy.wait('@getUsers');` : ''}
// Step 3: Interact with main feature
cy.get('[data-testid="primary-action-button"]').click();
// Step 4: Fill out form (if applicable)
cy.get('[data-testid="name-input"]').type('Test User');
cy.get('[data-testid="email-input"]').type('test@example.com');
// Step 5: Submit and verify success
cy.get('[data-testid="submit-button"]').click();
${hasApi ? `
cy.wait('@createUser');` : ''}
// Step 6: Verify success state
cy.get('[data-testid="success-message"]')
.should('be.visible')
.and('contain.text', 'Success');
// Step 7: Verify redirect or state change
cy.url().should('include', '/success');
});
it('should handle navigation between pages', () => {
// Test multi-page flows
cy.get('[data-testid="step-1"]').click();
cy.url().should('include', '/step-1');
cy.get('[data-testid="next-button"]').click();
cy.url().should('include', '/step-2');
cy.get('[data-testid="back-button"]').click();
cy.url().should('include', '/step-1');
});
});
describe('Error Handling', () => {
it('should handle form validation errors', () => {
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
// Submit form without required fields
cy.get('[data-testid="submit-button"]').click();
// Verify validation errors
cy.get('[data-testid="name-error"]')
.should('be.visible')
.and('contain.text', 'Name is required');
cy.get('[data-testid="email-error"]')
.should('be.visible')
.and('contain.text', 'Email is required');
});
${hasApi ? `
it('should handle API errors gracefully', () => {
// Mock API error
cy.intercept('POST', '/api/users', { statusCode: 500, body: { error: 'Server error' } }).as('serverError');
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
cy.get('[data-testid="name-input"]').type('Test User');
cy.get('[data-testid="email-input"]').type('test@example.com');
cy.get('[data-testid="submit-button"]').click();
cy.wait('@serverError');
// Verify error handling
cy.get('[data-testid="error-message"]')
.should('be.visible')
.and('contain.text', 'Something went wrong');
});` : ''}
it('should handle network failures', () => {
// Simulate offline behavior
cy.intercept('**', { forceNetworkError: true });
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
cy.get('[data-testid="submit-button"]').click();
cy.get('[data-testid="network-error"]')
.should('be.visible')
.and('contain.text', 'Network error');
});
});
describe('Edge Cases', () => {
it('should handle empty states', () => {
// Mock empty data response
cy.intercept('GET', '/api/users', { body: [] }).as('emptyUsers');
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
cy.wait('@emptyUsers');
cy.get('[data-testid="empty-state"]')
.should('be.visible')
.and('contain.text', 'No items found');
});
it('should handle long loading times', () => {
// Mock slow API response
cy.intercept('GET', '/api/users', { delay: 3000, fixture: 'users.json' }).as('slowUsers');
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
// Verify loading state
cy.get('[data-testid="loading-spinner"]').should('be.visible');
cy.wait('@slowUsers');
// Verify loading state disappears
cy.get('[data-testid="loading-spinner"]').should('not.exist');
});
it('should handle browser back/forward navigation', () => {
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
cy.get('[data-testid="step-1"]').click();
cy.go('back');
cy.url().should('include', '/${featureName.toLowerCase()}');
cy.go('forward');
cy.url().should('include', '/step-1');
});
});
describe('Mobile Responsive', () => {
it('should work on mobile viewport', () => {
cy.viewport('iphone-x');
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
// Verify mobile-specific elements
cy.get('[data-testid="mobile-menu"]').should('be.visible');
cy.get('[data-testid="desktop-menu"]').should('not.be.visible');
// Test mobile interactions
cy.get('[data-testid="mobile-menu-toggle"]').click();
cy.get('[data-testid="mobile-nav"]').should('be.visible');
});
it('should work on tablet viewport', () => {
cy.viewport('ipad-2');
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
// Verify tablet-specific layout
cy.get('[data-testid="tablet-layout"]').should('be.visible');
});
});
});`;
}
/**
* Generate API test
*/
static generateApiTest(options) {
const { featureName, hasAuth = false } = options;
return `describe('${featureName} - API Tests', () => {
let authToken: string;
before(() => {
${hasAuth ? `
// Get authentication token
cy.request({
method: 'POST',
url: '/api/auth/login',
body: {
email: 'test@example.com',
password: 'password123'
}
}).then((response) => {
expect(response.status).to.eq(200);
authToken = response.body.token;
});` : ''}
});
beforeEach(() => {
// Set base URL for API requests
cy.intercept('**').as('apiRequest');
});
describe('CRUD Operations', () => {
it('should create a new record via API', () => {
const newRecord = {
name: 'Test Record',
description: 'Test Description',
category: 'test'
};
cy.request({
method: 'POST',
url: '/api/${featureName.toLowerCase()}',
body: newRecord,
${hasAuth ? `headers: { Authorization: \`Bearer \${authToken}\` },` : ''}
}).then((response) => {
expect(response.status).to.eq(201);
expect(response.body).to.have.property('id');
expect(response.body.name).to.eq(newRecord.name);
});
});
it('should retrieve records via API', () => {
cy.request({
method: 'GET',
url: '/api/${featureName.toLowerCase()}',
${hasAuth ? `headers: { Authorization: \`Bearer \${authToken}\` },` : ''}
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.be.an('array');
expect(response.body.length).to.be.greaterThan(0);
});
});
it('should update a record via API', () => {
const recordId = 1;
const updatedData = {
name: 'Updated Record',
description: 'Updated Description'
};
cy.request({
method: 'PUT',
url: \`/api/${featureName.toLowerCase()}/\${recordId}\`,
body: updatedData,
${hasAuth ? `headers: { Authorization: \`Bearer \${authToken}\` },` : ''}
}).then((response) => {
expect(response.status).to.eq(200);
expect(response.body.name).to.eq(updatedData.name);
});
});
it('should delete a record via API', () => {
const recordId = 1;
cy.request({
method: 'DELETE',
url: \`/api/${featureName.toLowerCase()}/\${recordId}\`,
${hasAuth ? `headers: { Authorization: \`Bearer \${authToken}\` },` : ''}
}).then((response) => {
expect(response.status).to.eq(204);
});
});
});
describe('Error Handling', () => {
it('should handle 404 errors', () => {
cy.request({
method: 'GET',
url: '/api/${featureName.toLowerCase()}/999999',
failOnStatusCode: false,
${hasAuth ? `headers: { Authorization: \`Bearer \${authToken}\` },` : ''}
}).then((response) => {
expect(response.status).to.eq(404);
expect(response.body).to.have.property('error');
});
});
it('should handle validation errors', () => {
cy.request({
method: 'POST',
url: '/api/${featureName.toLowerCase()}',
body: {}, // Empty body to trigger validation
failOnStatusCode: false,
${hasAuth ? `headers: { Authorization: \`Bearer \${authToken}\` },` : ''}
}).then((response) => {
expect(response.status).to.eq(400);
expect(response.body).to.have.property('errors');
});
});
${hasAuth ? `
it('should handle unauthorized requests', () => {
cy.request({
method: 'GET',
url: '/api/${featureName.toLowerCase()}',
failOnStatusCode: false,
// No authorization header
}).then((response) => {
expect(response.status).to.eq(401);
});
});` : ''}
});
describe('Performance', () => {
it('should respond within acceptable time limits', () => {
const startTime = Date.now();
cy.request({
method: 'GET',
url: '/api/${featureName.toLowerCase()}',
${hasAuth ? `headers: { Authorization: \`Bearer \${authToken}\` },` : ''}
}).then((response) => {
const endTime = Date.now();
const responseTime = endTime - startTime;
expect(response.status).to.eq(200);
expect(responseTime).to.be.lessThan(2000); // 2 second threshold
});
});
});
});`;
}
/**
* Generate smoke test
*/
static generateSmokeTest(options) {
const { featureName, baseUrl = 'http://localhost:3000' } = options;
return `describe('${featureName} - Smoke Tests', () => {
it('should load the application successfully', () => {
cy.visit('${baseUrl}');
// Verify basic page elements load
cy.get('body').should('be.visible');
cy.title().should('not.be.empty');
// Check for critical navigation elements
cy.get('[data-testid="main-nav"]').should('be.visible');
cy.get('[data-testid="logo"]').should('be.visible');
});
it('should navigate to ${featureName} page', () => {
cy.visit('${baseUrl}');
cy.get('[data-testid="nav-${featureName.toLowerCase()}"]').click();
cy.url().should('include', '/${featureName.toLowerCase()}');
// Verify page loaded
cy.get('h1').should('be.visible');
});
it('should not have JavaScript errors', () => {
cy.visit('${baseUrl}');
cy.window().then((win) => {
expect(win.console.error).to.not.have.been.called;
});
});
it('should have working links', () => {
cy.visit('${baseUrl}');
// Test critical links don't return 404
cy.get('a[href]').each(($link) => {
const href = $link.attr('href');
if (href && !href.startsWith('http') && !href.startsWith('mailto:')) {
cy.request(href).its('status').should('eq', 200);
}
});
});
});`;
}
/**
* Generate visual regression test
*/
static generateVisualTest(options) {
const { featureName, viewport = { width: 1280, height: 720 } } = options;
return `describe('${featureName} - Visual Tests', () => {
beforeEach(() => {
cy.viewport(${viewport.width}, ${viewport.height});
});
it('should match visual baseline for desktop', () => {
cy.visit('/${featureName.toLowerCase()}');
// Wait for page to fully load
cy.get('[data-testid="${featureName.toLowerCase()}-page"]').should('be.visible');
// Take visual snapshot
cy.matchImageSnapshot('${featureName.toLowerCase()}-desktop');
});
it('should match visual baseline for mobile', () => {
cy.viewport('iphone-x');
cy.visit('/${featureName.toLowerCase()}');
cy.get('[data-testid="${featureName.toLowerCase()}-page"]').should('be.visible');
cy.matchImageSnapshot('${featureName.toLowerCase()}-mobile');
});
it('should match visual baseline for different states', () => {
cy.visit('/${featureName.toLowerCase()}');
// Test loading state
cy.get('[data-testid="loading-trigger"]').click();
cy.get('[data-testid="loading-spinner"]').should('be.visible');
cy.matchImageSnapshot('${featureName.toLowerCase()}-loading');
// Test error state
cy.get('[data-testid="error-trigger"]').click();
cy.get('[data-testid="error-message"]').should('be.visible');
cy.matchImageSnapshot('${featureName.toLowerCase()}-error');
// Test empty state
cy.get('[data-testid="empty-trigger"]').click();
cy.get('[data-testid="empty-state"]').should('be.visible');
cy.matchImageSnapshot('${featureName.toLowerCase()}-empty');
});
});`;
}
/**
* Generate accessibility test
*/
static generateAccessibilityTest(options) {
const { featureName } = options;
return `describe('${featureName} - Accessibility Tests', () => {
beforeEach(() => {
cy.visit('/${featureName.toLowerCase()}');
cy.injectAxe(); // Inject axe-core for accessibility testing
});
it('should not have accessibility violations', () => {
cy.checkA11y();
});
it('should be navigable with keyboard only', () => {
// Test tab navigation
cy.get('body').tab();
cy.focused().should('be.visible');
// Navigate through all interactive elements
cy.get('[data-testid="interactive-element"]').each(($el) => {
cy.wrap($el).focus().should('have.focus');
});
});
it('should work with screen reader', () => {
// Test ARIA labels and descriptions
cy.get('[data-testid="main-content"]')
.should('have.attr', 'aria-label')
.and('not.be.empty');
// Test heading hierarchy
cy.get('h1').should('exist');
cy.get('h2').should('exist');
// Test form labels
cy.get('input').each(($input) => {
cy.wrap($input).should('have.attr', 'aria-label').or('have.attr', 'aria-labelledby');
});
});
it('should have sufficient color contrast', () => {
cy.checkA11y(null, {
rules: {
'color-contrast': { enabled: true }
}
});
});
it('should support high contrast mode', () => {
// Simulate high contrast mode
cy.get('body').invoke('addClass', 'high-contrast');
// Verify elements are still visible and usable
cy.get('[data-testid="main-nav"]').should('be.visible');
cy.get('button').should('be.visible');
cy.checkA11y();
});
});`;
}
/**
* Generate basic test (fallback)
*/
static generateBasicTest(options) {
const { featureName, baseUrl = 'http://localhost:3000' } = options;
return `describe('${featureName}', () => {
beforeEach(() => {
cy.visit('${baseUrl}');
});
it('should load the page successfully', () => {
cy.get('[data-testid="${featureName.toLowerCase()}-page"]').should('be.visible');
cy.title().should('contain', '${featureName}');
});
it('should have working interactions', () => {
cy.get('[data-testid="primary-button"]').click();
cy.get('[data-testid="result"]').should('be.visible');
});
});`;
}
}
//# sourceMappingURL=cypress-generator.js.map