A comprehensive, production-ready E2E testing framework that combines Cucumber for BDD, Playwright for browser automation, and TypeScript for type safety. This framework provides advanced features including intelligent locator management, environment configuration, parallel execution, and sophisticated process management.
- BDD Testing: Cucumber.js integration with Gherkin syntax
- Cross-Browser Support: Chromium, Firefox, and WebKit via Playwright
- TypeScript: Full type safety and modern JavaScript features
- Intelligent Locator Management: JSON-based locator storage with path mapping
- Environment Configuration: Multi-environment support with JSON configuration
- Parallel Execution: Run tests in parallel for faster execution
- Advanced Process Management: Task spawner utility for complex test scenarios
- CLI Interface: Command-line tool with comprehensive options
- Code Quality: ESLint, Prettier, and TypeScript strict mode
- Hot Reload: Development mode with
tsxfor instant feedback
- Node.js: Version 18+ (LTS recommended)
- npm: Version 8+ or yarn: Version 1.22+
- Git: For version control
-
Clone the repository
git clone <repository-url> cd <repository-folder>
-
Install dependencies
npm install
-
Verify installation
npm run test
minimal_e2e/
├── src/
│ ├── config/
│ │ ├── cucumber/ # Cucumber configuration
│ │ ├── environments/ # Environment configurations
│ │ └── executor/ # World configuration
│ ├── features/ # Gherkin feature files
│ ├── hooks/ # Cucumber hooks
│ ├── locators/ # Page locators (JSON)
│ ├── mapping/ # URL to locator mapping
│ ├── reports/ # Test reports
│ ├── steps/ # Step definitions
│ │ ├── action/ # Action steps (click, type, navigate)
│ │ └── validation/ # Validation steps (assertions)
│ ├── types/ # TypeScript type definitions
│ └── utils/ # Utility functions
├── cucumber.mjs # Cucumber configuration
├── index.ts # Main CLI entry point
├── package.json
└── tsconfig.json
# Run all tests
npm run cli -- --environment staging
# Run with specific browser
npm run cli -- --environment staging --browser firefox
# Run in headless mode
npm run cli -- --environment staging --headless true
# Run with parallel execution
npm run cli -- --environment staging --parallel 4# Start development mode with hot reload
npm run dev
# Run tests with specific tags
npm run cli -- --environment staging --tags "@smoke"
# Run tests with custom tag expression
npm run cli -- --environment staging --tags "@smoke and @regression"Create feature files in src/features/:
@smoke
Feature: User Authentication
Scenario: User can login successfully
Given the user navigates to "staging" environment url
When the user fills in the "email" field with "demo@example.com"
And the user fills in the "password" field with "test1234"
And the user clicks on "loginButton"
Then the user should see "Welcome to Home Page" in ".container h1"
Scenario: User sees login form
Given the user navigates to "https://demo-test-site-beta.vercel.app/login"
Then the user should see "Login" in "button[data-test-id='login-button']"Step definitions are automatically organized in src/steps/:
Action Steps (src/steps/action/):
navigation.action.step.ts- Navigation stepsclick.action.step.ts- Click actionstype.action.step.ts- Input actions
Validation Steps (src/steps/validation/):
text.validation.step.ts- Text assertions
Create locator files in src/locators/:
src/locators/login/user login.json:
{
"email": "input[placeholder='Enter your email']",
"password": "input[type='password']",
"loginButton": "button[type='submit']"
}src/locators/home/home.json:
{
"username": "input[name='username']",
"email": "input[name='email']",
"saveChangesButton": "button[type='submit']"
}src/mapping/locator-map.json:
[
{
"name": "user login",
"path": "/login"
},
{
"name": "home",
"path": "/home"
}
]// In step definitions, use locator names instead of selectors
When(
'the user clicks on {string}',
async function (this: CustomWorld, selector: string) {
const locator = resolveLocator(this.page, selector)
await this.page.click(locator, { timeout: 10000 })
}
)src/config/environments/environments.json:
{
"staging": {
"url": "https://demo-test-site-beta.vercel.app",
"username": "demo@example.com",
"password": "test1234"
},
"production": {
"url": "https://production.example.com",
"username": "prod@example.com",
"password": "prod_password"
}
}cucumber.mjs:
export default {
paths: ['src/features/**/*.feature'],
import: ['src/steps/**/*.ts', 'src/hooks/hooks.ts', 'src/config/world.ts'],
loader: ['ts-node/esm'],
format: ['pretty', 'json:src/reports/cucumber.json'],
publishQuiet: true,
}tsconfig.json:
{
"compilerOptions": {
"target": "esnext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"types": ["node", "playwright"]
}
}The framework includes a sophisticated task spawner for managing test scenarios with different test configurations via the CLI:
import {
spawnTask,
spawnMultipleTasks,
taskSpawner,
} from './src/utils/spawner.util'
// Spawn a single process
const process = await spawnTask('npm', ['test'], {
streamLogs: true,
captureOutput: true,
logPrefix: 'test-runner',
})
// Spawn multiple processes concurrently
const services = await spawnMultipleTasks([
{
name: 'database',
command: 'docker',
args: ['run', 'postgres:latest'],
options: { streamLogs: true },
},
{
name: 'api-server',
command: 'npm',
args: ['run', 'start:api'],
options: { streamLogs: true, captureOutput: true },
},
])
// Wait for all processes
await taskSpawner.waitForAll()// Monitor running processes
const running = taskSpawner.getRunningProcesses()
console.log(`Running processes: ${running.size}`)
// Get process output
const output = taskSpawner.getProcessOutput('test-runner')
if (output) {
console.log('STDOUT:', output.stdout.join(''))
console.log('STDERR:', output.stderr.join(''))
}// Listen to process events
taskSpawner.on('spawn', (process) => {
console.log(`🚀 Process spawned: ${process.name}`)
})
taskSpawner.on('exit', ({ processName, code }) => {
console.log(`🏁 Process exited: ${processName} with code ${code}`)
})
taskSpawner.on('error', ({ processName, error }) => {
console.error(`❌ ${processName}: ${error.message}`)
})# Basic usage
npm run cli -- --environment <env>
# All available options
npm run cli -- --help| Option | Short | Description | Required | Default |
|---|---|---|---|---|
--environment |
-e |
Target environment | ✅ | - |
--tags |
-t |
Cucumber tag expression | ✅ | - |
--parallel |
-p |
Number of parallel workers | ❌ | 1 |
--browser |
-b |
Browser engine | ❌ | chromium |
--headless |
-h |
Headless mode | ❌ | true |
# Run smoke tests in parallel
npm run cli -- --environment staging --tags "@smoke" --parallel 4
# Run tests in Firefox with UI
npm run cli -- --environment staging --browser firefox --headless false
# Run regression tests
npm run cli -- --environment production --tags "@regression" --parallel 2# Development with hot reload
npm run dev
# Run tests
npm run test
# Lint code
npm run lint
# Fix linting issues
npm run lint:fix
# Format code
npm run format
# Run CLI
npm run cliThe project includes comprehensive code quality tools:
- ESLint: JavaScript, TypeScript, JSON, and Markdown linting
- Prettier: Code formatting
- TypeScript: Strict type checking
- Husky: Git hooks (if configured)
- Feature Files: High-level test scenarios in Gherkin
- Step Definitions: Reusable step implementations
- Locators: Centralized element selectors
- Environments: Configuration for different test environments
- Hooks: Setup and teardown logic
- Use Locator Repository Pattern: Organize locators by page/component
- Environment-Specific Data: Store test data in environment configs
- Reusable Steps: Create generic, reusable step definitions
- Proper Tagging: Use meaningful tags for test categorization
- Parallel Execution: Leverage parallel execution for faster feedback
-
Browser Installation: Ensure Playwright browsers are installed
npx playwright install
-
Environment Configuration: Verify environment files exist and are valid JSON
-
Locator Resolution: Check that locator mappings match actual URL paths
-
TypeScript Errors: Ensure all imports use
.jsextensions for ES modules
# Run tests in parallel (adjust based on your system)
npm run cli -- --environment staging --parallel 4# Faster execution in headless mode
npm run cli -- --environment staging --headless true- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linting
- Submit a pull request
This project is licensed under the ISC License.
For issues and questions:
- Check the troubleshooting section
- Review existing issues
- Create a new issue with detailed information
Happy Testing! 🎉