Skip to content

Repository files navigation

Playwright Automation Framework – Project Structure

1. Overview

This project is a Playwright automation framework built using JavaScript.

The framework follows:

  • Page Object Model (POM)
  • Playwright Test
  • Reusable fixtures
  • Test data separation
  • Utility functions
  • Environment-based configuration
  • UI and API automation support
  • HTML reporting
  • Screenshot and video capture
  • CI/CD readiness

2. Project Structure

Playwright-Automation/
│
├── tests/
│   ├── login/
│   │   ├── login.spec.js
│   │   └── forgotPassword.spec.js
│   │
│   ├── ecommerce/
│   │   ├── productListing.spec.js
│   │   ├── productDetails.spec.js
│   │   └── cart.spec.js
│   │
│   └── api/
│       └── auth.api.spec.js
│
├── pages/
│   ├── LoginPage.js
│   ├── ForgotPasswordPage.js
│   ├── ProductListingPage.js
│   ├── ProductDetailsPage.js
│   └── CartPage.js
│
├── fixtures/
│   └── base.fixture.js
│
├── test-data/
│   ├── users.json
│   └── products.json
│
├── utils/
│   ├── commonUtils.js
│   ├── apiHelper.js
│   └── randomData.js
│
├── config/
│   └── environments.js
│
├── reports/
│
├── screenshots/
│
├── downloads/
│
├── videos/
│   └── New Tab - Google Chrome 2026-08-08 11-36-07.mp4
│
├── playwright.config.js
├── package.json
├── .env
├── .env.example
├── .gitignore
└── README.md

3. Folder Description

3.1 tests/

The tests folder contains all Playwright test cases.

Tests should contain:

  • Test scenarios
  • Assertions
  • Test descriptions
  • Test grouping

Avoid putting:

  • Locators
  • Common reusable functions
  • Environment configuration
  • Large amounts of test data

Structure

tests/
├── login/
├── ecommerce/
└── api/

Example

import { test, expect } from '@playwright/test';
import { LoginPage } from '../../pages/LoginPage';

test.describe('Login Tests', () => {

    test('Verify user can login successfully', async ({ page }) => {

        const loginPage = new LoginPage(page);

        await loginPage.navigate();

        await loginPage.login(
            'test@example.com',
            'Password123'
        );

        await expect(page).toHaveURL(/dashboard/);

    });

});

4. pages/

The pages folder follows the Page Object Model (POM) design pattern.

Each application page should have a corresponding Page Object.

Example:

pages/
├── LoginPage.js
├── ForgotPasswordPage.js
├── ProductListingPage.js
├── ProductDetailsPage.js
└── CartPage.js

Page Objects should contain:

  • Locators
  • Page actions
  • Reusable page-level methods

Example

export class LoginPage {

    constructor(page) {

        this.page = page;

        this.emailInput = page.locator('#email');

        this.passwordInput = page.locator('#password');

        this.loginButton = page.getByRole(
            'button',
            { name: 'Login' }
        );
    }

    async navigate() {

        await this.page.goto('/login');

    }

    async enterEmail(email) {

        await this.emailInput.fill(email);

    }

    async enterPassword(password) {

        await this.passwordInput.fill(password);

    }

    async clickLogin() {

        await this.loginButton.click();

    }

    async login(email, password) {

        await this.enterEmail(email);

        await this.enterPassword(password);

        await this.clickLogin();

    }
}

5. fixtures/

The fixtures folder contains custom Playwright fixtures.

Fixtures can be used for:

  • Page Object initialization
  • Login setup
  • Authentication
  • Test data
  • Reusable setup/teardown

Example

import { test as base } from '@playwright/test';

import { LoginPage } from '../pages/LoginPage';

export const test = base.extend({

    loginPage: async ({ page }, use) => {

        const loginPage = new LoginPage(page);

        await use(loginPage);

    }

});

Tests can then use:

import { test } from '../../fixtures/base.fixture';

test('Login Test', async ({ loginPage }) => {

    await loginPage.navigate();

    await loginPage.login(
        'test@example.com',
        'Password123'
    );

});

6. test-data/

The test-data folder stores test data separately from test scripts.

Example:

test-data/
├── users.json
└── products.json

users.json

{
    "validUser": {
        "email": "test@example.com",
        "password": "Password123"
    },
    "invalidUser": {
        "email": "invalid@example.com",
        "password": "WrongPassword"
    }
}

This approach helps avoid hardcoding test data inside test cases.


7. utils/

The utils folder contains reusable helper functions.

utils/
├── commonUtils.js
├── apiHelper.js
└── randomData.js

commonUtils.js

Contains generic reusable functions.

Examples:

  • Wait helpers
  • Date helpers
  • Element utilities
  • Common browser actions

apiHelper.js

Contains reusable API functions.

Examples:

  • GET
  • POST
  • PUT
  • DELETE
  • Authentication requests

randomData.js

Contains functions for generating dynamic test data.

Example:

export function generateRandomEmail() {

    return `test_${Date.now()}@example.com`;

}

8. config/

The config folder contains environment-specific configuration.

Example:

config/
└── environments.js

Example

export const environments = {

    uat: {
        baseURL: 'https://uat.example.com'
    },

    staging: {
        baseURL: 'https://staging.example.com'
    },

    production: {
        baseURL: 'https://example.com'
    }

};

This makes it easier to run tests against different environments.


9. reports/

The reports folder contains generated Playwright reports.

Example:

reports/
└── html/

The HTML report can be opened using:

npx playwright show-report

Reports should generally not be committed to Git.


10. screenshots/

Screenshots generated during test execution can be stored here.

Recommended configuration:

use: {
    screenshot: 'only-on-failure'
}

Screenshots should primarily be captured when tests fail.


11. downloads/

The downloads folder is used for files downloaded during automation.

Examples:

  • PDF
  • Excel
  • CSV
  • Images
  • Reports

Example test:

const downloadPromise = page.waitForEvent('download');

await page.getByText('Download').click();

const download = await downloadPromise;

await download.saveAs(
    'downloads/report.xlsx'
);

11.1. videos/

The videos folder contains the reference/input meeting recording video(s) demonstrating the end-to-end user flows that need to be automated (e.g. New Tab - Google Chrome 2026-08-08 11-36-07.mp4).


12. playwright.config.js

This is the main Playwright configuration file.

It controls:

  • Test directory
  • Timeout
  • Browser configuration
  • Base URL
  • Retries
  • Workers
  • Reports
  • Screenshots
  • Videos
  • Trace
  • Browser projects

Recommended configuration

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({

    testDir: './tests',

    timeout: 30 * 1000,

    expect: {
        timeout: 5000
    },

    fullyParallel: true,

    forbidOnly: !!process.env.CI,

    retries: process.env.CI ? 2 : 0,

    workers: process.env.CI ? 2 : undefined,

    reporter: [
        ['html', {
            outputFolder: 'reports/html'
        }],
        ['list']
    ],

    use: {

        baseURL: process.env.BASE_URL,

        trace: 'retain-on-failure',

        screenshot: 'only-on-failure',

        video: 'retain-on-failure',

        headless: true

    },

    projects: [

        {
            name: 'chromium',

            use: {
                ...devices['Desktop Chrome']
            }
        },

        {
            name: 'firefox',

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

        {
            name: 'webkit',

            use: {
                ...devices['Desktop Safari']
            }
        }

    ]

});

13. .env

Environment variables should be stored in .env.

Example:

BASE_URL=https://uat.example.com
API_URL=https://uat.example.com/api

Sensitive credentials should also be stored through environment variables rather than directly inside test scripts.

Do not commit .env to Git.


14. .env.example

The .env.example file documents the required environment variables without exposing actual credentials.

Example:

BASE_URL=
API_URL=
USERNAME=
PASSWORD=

This file can safely be committed to Git.


15. .gitignore

The .gitignore should exclude generated and sensitive files.

Example:

node_modules/
.env

playwright-report/
test-results/

reports/
screenshots/
videos/
downloads/

*.log

16. package.json

The package.json contains:

  • Project information
  • Playwright dependency
  • Test scripts
  • Other npm dependencies

Example scripts:

{
    "scripts": {
        "test": "npx playwright test",
        "test:headed": "npx playwright test --headed",
        "test:debug": "npx playwright test --debug",
        "test:chromium": "npx playwright test --project=chromium",
        "test:firefox": "npx playwright test --project=firefox",
        "test:webkit": "npx playwright test --project=webkit",
        "report": "npx playwright show-report"
    }
}

17. README.md

The README should contain project documentation.

Recommended sections:

Project Overview
Prerequisites
Installation
Project Structure
Environment Setup
How to Run Tests
Browser Execution
Test Tags
Reports
Debugging
Coding Standards
Git Workflow
CI/CD
Troubleshooting

18. Automation Architecture

The recommended architecture is:

                    ┌──────────────────┐
                    │    Test Specs    │
                    │   tests/*.spec.js│
                    └────────┬─────────┘
                             │
                             ▼
                    ┌──────────────────┐
                    │     Fixtures     │
                    │ base.fixture.js  │
                    └────────┬─────────┘
                             │
                             ▼
                    ┌──────────────────┐
                    │   Page Objects   │
                    │    pages/*.js    │
                    └────────┬─────────┘
                             │
                 ┌───────────┴───────────┐
                 ▼                       ▼
        ┌─────────────────┐      ┌─────────────────┐
        │     Utils       │      │    API Layer    │
        │    utils/*.js   │      │     api/*.js    │
        └────────┬────────┘      └────────┬────────┘
                 │                        │
                 └────────────┬───────────┘
                              ▼
                    ┌──────────────────┐
                    │   Application    │
                    │ Web / API / SUT  │
                    └──────────────────┘

19. Recommended Coding Principles

Use Page Object Model

Do not write selectors directly in test files.

Avoid

await page.locator('#email').fill('test@example.com');

Prefer

await loginPage.enterEmail('test@example.com');

Use Playwright Locators

Prefer:

page.getByRole()
page.getByLabel()
page.getByText()
page.getByPlaceholder()

Use CSS/XPath only when necessary.


Avoid Hard Waits

Avoid

await page.waitForTimeout(5000);

Prefer

await expect(element).toBeVisible();

or:

await page.waitForLoadState('networkidle');

when appropriate.


20. Test Naming Convention

Use descriptive test names.

Recommended:

login.spec.js
forgotPassword.spec.js
productListing.spec.js
productDetails.spec.js
cart.spec.js

Test cases:

test('Verify user can login with valid credentials', async () => {});
test('Verify error message for invalid password', async () => {});

21. Recommended Execution Commands

Run all tests

npx playwright test

Run tests in headed mode

npx playwright test --headed

Run a specific test

npx playwright test tests/login/login.spec.js

Run Chromium

npx playwright test --project=chromium

Run Firefox

npx playwright test --project=firefox

Run WebKit

npx playwright test --project=webkit

Debug

npx playwright test --debug

Open HTML report

npx playwright show-report

22. Future Enhancements

The framework can later be extended with:

  • Authentication / storage state
  • API + UI hybrid testing
  • Cucumber BDD
  • Allure reporting
  • CI/CD with GitHub Actions
  • Docker execution
  • Parallel execution
  • Cross-browser testing
  • Mobile browser testing
  • Accessibility testing
  • Visual regression testing
  • Database validation
  • MCP integration
  • AI-assisted test generation
  • OpenCode-based framework maintenance

23. Final Recommended Structure

The final baseline structure should remain simple and scalable:

Playwright-Automation/
│
├── tests/
│   ├── login/
│   ├── ecommerce/
│   └── api/
│
├── pages/
│
├── fixtures/
│
├── test-data/
│
├── utils/
│
├── config/
│
├── reports/
├── screenshots/
├── downloads/
├── videos/
│
├── playwright.config.js
├── package.json
├── .env
├── .env.example
├── .gitignore
└── README.md

This structure provides a clean foundation for a maintainable, scalable Playwright JavaScript automation framework and can be expanded as the automation suite grows.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages