-
Notifications
You must be signed in to change notification settings - Fork 0
E2E Test using Playwright
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.
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)
- Contains all the React application code.
- Organized into
components/
,pages/
,hooks/
,context/
, andservices/
for modularity.
- 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.
- Contains unit tests for React components, hooks, and other logic.
- Use Jest and React Testing Library for unit testing.
- Auto-generated folder for Playwright test reports (e.g., HTML reports).
- Contains CI/CD pipelines for running Playwright tests in GitHub Actions.
// 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' }]],
});
// 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/);
});
// 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;
# .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": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"e2e": "npx playwright test",
"e2e:report": "npx playwright show-report"
}
- Modularity: Clear separation of React app code and tests.
- Scalability: Easy to add more tests, components, or pages.
- Maintainability: Organized folder structure for better readability.
- CI/CD Ready: GitHub Actions workflow for automated testing.
read
To debug your Playwright test, you can use the following approaches:
Playwright provides a built-in debug mode that pauses the test execution and opens the browser for inspection.
npx playwright test --debug
- 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.
Focus on a single test by adding .only
to the test you want to debug.
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');
});
npx playwright test
This will run only the specified test.
Insert page.pause()
in your test to pause execution and open the Playwright Inspector.
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');
});
npx playwright test
By default, Playwright runs tests in headless mode. You can disable headless mode to see the browser actions.
npx playwright test --headed
Add console.log
statements in your test or Page Object Model to log values and actions.
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');
});
Enable tracing to capture detailed logs, screenshots, and videos of the test execution.
npx playwright test --trace on
- Open the trace viewer:
npx playwright show-trace trace.zip
If the test fails, Playwright will display the error stack trace in the terminal. Use this information to identify the issue.
Ensure the FundManagerSelectorPage
class is correctly implemented and imported. If the FundManagerSelectorPage
is not working as expected, debug it separately.
const FundManagerSelectorPage = require('./FundManagerSelectorPage');
console.log(FundManagerSelectorPage); // Verify the import
If you want to debug only the
FundManagerSelector.spec.js
file, run it directly:
npx playwright test tests/e2e/tests/FundManagerSelector.spec.js
If you're using Visual Studio Code, you can debug Playwright tests with breakpoints.
- 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"
}
}
]
}
- Start debugging by pressing
F5
.
- Add
page.pause()
inside the test to inspect the browser. - Run the test in debug mode:
npx playwright test --debug
- Add
console.log
statements to verify the flow of the test. - Ensure the
FundManagerSelectorPage
is correctly implemented and imported.