testeiya 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/PIPELINES.md +3 -0
  2. package/README.md +10 -20
  3. package/dist/prompt/clis.d.ts +7 -0
  4. package/dist/prompt/pipeline-report.d.ts +1 -0
  5. package/dist/prompt/report.d.ts +10 -0
  6. package/dist/prompt/system-prompt.d.ts +22 -0
  7. package/dist/prompt/system-prompt.js +1 -1
  8. package/dist/prompt/system-prompt.js.map +1 -1
  9. package/dist/prompt/testomat.io.d.ts +19 -0
  10. package/dist/prompt/thread.d.ts +73 -0
  11. package/dist/src/args.d.ts +39 -0
  12. package/dist/src/attribution-extension.d.ts +3 -0
  13. package/dist/src/checkpoint.d.ts +30 -0
  14. package/dist/src/cli.d.ts +2 -0
  15. package/dist/src/cli.js +27 -32
  16. package/dist/src/cli.js.map +1 -1
  17. package/dist/src/doctor.d.ts +11 -0
  18. package/dist/src/env.d.ts +30 -0
  19. package/dist/src/exec.d.ts +11 -0
  20. package/dist/src/git.d.ts +41 -0
  21. package/dist/src/git.js +10 -0
  22. package/dist/src/git.js.map +1 -1
  23. package/dist/src/langfuse-extension.d.ts +7 -0
  24. package/dist/src/langfuse.d.ts +67 -0
  25. package/dist/src/mcp.d.ts +19 -0
  26. package/dist/src/model.d.ts +20 -0
  27. package/dist/src/model.js +2 -0
  28. package/dist/src/model.js.map +1 -1
  29. package/dist/src/models.d.ts +1 -0
  30. package/dist/src/output.d.ts +84 -0
  31. package/dist/src/pipeline/command-stage.d.ts +12 -0
  32. package/dist/src/pipeline/crash-guard.d.ts +12 -0
  33. package/dist/src/pipeline/crash-guard.js +21 -0
  34. package/dist/src/pipeline/crash-guard.js.map +1 -0
  35. package/dist/src/pipeline/diagram.d.ts +24 -0
  36. package/dist/src/pipeline/gate.d.ts +21 -0
  37. package/dist/src/pipeline/launcher.d.ts +33 -0
  38. package/dist/src/pipeline/launcher.js +16 -3
  39. package/dist/src/pipeline/launcher.js.map +1 -1
  40. package/dist/src/pipeline/log.d.ts +29 -0
  41. package/dist/src/pipeline/log.js +9 -0
  42. package/dist/src/pipeline/log.js.map +1 -1
  43. package/dist/src/pipeline/overlay.d.ts +29 -0
  44. package/dist/src/pipeline/pipeline-file.d.ts +44 -0
  45. package/dist/src/pipeline/pipeline-file.js +16 -8
  46. package/dist/src/pipeline/pipeline-file.js.map +1 -1
  47. package/dist/src/pipeline/pipeline.d.ts +78 -0
  48. package/dist/src/pipeline/pipeline.js +33 -7
  49. package/dist/src/pipeline/pipeline.js.map +1 -1
  50. package/dist/src/pipeline/report.d.ts +26 -0
  51. package/dist/src/pipeline/report.js +13 -0
  52. package/dist/src/pipeline/report.js.map +1 -1
  53. package/dist/src/pipeline/spec.d.ts +63 -0
  54. package/dist/src/pipeline/stage-env.d.ts +13 -0
  55. package/dist/src/pipeline/stage-env.js +31 -0
  56. package/dist/src/pipeline/stage-env.js.map +1 -0
  57. package/dist/src/pipeline/stage.d.ts +71 -0
  58. package/dist/src/pipeline/stage.js.map +1 -1
  59. package/dist/src/pipeline/state.d.ts +63 -0
  60. package/dist/src/pipeline/summary-stage.d.ts +24 -0
  61. package/dist/src/pipeline/task-stage.d.ts +24 -0
  62. package/dist/src/pipeline/task-stage.js +86 -2
  63. package/dist/src/pipeline/task-stage.js.map +1 -1
  64. package/dist/src/pipeline/variables.d.ts +20 -0
  65. package/dist/src/result.d.ts +6 -0
  66. package/dist/src/run.d.ts +69 -0
  67. package/dist/src/run.js +116 -60
  68. package/dist/src/run.js.map +1 -1
  69. package/dist/src/session.d.ts +43 -0
  70. package/dist/src/session.js +3 -1
  71. package/dist/src/session.js.map +1 -1
  72. package/dist/src/sessions.d.ts +23 -0
  73. package/dist/src/skills.d.ts +29 -0
  74. package/package.json +11 -2
  75. package/pipelines/api-testing.yml +16 -5
  76. package/pipelines/issue-test-cases.yml +3 -4
  77. package/pipelines/pr-review.yml +14 -5
  78. package/pipelines/regression.yml +1 -0
  79. package/pipelines/web-testing.yml +1 -0
  80. package/prompt/system-prompt.ts +1 -1
  81. package/scripts/vendor-skills.js +62 -0
  82. package/skills/codeceptjs/ci-fix-tests/SKILL.md +0 -119
  83. package/skills/codeceptjs/codeceptjs-auth/SKILL.md +0 -141
  84. package/skills/codeceptjs/codeceptjs-exploration/SKILL.md +0 -100
  85. package/skills/codeceptjs/codeceptjs-fundamentals/SKILL.md +0 -196
  86. package/skills/codeceptjs/codeceptjs-run-analysis/SKILL.md +0 -83
  87. package/skills/codeceptjs/debugging-codeceptjs-tests/SKILL.md +0 -126
  88. package/skills/codeceptjs/lint-codeceptjs-tests/SKILL.md +0 -104
  89. package/skills/codeceptjs/migrate-codeceptjs-4/SKILL.md +0 -109
  90. package/skills/codeceptjs/migrate-cypress-to-codeceptjs/SKILL.md +0 -295
  91. package/skills/codeceptjs/migrate-protractor-to-codeceptjs/SKILL.md +0 -339
  92. package/skills/codeceptjs/migrate-selenium-java-to-codeceptjs/SKILL.md +0 -459
  93. package/skills/codeceptjs/migrate-testcafe-to-codeceptjs/SKILL.md +0 -338
  94. package/skills/codeceptjs/refactoring-codeceptjs-tests/SKILL.md +0 -78
  95. package/skills/codeceptjs/writing-codeceptjs-tests/SKILL.md +0 -102
  96. package/skills/playwright/playwright-best-practices/SKILL.md +0 -303
  97. package/skills/playwright/playwright-best-practices/advanced/authentication-flows.md +0 -360
  98. package/skills/playwright/playwright-best-practices/advanced/authentication.md +0 -871
  99. package/skills/playwright/playwright-best-practices/advanced/clock-mocking.md +0 -364
  100. package/skills/playwright/playwright-best-practices/advanced/mobile-testing.md +0 -409
  101. package/skills/playwright/playwright-best-practices/advanced/multi-context.md +0 -288
  102. package/skills/playwright/playwright-best-practices/advanced/multi-user.md +0 -393
  103. package/skills/playwright/playwright-best-practices/advanced/network-advanced.md +0 -452
  104. package/skills/playwright/playwright-best-practices/advanced/third-party.md +0 -464
  105. package/skills/playwright/playwright-best-practices/architecture/pom-vs-fixtures.md +0 -363
  106. package/skills/playwright/playwright-best-practices/architecture/test-architecture.md +0 -369
  107. package/skills/playwright/playwright-best-practices/architecture/when-to-mock.md +0 -383
  108. package/skills/playwright/playwright-best-practices/browser-apis/browser-apis.md +0 -391
  109. package/skills/playwright/playwright-best-practices/browser-apis/iframes.md +0 -403
  110. package/skills/playwright/playwright-best-practices/browser-apis/service-workers.md +0 -504
  111. package/skills/playwright/playwright-best-practices/browser-apis/websockets.md +0 -403
  112. package/skills/playwright/playwright-best-practices/core/annotations.md +0 -424
  113. package/skills/playwright/playwright-best-practices/core/assertions-waiting.md +0 -361
  114. package/skills/playwright/playwright-best-practices/core/configuration.md +0 -452
  115. package/skills/playwright/playwright-best-practices/core/fixtures-hooks.md +0 -417
  116. package/skills/playwright/playwright-best-practices/core/global-setup.md +0 -434
  117. package/skills/playwright/playwright-best-practices/core/locators.md +0 -242
  118. package/skills/playwright/playwright-best-practices/core/page-object-model.md +0 -315
  119. package/skills/playwright/playwright-best-practices/core/projects-dependencies.md +0 -453
  120. package/skills/playwright/playwright-best-practices/core/test-data.md +0 -492
  121. package/skills/playwright/playwright-best-practices/core/test-suite-structure.md +0 -361
  122. package/skills/playwright/playwright-best-practices/core/test-tags.md +0 -298
  123. package/skills/playwright/playwright-best-practices/debugging/console-errors.md +0 -420
  124. package/skills/playwright/playwright-best-practices/debugging/debugging.md +0 -504
  125. package/skills/playwright/playwright-best-practices/debugging/error-testing.md +0 -360
  126. package/skills/playwright/playwright-best-practices/debugging/flaky-tests.md +0 -496
  127. package/skills/playwright/playwright-best-practices/frameworks/angular.md +0 -530
  128. package/skills/playwright/playwright-best-practices/frameworks/nextjs.md +0 -469
  129. package/skills/playwright/playwright-best-practices/frameworks/react.md +0 -531
  130. package/skills/playwright/playwright-best-practices/frameworks/vue.md +0 -574
  131. package/skills/playwright/playwright-best-practices/infrastructure-ci-cd/ci-cd.md +0 -468
  132. package/skills/playwright/playwright-best-practices/infrastructure-ci-cd/docker.md +0 -283
  133. package/skills/playwright/playwright-best-practices/infrastructure-ci-cd/github-actions.md +0 -546
  134. package/skills/playwright/playwright-best-practices/infrastructure-ci-cd/gitlab.md +0 -397
  135. package/skills/playwright/playwright-best-practices/infrastructure-ci-cd/other-providers.md +0 -521
  136. package/skills/playwright/playwright-best-practices/infrastructure-ci-cd/parallel-sharding.md +0 -371
  137. package/skills/playwright/playwright-best-practices/infrastructure-ci-cd/performance.md +0 -453
  138. package/skills/playwright/playwright-best-practices/infrastructure-ci-cd/reporting.md +0 -424
  139. package/skills/playwright/playwright-best-practices/infrastructure-ci-cd/test-coverage.md +0 -497
  140. package/skills/playwright/playwright-best-practices/testing-patterns/accessibility.md +0 -359
  141. package/skills/playwright/playwright-best-practices/testing-patterns/api-testing.md +0 -719
  142. package/skills/playwright/playwright-best-practices/testing-patterns/browser-extensions.md +0 -506
  143. package/skills/playwright/playwright-best-practices/testing-patterns/canvas-webgl.md +0 -493
  144. package/skills/playwright/playwright-best-practices/testing-patterns/component-testing.md +0 -500
  145. package/skills/playwright/playwright-best-practices/testing-patterns/drag-drop.md +0 -576
  146. package/skills/playwright/playwright-best-practices/testing-patterns/electron.md +0 -509
  147. package/skills/playwright/playwright-best-practices/testing-patterns/file-operations.md +0 -377
  148. package/skills/playwright/playwright-best-practices/testing-patterns/file-upload-download.md +0 -562
  149. package/skills/playwright/playwright-best-practices/testing-patterns/forms-validation.md +0 -561
  150. package/skills/playwright/playwright-best-practices/testing-patterns/graphql-testing.md +0 -331
  151. package/skills/playwright/playwright-best-practices/testing-patterns/i18n.md +0 -508
  152. package/skills/playwright/playwright-best-practices/testing-patterns/performance-testing.md +0 -476
  153. package/skills/playwright/playwright-best-practices/testing-patterns/security-testing.md +0 -430
  154. package/skills/playwright/playwright-best-practices/testing-patterns/visual-regression.md +0 -634
  155. package/skills/playwright/playwright-cli/SKILL.md +0 -489
  156. package/skills/playwright/playwright-cli/references/element-attributes.md +0 -23
  157. package/skills/playwright/playwright-cli/references/playwright-tests.md +0 -39
  158. package/skills/playwright/playwright-cli/references/pr-attachments.md +0 -60
  159. package/skills/playwright/playwright-cli/references/request-mocking.md +0 -87
  160. package/skills/playwright/playwright-cli/references/running-code.md +0 -245
  161. package/skills/playwright/playwright-cli/references/session-management.md +0 -227
  162. package/skills/playwright/playwright-cli/references/storage-state.md +0 -275
  163. package/skills/playwright/playwright-cli/references/test-generation.md +0 -433
  164. package/skills/playwright/playwright-cli/references/tracing.md +0 -139
  165. package/skills/playwright/playwright-cli/references/video-recording.md +0 -216
  166. package/skills/skills.lock.json +0 -89
  167. package/skills/skills.yaml +0 -35
  168. /package/skills/{testomatio/explorbot → explorbot}/explorbot-fundamentals/SKILL.md +0 -0
  169. /package/skills/{testomatio/explorbot → explorbot}/explorbot-fundamentals/references/no-install.md +0 -0
  170. /package/skills/{testomatio/explorbot → explorbot}/explorbot-plan/SKILL.md +0 -0
  171. /package/skills/{testomatio/explorbot → explorbot}/explorbot-setup/SKILL.md +0 -0
  172. /package/skills/{testomatio/explorbot → explorbot}/prima/SKILL.md +0 -0
  173. /package/skills/{testomatio/qa-process → qa-process}/qa-lead-strategy-advisor/SKILL.md +0 -0
  174. /package/skills/{testomatio/qa-process → qa-process}/qa-lead-strategy-advisor/references/output-format.md +0 -0
  175. /package/skills/{testomatio/qa-process → qa-process}/qa-review-pr/SKILL.md +0 -0
  176. /package/skills/{testomatio/qa-process → qa-process}/testing-workflow/SKILL.md +0 -0
  177. /package/skills/{testomatio/requirements → requirements}/catalog-features/SKILL.md +0 -0
  178. /package/skills/{testomatio/requirements → requirements}/catalog-features/references/layout.md +0 -0
  179. /package/skills/{testomatio/requirements → requirements}/detect-product-mismatches/SKILL.md +0 -0
  180. /package/skills/{testomatio/requirements → requirements}/detect-product-mismatches/references/features.md +0 -0
  181. /package/skills/{testomatio/requirements → requirements}/detect-product-mismatches/references/layout.md +0 -0
  182. /package/skills/{testomatio/requirements → requirements}/pull-request-diff-analyzer/SKILL.md +0 -0
  183. /package/skills/{testomatio/requirements → requirements}/qa-explain-behavior/SKILL.md +0 -0
  184. /package/skills/{testomatio/requirements → requirements}/qa-explain-behavior/references/answer-shapes.md +0 -0
  185. /package/skills/{testomatio/requirements → requirements}/qa-explain-behavior/references/examples.md +0 -0
  186. /package/skills/{testomatio/requirements → requirements}/qa-pr-requirements-analyzer/SKILL.md +0 -0
  187. /package/skills/{testomatio/requirements → requirements}/qa-pr-requirements-analyzer/references/summary-example.md +0 -0
  188. /package/skills/{testomatio/requirements → requirements}/qa-requirement-reviewer/SKILL.md +0 -0
  189. /package/skills/{testomatio/requirements → requirements}/qa-requirement-reviewer/references/requirements_reviewer_examples.md +0 -0
  190. /package/skills/{testomatio/requirements → requirements}/qa-thinking/SKILL.md +0 -0
  191. /package/skills/{testomatio/requirements → requirements}/wiki-from-code/SKILL.md +0 -0
  192. /package/skills/{testomatio/requirements → requirements}/wiki-from-code/references/behaviors.md +0 -0
  193. /package/skills/{testomatio/requirements → requirements}/wiki-from-code/references/layout.md +0 -0
  194. /package/skills/{testomatio/requirements → requirements}/write-user-story/SKILL.md +0 -0
  195. /package/skills/{testomatio/test-automation → test-automation}/automate-manual-test-cases/CLAUDE.md +0 -0
  196. /package/skills/{testomatio/test-automation → test-automation}/automate-manual-test-cases/SKILL.md +0 -0
  197. /package/skills/{testomatio/test-automation → test-automation}/automate-manual-test-cases/references/CODECEPTJS_BEST_PRACTICES.md +0 -0
  198. /package/skills/{testomatio/test-automation → test-automation}/automate-manual-test-cases/references/FINAL_SUMMARY_TEMPLATE.md +0 -0
  199. /package/skills/{testomatio/test-automation → test-automation}/automate-manual-test-cases/references/PLAYWRIGHT_BEST_PRACTICES.md +0 -0
  200. /package/skills/{testomatio/test-automation → test-automation}/automate-manual-test-cases/references/POM_BEST_PRACTICES.md +0 -0
  201. /package/skills/{testomatio/test-automation → test-automation}/automate-manual-test-cases/references/TEST_DATA_MANAGEMENT.md +0 -0
  202. /package/skills/{testomatio/test-automation → test-automation}/debug-fix-failed-flaky-autotests/SKILL.md +0 -0
  203. /package/skills/{testomatio/test-automation → test-automation}/debug-fix-failed-flaky-autotests/references/DEBUGGING_QUICK_REFERENCE.md +0 -0
  204. /package/skills/{testomatio/test-automation → test-automation}/epic-requirements-specification/SKILL.md +0 -0
  205. /package/skills/{testomatio/test-automation → test-automation}/qa-automation-test-consolidation/SKILL.md +0 -0
  206. /package/skills/{testomatio/test-automation → test-automation}/qa-data-seeder/SKILL.md +0 -0
  207. /package/skills/{testomatio/test-automation → test-automation}/run-tests-with-testomatio-reporter/SKILL.md +0 -0
  208. /package/skills/{testomatio/test-automation → test-automation}/setup-change-aware-pr-testing/SKILL.md +0 -0
  209. /package/skills/{testomatio/test-automation → test-automation}/setup-ci-automation/SKILL.md +0 -0
  210. /package/skills/{testomatio/test-automation → test-automation}/testomat-allure-adapter/SKILL.md +0 -0
  211. /package/skills/{testomatio/test-management → test-management}/detect-duplicate-test-cases/SKILL.md +0 -0
  212. /package/skills/{testomatio/test-management → test-management}/detect-duplicate-test-cases/references/DUPLICATE_INSTRUCTIONS.md +0 -0
  213. /package/skills/{testomatio/test-management → test-management}/detect-useless-tests/SKILL.md +0 -0
  214. /package/skills/{testomatio/test-management → test-management}/improve-test-cases/SKILL.md +0 -0
  215. /package/skills/{testomatio/test-management → test-management}/improve-test-cases/references/TESTOMAT_MARKDOWN_EXAMPLE.md +0 -0
  216. /package/skills/{testomatio/test-management → test-management}/migrate-to-testomatio/SKILL.md +0 -0
  217. /package/skills/{testomatio/test-management → test-management}/migrate-to-testomatio/references/CSV_MIGRATION.md +0 -0
  218. /package/skills/{testomatio/test-management → test-management}/migrate-to-testomatio/references/CUSTOM_MIGRATION.md +0 -0
  219. /package/skills/{testomatio/test-management → test-management}/migrate-to-testomatio/references/TESTMO_MIGRATION.md +0 -0
  220. /package/skills/{testomatio/test-management → test-management}/migrate-to-testomatio/references/TESTRAIL_MIGRATION.md +0 -0
  221. /package/skills/{testomatio/test-management → test-management}/migrate-to-testomatio/references/XRAY_MIGRATION.md +0 -0
  222. /package/skills/{testomatio/test-management → test-management}/qa-e2e-tests-reporting/SKILL.md +0 -0
  223. /package/skills/{testomatio/test-management → test-management}/qa-e2e-tests-reporting/references/TESTOMATIO_ARTIFACTS.md +0 -0
  224. /package/skills/{testomatio/test-management → test-management}/qa-e2e-tests-reporting/references/TESTOMATIO_HTML_REPORT.md +0 -0
  225. /package/skills/{testomatio/test-management → test-management}/qa-e2e-tests-reporting/references/TESTOMATIO_REPORTERS_CONFIG.md +0 -0
  226. /package/skills/{testomatio/test-management → test-management}/qa-split-testing-levels-pyramid/SKILL.md +0 -0
  227. /package/skills/{testomatio/test-management → test-management}/qa-sprint-report-by-testomatio/SKILL.md +0 -0
  228. /package/skills/{testomatio/test-management → test-management}/qa-sprint-report-by-testomatio/references/qa-sprint-report.md +0 -0
  229. /package/skills/{testomatio/test-management → test-management}/qa-test-code-coverage/SKILL.md +0 -0
  230. /package/skills/{testomatio/test-management → test-management}/qa-test-code-coverage/references/COVERAGE_FILE_FORMAT.md +0 -0
  231. /package/skills/{testomatio/test-management → test-management}/qa-test-code-coverage/references/E2E_FRAMEWORKS.md +0 -0
  232. /package/skills/{testomatio/test-management → test-management}/qa-test-code-coverage/scripts/check-coverage.mjs +0 -0
  233. /package/skills/{testomatio/test-management → test-management}/qa-write-test-cases/SKILL.md +0 -0
  234. /package/skills/{testomatio/test-management → test-management}/qa-write-test-cases/references/test-case-format.md +0 -0
  235. /package/skills/{testomatio/test-management → test-management}/qa-write-test-cases/references/testomat-tms-guide.md +0 -0
  236. /package/skills/{testomatio/test-management → test-management}/qa-write-test-cases/references/writing-rule.md +0 -0
  237. /package/skills/{testomatio/test-management → test-management}/scan-automation-project/SKILL.md +0 -0
  238. /package/skills/{testomatio/test-management → test-management}/sync-test-cases-with-tms/SKILL.md +0 -0
  239. /package/skills/{testomatio/test-management → test-management}/sync-test-cases-with-tms/references/TESTOMATIO_CLI.md +0 -0
  240. /package/skills/{testomatio/test-management → test-management}/testomatio-mcp/SKILL.md +0 -0
  241. /package/skills/{testomatio/test-management → test-management}/testomatio-mcp/references/MCP_SETUP.md +0 -0
@@ -1,531 +0,0 @@
1
- # React Application Testing
2
-
3
- ## Table of Contents
4
-
5
- 1. [Patterns](#patterns)
6
- 2. [Setup](#setup)
7
- 3. [Framework Tips](#framework-tips)
8
- 4. [Anti-Patterns](#anti-patterns)
9
- 5. [Related](#related)
10
-
11
- > **When to use**: Testing React apps built with Vite, Create React App, or custom bundlers. Covers E2E testing, component testing, React Router navigation, form libraries, portals, error boundaries, and context/state verification.
12
- > **Prerequisites**: [configuration.md](../core/configuration.md), [locators.md](../core/locators.md)
13
-
14
- ## Patterns
15
-
16
- ### Testing Context and Global State
17
-
18
- **Use when**: Verifying React context (theme, auth, locale) and state management (Redux, Zustand) produce correct UI changes.
19
- **Avoid when**: You want to assert on raw state objects—test the UI, not internal state.
20
-
21
- ```typescript
22
- import { test, expect } from '@playwright/test';
23
-
24
- test.describe('theme switching', () => {
25
- test('toggle applies dark mode across pages', async ({ page }) => {
26
- await page.goto('/preferences');
27
-
28
- const root = page.locator('html');
29
- await expect(root).not.toHaveClass(/dark-mode/);
30
-
31
- await page.getByRole('switch', { name: 'Enable dark theme' }).click();
32
- await expect(root).toHaveClass(/dark-mode/);
33
-
34
- await page.getByRole('link', { name: 'Dashboard' }).click();
35
- await expect(page.locator('html')).toHaveClass(/dark-mode/);
36
- });
37
- });
38
-
39
- test.describe('cart state persistence', () => {
40
- test('item count updates globally', async ({ page }) => {
41
- await page.goto('/catalog');
42
-
43
- const badge = page.getByTestId('cart-badge');
44
-
45
- await page.getByRole('listitem')
46
- .filter({ hasText: 'Wireless Headphones' })
47
- .getByRole('button', { name: 'Add' })
48
- .click();
49
- await expect(badge).toHaveText('1');
50
-
51
- await page.getByRole('link', { name: 'Contact' }).click();
52
- await expect(badge).toHaveText('1');
53
- });
54
- });
55
-
56
- test.describe('auth state', () => {
57
- test('login updates header across components', async ({ page }) => {
58
- await page.goto('/');
59
-
60
- await expect(page.getByRole('link', { name: 'Login' })).toBeVisible();
61
-
62
- await page.getByRole('link', { name: 'Login' }).click();
63
- await page.getByLabel('Username').fill('testuser');
64
- await page.getByLabel('Password').fill('secret123');
65
- await page.getByRole('button', { name: 'Submit' }).click();
66
-
67
- await expect(page.getByRole('link', { name: 'Login' })).toBeHidden();
68
- await expect(page.getByText('testuser')).toBeVisible();
69
- });
70
- });
71
- ```
72
-
73
- ### React Router Navigation
74
-
75
- **Use when**: Testing client-side routing with React Router v6+—route transitions, URL parameters, protected routes, browser history.
76
- **Avoid when**: Server-side routing (Next.js App Router—see [nextjs.md](nextjs.md)).
77
-
78
- ```typescript
79
- import { test, expect } from '@playwright/test';
80
-
81
- test.describe('client routing', () => {
82
- test('navigation preserves SPA state', async ({ page }) => {
83
- await page.goto('/');
84
-
85
- await page.evaluate(() => {
86
- (window as any).__spaMarker = 'active';
87
- });
88
-
89
- await page.getByRole('link', { name: 'Inventory' }).click();
90
- await page.waitForURL('/inventory');
91
-
92
- const marker = await page.evaluate(() => (window as any).__spaMarker);
93
- expect(marker).toBe('active');
94
- });
95
-
96
- test('query params filter content', async ({ page }) => {
97
- await page.goto('/items?type=books');
98
-
99
- await expect(page.getByRole('heading', { name: 'Books' })).toBeVisible();
100
-
101
- await page.getByRole('link', { name: 'Music' }).click();
102
- await page.waitForURL('/items?type=music');
103
-
104
- await expect(page.getByRole('heading', { name: 'Music' })).toBeVisible();
105
- });
106
-
107
- test('nested routes render layouts', async ({ page }) => {
108
- await page.goto('/account/security');
109
-
110
- await expect(page.getByRole('heading', { name: 'Account' })).toBeVisible();
111
- await expect(page.getByRole('heading', { name: 'Security', level: 2 })).toBeVisible();
112
-
113
- await page.getByRole('link', { name: 'Privacy' }).click();
114
- await page.waitForURL('/account/privacy');
115
-
116
- await expect(page.getByRole('heading', { name: 'Account' })).toBeVisible();
117
- await expect(page.getByRole('heading', { name: 'Privacy', level: 2 })).toBeVisible();
118
- });
119
-
120
- test('history navigation works', async ({ page }) => {
121
- await page.goto('/');
122
- await page.getByRole('link', { name: 'Inventory' }).click();
123
- await page.waitForURL('/inventory');
124
- await page.getByRole('link', { name: 'Help' }).click();
125
- await page.waitForURL('/help');
126
-
127
- await page.goBack();
128
- await expect(page).toHaveURL(/\/inventory/);
129
-
130
- await page.goBack();
131
- await expect(page).toHaveURL(/\/$/);
132
- });
133
-
134
- test('protected route redirects', async ({ page }) => {
135
- await page.goto('/admin/users');
136
-
137
- await expect(page).toHaveURL(/\/login/);
138
- });
139
-
140
- test('unknown route shows 404', async ({ page }) => {
141
- await page.goto('/nonexistent-path');
142
-
143
- await expect(page.getByRole('heading', { name: 'Not Found' })).toBeVisible();
144
- });
145
- });
146
- ```
147
-
148
- ### Testing Hooks Through UI
149
-
150
- **Use when**: Verifying custom hooks produce correct UI behavior—Playwright cannot call hooks directly.
151
- **Avoid when**: Hook logic is pure computation—use unit tests instead.
152
-
153
- ```typescript
154
- import { test, expect } from '@playwright/test';
155
-
156
- test.describe('useDebounce via SearchBox', () => {
157
- test('batches rapid input', async ({ page }) => {
158
- await page.goto('/search');
159
-
160
- const apiCalls: string[] = [];
161
- await page.route('**/api/query*', async (route) => {
162
- apiCalls.push(route.request().url());
163
- await route.continue();
164
- });
165
-
166
- await page.getByRole('textbox', { name: 'Search' }).pressSequentially('testing', {
167
- delay: 40,
168
- });
169
-
170
- await expect(page.getByRole('listitem')).toHaveCount(3);
171
- expect(apiCalls.length).toBeLessThanOrEqual(2);
172
- });
173
- });
174
-
175
- test.describe('usePagination via DataGrid', () => {
176
- test('page controls work', async ({ page }) => {
177
- await page.goto('/records');
178
-
179
- await expect(page.getByText('Page 1 of 10')).toBeVisible();
180
-
181
- await page.getByRole('button', { name: 'Next' }).click();
182
- await expect(page.getByText('Page 2 of 10')).toBeVisible();
183
-
184
- await page.getByRole('button', { name: 'Previous' }).click();
185
- await expect(page.getByText('Page 1 of 10')).toBeVisible();
186
- await expect(page.getByRole('button', { name: 'Previous' })).toBeDisabled();
187
- });
188
- });
189
- ```
190
-
191
- ### Form Libraries (React Hook Form, Formik)
192
-
193
- **Use when**: Testing forms built with react-hook-form or Formik—Playwright interacts with DOM, form library is transparent.
194
-
195
- ```typescript
196
- import { test, expect } from '@playwright/test';
197
-
198
- test.describe('signup form', () => {
199
- test.beforeEach(async ({ page }) => {
200
- await page.goto('/signup');
201
- });
202
-
203
- test('validation on empty submit', async ({ page }) => {
204
- await page.getByRole('button', { name: 'Register' }).click();
205
-
206
- await expect(page.getByText('Email required')).toBeVisible();
207
- await expect(page.getByText('Password required')).toBeVisible();
208
- });
209
-
210
- test('inline validation on blur', async ({ page }) => {
211
- const email = page.getByLabel('Email');
212
- await email.fill('invalid');
213
- await email.blur();
214
-
215
- await expect(page.getByText('Invalid email format')).toBeVisible();
216
- });
217
-
218
- test('password strength indicator', async ({ page }) => {
219
- const pwd = page.getByLabel('Password', { exact: true });
220
-
221
- await pwd.fill('weak');
222
- await expect(page.getByText('Minimum 8 characters')).toHaveClass(/invalid/);
223
-
224
- await pwd.fill('StrongPass1!');
225
- await expect(page.getByText('Minimum 8 characters')).toHaveClass(/valid/);
226
- });
227
-
228
- test('successful submission redirects', async ({ page }) => {
229
- await page.getByLabel('Name').fill('Alice');
230
- await page.getByLabel('Email').fill('alice@test.com');
231
- await page.getByLabel('Password', { exact: true }).fill('Secure123!');
232
- await page.getByLabel('Confirm').fill('Secure123!');
233
- await page.getByLabel('Accept terms').check();
234
-
235
- await page.getByRole('button', { name: 'Register' }).click();
236
-
237
- await page.waitForURL('/welcome');
238
- await expect(page.getByText('Hello, Alice')).toBeVisible();
239
- });
240
-
241
- test('submit button disabled during request', async ({ page }) => {
242
- await page.route('**/api/signup', async (route) => {
243
- await new Promise((r) => setTimeout(r, 800));
244
- await route.fulfill({ status: 201, json: { id: 1 } });
245
- });
246
-
247
- await page.getByLabel('Name').fill('Bob');
248
- await page.getByLabel('Email').fill('bob@test.com');
249
- await page.getByLabel('Password', { exact: true }).fill('Secure123!');
250
- await page.getByLabel('Confirm').fill('Secure123!');
251
- await page.getByLabel('Accept terms').check();
252
-
253
- await page.getByRole('button', { name: 'Register' }).click();
254
-
255
- await expect(page.getByRole('button', { name: /Registering|Loading/ })).toBeDisabled();
256
- });
257
- });
258
- ```
259
-
260
- ### Portals (Modals, Tooltips, Dropdowns)
261
-
262
- **Use when**: Testing components rendered via `ReactDOM.createPortal()`—modals, dialogs, tooltips, menus. These render outside parent DOM but Playwright sees the full document.
263
-
264
- ```typescript
265
- import { test, expect } from '@playwright/test';
266
-
267
- test.describe('portal components', () => {
268
- test('modal interaction', async ({ page }) => {
269
- await page.goto('/items');
270
-
271
- await page.getByRole('button', { name: 'Remove' }).first().click();
272
-
273
- const dialog = page.getByRole('dialog', { name: 'Confirm removal' });
274
- await expect(dialog).toBeVisible();
275
- await expect(dialog.getByRole('button', { name: 'Cancel' })).toBeFocused();
276
-
277
- await dialog.getByRole('button', { name: 'Remove' }).click();
278
- await expect(dialog).toBeHidden();
279
- });
280
-
281
- test('escape closes modal', async ({ page }) => {
282
- await page.goto('/items');
283
- await page.getByRole('button', { name: 'Remove' }).first().click();
284
-
285
- const dialog = page.getByRole('dialog');
286
- await expect(dialog).toBeVisible();
287
-
288
- await page.keyboard.press('Escape');
289
- await expect(dialog).toBeHidden();
290
- });
291
-
292
- test('tooltip on hover', async ({ page }) => {
293
- await page.goto('/panel');
294
-
295
- await page.getByRole('button', { name: 'Help' }).hover();
296
- await expect(page.getByRole('tooltip')).toBeVisible();
297
-
298
- await page.mouse.move(0, 0);
299
- await expect(page.getByRole('tooltip')).toBeHidden();
300
- });
301
-
302
- test('dropdown menu', async ({ page }) => {
303
- await page.goto('/panel');
304
-
305
- await page.getByRole('button', { name: 'Actions' }).click();
306
-
307
- const menu = page.getByRole('menu');
308
- await expect(menu).toBeVisible();
309
-
310
- await menu.getByRole('menuitem', { name: 'Rename' }).click();
311
- await expect(menu).toBeHidden();
312
- });
313
-
314
- test('toast auto-dismisses', async ({ page }) => {
315
- await page.goto('/preferences');
316
-
317
- await page.getByRole('button', { name: 'Save' }).click();
318
- await expect(page.getByText('Preferences saved')).toBeVisible();
319
-
320
- await expect(page.getByText('Preferences saved')).toBeHidden({ timeout: 8000 });
321
- });
322
- });
323
- ```
324
-
325
- ### Error Boundaries
326
-
327
- **Use when**: Verifying error boundaries catch rendering errors and show fallback UI.
328
- **Avoid when**: Testing error handling in event handlers or async code—error boundaries only catch render errors.
329
-
330
- ```typescript
331
- import { test, expect } from '@playwright/test';
332
-
333
- test.describe('error boundary', () => {
334
- test('shows fallback on crash', async ({ page }) => {
335
- await page.route('**/api/widgets', (route) => {
336
- route.fulfill({
337
- status: 200,
338
- json: { widgets: null },
339
- });
340
- });
341
-
342
- await page.goto('/panel');
343
-
344
- await expect(page.getByText('Something went wrong')).toBeVisible();
345
- await expect(page.getByRole('button', { name: 'Retry' })).toBeVisible();
346
- await expect(page.getByRole('navigation')).toBeVisible();
347
- });
348
-
349
- test('retry recovers component', async ({ page }) => {
350
- let calls = 0;
351
- await page.route('**/api/widgets', (route) => {
352
- calls++;
353
- if (calls === 1) {
354
- route.fulfill({ status: 200, json: { widgets: null } });
355
- } else {
356
- route.fulfill({ status: 200, json: { widgets: [{ id: 1, name: 'Chart' }] } });
357
- }
358
- });
359
-
360
- await page.goto('/panel');
361
-
362
- await expect(page.getByText('Something went wrong')).toBeVisible();
363
-
364
- await page.getByRole('button', { name: 'Retry' }).click();
365
-
366
- await expect(page.getByText('Something went wrong')).toBeHidden();
367
- await expect(page.getByText('Chart')).toBeVisible();
368
- });
369
- });
370
- ```
371
-
372
- ### Component Testing (Experimental)
373
-
374
- **Use when**: Testing complex interactive components in isolation—data tables, form wizards, rich editors. Needs real browser but not full app.
375
- **Avoid when**: Component depends heavily on backend data or routing—use E2E instead.
376
-
377
- ```typescript
378
- // playwright-ct.config.ts
379
- import { defineConfig, devices } from '@playwright/experimental-ct-react';
380
-
381
- export default defineConfig({
382
- testDir: './tests/components',
383
- testMatch: '**/*.ct.ts',
384
- use: {
385
- trace: 'on-first-retry',
386
- ctPort: 3100,
387
- },
388
- projects: [
389
- { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
390
- ],
391
- });
392
- ```
393
-
394
- ```typescript
395
- // tests/components/Stepper.ct.ts
396
- import { test, expect } from '@playwright/experimental-ct-react';
397
- import Stepper from '../../src/components/Stepper';
398
-
399
- test('increments on click', async ({ mount }) => {
400
- const component = await mount(<Stepper initial={0} />);
401
-
402
- await expect(component.getByText('Value: 0')).toBeVisible();
403
- await component.getByRole('button', { name: '+' }).click();
404
- await expect(component.getByText('Value: 1')).toBeVisible();
405
- });
406
-
407
- test('fires onChange callback', async ({ mount }) => {
408
- const values: number[] = [];
409
- const component = await mount(
410
- <Stepper initial={0} onChange={(v) => values.push(v)} />
411
- );
412
-
413
- await component.getByRole('button', { name: '+' }).click();
414
- await component.getByRole('button', { name: '+' }).click();
415
-
416
- expect(values).toEqual([1, 2]);
417
- });
418
-
419
- test('respects min boundary', async ({ mount }) => {
420
- const component = await mount(<Stepper initial={0} min={0} />);
421
-
422
- await expect(component.getByRole('button', { name: '-' })).toBeDisabled();
423
- });
424
- ```
425
-
426
- ## Setup
427
-
428
- ### E2E Config (Vite)
429
-
430
- ```typescript
431
- // playwright.config.ts
432
- import { defineConfig, devices } from '@playwright/test';
433
-
434
- export default defineConfig({
435
- testDir: './tests',
436
- fullyParallel: true,
437
- forbidOnly: !!process.env.CI,
438
- retries: process.env.CI ? 2 : 0,
439
- workers: process.env.CI ? '50%' : undefined,
440
-
441
- use: {
442
- baseURL: 'http://localhost:5173',
443
- trace: 'on-first-retry',
444
- screenshot: 'only-on-failure',
445
- },
446
-
447
- projects: [
448
- { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
449
- { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
450
- { name: 'mobile', use: { ...devices['iPhone 14'] } },
451
- ],
452
-
453
- webServer: {
454
- command: process.env.CI ? 'npm run build && npx vite preview --port 5173' : 'npm run dev',
455
- url: 'http://localhost:5173',
456
- reuseExistingServer: !process.env.CI,
457
- timeout: 120_000,
458
- },
459
- });
460
- ```
461
-
462
- ### CRA vs Vite Differences
463
-
464
- | Aspect | Create React App | Vite |
465
- |---|---|---|
466
- | Default port | `3000` | `5173` |
467
- | Build output | `build/` | `dist/` |
468
- | Serve production | `npx serve -s build -l 3000` | `npx vite preview --port 5173` |
469
- | Env var prefix | `REACT_APP_*` | `VITE_*` |
470
-
471
- ## Framework Tips
472
-
473
- ### Strict Mode Double Effects
474
-
475
- React Strict Mode runs effects twice in development. Tests should be resilient:
476
-
477
- - Don't assert exact API call counts in dev mode
478
- - Run against production build for call count assertions, or account for double invocations
479
-
480
- ### Suspense and Lazy Components
481
-
482
- ```typescript
483
- test('lazy route loads content', async ({ page }) => {
484
- await page.goto('/');
485
-
486
- await page.getByRole('link', { name: 'Analytics' }).click();
487
-
488
- await expect(page.getByRole('heading', { name: 'Analytics' })).toBeVisible();
489
- });
490
- ```
491
-
492
- ### Detecting Memory Leaks
493
-
494
- ```typescript
495
- test('no unmounted state warnings', async ({ page }) => {
496
- const warnings: string[] = [];
497
- page.on('console', (msg) => {
498
- if (msg.type() === 'warning' && msg.text().includes('unmounted')) {
499
- warnings.push(msg.text());
500
- }
501
- });
502
-
503
- await page.goto('/panel');
504
- await page.getByRole('link', { name: 'Settings' }).click();
505
- await page.goBack();
506
- await page.getByRole('link', { name: 'Profile' }).click();
507
-
508
- expect(warnings).toEqual([]);
509
- });
510
- ```
511
-
512
- ## Anti-Patterns
513
-
514
- | Don't | Problem | Do Instead |
515
- |---|---|---|
516
- | `page.evaluate(() => store.getState())` | Couples tests to implementation | Assert on UI: `expect(badge).toHaveText('3')` |
517
- | Import components in E2E tests | E2E runs in Node, not browser | Use `@playwright/experimental-ct-react` for components |
518
- | `page.waitForTimeout(500)` after state changes | Timing varies across machines | `expect(locator).toHaveText('value')` auto-retries |
519
- | `page.locator('.MuiButton-root')` | Class names change between versions | `page.getByRole('button', { name: 'Submit' })` |
520
- | Test every component with CT | Overhead for simple components | CT for complex widgets, unit tests for logic, E2E for flows |
521
- | Skip keyboard navigation tests | Accessibility regressions common | Test Tab, Enter, Escape, Arrow interactions |
522
- | Assert on `__REACT_FIBER__` internals | Not stable across versions | Only interact with rendered DOM |
523
-
524
- ## Related
525
-
526
- - [locators.md](../core/locators.md) — locator strategies for any React component library
527
- - [assertions-waiting.md](../core/assertions-waiting.md) — auto-waiting for React state changes
528
- - [forms-validation.md](../testing-patterns/forms-validation.md) — form testing patterns
529
- - [component-testing.md](../testing-patterns/component-testing.md) — in-depth component testing
530
- - [test-architecture.md](../architecture/test-architecture.md) — E2E vs component vs unit decisions
531
- - [nextjs.md](nextjs.md) — Next.js-specific patterns for SSR