E2E Test using Playwright - FullstackCodingGuy/Developer-Fundamentals GitHub Wiki

Here’s a typical project structure for a React project that uses Playwright for end-to-end (E2E) testing. This structure ensures a clean separation of concerns and organizes your code and tests effectively.


Project Structure

my-react-app/
β”œβ”€β”€ public/                     # Static assets (e.g., index.html, images)
β”œβ”€β”€ src/                        # Source code for the React app
β”‚   β”œβ”€β”€ components/             # Reusable React components
β”‚   β”‚   β”œβ”€β”€ Header.jsx
β”‚   β”‚   β”œβ”€β”€ Footer.jsx
β”‚   β”‚   └── ...
β”‚   β”œβ”€β”€ pages/                  # Page-level components
β”‚   β”‚   β”œβ”€β”€ Home.jsx
β”‚   β”‚   β”œβ”€β”€ About.jsx
β”‚   β”‚   └── ...
β”‚   β”œβ”€β”€ hooks/                  # Custom React hooks
β”‚   β”‚   └── useAuth.js
β”‚   β”œβ”€β”€ context/                # React Context for global state
β”‚   β”‚   └── AuthContext.js
β”‚   β”œβ”€β”€ services/               # API calls and external services
β”‚   β”‚   └── api.js
β”‚   β”œβ”€β”€ styles/                 # Global and component-specific styles
β”‚   β”‚   └── main.css
β”‚   β”œβ”€β”€ App.jsx                 # Main React component
β”‚   β”œβ”€β”€ index.js                # Entry point for React
β”‚   └── ...
β”œβ”€β”€ tests/                      # All test-related files
β”‚   β”œβ”€β”€ e2e/                    # Playwright end-to-end tests
β”‚   β”‚   β”œβ”€β”€ example.spec.js     # Example Playwright test
β”‚   β”‚   β”œβ”€β”€ fixtures/           # Playwright fixtures (e.g., test data)
β”‚   β”‚   β”‚   └── userData.js
β”‚   β”‚   β”œβ”€β”€ pages/              # Page Object Models for Playwright
β”‚   β”‚   β”‚   β”œβ”€β”€ HomePage.js
β”‚   β”‚   β”‚   β”œβ”€β”€ LoginPage.js
β”‚   β”‚   β”‚   └── ...
β”‚   β”‚   └── playwright.config.js # Playwright configuration
β”‚   β”œβ”€β”€ unit/                   # Unit tests (e.g., Jest or React Testing Library)
β”‚   β”‚   β”œβ”€β”€ components/         # Unit tests for components
β”‚   β”‚   β”‚   └── Header.test.js
β”‚   β”‚   β”œβ”€β”€ hooks/              # Unit tests for custom hooks
β”‚   β”‚   β”‚   └── useAuth.test.js
β”‚   β”‚   └── ...
β”‚   └── integration/            # Integration tests (optional)
β”œβ”€β”€ .github/                    # GitHub workflows (e.g., CI/CD pipelines)
β”‚   └── workflows/
β”‚       └── playwright.yml      # GitHub Actions for Playwright tests
β”œβ”€β”€ .vscode/                    # VS Code settings and extensions
β”‚   └── settings.json
β”œβ”€β”€ node_modules/               # Installed dependencies
β”œβ”€β”€ .env                        # Environment variables
β”œβ”€β”€ .gitignore                  # Files to ignore in Git
β”œβ”€β”€ package.json                # Project dependencies and scripts
β”œβ”€β”€ package-lock.json           # Lockfile for dependencies
β”œβ”€β”€ README.md                   # Project documentation
└── playwright-report/          # Playwright test reports (auto-generated)

Key Folders and Files

1. src

  • Contains all the React application code.
  • Organized into components/, pages/, hooks/, context/, and services/ for modularity.

2. tests/e2e/

  • Contains Playwright end-to-end tests.
  • playwright.config.js: Configuration file for Playwright (e.g., browser settings, base URL).
  • pages/: Page Object Models (POM) for Playwright tests to encapsulate page-specific logic.
  • fixtures/: Test data or reusable utilities for Playwright tests.

3. tests/unit/

  • Contains unit tests for React components, hooks, and other logic.
  • Use Jest and React Testing Library for unit testing.

4. playwright-report/

  • Auto-generated folder for Playwright test reports (e.g., HTML reports).

5. .github/workflows/

  • Contains CI/CD pipelines for running Playwright tests in GitHub Actions.

Example Playwright Configuration (playwright.config.js)

// tests/e2e/playwright.config.js
const { defineConfig } = require('@playwright/test');

module.exports = defineConfig({
  testDir: './tests/e2e',
  timeout: 30000,
  retries: 2,
  use: {
    baseURL: 'http://localhost:3000',
    headless: true,
    viewport: { width: 1280, height: 720 },
    actionTimeout: 5000,
    trace: 'on-first-retry',
  },
  reporter: [['html', { outputFolder: 'playwright-report' }]],
});

Example Playwright Test (example.spec.js)

// tests/e2e/example.spec.js
const { test, expect } = require('@playwright/test');

test('homepage has title and links to about page', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveTitle(/React App/);

  const aboutLink = page.locator('text=About');
  await expect(aboutLink).toBeVisible();
  await aboutLink.click();

  await expect(page).toHaveURL(/about/);
});

Example Page Object Model (HomePage.js)

// tests/e2e/pages/HomePage.js
class HomePage {
  constructor(page) {
    this.page = page;
    this.aboutLink = page.locator('text=About');
  }

  async navigate() {
    await this.page.goto('/');
  }

  async clickAbout() {
    await this.aboutLink.click();
  }
}

module.exports = HomePage;

Example GitHub Actions Workflow (playwright.yml)

# .github/workflows/playwright.yml
name: Playwright Tests

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16

      - name: Install dependencies
        run: npm install

      - name: Run Playwright tests
        run: npx playwright test

      - name: Upload Playwright report
        if: failure()
        uses: actions/upload-artifact@v3
        with:
          name: playwright-report
          path: playwright-report

Scripts in package.json

"scripts": {
  "start": "react-scripts start",
  "build": "react-scripts build",
  "test": "react-scripts test",
  "e2e": "npx playwright test",
  "e2e:report": "npx playwright show-report"
}

Benefits of This Structure:

  1. Modularity: Clear separation of React app code and tests.
  2. Scalability: Easy to add more tests, components, or pages.
  3. Maintainability: Organized folder structure for better readability.
  4. CI/CD Ready: GitHub Actions workflow for automated testing.

Debug

read

To debug your Playwright test, you can use the following approaches:


1. Run Playwright in Debug Mode

Playwright provides a built-in debug mode that pauses the test execution and opens the browser for inspection.

Command:

npx playwright test --debug

What Happens:

  • The browser will open in non-headless mode.
  • You can step through the test interactively.
  • Playwright Inspector will appear, allowing you to inspect elements, view logs, and replay actions.

2. Add test.only

Focus on a single test by adding .only to the test you want to debug.

Example:

test.only('should allow selecting a fund manager', async () => {
  // Select a fund manager
  await fundManagerSelector.selectFundManager('Fund Manager 1'); // Replace with actual value

  // Verify the selection
  // await fundManagerSelector.verifySelectedFundManager('Fund Manager 1');
});

Command:

npx playwright test

This will run only the specified test.


3. Use page.pause()

Insert page.pause() in your test to pause execution and open the Playwright Inspector.

Example:

test('should allow selecting a fund manager', async ({ page }) => {
  await page.pause(); // Pauses the test and opens the inspector

  // Select a fund manager
  await fundManagerSelector.selectFundManager('Fund Manager 1'); // Replace with actual value

  // Verify the selection
  // await fundManagerSelector.verifySelectedFundManager('Fund Manager 1');
});

Command:

npx playwright test

4. Run in Non-Headless Mode

By default, Playwright runs tests in headless mode. You can disable headless mode to see the browser actions.

Command:

npx playwright test --headed

5. Add Debugging Logs

Add console.log statements in your test or Page Object Model to log values and actions.

Example:

test('should allow selecting a fund manager', async () => {
  console.log('Starting test: should allow selecting a fund manager');
  
  // Select a fund manager
  await fundManagerSelector.selectFundManager('Fund Manager 1');
  console.log('Selected Fund Manager 1');

  // Verify the selection
  // await fundManagerSelector.verifySelectedFundManager('Fund Manager 1');
  console.log('Verified selection');
});

6. Use --trace for Tracing

Enable tracing to capture detailed logs, screenshots, and videos of the test execution.

Command:

npx playwright test --trace on

After Test Execution:

  • Open the trace viewer:
    npx playwright show-trace trace.zip

7. Check for Errors in the Console

If the test fails, Playwright will display the error stack trace in the terminal. Use this information to identify the issue.


8. Verify Page Object Model

Ensure the FundManagerSelectorPage class is correctly implemented and imported. If the FundManagerSelectorPage is not working as expected, debug it separately.

Example:

const FundManagerSelectorPage = require('./FundManagerSelectorPage');
console.log(FundManagerSelectorPage); // Verify the import

9. Run a Specific Test File

If you want to debug only the

FundManagerSelector.spec.js

file, run it directly:

npx playwright test tests/e2e/tests/FundManagerSelector.spec.js

10. Use Breakpoints in VS Code

If you're using Visual Studio Code, you can debug Playwright tests with breakpoints.

Steps:

  1. Open the

FundManagerSelector.spec.js

file in VS Code. 2. Add breakpoints by clicking on the left margin of the editor. 3. Create a launch.json file for Playwright debugging:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Playwright Tests",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/node_modules/@playwright/test/lib/cli.js",
      "args": ["test", "--project=chromium"],
      "cwd": "${workspaceFolder}",
      "env": {
        "PWDEBUG": "1"
      }
    }
  ]
}
  1. Start debugging by pressing F5.

Recommended Debugging Steps for Your Test:

  1. Add page.pause() inside the test to inspect the browser.
  2. Run the test in debug mode:
    npx playwright test --debug
  3. Add console.log statements to verify the flow of the test.
  4. Ensure the FundManagerSelectorPage is correctly implemented and imported.
⚠️ **GitHub.com Fallback** ⚠️