playwright-test-generator
Version:
Automated Page Object and Functional Test Generator for Playwright
227 lines (224 loc) โข 9.95 kB
JavaScript
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
;