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
119 changes: 119 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Copilot Instructions for PlaywrightTypeScriptDemo

## Project Architecture

This is a Playwright TypeScript test automation framework using the **Page Object Model (POM)** pattern with a custom fixture-based architecture. Tests run against external practice sites.

### Key Structure
- `tests/specs/` - Test specifications using extended fixtures
- `tests/pageObejcts/` - Page object classes (note: typo in directory name is intentional)
- `tests/locators/` - JSON files containing element selectors
- `tests/data/` - JSON test data files
- `tests/utilities/setup.ts` - Custom Playwright fixture extensions

## Critical Framework Pattern: Custom Fixtures

**This project uses a custom test fixture pattern in `tests/utilities/setup.ts` that automatically instantiates page objects.**

```typescript
// In tests, import from setup.ts, NOT from @playwright/test
import { test } from '../utilities/setup';

// Page objects are injected as fixtures:
test('example', async ({ loginPage, examplePage }) => {
// loginPage and examplePage are already instantiated
await loginPage.loginValidCredentials(user, pass);
});
```

**Never import `{ test }` directly from '@playwright/test' in specs** - always use the extended test from `setup.ts`.

## Locator Management

All selectors live in JSON files in `tests/locators/`:

```json
{
"username": "input[id='username']",
"loginButton": "button[id='submit']",
"loginSuccessHeader": ".post-title:has-text('Logged In Successfully')"
}
```

Import and use in page objects:
```typescript
import loginLocator from '../locators/example.json';
await this.page.fill(loginLocator.username, username);
```

**Never hardcode selectors in page objects or tests.** Use Playwright's `:has-text()` for text-based selectors with specific text content.

## Page Object Pattern

Constructor signature:
```typescript
export class LoginPage {
constructor(private page: Page) {}
// Methods use this.page
}
```

Use `private page: Page` in constructor (TypeScript shorthand). Methods should be async and focused on user actions, not assertions.

## Test Data

Centralized in JSON files at `tests/data/`. Contains URLs, credentials, and expected values:
```typescript
import testData from '../data/example.json';
await examplePage.navigateTo(testData.BASE_URL);
```

## Test Execution

**Primary test command (from package.json):**
```bash
npm run test # Runs login.spec.ts in headed mode
```

Standard Playwright commands work but respect `testDir: './tests'` in config:
```bash
npx playwright test # Run all tests
npx playwright test login.spec.ts # Specific test
npx playwright show-report # View HTML report
```

Tests run in Chromium only (Firefox/WebKit commented out in config).

## Adding New Features

### New Page Object
1. Create class in `tests/pageObejcts/` with `constructor(private page: Page)`
2. Create locators JSON in `tests/locators/`
3. Add fixture to `tests/utilities/setup.ts`:
```typescript
const test = base.extend<{
newPage: NewPage;
}>({
newPage: async ({ page }, use) => {
await use(new NewPage(page));
},
});
```

### New Test
1. Import extended test: `import { test } from '../utilities/setup'`
2. Use page object fixtures in test signatures
3. Reference `FRAMEWORK_RULES.md` for error handling, screenshots, and resilience patterns

## Common Patterns

- **Waits**: Use `await this.page.waitForTimeout(3000)` sparingly; prefer `waitForSelector` or `expect().toBeVisible()`
- **Assertions**: Import `expect` from setup.ts, use in page objects when verifying page state
- **BeforeEach**: Used for navigation and common setup, receives page objects as fixtures

## Important Context

- Directory `tests/pageObejcts/` has intentional typo - maintain consistency
- Tests target external site: for example `https://practicetestautomation.com/practice-test-login/`
- Framework follows strict separation: locators → page objects → tests → data
- See `FRAMEWORK_RULES.md` for comprehensive patterns on resilience, error handling, TypeScript best practices, and framework conventions
25 changes: 22 additions & 3 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ on:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
types: [ opened, synchronize, closed ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true)
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand All @@ -19,9 +21,26 @@ jobs:
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
- name: Upload HTML Report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
name: playwright-html-report
path: playwright-report/
retention-days: 30
- name: Upload Test Results JSON
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-json
path: test-results/test-results.json
retention-days: 30
- name: Upload Screenshots and Videos
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-artifacts
path: |
test-results/**/*.png
test-results/**/*.webm
retention-days: 30
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@ node_modules/
/playwright-report/
/blob-report/
/playwright/.cache/

# Test artifacts
*.mp4
*.webm
test-results.json
Loading