UNPKG

playwright-test-generator

Version:

Automated Page Object and Functional Test Generator for Playwright

227 lines (224 loc) โ€ข 9.95 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.TestScenarioGenerator = void 0; const PageObjectGenerator_1 = require("./PageObjectGenerator"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); class TestScenarioGenerator { constructor(page, baseOutputDir) { this.page = page; this.pageObjectGenerator = new PageObjectGenerator_1.PageObjectGenerator(page); this.baseOutputDir = baseOutputDir; } async generateTestScenarios(pageName, elements) { console.log('๐Ÿงช Generating test scenarios...'); const scenarios = []; // Generate navigation scenarios const navigationScenarios = this.generateNavigationScenarios(pageName, elements); scenarios.push(...navigationScenarios); // Generate form scenarios const formScenarios = this.generateFormScenarios(pageName, elements); scenarios.push(...formScenarios); // Generate validation scenarios const validationScenarios = this.generateValidationScenarios(pageName, elements); scenarios.push(...validationScenarios); console.log(`โœ… Generated ${scenarios.length} test scenarios`); return scenarios; } generateNavigationScenarios(pageName, elements) { const scenarios = []; const clickableElements = elements.filter(el => ['button', 'link'].includes(el.type)); clickableElements.forEach((element, index) => { scenarios.push({ id: `nav_pos_${index + 1}`, name: `Should navigate successfully when clicking ${element.suggestedVariableName}`, type: 'positive', category: 'navigation', steps: [ { action: 'click', element: element.suggestedVariableName, description: `Click on ${element.suggestedVariableName}` }, { action: 'wait', value: '2000', description: 'Wait for navigation to complete' }, { action: 'verify', assertion: 'page should navigate to new location', description: 'Verify navigation occurred' } ], expectedOutcome: `Successfully navigates to the target page when ${element.suggestedVariableName} is clicked`, pageObjectsNeeded: [pageName] }); }); return scenarios; } generateFormScenarios(pageName, elements) { const scenarios = []; const formElements = elements.filter(el => ['input', 'select', 'checkbox', 'radio'].includes(el.type)); if (formElements.length === 0) return scenarios; scenarios.push({ id: 'form_pos_1', name: 'Should successfully fill and submit form with valid data', type: 'positive', category: 'form', steps: [ ...formElements.map(element => ({ action: 'fill', element: element.suggestedVariableName, value: this.generateTestData(element), description: `Fill ${element.suggestedVariableName} with valid data` })), { action: 'verify', assertion: 'form should accept valid data', description: 'Verify form accepts all valid inputs' } ], expectedOutcome: 'Form should accept and process valid data successfully', pageObjectsNeeded: [pageName] }); return scenarios; } generateValidationScenarios(pageName, elements) { const scenarios = []; const textElements = elements.filter(el => ['heading', 'text'].includes(el.type)); textElements.forEach((element, index) => { scenarios.push({ id: `val_pos_${index + 1}`, name: `Should display correct ${element.suggestedVariableName} text`, type: 'positive', category: 'validation', steps: [ { action: 'verify', element: element.suggestedVariableName, assertion: 'should be visible and contain expected text', description: `Verify ${element.suggestedVariableName} is displayed correctly` } ], expectedOutcome: `${element.suggestedVariableName} should display the correct text content`, pageObjectsNeeded: [pageName] }); }); return scenarios; } generateTestData(element) { const elementName = element.suggestedVariableName.toLowerCase(); if (elementName.includes('email')) return 'test@example.com'; if (elementName.includes('name')) return 'Test User'; if (elementName.includes('phone')) return '+1234567890'; if (elementName.includes('age')) return '25'; if (elementName.includes('date')) return '2024-01-01'; if (elementName.includes('password')) return 'Test123!'; if (elementName.includes('url')) return 'https://example.com'; if (elementName.includes('number')) return '123'; return 'Test Data'; } generateTestFileCode(scenarios, pageName) { const className = `${pageName.replace(/\s+/g, '')}Page`; const pageVariableName = pageName.toLowerCase().replace(/\s+/g, '') + 'Page'; const imports = `import { test, expect } from '@playwright/test'; import { ${className} } from '../pageObjects/${className}';`; const describeBlock = `test.describe('${pageName} Functional Tests', () => { let ${pageVariableName}: ${className}; test.beforeEach(async ({ page }) => { ${pageVariableName} = new ${className}(page); await ${pageVariableName}.verifyPageLoaded(); }); ${this.generateTestMethods(scenarios, pageName)} });`; return `${imports} ${describeBlock}`; } generateTestMethods(scenarios, pageName) { const pageVariable = pageName.toLowerCase().replace(/\s+/g, '') + 'Page'; return scenarios.map(scenario => { const testSteps = scenario.steps.map(step => { switch (step.action) { case 'click': return step.element ? ` await ${pageVariable}.${step.element}.click();` : ` // ${step.description}`; case 'fill': return step.element && step.value ? ` await ${pageVariable}.fill${step.element.charAt(0).toUpperCase() + step.element.slice(1)}('${step.value}');` : ` // ${step.description}`; case 'verify': return step.element ? ` await expect(${pageVariable}.${step.element}).toBeVisible();` : ` // ${step.description}`; case 'wait': return ` await page.waitForTimeout(${step.value || '1000'});`; default: return ` // ${step.description}`; } }).join('\n'); return ` test('${scenario.name}', async ({ page }) => { // ${scenario.expectedOutcome} ${testSteps} });`; }).join('\n\n'); } // Fixed method signature - removed navigationResults parameter async saveTestFile(scenarios, pageName) { const testCode = this.generateTestFileCode(scenarios, pageName); const testFileName = `${pageName.replace(/\s+/g, '').toLowerCase()}Tests.spec.ts`; const testOutputPath = path.join(this.baseOutputDir, 'e2e', testFileName); const dir = path.dirname(testOutputPath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(testOutputPath, testCode); console.log(`โœ… Test file saved to: ${testOutputPath}`); return testOutputPath; } } exports.TestScenarioGenerator = TestScenarioGenerator; //# sourceMappingURL=TestScenarioGenerator.js.map