您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. # Playwright Utils Overview
  2. ## Principle
  3. Use production-ready, fixture-based utilities from `@seontechnologies/playwright-utils` for common Playwright testing patterns. Build test helpers as pure functions first, then wrap in framework-specific fixtures for composability and reuse. **Works equally well for pure API testing (no browser) and UI testing.**
  4. ## Rationale
  5. Writing Playwright utilities from scratch for every project leads to:
  6. - Duplicated code across test suites
  7. - Inconsistent patterns and quality
  8. - Maintenance burden when Playwright APIs change
  9. - Missing advanced features (schema validation, HAR recording, auth persistence)
  10. `@seontechnologies/playwright-utils` provides:
  11. - **Production-tested**: Used in enterprise production environments
  12. - **Functional-first design**: Core logic as pure functions, fixtures for convenience
  13. - **Composable fixtures**: Use `mergeTests` to combine utilities
  14. - **TypeScript support**: Full type safety with generic types
  15. - **Comprehensive coverage**: API requests, auth, network, logging, file handling, burn-in
  16. - **Backend-first mentality**: Most utilities work without a browser - pure API/service testing is a first-class use case
  17. ## Installation
  18. ```bash
  19. npm install -D @seontechnologies/playwright-utils
  20. ```
  21. **Peer Dependencies:**
  22. - `@playwright/test` >= 1.54.1 (required)
  23. - `ajv` >= 8.0.0 (optional - for JSON Schema validation)
  24. - `zod` >= 3.0.0 (optional - for Zod schema validation)
  25. ## Available Utilities
  26. ### Core Testing Utilities
  27. | Utility | Purpose | Test Context |
  28. | -------------------------- | ----------------------------------------------------------------------------- | ------------------ |
  29. | **api-request** | Typed HTTP client with schema validation, retry, and operation-based overload | **API/Backend** |
  30. | **recurse** | Polling for async operations, background jobs | **API/Backend** |
  31. | **auth-session** | Token persistence, multi-user, service-to-service | **API/Backend/UI** |
  32. | **log** | Playwright report-integrated logging | **API/Backend/UI** |
  33. | **file-utils** | CSV/XLSX/PDF/ZIP reading & validation | **API/Backend/UI** |
  34. | **burn-in** | Smart test selection with git diff | **CI/CD** |
  35. | **network-recorder** | HAR record/playback for offline testing | UI only |
  36. | **intercept-network-call** | Network spy/stub with auto JSON parsing | UI only |
  37. | **network-error-monitor** | Automatic HTTP 4xx/5xx detection | UI only |
  38. **Note**: 6 of 9 utilities work without a browser. Only 3 are UI-specific (network-recorder, intercept-network-call, network-error-monitor).
  39. ## Design Patterns
  40. ### Pattern 1: Functional Core, Fixture Shell
  41. **Context**: All utilities follow the same architectural pattern - pure function as core, fixture as wrapper.
  42. **Implementation**:
  43. ```typescript
  44. // Direct import (pass Playwright context explicitly)
  45. import { apiRequest } from '@seontechnologies/playwright-utils';
  46. test('direct usage', async ({ request }) => {
  47. const { status, body } = await apiRequest({
  48. request, // Must pass request context
  49. method: 'GET',
  50. path: '/api/users',
  51. });
  52. });
  53. // Fixture import (context injected automatically)
  54. import { test } from '@seontechnologies/playwright-utils/fixtures';
  55. test('fixture usage', async ({ apiRequest }) => {
  56. const { status, body } = await apiRequest({
  57. // No need to pass request context
  58. method: 'GET',
  59. path: '/api/users',
  60. });
  61. });
  62. ```
  63. **Key Points**:
  64. - Pure functions testable without Playwright running
  65. - Fixtures inject framework dependencies automatically
  66. - Choose direct import (more control) or fixture (convenience)
  67. ### Pattern 2: Subpath Imports for Tree-Shaking
  68. **Context**: Import only what you need to keep bundle sizes small.
  69. **Implementation**:
  70. ```typescript
  71. // Import specific utility
  72. import { apiRequest } from '@seontechnologies/playwright-utils/api-request';
  73. // Import specific fixture
  74. import { test } from '@seontechnologies/playwright-utils/api-request/fixtures';
  75. // Import everything (use sparingly)
  76. import { apiRequest, recurse, log } from '@seontechnologies/playwright-utils';
  77. ```
  78. **Key Points**:
  79. - Subpath imports enable tree-shaking
  80. - Keep bundle sizes minimal
  81. - Import from specific paths for production builds
  82. ### Pattern 3: Fixture Composition with mergeTests
  83. **Context**: Combine multiple playwright-utils fixtures with your own custom fixtures.
  84. **Implementation**:
  85. ```typescript
  86. // playwright/support/merged-fixtures.ts
  87. import { mergeTests } from '@playwright/test';
  88. import { test as apiRequestFixture } from '@seontechnologies/playwright-utils/api-request/fixtures';
  89. import { test as authFixture } from '@seontechnologies/playwright-utils/auth-session/fixtures';
  90. import { test as recurseFixture } from '@seontechnologies/playwright-utils/recurse/fixtures';
  91. import { test as logFixture } from '@seontechnologies/playwright-utils/log/fixtures';
  92. // Merge all fixtures into one test object
  93. export const test = mergeTests(apiRequestFixture, authFixture, recurseFixture, logFixture);
  94. export { expect } from '@playwright/test';
  95. ```
  96. ```typescript
  97. // In your tests
  98. import { test, expect } from '../support/merged-fixtures';
  99. test('all utilities available', async ({ apiRequest, authToken, recurse, log }) => {
  100. await log.step('Making authenticated API request');
  101. const { body } = await apiRequest({
  102. method: 'GET',
  103. path: '/api/protected',
  104. headers: { Authorization: `Bearer ${authToken}` },
  105. });
  106. await recurse(
  107. () => apiRequest({ method: 'GET', path: `/status/${body.id}` }),
  108. (res) => res.body.ready === true,
  109. );
  110. });
  111. ```
  112. **Key Points**:
  113. - `mergeTests` combines multiple fixtures without conflicts
  114. - Create one merged-fixtures.ts file per project
  115. - Import test object from your merged fixtures in all tests
  116. - All utilities available in single test signature
  117. ## Integration with Existing Tests
  118. ### Gradual Adoption Strategy
  119. **1. Start with logging** (zero breaking changes):
  120. ```typescript
  121. import { log } from '@seontechnologies/playwright-utils';
  122. test('existing test', async ({ page }) => {
  123. await log.step('Navigate to page'); // Just add logging
  124. await page.goto('/dashboard');
  125. // Rest of test unchanged
  126. });
  127. ```
  128. **2. Add API utilities** (for API tests):
  129. ```typescript
  130. import { test } from '@seontechnologies/playwright-utils/api-request/fixtures';
  131. test('API test', async ({ apiRequest }) => {
  132. const { status, body } = await apiRequest({
  133. method: 'GET',
  134. path: '/api/users',
  135. });
  136. expect(status).toBe(200);
  137. });
  138. ```
  139. **3. Expand to network utilities** (for UI tests):
  140. ```typescript
  141. import { test } from '@seontechnologies/playwright-utils/fixtures';
  142. test('UI with network control', async ({ page, interceptNetworkCall }) => {
  143. const usersCall = interceptNetworkCall({
  144. url: '**/api/users',
  145. });
  146. await page.goto('/dashboard');
  147. const { responseJson } = await usersCall;
  148. expect(responseJson).toHaveLength(10);
  149. });
  150. ```
  151. **4. Full integration** (merged fixtures):
  152. Create merged-fixtures.ts and use across all tests.
  153. ## Related Fragments
  154. - `api-request.md` - HTTP client with schema validation
  155. - `network-recorder.md` - HAR-based offline testing
  156. - `auth-session.md` - Token management
  157. - `intercept-network-call.md` - Network interception
  158. - `recurse.md` - Polling patterns
  159. - `log.md` - Logging utility
  160. - `file-utils.md` - File operations
  161. - `fixtures-composition.md` - Advanced mergeTests patterns
  162. ## Anti-Patterns
  163. **❌ Don't mix direct and fixture imports in same test:**
  164. ```typescript
  165. import { apiRequest } from '@seontechnologies/playwright-utils';
  166. import { test } from '@seontechnologies/playwright-utils/auth-session/fixtures';
  167. test('bad', async ({ request, authToken }) => {
  168. // Confusing - mixing direct (needs request) and fixture (has authToken)
  169. await apiRequest({ request, method: 'GET', path: '/api/users' });
  170. });
  171. ```
  172. **✅ Use consistent import style:**
  173. ```typescript
  174. import { test } from '../support/merged-fixtures';
  175. test('good', async ({ apiRequest, authToken }) => {
  176. // Clean - all from fixtures
  177. await apiRequest({ method: 'GET', path: '/api/users' });
  178. });
  179. ```
  180. **❌ Don't import everything when you need one utility:**
  181. ```typescript
  182. import * as utils from '@seontechnologies/playwright-utils'; // Large bundle
  183. ```
  184. **✅ Use subpath imports:**
  185. ```typescript
  186. import { apiRequest } from '@seontechnologies/playwright-utils/api-request'; // Small bundle
  187. ```
  188. ## Reference Implementation
  189. The official `@seontechnologies/playwright-utils` repository provides working examples of all patterns described in these fragments.
  190. **Repository:** <https://github.com/seontechnologies/playwright-utils>
  191. **Key resources:**
  192. - **Test examples:** `playwright/tests` - All utilities in action
  193. - **Framework setup:** `playwright.config.ts`, `playwright/support/merged-fixtures.ts`
  194. - **CI patterns:** `.github/workflows/` - GitHub Actions with sharding, parallelization
  195. **Quick start:**
  196. ```bash
  197. git clone https://github.com/seontechnologies/playwright-utils.git
  198. cd playwright-utils
  199. nvm use
  200. npm install
  201. npm run test:pw-ui # Explore tests with Playwright UI
  202. npm run test:pw
  203. ```
  204. All patterns in TEA fragments are production-tested in this repository.