@vardot/varbase-e2e 2.0.0

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 (301) hide show
  1. package/AGENTS.md +148 -0
  2. package/CLAUDE.md +544 -0
  3. package/README.md +22 -0
  4. package/bin/generate-reports.js +363 -0
  5. package/bin/init-varbase-e2e.js +330 -0
  6. package/bin/postinstall.js +26 -0
  7. package/cucumber.js +125 -0
  8. package/docs/00-quick-start.md +102 -0
  9. package/docs/01-getting-started.md +102 -0
  10. package/docs/02-bbr-smart-waits.md +77 -0
  11. package/docs/03-selector-registry.md +95 -0
  12. package/docs/04-step-reference.md +801 -0
  13. package/docs/05-web-first-assertions.md +91 -0
  14. package/docs/06-network-and-dialogs.md +83 -0
  15. package/docs/07-auth-state.md +75 -0
  16. package/docs/08-clock-mocking.md +59 -0
  17. package/docs/09-api-testing.md +114 -0
  18. package/docs/10-accessibility.md +167 -0
  19. package/docs/11-debugging.md +129 -0
  20. package/docs/12-ai-agent-guide.md +338 -0
  21. package/docs/13-faq.md +236 -0
  22. package/docs/14-recipes-cookbook.md +255 -0
  23. package/docs/15-tag-conventions.md +76 -0
  24. package/docs/16-ci-cd.md +90 -0
  25. package/docs/README.md +125 -0
  26. package/docs/advanced-screenshots/then-i-save-fullscreen-screenshot.md +36 -0
  27. package/docs/advanced-screenshots/then-i-save-width-x-height-screenshot.md +34 -0
  28. package/docs/advanced-screenshots/when-i-save-screenshot-name-filename.md +45 -0
  29. package/docs/advanced-screenshots.md +52 -0
  30. package/docs/advanced-selectors.md +18 -0
  31. package/docs/api-step-definitions.md +45 -0
  32. package/docs/global-settings.md +267 -0
  33. package/docs/install-varbase-e2e/ddev-varbase-e2e.md +52 -0
  34. package/docs/install-varbase-e2e.md +34 -0
  35. package/docs/overview.md +40 -0
  36. package/docs/step-definitions/given-i-am-anonymous-user.md +67 -0
  37. package/docs/step-definitions/given-i-am-homepage.md +68 -0
  38. package/docs/step-definitions/given-i-am-specific-page.md +72 -0
  39. package/docs/step-definitions/then-i-should-be.md +56 -0
  40. package/docs/step-definitions/then-i-should-see.md +62 -0
  41. package/docs/step-definitions/then-item-checkbox.md +54 -0
  42. package/docs/step-definitions/then-item-link-should-contain-url.md +84 -0
  43. package/docs/step-definitions/then-item-should-contain.md +67 -0
  44. package/docs/step-definitions/then-radio-button-value-should-be-selected.md +68 -0
  45. package/docs/step-definitions/then-response-status-code-should-be-number.md +69 -0
  46. package/docs/step-definitions/then-value-radio-button-selected.md +62 -0
  47. package/docs/step-definitions/when-i-attach-file-file-name-element.md +71 -0
  48. package/docs/step-definitions/when-i-check-checkbox.md +60 -0
  49. package/docs/step-definitions/when-i-click-link.md +51 -0
  50. package/docs/step-definitions/when-i-click-operation-text-row.md +71 -0
  51. package/docs/step-definitions/when-i-fill.md +59 -0
  52. package/docs/step-definitions/when-i-go-homepage.md +60 -0
  53. package/docs/step-definitions/when-i-go-specific-page.md +67 -0
  54. package/docs/step-definitions/when-i-move-backward-one-page.md +49 -0
  55. package/docs/step-definitions/when-i-move-forward-one-page.md +58 -0
  56. package/docs/step-definitions/when-i-press-button.md +58 -0
  57. package/docs/step-definitions/when-i-reload-page.md +51 -0
  58. package/docs/step-definitions/when-i-scroll.md +73 -0
  59. package/docs/step-definitions/when-i-select-option-select-list.md +53 -0
  60. package/docs/step-definitions/when-i-select-radio-button-value.md +62 -0
  61. package/docs/step-definitions/when-i-uncheck-checkbox.md +57 -0
  62. package/docs/step-definitions/when-i-wait-ajax-finish.md +64 -0
  63. package/docs/step-definitions/when-i-wait.md +62 -0
  64. package/docs/step-definitions.md +82 -0
  65. package/docs/steps/README.md +137 -0
  66. package/docs/steps/a11y.md +731 -0
  67. package/docs/steps/action.md +181 -0
  68. package/docs/steps/api.md +679 -0
  69. package/docs/steps/assertion.md +328 -0
  70. package/docs/steps/auth.md +108 -0
  71. package/docs/steps/clock.md +171 -0
  72. package/docs/steps/cookie.md +293 -0
  73. package/docs/steps/debug.md +52 -0
  74. package/docs/steps/dialog.md +226 -0
  75. package/docs/steps/drupal-canvas.md +414 -0
  76. package/docs/steps/drupal-ckeditor.md +118 -0
  77. package/docs/steps/drupal-core.md +688 -0
  78. package/docs/steps/drupal-layout-builder.md +437 -0
  79. package/docs/steps/drupal-media.md +107 -0
  80. package/docs/steps/drupal-moderation.md +81 -0
  81. package/docs/steps/drupal-paragraphs.md +36 -0
  82. package/docs/steps/element.md +455 -0
  83. package/docs/steps/field.md +648 -0
  84. package/docs/steps/file-download.md +235 -0
  85. package/docs/steps/form.md +344 -0
  86. package/docs/steps/iframe.md +248 -0
  87. package/docs/steps/input.md +220 -0
  88. package/docs/steps/javascript.md +111 -0
  89. package/docs/steps/keyboard.md +107 -0
  90. package/docs/steps/link.md +217 -0
  91. package/docs/steps/metatag.md +99 -0
  92. package/docs/steps/modal.md +232 -0
  93. package/docs/steps/navigation.md +275 -0
  94. package/docs/steps/network.md +284 -0
  95. package/docs/steps/path.md +203 -0
  96. package/docs/steps/response.md +102 -0
  97. package/docs/steps/responsive.md +139 -0
  98. package/docs/steps/rest.md +140 -0
  99. package/docs/steps/screenshot.md +211 -0
  100. package/docs/steps/scroll.md +266 -0
  101. package/docs/steps/selectors.md +848 -0
  102. package/docs/steps/storage.md +254 -0
  103. package/docs/steps/table.md +216 -0
  104. package/docs/steps/varbase.md +391 -0
  105. package/docs/steps/video.md +111 -0
  106. package/docs/steps/wait.md +553 -0
  107. package/docs/steps/web-first.md +289 -0
  108. package/docs/steps/xml.md +505 -0
  109. package/docs/steps/yaml.md +951 -0
  110. package/examples/a11y.html +31 -0
  111. package/examples/about-us.html +11 -0
  112. package/examples/account.html +32 -0
  113. package/examples/ajax-wait-examples.html +147 -0
  114. package/examples/contact-us.html +10 -0
  115. package/examples/cookies.html +10 -0
  116. package/examples/date.html +12 -0
  117. package/examples/dynamic-examples.html +498 -0
  118. package/examples/element.html +11 -0
  119. package/examples/example-api.json +28 -0
  120. package/examples/existing-page.html +11 -0
  121. package/examples/field.html +24 -0
  122. package/examples/index.html +37 -0
  123. package/examples/keyboard.html +11 -0
  124. package/examples/links.html +9 -0
  125. package/examples/modal.html +14 -0
  126. package/examples/path.html +3 -0
  127. package/examples/table.html +13 -0
  128. package/examples/test--modal-dialogs.html +252 -0
  129. package/examples/test--then--i-should--not--see-text-in-element.html +48 -0
  130. package/examples/test--then--i-should--see-text-in-element.html +48 -0
  131. package/examples/test--then--i-should--see-text-matching-pattern.html +31 -0
  132. package/examples/test--then--i-should-see-text-in-table-row.html +232 -0
  133. package/examples/test--then--the-checkbox-checked.html +68 -0
  134. package/examples/test--then--the-element-should_not-contain-cssproperty.html +47 -0
  135. package/examples/test--then--the-link-should-contain.html +21 -0
  136. package/examples/test--when--i-additionally-select.html +27 -0
  137. package/examples/test--when--i-attach-file-to-feild.html +50 -0
  138. package/examples/test--when--i-check-uncheck-checkbox.html +47 -0
  139. package/examples/test--when--i-click-link.html +18 -0
  140. package/examples/test--when--i-click-text-in-table-row.html +178 -0
  141. package/examples/test--when--i-fill-in.html +48 -0
  142. package/examples/test--when--i-press-button.html +31 -0
  143. package/examples/test--when--i-reload-page.html +27 -0
  144. package/examples/test--when--i-scroll-functionality.html +177 -0
  145. package/examples/test--when--i-scroll-left-right-functionality.html +149 -0
  146. package/examples/test--when--i-select-option-from-dropdownlist.html +35 -0
  147. package/examples/test--when--i-select-radio-button.html +95 -0
  148. package/examples/test--when-i-wait-max-of-time.html +39 -0
  149. package/examples/test--when-i-wait-page-until-is-loaded.html +47 -0
  150. package/examples/test--when-i-wait-specific-time.html +39 -0
  151. package/examples/test-acceptable-url-path.html +11 -0
  152. package/examples/video-demo.html +43 -0
  153. package/package.json +56 -0
  154. package/playwright.config.ts +39 -0
  155. package/tests/assets/test-document.pdf +14 -0
  156. package/tests/assets/vardot.png +0 -0
  157. package/tests/features/a11y.feature +39 -0
  158. package/tests/features/ajax-wait-examples.feature +24 -0
  159. package/tests/features/api-step-definitions-individual.feature +185 -0
  160. package/tests/features/complete-api-testing-examples.feature +205 -0
  161. package/tests/features/cookie.feature +13 -0
  162. package/tests/features/date.feature +11 -0
  163. package/tests/features/dynamic-content-examples.feature +156 -0
  164. package/tests/features/element.feature +16 -0
  165. package/tests/features/field.feature +25 -0
  166. package/tests/features/keyboard.feature +10 -0
  167. package/tests/features/link.feature +11 -0
  168. package/tests/features/modal-advanced-example.feature +54 -0
  169. package/tests/features/modal-basic-example.feature +42 -0
  170. package/tests/features/modal-error-handling-example.feature +37 -0
  171. package/tests/features/modal.feature +11 -0
  172. package/tests/features/path.feature +16 -0
  173. package/tests/features/response.feature +8 -0
  174. package/tests/features/responsive.feature +10 -0
  175. package/tests/features/table.feature +18 -0
  176. package/tests/features/test--given--i-am-an-anonymous-user.feature +10 -0
  177. package/tests/features/test--given--i-am-on-homepage.feature +16 -0
  178. package/tests/features/test--then--i-save-screenshot.feature +33 -0
  179. package/tests/features/test--then--i-see-locator.feature +320 -0
  180. package/tests/features/test--then--i-should--not--see-text-in-element.feature +13 -0
  181. package/tests/features/test--then--i-should--see-text-in-element-by-attr.feature +10 -0
  182. package/tests/features/test--then--i-should--see-text-in-element.feature +10 -0
  183. package/tests/features/test--then--i-should--see-text-matching-pattern-in-element.feature +13 -0
  184. package/tests/features/test--then--i-should--see-text-matching-pattern.feature +18 -0
  185. package/tests/features/test--then--i-should-be-on-page.feature +10 -0
  186. package/tests/features/test--then--i-should-be-on-the-homepage.feature +10 -0
  187. package/tests/features/test--then--i-should-not-see-an-element-by-attr.feature +8 -0
  188. package/tests/features/test--then--i-should-not-see-an-element.feature +8 -0
  189. package/tests/features/test--then--i-should-see-an-element-by-attr.feature +8 -0
  190. package/tests/features/test--then--i-should-see-an-element.feature +8 -0
  191. package/tests/features/test--then--i-should-see-n-elements.feature +24 -0
  192. package/tests/features/test--then--i-should-see-text-in-table-row.feature +96 -0
  193. package/tests/features/test--then--print-current-url-and-response.feature +21 -0
  194. package/tests/features/test--then--the-checkbox-is-checked.feature +18 -0
  195. package/tests/features/test--then--the-checkbox-should-be-checked.feature +16 -0
  196. package/tests/features/test--then--the-element-should-contain-cssproperty.feature +9 -0
  197. package/tests/features/test--then--the-element-should-not-contain-cssproperty.feature +10 -0
  198. package/tests/features/test--then--the-field-should-contain-value.feature +11 -0
  199. package/tests/features/test--then--the-response-should-contain.feature +11 -0
  200. package/tests/features/test--then--the-response-status-code-should-be.feature +31 -0
  201. package/tests/features/test--then--the-url-should-match.feature +7 -0
  202. package/tests/features/test--then-the-link-should-contain-by-attribute.feature +18 -0
  203. package/tests/features/test--then-the-link-should-contain.feature +7 -0
  204. package/tests/features/test--when--i-additionally-select.feature +30 -0
  205. package/tests/features/test--when--i-attach-file-to-feild.feature +9 -0
  206. package/tests/features/test--when--i-check-checkbox.feature +21 -0
  207. package/tests/features/test--when--i-click-link-by-attribute.feature +21 -0
  208. package/tests/features/test--when--i-click-link.feature +9 -0
  209. package/tests/features/test--when--i-click-text-in-table-row.feature +37 -0
  210. package/tests/features/test--when--i-fill-in-by-attr.feature +31 -0
  211. package/tests/features/test--when--i-fill-in-table-by-attr.feature +19 -0
  212. package/tests/features/test--when--i-fill-in.feature +32 -0
  213. package/tests/features/test--when--i-follow.feature +22 -0
  214. package/tests/features/test--when--i-go-to-homepage.feature +9 -0
  215. package/tests/features/test--when--i-move-forward-backward-one-page.feature +14 -0
  216. package/tests/features/test--when--i-press-button-by-attribute.feature +18 -0
  217. package/tests/features/test--when--i-press-button.feature +13 -0
  218. package/tests/features/test--when--i-reload-page.feature +11 -0
  219. package/tests/features/test--when--i-scroll-left-right.feature +48 -0
  220. package/tests/features/test--when--i-scroll.feature +48 -0
  221. package/tests/features/test--when--i-select-option-from-dropdownlist.feature +21 -0
  222. package/tests/features/test--when--i-select-radio-button.feature +37 -0
  223. package/tests/features/test--when--i-wait-page-is-loaded.feature +8 -0
  224. package/tests/features/test--when--i-wait-time.feature +21 -0
  225. package/tests/features/video.feature +18 -0
  226. package/tests/features/wait.feature +7 -0
  227. package/tests/features/yaml.feature +102 -0
  228. package/tests/selectors/_canonical-keys.json +113 -0
  229. package/tests/selectors/back-end-selectors.json +19 -0
  230. package/tests/selectors/cms-contentful-admin.json +35 -0
  231. package/tests/selectors/cms-craft-admin.json +39 -0
  232. package/tests/selectors/cms-drupal-cms-gin.json +56 -0
  233. package/tests/selectors/cms-drupal-core-claro.json +50 -0
  234. package/tests/selectors/cms-generic-admin.json +34 -0
  235. package/tests/selectors/cms-ghost-admin.json +34 -0
  236. package/tests/selectors/cms-joomla-admin.json +41 -0
  237. package/tests/selectors/cms-magento2-admin.json +32 -0
  238. package/tests/selectors/cms-prestashop-admin.json +38 -0
  239. package/tests/selectors/cms-shopify-admin.json +25 -0
  240. package/tests/selectors/cms-strapi-admin.json +42 -0
  241. package/tests/selectors/cms-typo3-admin.json +41 -0
  242. package/tests/selectors/cms-woocommerce-front.json +50 -0
  243. package/tests/selectors/cms-wordpress-admin.json +31 -0
  244. package/tests/selectors/framework-ant-design.json +80 -0
  245. package/tests/selectors/framework-bootstrap.json +86 -0
  246. package/tests/selectors/framework-bulma.json +74 -0
  247. package/tests/selectors/framework-chakra.json +58 -0
  248. package/tests/selectors/framework-foundation.json +51 -0
  249. package/tests/selectors/framework-material-ui.json +72 -0
  250. package/tests/selectors/framework-shadcn.json +51 -0
  251. package/tests/selectors/framework-tailwind.json +40 -0
  252. package/tests/selectors/framework-vuetify.json +61 -0
  253. package/tests/selectors/front-end-selectors.json +16 -0
  254. package/tests/selectors/homepage-selectors.json +13 -0
  255. package/tests/step-definitions/a11y.steps.js +800 -0
  256. package/tests/step-definitions/action.steps.js +167 -0
  257. package/tests/step-definitions/api.steps.js +732 -0
  258. package/tests/step-definitions/assertion.steps.js +352 -0
  259. package/tests/step-definitions/auth.steps.js +126 -0
  260. package/tests/step-definitions/clock.steps.js +128 -0
  261. package/tests/step-definitions/cookie.steps.js +216 -0
  262. package/tests/step-definitions/debug.steps.js +39 -0
  263. package/tests/step-definitions/dialog.steps.js +193 -0
  264. package/tests/step-definitions/drupal-canvas.steps.js +764 -0
  265. package/tests/step-definitions/drupal-ckeditor.steps.js +108 -0
  266. package/tests/step-definitions/drupal-core.steps.js +665 -0
  267. package/tests/step-definitions/drupal-helpers.js +371 -0
  268. package/tests/step-definitions/drupal-layout-builder.steps.js +466 -0
  269. package/tests/step-definitions/drupal-media.steps.js +99 -0
  270. package/tests/step-definitions/drupal-moderation.steps.js +71 -0
  271. package/tests/step-definitions/drupal-paragraphs.steps.js +50 -0
  272. package/tests/step-definitions/element.steps.js +356 -0
  273. package/tests/step-definitions/field.steps.js +653 -0
  274. package/tests/step-definitions/file-download.steps.js +211 -0
  275. package/tests/step-definitions/form.steps.js +333 -0
  276. package/tests/step-definitions/iframe.steps.js +228 -0
  277. package/tests/step-definitions/input.steps.js +202 -0
  278. package/tests/step-definitions/javascript.steps.js +232 -0
  279. package/tests/step-definitions/keyboard.steps.js +112 -0
  280. package/tests/step-definitions/link.steps.js +142 -0
  281. package/tests/step-definitions/metatag.steps.js +91 -0
  282. package/tests/step-definitions/modal.steps.js +244 -0
  283. package/tests/step-definitions/navigation.steps.js +218 -0
  284. package/tests/step-definitions/network.steps.js +280 -0
  285. package/tests/step-definitions/path.steps.js +141 -0
  286. package/tests/step-definitions/response.steps.js +98 -0
  287. package/tests/step-definitions/responsive.steps.js +125 -0
  288. package/tests/step-definitions/rest.steps.js +111 -0
  289. package/tests/step-definitions/screenshot.steps.js +423 -0
  290. package/tests/step-definitions/scroll.steps.js +189 -0
  291. package/tests/step-definitions/selectors.steps.js +1003 -0
  292. package/tests/step-definitions/storage.steps.js +194 -0
  293. package/tests/step-definitions/table.steps.js +181 -0
  294. package/tests/step-definitions/varbase-e2e.js +897 -0
  295. package/tests/step-definitions/varbase.steps.js +458 -0
  296. package/tests/step-definitions/video.steps.js +178 -0
  297. package/tests/step-definitions/wait.steps.js +400 -0
  298. package/tests/step-definitions/web-first.steps.js +298 -0
  299. package/tests/step-definitions/xml.steps.js +411 -0
  300. package/tests/step-definitions/yaml.steps.js +913 -0
  301. package/tsconfig.json +26 -0
package/CLAUDE.md ADDED
@@ -0,0 +1,544 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ It is also the durable contract between human maintainers of varbase-e2e and
6
+ any AI coding assistant working on the repository. Read it in full before
7
+ making changes. Follow it to the letter — these rules emerged from real
8
+ sessions and reflect strong preferences. `AGENTS.md` is the short,
9
+ machine-readable extract of the same rules; keep the two in sync.
10
+
11
+ ## 0. Identity
12
+
13
+ varbase-e2e is a BDD-first browser automation harness built on
14
+ **Playwright + Cucumber-js**. It is its own product. It is **NOT** Behat,
15
+ DrevOps, Drupal, or PHP. Code, file names, comments, and step phrasings
16
+ must never reference those tools or imply that varbase-e2e was ported from
17
+ them. Treat varbase-e2e as the source of truth.
18
+
19
+ Current line: **2.0.x** (branch `2.0.x`; `1.0.x` is the older main branch).
20
+ Node **≥ 20**.
21
+
22
+ ## 1. Commands
23
+
24
+ ```bash
25
+ npm install # required first — node_modules is not committed
26
+ npx playwright install --with-deps chromium # browser binaries (CI does this too)
27
+ npm start # http-server over examples/ on :8080 (the fixture site)
28
+ npm test # full suite, pretty output, slowMo 300ms
29
+ ```
30
+
31
+ `npm start` must be running (or `LAUNCH_URL` pointed elsewhere) before the
32
+ suite — nearly every bundled feature loads a static fixture from `examples/`.
33
+
34
+ | Command | Effect |
35
+ | --- | --- |
36
+ | `npm test` | Default — pretty output, slow-mo 300 ms, headless chromium. |
37
+ | `npm run test:headed` | `HEADLESS=false`, slow-mo auto-bumps to 800 ms. |
38
+ | `npm run test:fast` | `SLOW_MO=0`. |
39
+ | `npm run test:chromium` / `:firefox` / `:webkit` | Pick the browser (same as `BROWSER=…`). |
40
+ | `npx cucumber-js --dry-run` | Ambiguity / undefined-step check. Run this before declaring done. |
41
+ | `npm run generate-reports` | HTML (+ optional PDF) report from `tests/reports/cucumber_report.json`. |
42
+
43
+ Targeting a subset:
44
+
45
+ ```bash
46
+ npx cucumber-js tests/features/modal.feature # one feature file
47
+ npx cucumber-js tests/features/modal.feature:12 # one scenario, by line
48
+ npx cucumber-js --name "Dashboard renders" # by scenario name
49
+ npx cucumber-js --tags "@critical and not @wip" # by tag
50
+ npx cucumber-js --parallel 4 --retry 1 --retry-tag-filter @flaky
51
+ LAUNCH_URL=http://localhost:8080 npx cucumber-js # point at another target
52
+ HEADLESS=false SLOW_MO=800 npx cucumber-js tests/features/x.feature # watch a flake
53
+ ```
54
+
55
+ Env vars: `LAUNCH_URL`, `BROWSER`, `HEADLESS`, `SLOW_MO`, `FORCE_COLOR`,
56
+ `VARBASE_E2E_AUTO_SETTLE`, `VARBASE_E2E_REPORT_DISABLE`, `VARBASE_E2E_REPORT_ARGS`,
57
+ `VARBASE_E2E_FILTER_HOOK_LINES`, `VARBASE_E2E_SCREENSHOT_*`, `VARBASE_E2E_VIDEO*`,
58
+ `VARBASE_E2E_JS_ERROR_*`, `VARBASE_E2E_SELECTORS_OFFSET`,
59
+ `VARBASE_E2E_SELECTORS_BREAKPOINTS`, `DIFFY_*`. Every one of them mirrors a
60
+ `worldParameters` key in `cucumber.js` — that file is the annotated
61
+ reference; read it before inventing a new knob.
62
+
63
+ ## 2. Architecture
64
+
65
+ ### 2.1 This repo is a library **and** its own test suite
66
+
67
+ `tests/` serves double duty: it is the step-definition library shipped to
68
+ consumers on npm *and* the self-test suite proving those steps work
69
+ against the static fixtures in `examples/`. A change to a step must keep
70
+ both roles green.
71
+
72
+ Consumer projects install the package and get scaffolded by
73
+ `bin/postinstall.js` → `bin/init-varbase-e2e.js`, which writes a `cucumber.js`
74
+ whose `require` array points at
75
+ `node_modules/@vardot/varbase-e2e/tests/step-definitions/**/*.js` plus the
76
+ project's own `tests/step-definitions/`. Postinstall is a no-op when a
77
+ `cucumber.js` already exists, so re-installs never clobber user config.
78
+ **If you change the shape of `cucumber.js` `worldParameters`, update the
79
+ `CUCUMBER_JS` template inside `bin/init-varbase-e2e.js` in the same change** —
80
+ otherwise new projects get scaffolded with a stale config.
81
+
82
+ ### 2.2 `tests/step-definitions/varbase-e2e.js` — the single canonical entry point
83
+
84
+ Everything shared lives here; every `*.steps.js` does
85
+ `require('./varbase-e2e')`. It owns, in one file:
86
+
87
+ * **The World** (`PlaywrightWorld extends World`) — `page`, `context`,
88
+ `playwrightBrowser`, `frame` (iframe scope), `launchUrl`, `minWaitTime`,
89
+ `assetsFolder`, and the named-selector registries `__selectorsCss` /
90
+ `__selectorsXpath`. `setDefaultTimeout(45s)` — deliberately above
91
+ Playwright's 30 s default so locator timeouts reach our try/catch
92
+ wrappers and testers see a friendly message, not "function timed out".
93
+ The 45 s in `cucumber.js` exists for the same reason; keep them aligned.
94
+ * **The init script** installed via `context.addInitScript()` in
95
+ `openBrowser()` — monkey-patches `fetch`, `XMLHttpRequest.send`,
96
+ `setTimeout`/`clearTimeout` and attaches a `MutationObserver` to
97
+ maintain `window.__varbaseE2eAjaxCount`, `__varbaseE2ePendingTimers`,
98
+ `__varbaseE2eLastMutation`. This is the substrate the whole wait policy
99
+ stands on. **Never strip it.**
100
+ * **Hooks** — `Before({order:5})` opens the browser (merging
101
+ `recordVideo` context options when video is on); `After({order:5})`
102
+ captures the video path *before* closing the context, saves/deletes per
103
+ mode, then closes the browser; `BeforeStep` resolves `[relative:…]` date
104
+ tokens in step text, doc strings, and data-table cells; `AfterStep`
105
+ runs the auto-settle.
106
+ * **Shared helpers** (exported): `smartSettle`, `waitForPageLoad`,
107
+ `buildSelector`, `gotoUrl`, `fillField`, `getLocatorText`, `pad`,
108
+ the modal probes (`getModalSelector`, `getModalLocator`,
109
+ `waitForModalState`, `findVisibleModal`, `isAnyModalVisible`), the date
110
+ helpers (`resolveRelativeDate`, `parseRelativeOffset`,
111
+ `formatRelativeDate`), and the error builders (`friendly`, `humanize`).
112
+ * **Two process-level side effects**: a stdout/stderr filter that strips
113
+ noisy `✔ Before # …` hook lines from cucumber's failure dump
114
+ (`VARBASE_E2E_FILTER_HOOK_LINES=off` to disable), and a `process.on('exit')`
115
+ hook that auto-generates the HTML report via `bin/generate-reports`
116
+ (`VARBASE_E2E_REPORT_DISABLE=1` to disable, `VARBASE_E2E_REPORT_ARGS` to pass
117
+ flags).
118
+
119
+ ### 2.3 Config layering
120
+
121
+ `playwright.config.ts` (browser choice, launch args, context options) is
122
+ loaded by `varbase-e2e.js` from `process.cwd()` — so a consumer project's own
123
+ copy wins. `cucumber.js` supplies `worldParameters` (launch URL, wait
124
+ padding, selector registry + files + breakpoints, screenshot, video,
125
+ and javascript-error settings). Resolution order everywhere is
126
+ **env var → `worldParameters` → built-in default**; follow that order in
127
+ any new option.
128
+
129
+ ### 2.4 Error contract — tester-facing, not developer-facing
130
+
131
+ Risky locator work is wrapped and re-thrown through `friendly()`, which
132
+ renders `Could not <action> "<target>". / Why: <humanize(cause)> /
133
+ Hint: …` and sets `err.stack` to that body so cucumber prints no JS stack.
134
+ `humanize()` maps ~20 Playwright/Node/HTTP patterns to plain English.
135
+ `action.steps.js`'s `actOrExplain(label, target, fn)` is the reference
136
+ wrapper — copy that shape for new interaction steps. Never let a raw
137
+ Playwright error reach the tester.
138
+
139
+ ### 2.5 Named selector registry
140
+
141
+ `selectors.steps.js` owns the registry. Selectors resolve **css first,
142
+ then xpath** (auto-prefixed `xpath=`). Three registration paths: inline
143
+ step, bulk data table, or JSON files listed in
144
+ `worldParameters.selectors.files` (loaded from `filesPath`). 26 presets
145
+ ship in `tests/selectors/` (14 CMS admin skins, 9 CSS frameworks, generic
146
+ front/back-end/homepage), normalised against `_canonical-keys.json`. Registry keys
147
+ are also what the human-language steps read — `Then I see main nav above
148
+ breadcrumb`, `When I click primary button` — which is why canonical key
149
+ names matter more than they look.
150
+
151
+ ### 2.6 Visual regression lives outside this repo
152
+
153
+ The Diffy step-pack was extracted to its own plugin,
154
+ [`diffy-steps`](https://github.com/webship/diffy-steps). varbase-e2e no
155
+ longer ships `tests/step-definitions-diffy/`, the `diffy`
156
+ `worldParameters` block, or the mock Diffy API. Consumers install the
157
+ plugin and add `node_modules/@webship-js/diffy-steps/tests/step-definitions/**/*.js`
158
+ to their own `require:` list. Nothing in this repo depends on it — the
159
+ steps only ever used `@cucumber/cucumber`, `axios`, and Node built-ins.
160
+ Treat any `diffy` question as a `diffy-steps` question.
161
+
162
+ ### 2.7 CI
163
+
164
+ One provider: **GitHub Actions**, `.github/workflows/github-actions.yml`.
165
+ It runs install → `npx playwright install --with-deps chromium` →
166
+ `npm start &` → `npm test`. Change it and update `docs/16-ci-cd.md`.
167
+
168
+ ## 3. Communication & change rules
169
+
170
+ 1. **Never commit on the user's behalf.** The user always invokes git
171
+ commits manually. AI work stays uncommitted unless asked.
172
+ 2. **Pause for irreversible operations.** Never `rm -rf`, `git push --force`,
173
+ `npm publish`, or anything that affects shared state without explicit
174
+ confirmation in the same turn.
175
+ 3. **Caveman mode.** When the user has caveman mode active, drop articles,
176
+ filler, and pleasantries in chat replies. Code, commits, security notes,
177
+ and documentation always stay normal English.
178
+ 4. **Update docs with every change.** When you add, rename, remove, or
179
+ restructure a step / selector / configuration option, update the matching
180
+ page under `docs/` in the same turn. Specifically:
181
+ * New / removed step → update `docs/04-step-reference.md`.
182
+ * New step file → add it to the source layout block in `docs/README.md`
183
+ (which carries per-file step counts — keep them accurate).
184
+ * Topic-level addition (auth, network, clock, …) → add or refresh the
185
+ dedicated page (`docs/07-auth-state.md`, `docs/06-network-and-dialogs.md`,
186
+ etc.).
187
+ * Selector preset added under `tests/selectors/` → add to the table in
188
+ `docs/03-selector-registry.md`.
189
+ * New config key → `cucumber.js` comment, `bin/init-varbase-e2e.js`
190
+ template, and `docs/global-settings.md`.
191
+ 5. **Backups.** When the user says "backup" or asks for a versioned zip,
192
+ bump the patch version in `package.json` and produce
193
+ `~/workspace/products/varbase-e2e-<version>.zip`. Excludes:
194
+ `node_modules/`, `tests/reports/`, `screenshots/`, `.git/`.
195
+
196
+ ## 4. Step definition rules
197
+
198
+ ### 4.1 Phrasing
199
+
200
+ * Every step MUST support the pronoun prefix `(I |we )*`. Use a regex
201
+ pattern, not a Cucumber Expression with `'I ...'`, for any step where the
202
+ user could plausibly say "I" or "we".
203
+ * Use plain English in the user-visible step text. Avoid camelCase. Examples:
204
+ * `local storage` — NOT `localStorage`
205
+ * `session storage` — NOT `sessionStorage`
206
+ * Keep technical identifiers (CSS selectors, JSON Pointer paths, header
207
+ names) verbatim — they are domain language, not prose.
208
+ * Never reference Behat, DrevOps, Drupal, PHP, or Vardot versioned
209
+ product names in step phrasings or examples. Use neutral placeholders
210
+ (`example`, `Sample title`, `test-runner`).
211
+
212
+ ### 4.2 JSDoc block — required for every step
213
+
214
+ Every step definition MUST be preceded by a JSDoc block with:
215
+
216
+ * A short description of what the step asserts or does.
217
+ * Implementation notes only when the WHY is non-obvious (e.g. "uses
218
+ Playwright's networkidle plus a custom AJAX counter so late-firing
219
+ setTimeout callbacks re-arm the wait").
220
+ * **At least 5 `Example #N:` lines** of valid Gherkin that match the step
221
+ pattern. Multi-line examples are permitted (continuation lines are
222
+ context — only the example header line needs to match the pattern).
223
+ * Examples MUST use real, plausible data — no escaped JSON inside `"..."`
224
+ strings unless the step accepts a doc string. Avoid quotes-within-quotes
225
+ Gherkin in examples.
226
+
227
+ Audit the examples by walking every JSDoc `Example #N:` line, stripping the
228
+ Gherkin keyword, and confirming the remainder matches the step regex. Keep
229
+ mismatches at zero. (Past sessions used a throwaway `audit-examples.js`
230
+ for this; write it into the scratchpad, not the repo.)
231
+
232
+ ### 4.3 No duplicate logic
233
+
234
+ Before adding a step, search existing files. Identical Playwright calls
235
+ under different phrasings ARE allowed when the phrasings target different
236
+ audiences (e.g. `I hover over "X"` versus `I hover over the element "X"`).
237
+ True duplicate logic — same code, same conceptual scope — must be merged
238
+ or deleted.
239
+
240
+ ### 4.4 Do NOT merge
241
+
242
+ Some pairs look similar but cover different domains. NEVER merge:
243
+
244
+ | Pair | Domain boundary |
245
+ | --- | --- |
246
+ | `modal.steps.js` vs `dialog.steps.js` | HTML modal overlay (`role="dialog"`, `.modal`) vs native browser alert / confirm / prompt. |
247
+ | `field.steps.js` vs `form.steps.js` | CSS-selector field control vs label / placeholder / name form fills. |
248
+ | `assertion.steps.js` vs `web-first.steps.js` | Single-snapshot page assertions vs auto-retrying matchers (`within N seconds`). |
249
+ | `xml.steps.js` vs `yaml.steps.js` | Different parsers, different path conventions. |
250
+ | `api.steps.js` vs `rest.steps.js` | Long form (header + body table) vs short-form REST. |
251
+ | `element.steps.js` vs `input.steps.js` | Element-scoped (`the element "X"`) vs short pointer (`"X"`). |
252
+
253
+ ## 5. File organisation
254
+
255
+ 495 built-in steps across 44 step files. Cucumber auto-loads every
256
+ `*.steps.js` in `tests/step-definitions/`.
257
+
258
+ ```
259
+ tests/step-definitions/
260
+ ├── varbase-e2e.js # World, hooks, init script, shared helpers — see §2.2. Not a steps file.
261
+ ├── drupal-helpers.js # Shared helpers + Before hooks for the drupal-*/varbase step packs. Not a steps file.
262
+ ├── a11y.steps.js (26) # axe-core WCAG audits + POUR hygiene probes (axe loaded lazily)
263
+ ├── action.steps.js (7) # press / click / follow / attach file (actOrExplain lives here)
264
+ ├── api.steps.js (22) # REST long form — base URL, headers, query, body, JSON Pointer
265
+ ├── assertion.steps.js (14) # see / not see, in row, in element, response, count
266
+ ├── auth.steps.js (3) # storageState save / restore / clear
267
+ ├── clock.steps.js (7) # page.clock — install / advance / pause / set
268
+ ├── cookie.steps.js (12) # cookie exists / equals / contains
269
+ ├── debug.steps.js (2) # print URL / last response
270
+ ├── dialog.steps.js (8) # native alert / confirm / prompt handlers
271
+ ├── element.steps.js (19) # focus / scroll-to / dispatch / count / position
272
+ ├── field.steps.js (27) # field, checkbox, radio, select-list state assertions
273
+ ├── file-download.steps.js (8) # download capture + filename / mime / path assertions
274
+ ├── form.steps.js (13) # fill / select / additionally select / check / uncheck / radio
275
+ ├── iframe.steps.js (10) # frameLocator switch + frame-scoped interactions
276
+ ├── input.steps.js (9) # hover / drag / dbl-click / right-click / tap / viewport size
277
+ ├── javascript.steps.js (4) # JS error tracking + assertion (warn / fail / off)
278
+ ├── keyboard.steps.js (4) # single key + combos with alias normalisation
279
+ ├── link.steps.js (9) # href / title / target / rel assertions
280
+ ├── metatag.steps.js (3) # <meta> description / keywords / OG / Twitter
281
+ ├── modal.steps.js (9) # HTML modal visibility / content / interactions
282
+ ├── navigation.steps.js (11) # anonymous user, homepage, paths, history, URL assertions
283
+ ├── network.steps.js (10) # route stubs / blocks / delays / offline
284
+ ├── path.steps.js (8) # URL path / query parameter / fragment
285
+ ├── response.steps.js (4) # response header inspection
286
+ ├── responsive.steps.js (5) # named breakpoints + explicit viewport
287
+ ├── rest.steps.js (5) # REST short form
288
+ ├── screenshot.steps.js (6) # manual + auto-on-failure + per-step capture
289
+ ├── scroll.steps.js (12) # ALL scroll phrasings (page + scoped element)
290
+ ├── selectors.steps.js (24) # named CSS / XPath registry + position + human-language steps
291
+ ├── storage.steps.js (9) # local storage + session storage
292
+ ├── table.steps.js (8) # data-table row / column assertions
293
+ ├── video.steps.js (4) # start / stop / save webm recording
294
+ ├── wait.steps.js (21) # ALL wait phrasings (BBR — see §6)
295
+ ├── web-first.steps.js (12) # auto-retrying state matchers
296
+ ├── xml.steps.js (20) # XPath equals / contains / count / attr
297
+ ├── drupal-canvas.steps.js (12) # Drupal Canvas editor + authoring API (pages, library, patterns, publish)
298
+ ├── drupal-ckeditor.steps.js (4) # CKEditor 5 body writing, toolbar commands, Linkit dialog
299
+ ├── drupal-core.steps.js (27) # Drupal core: session, rows, operations, breadcrumbs, toolbar, waits
300
+ ├── drupal-layout-builder.steps.js (17) # Layout Builder sections + the form controls that configure them
301
+ ├── drupal-media.steps.js (4) # media library open / select / insert / submit dialog
302
+ ├── drupal-moderation.steps.js (3)# moderation sidebar open + shows / does not show
303
+ ├── drupal-paragraphs.steps.js (1)# choose a paragraph component in the add-widget dialog
304
+ ├── varbase.steps.js (14) # Varbase: users, tour, theme settings, sticky header, a11y checker, warm-up
305
+ └── yaml.steps.js (38) # multi-doc, types, numerics, JSON Schema, diff
306
+
307
+ tests/features/ # 71 .feature files
308
+ tests/selectors/ # 26 JSON presets + _canonical-keys.json
309
+ tests/assets/ # upload fixtures (pdf, png)
310
+ examples/ # static HTML fixtures served by `npm start`
311
+ bin/ # init-varbase-e2e / postinstall / generate-reports
312
+ docs/ # 17 numbered guides + mirrored reference pages
313
+ ```
314
+
315
+ When you add a new step, place it in the file whose topic matches. Do NOT
316
+ spawn a new file unless the topic is genuinely orthogonal to every
317
+ existing file. New file → mention it in `docs/README.md` AND update the
318
+ table above.
319
+
320
+ ## 6. Behavior-Based Robotics (BBR) wait policy
321
+
322
+ Static `sleep` is forbidden in step bodies. Every wait step uses
323
+ `smartSettle(page, budget)` from `varbase-e2e.js`, which composites:
324
+
325
+ 1. `<body>` attached
326
+ 2. `DOMContentLoaded` fired
327
+ 3. Playwright `networkidle`
328
+ 4. `window.__varbaseE2eAjaxCount === 0` (custom fetch / XHR counter)
329
+ 5. `window.__varbaseE2ePendingTimers === 0` (custom `setTimeout` counter)
330
+ 6. `Date.now() - window.__varbaseE2eLastMutation >= 250 ms` (DOM-quiet)
331
+
332
+ Conditions 4/5/6 are evaluated atomically in one `waitForFunction`, so a
333
+ late-firing `setTimeout` that mutates the DOM re-arms the wait.
334
+
335
+ Auto-settle hook: `AfterStep` runs `smartSettle(page, 1500)` after every
336
+ step whose text matches `STATE_MUTATING_STEP` (click / press / fill /
337
+ select / check / attach / reload / navigate / …). This is what makes
338
+ `When I click "X" Then I should see "Y"` work without an explicit wait.
339
+ Disable per-run with `VARBASE_E2E_AUTO_SETTLE=off`. If a wait is flaky only in
340
+ CI, raise the budget — never add a static sleep.
341
+
342
+ ## 7. Selector registry
343
+
344
+ * Selectors live in `tests/selectors/*.json`, two top-level keys: `css`,
345
+ `xpath`.
346
+ * Built-in presets are normalised against `_canonical-keys.json`. New
347
+ presets MUST use canonical key names where possible — `notice success`
348
+ not `alert-success`, `main nav` not `admin menu`, `data table` not
349
+ `entries table`.
350
+ * Named selector resolution priority: `css` registry first, then `xpath`
351
+ (auto-prefixed with `xpath=`). Register in three ways: inline (`When I
352
+ add "X" selector for "Y" css selector`), bulk via data table, or JSON
353
+ files listed in `worldParameters.selectors.files`.
354
+ * Custom modal selector: every preset SHOULD expose a `modal` key. The
355
+ modal helpers in `varbase-e2e.js` use it before falling back to
356
+ `[role="dialog"], dialog`.
357
+ * When a UI change breaks tests, fix the selector in the JSON preset —
358
+ not the feature files.
359
+
360
+ ## 8. Tests must stay green
361
+
362
+ Before declaring a task done:
363
+
364
+ 1. `npm install` if `node_modules/` is absent (it is not committed).
365
+ 2. Run `npx cucumber-js --dry-run` — no ambiguity, no undefined steps.
366
+ 3. Run the full suite with the fixture server up:
367
+ `npm start &` then `LAUNCH_URL=http://localhost:8080 npx cucumber-js`.
368
+ All scenarios must pass.
369
+ 4. Fix any mismatch between JSDoc examples and step patterns (§4.2).
370
+ 5. Report honestly: if you could not run the suite, say so rather than
371
+ implying green.
372
+
373
+ ## 9. AI agent wisdom — see [docs/12-ai-agent-guide.md](docs/12-ai-agent-guide.md)
374
+
375
+ That page distils the canonical guidance from *Varbase-E2E-Recipes v1.0.30*
376
+ into one reference. Internalise these:
377
+
378
+ * **AI generates. Humans validate. Tests verify.** AI does not know what
379
+ "correct" means for the business. The test suite is the executable
380
+ contract.
381
+ * **Test-Drive-Develop loop.** Human writes feature file → human
382
+ prompts AI → AI implements → tests verify. Pass = ship. Fail =
383
+ iterate.
384
+ * **SPDD REASONS canvas.** Every prompt covers Requirements, Entities,
385
+ Approach, Structure, Operations, Norms, Safeguards. Varbase E2E
386
+ feature files map cleanly to it.
387
+ * **Cardinal SPDD rule.** When reality diverges from the prompt,
388
+ **fix the prompt first**, then update the code.
389
+ * **Three Amigos before scenarios.** Product / QA / Dev questions get
390
+ answered in `Feature:` description before any `Scenario:` lines.
391
+ * **DAMP / KISS / YAGNI / MMF.** Self-contained scenarios, simplest
392
+ test that fails, no speculative features, smallest piece of value.
393
+ * **Golden rules** — top three: test behaviour not implementation, wait
394
+ for events not time, one behaviour per scenario.
395
+ * **AI pitfalls.** Over-trusting output, implementation tests, missing
396
+ edge cases, false confidence. Mitigation: AI generates, humans
397
+ validate against business requirements.
398
+
399
+ Tag conventions live in `docs/15-tag-conventions.md` — `@critical`,
400
+ `@smoke`, `@auth`, `@security`, `@a11y`, `@i18n`, `@perf`, `@flaky`,
401
+ `@wip`, `@desktop`/`@mobile`, `@external`, `@auth-setup`, plus the
402
+ recording tags `@video` / `@no-video` and the JS-error tags `@js-fail` /
403
+ `@js-warn` / `@js-off`.
404
+
405
+ ## 10. AI prompts — concrete templates
406
+
407
+ When asked to do common tasks, use these templates. They are battle-tested.
408
+
409
+ ### Generate a feature file from a user story
410
+
411
+ ```
412
+ Read templates/spdd-feature.md (REASONS canvas).
413
+ Fill every section before writing any Gherkin.
414
+ Place the filled-in canvas as # comments at the top of tests/features/<name>.feature.
415
+ Generate one Scenario per Operations item.
416
+ Tag each scenario with the relevant Norm / Safeguard category
417
+ (@critical, @auth, @a11y, @security, @i18n).
418
+ Use built-in steps. Only write a custom step when no preset matches —
419
+ and place it in the file whose topic matches (see CLAUDE.md §5).
420
+ Run npx cucumber-js tests/features/<name>.feature when done.
421
+ ```
422
+
423
+ ### Add a custom step
424
+
425
+ ```
426
+ Search tests/step-definitions/*.steps.js for an existing matching step.
427
+ If one exists, point me at it instead of duplicating.
428
+ Pick the file whose topic matches.
429
+ Use a regex with (I |we )* — never plain 'I ...' Cucumber Expressions.
430
+ Plain English only — no camelCase identifiers in step text.
431
+ Add a JSDoc block with at least 5 Example #N: Gherkin lines.
432
+ Wrap risky locator actions with a friendly try/catch that explains
433
+ the failure (see action.steps.js actOrExplain helper).
434
+ Run npx cucumber-js --dry-run to confirm no ambiguity.
435
+ Run the affected feature(s) to confirm green.
436
+ ```
437
+
438
+ ### Maintain tests after a UI change
439
+
440
+ ```
441
+ Run the suite. Capture every failure: scenario name + step + expected/actual.
442
+ Group failures by root cause (usually 2-3 causes drive 90% of red).
443
+ For text-only changes, find/replace the step text in feature files.
444
+ For structural changes, update the named selector in tests/selectors/<preset>.json.
445
+ Re-run. Iterate until green. Commit prompt + code + selector changes together.
446
+ ```
447
+
448
+ ### Debug a flaky test
449
+
450
+ ```
451
+ Re-run with HEADLESS=false SLOW_MO=800 to watch what really happens.
452
+ Look at screenshots/failed_*.png for the moment of failure.
453
+ Record it: VARBASE_E2E_VIDEO=on npx cucumber-js <path> (or tag the scenario @video).
454
+ Replace any wait Ns with an edge wait:
455
+ wait until the URL contains "..."
456
+ wait for "selector" to appear
457
+ web-first matcher with within N seconds.
458
+ Verify each scenario creates its own data — no cross-scenario state.
459
+ If the bug is timing only in CI, bump the budget on the smart wait,
460
+ do NOT add static sleeps.
461
+ ```
462
+
463
+ ### Rules of engagement (for the prompt itself)
464
+
465
+ When the user gives an ambiguous task, ASK before guessing. Specifically:
466
+
467
+ - "Where should this step live?" — pick the file whose topic matches §5.
468
+ - "Should this be a custom step or compose existing ones?" — prefer
469
+ composing existing steps inside a feature scenario.
470
+ - "Should I commit?" — never. The user always commits manually.
471
+ - "Should I update docs?" — yes, in the same change. See §3.4.
472
+ - "Should I bump the version + zip?" — only when the user says "backup".
473
+
474
+ ## 11. Local AI agents & skills that drive varbase-e2e
475
+
476
+ Seven local Claude Code definitions target varbase-e2e. They are **not**
477
+ part of this repo (`.gitignore` excludes `.claude`) — they are authored in
478
+ the workspace repos and installed into `~/.claude/`:
479
+
480
+ | Source of truth | Installed to | Sync |
481
+ | --- | --- | --- |
482
+ | `~/workspace/agents/*.md` | `~/.claude/agents/` | `agents/cmd-tool-sync-agents.sh --install` (also mirrors the shared `Vardot/ai-agents` repo) |
483
+ | `~/workspace/skills/<name>/SKILL.md` | `~/.claude/skills/` | `skills/cmd-tool-sync-skills.sh` |
484
+
485
+ ### Agents
486
+
487
+ | Agent | Model | Scope |
488
+ | --- | --- | --- |
489
+ | `agent-varbase-e2e` | opus | The full specialist. Scaffold (Node.js or DDEV) → author `.feature` files → write custom steps → run → debug → HTML/PDF report. Carries a distilled copy of the whole step catalog, the BBR/selector/tag sections, the 20-recipe cookbook, Varbase learnings, and recipes AI-1…AI-5. Use for anything non-trivial. |
490
+ | `varbase-e2e-ai-agent` | sonnet | The loop-until-green worker for a consumer project: read available steps → write/fix scenarios → run → fix root cause → iterate to zero failures. Lighter, autonomous, Drupal/DDEV-flavoured (`NN-NN-NN-name.feature`, `https://<project>.ddev.site`). |
491
+
492
+ ### Skills (slash commands)
493
+
494
+ | Skill | Does |
495
+ | --- | --- |
496
+ | `/varbase-e2e-init` | Scaffold a test project for a URL, or `--ddev` for the `ddev-varbase-e2e` add-on. Idempotent; never clobbers `cucumber.js` without `--force`. |
497
+ | `/varbase-e2e-create` | Author `tests/features/<page>--<category>.feature` for a page or flow — desktop + mobile, web-first assertions, named selectors, tags. |
498
+ | `/varbase-e2e-run` | Run the suite (tag expression or feature path), generate HTML/PDF, and return a root-cause summary per failure. |
499
+ | `/varbase-e2e-audit` | Lint features + custom steps against the documented anti-patterns — sleep-driven waits, god scenarios, brittle selectors, implementation testing, premature custom steps, leaked module state. Output is `file:line — severity — pattern — fix`. |
500
+ | `/varbase-e2e-steps` | Step catalog reference, filterable by category. |
501
+
502
+ `barmoog-varbase-e2e-{init,create,run,audit,steps}` are the same five skills
503
+ hard-targeted at a Barmoog Odoo 18.0 instance. Don't edit them for
504
+ varbase-e2e changes — fix the `varbase-e2e-*` originals and let the Barmoog
505
+ copies be re-derived.
506
+
507
+ ### What this means when working *inside* this repo
508
+
509
+ 1. **Every one of them reads `node_modules/@vardot/varbase-e2e/…` as the source of
510
+ truth.** That path does not exist here — this *is* the package. Translate:
511
+ `node_modules/@vardot/varbase-e2e/tests/step-definitions/` → `tests/step-definitions/`,
512
+ `node_modules/@vardot/varbase-e2e/docs/` → `docs/`,
513
+ `node_modules/@vardot/varbase-e2e/bin/` → `bin/`.
514
+ Running one of these skills unmodified in this repo will find nothing and
515
+ fall back to fetching from GitHub — i.e. it will read the *published*
516
+ step regex, not your uncommitted change. Read the local files directly
517
+ instead.
518
+ 2. **Step regex, JSDoc examples, and `docs/` are their API.** The agents are
519
+ explicitly instructed to verify phrasing against the installed
520
+ `<category>.steps.js` and its JSDoc before recommending a step. A
521
+ rename here silently changes what every agent tells every user — which
522
+ is the real reason for the docs rule in §3.4 and the ≥5-examples rule
523
+ in §4.2.
524
+ 3. **Known drift to be aware of, not to "fix" here:** the agents and the
525
+ `/varbase-e2e-run` skill reference a `worldParameters.users` registry and
526
+ an auth helper built on it. There is no `users` key in this repo's
527
+ `cucumber.js` or in `bin/init-varbase-e2e.js` — it is a Varbase-project
528
+ convention layered on top. If a user asks about `users`, say so rather
529
+ than adding the key on the agents' say-so.
530
+ 4. **Guardrails they already carry** (so don't re-litigate them): never
531
+ commit; never overwrite a user's `.feature` or `cucumber.js` without
532
+ explicit consent; verify a step exists before recommending it; when
533
+ reality diverges from the prompt, fix the prompt first.
534
+
535
+ ## 12. Avoid
536
+
537
+ * Comments that describe WHAT the code does — names already do that.
538
+ * Backwards-compatibility shims for unused code paths — delete unused code.
539
+ * Renaming `_unused` for variables — delete them.
540
+ * Adding feature flags for hypothetical future requirements.
541
+ * `// removed` comments — git history is the record, not the file.
542
+ * Replacing existing selectors with synonyms when canonical keys exist.
543
+ * Raw Playwright errors surfacing to testers — always go through
544
+ `friendly()` / `humanize()`.
package/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # Varbase E2E
2
+
3
+ [![Github Actions](https://github.com/Vardot/varbase-e2e/actions/workflows/github-actions.yml/badge.svg?branch=2.0.x)](https://github.com/Vardot/varbase-e2e/actions)
4
+
5
+
6
+ Varbase E2E is an Automated Functional Acceptance Testing tool. Helps to ease and speed the work with the End-to-end testing features in web apps or projects. Utilizing [Playwright](https://playwright.dev) and [Cucumber-js](https://github.com/cucumber/cucumber-js). Having custom and advanced general step definitions.
7
+
8
+ ### Varbase E2E Documentation
9
+ All you need to know is in [`docs/`](docs/README.md).
10
+
11
+
12
+ ## Install varbase-e2e using npm
13
+
14
+ ```
15
+ npm install @vardot/varbase-e2e
16
+ ```
17
+
18
+ ## Automated Functional Acceptance Testing
19
+
20
+ ```
21
+ npm test
22
+ ```