A practice project covering the basics of Playwright UI testing, designed to be flexible to work with either BDD (Gherkin) or non-BDD style — both sharing the same Page Object Model.
| Feature | Purpose |
|---|---|
| Playwright | Cross-browser automation engine |
| Page Object Model | Reusable page abstractions decoupling test logic from UI selectors |
| BDD (playwright-bdd) | Gherkin feature files + step definitions |
| Non-BDD (POM direct) | Plain Playwright tests using page objects directly |
| dotenv | Environment variable management with explicit config path |
| Allure Reporting | Interactive HTML reports with screenshots, videos, and traces |
| Prettier | Consistent code formatting |
| VS Code integration | Cucumber extension auto-complete and step-definition navigation |
| Project-based isolation | bdd-tests and non-bdd-tests projects run independently or together |
├── src/
│ ├── features/ # Gherkin .feature files (BDD scenarios)
│ ├── steps/ # Step definitions mapped to feature files
│ ├── pages/ # Page Object Model classes (shared)
│ └── fixtures/ # Playwright test fixtures
├── tests/
│ └── non-bdd/ # Non-BDD test specs using POM directly
├── .features-gen/ # Auto-generated BDD test specs (do not edit)
├── playwright.config.ts # Central test configuration
├── .env # Local environment variables (gitignored)
├── .env.example # Environment variable template
├── .prettierrc # Code formatting rules
└── .vscode/ # VS Code workspace settings
- Node.js 18+
- npm
git clone <repo>
npm run setupThis installs dependencies and downloads Playwright browsers.
npm test # Run all suites (BDD + non-BDD)
npm run test:bdd # Run BDD tests only
npm run test:non-bdd # Run non-BDD tests onlyFilter by tag in the HTML report or via CLI:
npx playwright test --grep "@bdd-tests"
npx playwright test --grep "@non-bdd-tests"Add :info after any script name to see its description:
npm run test:infoValues are loaded from .env via explicit path (dotenv.config({ path: '.env' })):
BASE_URL="https://www.saucedemo.com"
STANDARD_USER="standard_user"
LOCKED_OUT_USER="locked_out_user"
PASSWORD="secret_sauce"baseURLreads directly fromprocess.env.BASE_URLwith no fallback —.envis required, and a missing.envthrows a clear error instead of silently using a wrong URL- Non-BDD tests use
??fallbacks for their inline variables so they still work if a single env var is missing
npm run allure:serve # Serve Allure report in browser
npm run report # Open Playwright's built-in HTML reportAllure raw results are written to allure-results/ on every test run. Screenshots, videos, and traces are captured on failure.
Both test suites include one deliberately failing scenario to demonstrate failure capture:
- BDD:
src/features/LoginTest.feature— scenario ID 1 in "Empty Credentials" - Non-BDD:
tests/non-bdd/login.spec.ts— "unsuccessful login - empty username"
Both BDD and non-BDD tests share the same Page Object Model (src/pages/). You can start with either approach and switch later without rewriting tests.
Sensitive data lives in .env, not in code. The dotenv setup loads values at startup. baseURL has no fallback — missing .env throws a clear error instead of running against the wrong environment. Non-BDD tests use ?? for their inline variables so a single missing env var won't break them.
BasePage(src/pages/BasePage.ts) — shared base class withprotected readonly pageandgoto(url)LoginPage,InventoryPage— extendBasePage, use getter methods for locators withprivateaccess modifiers- Tests interact through public methods (
login(),getErrorMessage(),expectOnPage()), never directly with locators
Locator getter methods use private by default so tests interact through the page's public API (login(), getErrorMessage()) rather than manipulating elements directly. This enforces encapsulation — if a selector changes, you update one file, not every test.
| Modifier | In class | In subclass | From test |
|---|---|---|---|
private |
✅ | ❌ | ❌ |
protected |
✅ | ✅ | ❌ |
public |
✅ | ✅ | ✅ |
Page objects are provided to tests as custom fixtures via src/fixtures/fixtures.ts. When using custom fixtures, import test from the fixture file (../fixtures/fixtures), not from @playwright/test — otherwise your fixtures won't be available.
- Playwright — playwright.dev
- playwright-bdd — vitalets.github.io/playwright-bdd
- Allure Framework — docs.qameta.io/allure-report
- SauceDemo — test site at saucedemo.com
- Prettier — prettier.io
- dotenv — github.com/motdotla/dotenv