Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
16 changes: 2 additions & 14 deletions .github/workflows/cucumber.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,6 @@ on:
required: false
type: string

browser:
description: 'Browser to run the tests in'
required: true
type: choice
default: 'chrome'
options:
- chrome
- firefox
- webkit
- chromium

jobs:
cucumber:
timeout-minutes: 60
Expand All @@ -44,11 +33,10 @@ jobs:
cache: npm
- name: Install dependencies
run: npm ci
- name: Install Playwright browser
run: npx playwright install --with-deps ${{ inputs.browser }}
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium
- name: Run Cucumber tests
env:
BROWSER: ${{ inputs.browser }}
SELECTED_TAGS: ${{ inputs.custom_tags != '' && inputs.custom_tags || inputs.tags }}
run: |
if [ "$SELECTED_TAGS" = "all" ]; then
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ node_modules/
/blob-report/
/playwright/.cache/
/playwright/.auth/
.DS_Store
20 changes: 5 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This repository contains a robust automation framework using **Playwright with T
│ └── dataUtils.ts # Reusable JsonReader utility to load & extract test data
├── cucumber.json # Cucumber configuration and profiles
├── tsconfig.json # TypeScript compiler settings
├── playwright.config.ts # Playwright standard runner configuration
└── package.json # Dependencies and npm test runner scripts
```

Expand All @@ -36,23 +37,13 @@ This repository contains a robust automation framework using **Playwright with T
```bash
npm run test:cucumber
```
Locally every browser (chrome, chromium, firefox, webkit) launches headed; Chrome is maximized and the
others open at the default 1280x720 size. Only on GitHub Actions does it run headless. This is
Locally the browser launches maximized in headed mode; on CI (`CI=true`) it runs headless. This is
controlled globally in `src/test/hooks/browserConfig.ts`.

### Choose the browser
Supported: `chrome` (default), `firefox`, `webkit`, `chromium`. Set it per run with the `BROWSER`
variable, or change `DEFAULT_BROWSER` in `src/test/hooks/browserConfig.ts`.
```bash
BROWSER=firefox npx cucumber-js --tags "@smoke" # macOS / Linux
npx cross-env BROWSER=webkit cucumber-js --tags "@smoke" # any OS, incl. Windows
```

### Run on GitHub Actions
The **Cucumber Tests** workflow (`.github/workflows/cucumber.yml`) runs manually only, never on push
or pull request. Go to **Actions → Cucumber Tests → Run workflow**, pick a browser and a tag (or
`all`, or enter a custom tag expression), then download the `cucumber-report` artifact
from the finished run.
or pull request. Go to **Actions → Cucumber Tests → Run workflow**, pick a tag (or `all`, or enter a
custom tag expression), then download the `cucumber-report` artifact from the finished run.

### 2. Run by tag
```bash
Expand All @@ -78,5 +69,4 @@ After test execution, a rich HTML report is automatically generated at:
```
test-results/cucumber-report.html
```
Open it in any browser to inspect step-by-step results and screenshots. On GitHub Actions it is in the
`cucumber-report` artifact.
Open it in any browser to inspect step-by-step results and screenshots if any step fails.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "This repository will be used to create a robust automation framework using Playwright with Type Script",
"main": "index.js",
"scripts": {
"test": "playwright test",
"test:cucumber": "cucumber-js"
},
"repository": {
Expand Down
83 changes: 83 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { defineConfig, devices } from '@playwright/test';

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// import path from 'path';
// dotenv.config({ path: path.resolve(__dirname, '.env') });

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {

// headless: false,
// launchOptions: {
// slowMo: 1000, // 1 second delay between each action
// },
/* Base URL to use in actions like `await page.goto('')`. */
// baseURL: 'http://localhost:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

// {
// name: 'firefox',
// use: { ...devices['Desktop Firefox'] },
// },

{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},

/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://localhost:3000',
// reuseExistingServer: !process.env.CI,
// },
});
32 changes: 2 additions & 30 deletions src/test/hooks/browserConfig.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,7 @@
import { chromium, firefox, webkit, BrowserType } from 'playwright';

declare const process: { env: Record<string, string | undefined> };

// Global browser settings applied to every scenario, regardless of which
// feature, scenario or tag is executed.
//
// Supported browsers: chrome, chromium, firefox, webkit.
// Edit DEFAULT_BROWSER to change the default, or override per run with the BROWSER env variable.
const DEFAULT_BROWSER = 'chrome';
const browserName = (process.env.BROWSER ?? DEFAULT_BROWSER).toLowerCase();

const browsers: Record<string, { type: BrowserType; channel?: string }> = {
chrome: { type: chromium, channel: 'chrome' },
chromium: { type: chromium },
firefox: { type: firefox },
webkit: { type: webkit },
};

if (!browsers[browserName]) {
throw new Error(
`Unsupported BROWSER "${browserName}". Use one of: ${Object.keys(browsers).join(', ')}`
);
}

export const browserConfig = {
name: browserName,
type: browsers[browserName].type,
channel: browsers[browserName].channel,
// Only Chrome is maximized locally; other browsers open at the default size
maximize: browserName === 'chrome',
// Headed for every browser locally; headless only on GitHub Actions (which sets GITHUB_ACTIONS=true)
headed: process.env.GITHUB_ACTIONS !== 'true',
// Headed locally; CI runners (GitHub Actions sets CI=true) have no display, so run headless there
headed: !process.env.CI,
slowMo: 300, // slight delay in headed mode to make watching easier
};
18 changes: 8 additions & 10 deletions src/test/hooks/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Before, After, AfterStep, setDefaultTimeout } from '@cucumber/cucumber';
import { chromium } from 'playwright';
import { CustomWorld } from './customWorld';
import { browserConfig } from './browserConfig';
import { LoginPage } from '../../pages/LoginPage';
Expand All @@ -21,22 +22,19 @@ async function maximizeWindow(world: CustomWorld): Promise<void> {
Before(async function (this: CustomWorld) {
const isHeaded = browserConfig.headed;

this.browser = await browserConfig.type.launch({
this.browser = await chromium.launch({
headless: !isHeaded,
channel: browserConfig.channel,
slowMo: isHeaded ? browserConfig.slowMo : 0,
args: browserConfig.maximize ? ['--window-position=0,0'] : [],
args: ['--window-position=0,0'],
});

// Maximized Chrome follows its window (viewport null); other browsers use a fixed default size
let viewport: { width: number; height: number } | null = { width: 1280, height: 720 };
if (!isHeaded) viewport = { width: 1920, height: 1080 };
else if (browserConfig.maximize) viewport = null;

this.context = await this.browser.newContext({ viewport });
// viewport: null lets the page follow the maximized window; headless has no window, so use a large fixed size
this.context = await this.browser.newContext({
viewport: isHeaded ? null : { width: 1920, height: 1080 },
});

this.page = await this.context.newPage();
if (isHeaded && browserConfig.maximize) await maximizeWindow(this);
if (isHeaded) await maximizeWindow(this);
this.loginPage = new LoginPage(this.page);
this.dashboardPage = new DashboardPage(this.page);
});
Expand Down
18 changes: 18 additions & 0 deletions tests/example.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');

// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});

test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');

// Click the get started link.
await page.getByRole('link', { name: 'Get started' }).click();

// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
Loading