Playwright Typescript Test Automation Project Structure
Below is a comprehensive project structure leveraging the UI and API testing framework using Playwright, following the Page Object Model, with additional GitHub CI/CD integration and reusable utilities.
Project Structure
playwright-testing-project/
├── .github/
│ ├── CODEOWNERS
│ ├── workflows/
│ │ └── nightly-build.yml
│ └── PULL_REQUEST_TEMPLATE.md
├── src/
│ ├── api/
│ │ ├── endpoints/
│ │ │ ├── user.ts
│ │ │ ├── auth.ts
│ │ │ └── product.ts
│ │ ├── helpers/
│ │ │ ├── apiClient.ts
│ │ │ └── authHelper.ts
│ │ └── tests/
│ │ ├── userApi.test.ts
│ │ └── productApi.test.ts
│ ├── ui/
│ │ ├── pages/
│ │ │ ├── loginPage.ts
│ │ │ ├── homePage.ts
│ │ │ └── productPage.ts
│ │ ├── tests/
│ │ │ ├── login.test.ts
│ │ │ ├── navigation.test.ts
│ │ │ └── productFlow.test.ts
│ │ ├── components/
│ │ │ ├── header.ts
│ │ │ ├── footer.ts
│ │ │ └── sidebar.ts
│ │ └── utils/
│ │ ├── config.ts
│ │ ├── logger.ts
│ │ └── helperFunctions.ts
├── .gitignore
├── README.md
├── playwright.config.ts
├── package.json
├── tsconfig.json
└── allure-results/
File Descriptions and Examples
.github/
CODEOWNERS
* @username1 @username2
Ensures specific team members are assigned to review PRs.
workflows/nightly-build.yml
name: Nightly Build on: schedule: - cron: "0 2 * * *" push: branches: - main 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: '18' - name: Install Dependencies run: npm install - name: Run Tests run: npm run test:all - name: Upload Allure Results uses: actions/upload-artifact@v3 with: name: allure-results path: allure-results
PULL_REQUEST_TEMPLATE.md
# Pull Request Template ## Description - [ ] Added/Updated tests - [ ] Fixed issue # - [ ] Other (explain): ## How Has This Been Tested? - [ ] Locally - [ ] CI/CD ## Checklist - [ ] Code follows coding standards - [ ] No console errors or warnings - [ ] Documentation updated (if applicable)
src/api/
endpoints/user.ts
export const getUserDetails = async (id: string) => { const response = await fetch(`https://api.example.com/users/${id}`); return response.json(); };
helpers/apiClient.ts
import fetch from 'node-fetch'; export const apiClient = async (url: string, method: string = 'GET', body?: object) => { const response = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: body ? JSON.stringify(body) : undefined, }); return response.json(); };
src/ui/pages/
loginPage.ts
import { Page } from '@playwright/test'; export class LoginPage { constructor(private page: Page) {} async navigate() { await this.page.goto('/login'); } async login(username: string, password: string) { await this.page.fill('#username', username); await this.page.fill('#password', password); await this.page.click('#loginButton'); } }
Utilities
src/ui/utils/config.ts
export const config = { baseURL: 'https://example.com', apiBaseURL: 'https://api.example.com', };
src/ui/utils/logger.ts
export const log = (message: string) => console.log(`[LOG]: ${message}`);
Test Scripts
src/ui/tests/login.test.ts
import { test } from '@playwright/test'; import { LoginPage } from '../pages/loginPage'; test('Login test', async ({ page }) => { const loginPage = new LoginPage(page); await loginPage.navigate(); await loginPage.login('testuser', 'password'); // Assertions });
src/api/tests/userApi.test.ts
import { test } from '@playwright/test'; import { getUserDetails } from '../endpoints/user'; test('Get user details', async () => { const user = await getUserDetails('123'); expect(user.name).toBeDefined(); });
Config Files
.gitignore
node_modules/ allure-results/ dist/ .env
playwright.config.ts
import { defineConfig } from '@playwright/test'; export default defineConfig({ testDir: './src', timeout: 30000, reporter: [['html'], ['allure-playwright']], use: { baseURL: 'https://example.com', headless: true, }, });
package.json
{ "name": "playwright-testing-project", "version": "1.0.0", "scripts": { "test": "playwright test", "test:all": "playwright test --project=all" }, "dependencies": { "@playwright/test": "^1.38.0", "allure-playwright": "^2.0.0" } }
This structure ensures maintainability, scalability, and proper CI/CD integration for both UI and API tests.