strategy change to TDD
This commit is contained in:
137
openspec/templates/PlaywrightE2ETest.spec.ts
Normal file
137
openspec/templates/PlaywrightE2ETest.spec.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
/*
|
||||
* Test Template for Playwright E2E Tests
|
||||
*
|
||||
* Copy this file and replace:
|
||||
* - {{capability}} with the capability name (e.g., 'authentication')
|
||||
* - {{scenario_description}} with the spec scenario description
|
||||
*
|
||||
* Mark pending tests with test.fixme() during Red Phase
|
||||
* Remove test.fixme() and implement during Green Phase
|
||||
*/
|
||||
|
||||
test.describe('{{capability}} Flow', () => {
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Setup: Navigate to base URL, login, etc.
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
/*
|
||||
* Scenario: {{scenario_description}}
|
||||
*
|
||||
* Spec Reference: specs/{{capability}}/spec.md
|
||||
* Scenario: {{scenario_number}}
|
||||
*/
|
||||
test('{{scenario_description}}', async ({ page }) => {
|
||||
// Arrange (GIVEN)
|
||||
// Set up initial state
|
||||
await page.goto('/{{route}}');
|
||||
|
||||
// Act (WHEN)
|
||||
// Perform user actions
|
||||
await page.fill('[name="email"]', 'test@example.com');
|
||||
await page.fill('[name="password"]', 'password');
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Assert (THEN)
|
||||
// Verify expected outcome
|
||||
await expect(page).toHaveURL('/dashboard');
|
||||
await expect(page.locator('[data-testid="success-message"]')).toBeVisible();
|
||||
await expect(page.locator('[data-testid="user-name"]')).toContainText('Test User');
|
||||
});
|
||||
|
||||
/*
|
||||
* Example: Error scenario
|
||||
*/
|
||||
test('displays error when {{error_condition}}', async ({ page }) => {
|
||||
// Arrange
|
||||
await page.goto('/{{route}}');
|
||||
|
||||
// Act
|
||||
await page.fill('[name="email"]', 'invalid@example.com');
|
||||
await page.fill('[name="password"]', 'wrongpassword');
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Assert
|
||||
await expect(page.locator('[data-testid="error-message"]')).toBeVisible();
|
||||
await expect(page.locator('[data-testid="error-message"]')).toContainText('Invalid credentials');
|
||||
await expect(page).toHaveURL('/{{route}}');
|
||||
});
|
||||
|
||||
/*
|
||||
* Example: Form validation
|
||||
*/
|
||||
test('validates required fields', async ({ page }) => {
|
||||
// Arrange
|
||||
await page.goto('/{{route}}');
|
||||
|
||||
// Act
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Assert
|
||||
await expect(page.locator('[data-testid="error-email"]')).toContainText('Email is required');
|
||||
await expect(page.locator('[data-testid="error-password"]')).toContainText('Password is required');
|
||||
});
|
||||
|
||||
/*
|
||||
* Example: CRUD operation
|
||||
*/
|
||||
test('completes full {{resource}} CRUD flow', async ({ page }) => {
|
||||
// Create
|
||||
await page.goto('/{{resource}}/new');
|
||||
await page.fill('[name="name"]', 'Test {{resource}}');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page.locator('[data-testid="success-message"]')).toBeVisible();
|
||||
|
||||
// Read
|
||||
await page.goto('/{{resource}}');
|
||||
await expect(page.locator('text=Test {{resource}}')).toBeVisible();
|
||||
|
||||
// Update
|
||||
await page.click('[data-testid="edit-{{resource}}"]');
|
||||
await page.fill('[name="name"]', 'Updated {{resource}}');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page.locator('[data-testid="success-message"]')).toBeVisible();
|
||||
|
||||
// Delete
|
||||
await page.click('[data-testid="delete-{{resource}}"]');
|
||||
await page.click('[data-testid="confirm-delete"]');
|
||||
await expect(page.locator('text=Updated {{resource}}')).not.toBeVisible();
|
||||
});
|
||||
|
||||
/*
|
||||
* Example: RBAC test
|
||||
*/
|
||||
test('restricts access based on role', async ({ page }) => {
|
||||
// Login as developer (limited permissions)
|
||||
await loginAs(page, 'developer');
|
||||
|
||||
// Try to access admin page
|
||||
await page.goto('/admin/{{resource}}');
|
||||
|
||||
// Should be redirected or show access denied
|
||||
await expect(page.locator('[data-testid="access-denied"]')).toBeVisible();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
*/
|
||||
async function loginAs(page, role: string) {
|
||||
await page.goto('/login');
|
||||
await page.fill('[name="email"]', `${role}@example.com`);
|
||||
await page.fill('[name="password"]', 'password');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page).toHaveURL('/dashboard');
|
||||
}
|
||||
|
||||
async function create{{model}}(page, data: object) {
|
||||
await page.goto('/{{resource}}/new');
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
await page.fill(`[name="${key}"]`, value);
|
||||
}
|
||||
await page.click('button[type="submit"]');
|
||||
}
|
||||
Reference in New Issue
Block a user