End-to-end test automation framework for Jobindex.dk - Denmark's leading job search platform - using Playwright and TypeScript.
View the latest automated test results: Live Dashboard
Reports auto-update on every push to main
Automated E2E testing ensures critical user journeys work correctly across browsers:
- Regression Prevention: Catch breaking changes before production
- Cross-Browser Validation: Verify functionality across Chrome, Firefox, Safari, and mobile
- Documentation: Tests serve as living documentation of expected behavior
Jobindex.dk - Denmark's largest job portal with millions of job listings.
- URL: https://www.jobindex.dk
- Type: Server-rendered pages with dynamic elements
- Features Tested: Search, filters, job details, navigation, pagination
┌─────────────────────────────────────────────────────────────────┐
│ Test Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Job Search │ │ Filters │ │ Navigation │ ... │
│ │ Tests │ │ Tests │ │ Tests │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ Page Object Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ HomePage │ │SearchResults │ │ JobDetails │ │
│ │ │ │ Page │ │ Page │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ▲ │
│ ┌────┴────┐ │
│ │BasePage │ │
│ └─────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ Utilities Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Constants │ │ Helpers │ │ Fixtures │ │
│ │ (Selectors) │ │ (Utilities) │ │ (Setup) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
| Metric | Value |
|---|---|
| Total Tests | 31 unique scenarios |
| Browser Coverage | 4 (Chromium, Firefox, WebKit, Mobile) |
| Total Executions | 124 (31 × 4 browsers) |
| Test Tags | @smoke, @regression, @e2e |
| CI Execution | On every push/PR |
| Component | Technology |
|---|---|
| Test Framework | Playwright 1.57 |
| Language | TypeScript 5.9 (strict mode) |
| Pattern | Page Object Model |
| CI/CD | GitHub Actions |
| Reporting | HTML Dashboard + Chart.js |
| Containerization | Docker + Docker Compose |
| Code Quality | ESLint + Prettier |
- Node.js 18+ (20 LTS recommended)
- npm 9+
# Clone repository
git clone https://github.com/Trittton/web-e2e-playwright-ts.git
cd web-e2e-playwright-ts
# Install dependencies
npm install
# Install Playwright browsers
npx playwright install
# Verify installation
npm testnpm testnpm run test:chromium
npm run test:firefox
npm run test:webkit
npm run test:mobilenpm run test:smoke # Core functionality
npm run test:regression # Extended coverage
npm run test:e2e # Full user journeysnpm run test:ui # Playwright UI mode
npm run test:headed # Visible browser
npm run test:debug # Step-by-step debuggingnpm run report/
├── .github/workflows/
│ └── playwright.yml # CI/CD pipeline
├── src/
│ ├── tests/ # Test specifications
│ │ ├── 01-job-search.spec.ts
│ │ ├── 02-filters.spec.ts
│ │ ├── 03-navigation.spec.ts
│ │ ├── 04-pagination.spec.ts
│ │ └── 05-e2e-journey.spec.ts
│ ├── pages/ # Page Object classes
│ │ ├── BasePage.ts
│ │ ├── HomePage.ts
│ │ ├── SearchResultsPage.ts
│ │ └── JobDetailsPage.ts
│ ├── fixtures/ # Custom test fixtures
│ │ └── test-fixtures.ts
│ └── utils/ # Utilities
│ ├── constants.ts # Selectors & config
│ └── helpers.ts # Helper functions
├── scripts/
│ └── generate-report.js # Dashboard generator
├── test-data/
│ └── search-keywords.json # Test data
└── playwright.config.ts # Playwright configuration
| Test Suite | Tests | Description |
|---|---|---|
| Job Search | 11 | Keyword search, URL parameters, edge cases (special chars, Danish chars, empty search) |
| Filters & Results | 10 | Results validation, job preview details, company names |
| Navigation | 4 | Job details page, back navigation, external links |
| Pagination | 4 | Page controls, context preservation, results continuity |
| E2E Journey | 2 | Complete user flows from search to job details |
Job Search
├── Basic keyword search
├── Search with Danish characters (æøå)
├── Search with special characters
├── Empty search handling
├── Long query handling
├── URL parameter verification
└── Search form visibility
Filters & Results
├── Results count display
├── Job title extraction
├── Company name extraction
├── Job preview details
└── Filter application
Navigation
├── Job details from listing
├── Back navigation
├── External job links
└── New tab handling
Pagination
├── Next/previous page
├── Page number display
├── Results count per page
└── Context preservation
| Method | Description |
|---|---|
goto() |
Navigate to homepage |
search(keyword) |
Perform job search |
searchWithLocation(keyword, location) |
Search with location filter |
isSearchFormVisible() |
Verify search form exists |
acceptCookies() |
Handle cookie consent |
| Method | Description |
|---|---|
getJobCount() |
Get total job count |
getJobTitles() |
Extract all visible job titles |
getCompanyNames() |
Extract company names |
clickFirstJob() |
Navigate to first job listing |
hasPagination() |
Check if pagination exists |
goToNextPage() |
Navigate to next page |
| Method | Description |
|---|---|
getJobTitle() |
Get job title (handles external sites) |
getCompanyName() |
Get company name |
isJobDetailsVisible() |
Verify page loaded |
Copy .env.example to .env:
BASE_URL=https://www.jobindex.dkKey settings in playwright.config.ts:
| Setting | Local | CI |
|---|---|---|
| Timeout | 30s | 30s |
| Retries | 0 | 1 |
| Workers | 4 | 1 |
| Browsers | 4 | 1 (Chromium) |
| Screenshots | On failure | On failure |
| Traces | On first retry | On first retry |
Run tests in containerized environment:
# Run all tests
docker-compose up playwright-tests
# Run smoke tests only
docker-compose up smoke-tests
# Run with UI mode
docker-compose up ui-testsBuild and run manually:
docker build -t jobindex-e2e-tests .
docker run --rm -v $(pwd)/playwright-report:/app/playwright-report jobindex-e2e-testsTests run automatically on:
- Every push to
main - Every pull request
- Manual trigger via
workflow_dispatch
- Setup: Node.js 20, install dependencies
- Install: Playwright browsers with system deps
- Execute: Run tests with JSON reporter
- Generate: Create HTML dashboard
- Deploy: Publish to GitHub Pages
- Archive: Upload artifacts (30-day retention)
- HTML Dashboard (
gh-pages/index.html) - Detailed Playwright Report (
playwright-report/) - Test Results JSON (
test-results/results.json)
The website has two search implementations. Our selectors handle both:
- Modern Search: Uses placeholder/aria-label selectors
- Traditional Search: Uses
name="qs"selector
# Increase timeout for slow connections
npx playwright test --timeout 60000# Show trace for failed test
npx playwright show-trace test-results/[test-name]/trace.zip
# Run in debug mode
npm run test:debug# Use codegen to find current selectors
npm run codegenThe framework uses multiple fallback selectors for reliability:
// Example from constants.ts
SEARCH_INPUT: 'input[placeholder*="Hvilket job"], input[aria-label*="Hvilket job"], input.jobsearch-frontpage__input--general, input[name="qs"]'JobDetailsPage uses 5 strategies to extract job titles, handling both internal pages and external career sites.
- Automatic retry on CI (1 attempt)
- Trace capture on first retry for debugging
- Screenshot capture on all failures