@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
@@ -0,0 +1,91 @@
1
+ # Web-first Assertions
2
+
3
+ A "web-first" assertion is an auto-retrying matcher: it polls the page until the condition holds or a budget elapses, instead of taking a single snapshot. Varbase E2E exposes a thin BDD wrapper over Playwright's locator state-checks so feature files never need explicit waits between an action and its assertion.
4
+
5
+ ## Default timeout
6
+
7
+ Every web-first step has a 5-second budget. Override per step with the trailing `within N seconds` clause:
8
+
9
+ ```gherkin
10
+ Then "#dashboard" should be visible
11
+ Then "#dashboard" should be visible within 12 seconds
12
+ ```
13
+
14
+ ## State matchers
15
+
16
+ ```gherkin
17
+ Then "<sel>" should be visible
18
+ Then "<sel>" should be hidden
19
+ Then "<sel>" should be attached
20
+ Then "<sel>" should be focused
21
+ Then "<sel>" should be enabled
22
+ Then "<sel>" should be disabled
23
+ Then "<sel>" should be editable
24
+ ```
25
+
26
+ Negated form:
27
+
28
+ ```gherkin
29
+ Then "<sel>" should not be visible
30
+ Then "<sel>" should not be focused
31
+ ```
32
+
33
+ ## Viewport
34
+
35
+ ```gherkin
36
+ Then "<sel>" should be in the viewport
37
+ Then "<sel>" should not be in the viewport within 3 seconds
38
+ ```
39
+
40
+ ## Count
41
+
42
+ ```gherkin
43
+ Then "<sel>" should have a count of 5
44
+ Then "<sel>" should have a count of 0 within 10 seconds
45
+ ```
46
+
47
+ ## Text / value
48
+
49
+ ```gherkin
50
+ Then "<sel>" should have text "Total: $99.00"
51
+ Then "<sel>" should contain text "$99"
52
+ Then "<sel>" should have value "alice@example.com"
53
+ ```
54
+
55
+ ## Attributes / classes
56
+
57
+ ```gherkin
58
+ Then "<sel>" should have attribute "data-state" with value "open"
59
+ Then "<sel>" should have class "is-active"
60
+ ```
61
+
62
+ ## Role-based interactions
63
+
64
+ When you want accessibility-aligned tests, use the role family. These resolve via `page.getByRole(role, { name })` — the same rules screen readers use:
65
+
66
+ ```gherkin
67
+ When I click the "Sign in" button
68
+ When I click the "Profile" link
69
+ When I click the "Notifications" tab
70
+ Then the "Save changes" button should be visible
71
+ Then the "Privacy" tab should be visible within 3 seconds
72
+ ```
73
+
74
+ Supported roles: `button`, `link`, `tab`, `menuitem`, `checkbox`, `radio`, `option`.
75
+
76
+ ## Why prefer web-first
77
+
78
+ A boolean check + sleep is brittle:
79
+
80
+ ```gherkin
81
+ # BAD — sleep then check; fails if the server is 1ms slower than expected.
82
+ When I press "Save"
83
+ And I wait 2 seconds
84
+ Then "<sel>" should be visible
85
+
86
+ # GOOD — wait IS the assertion; passes the moment the element appears.
87
+ When I press "Save"
88
+ Then "<sel>" should be visible within 5 seconds
89
+ ```
90
+
91
+ The web-first wrapper is also strictly faster on the happy path: it returns the instant the matcher passes, instead of always sleeping the full configured duration.
@@ -0,0 +1,83 @@
1
+ # Networking & Dialogs
2
+
3
+ Varbase E2E makes it easy to stub external dependencies, simulate offline / slow networks, and respond to native browser dialogs from within a feature file.
4
+
5
+ ## Stubbing requests
6
+
7
+ ```gherkin
8
+ Scenario: Dashboard renders mocked data
9
+ Given I am on the homepage
10
+ And the URL "**/api/users" returns the JSON:
11
+ """
12
+ {"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}
13
+ """
14
+ When I go to "/dashboard"
15
+ And I wait for AJAX to finish
16
+ Then "<#user-list>" should contain text "Alice"
17
+ ```
18
+
19
+ Patterns use Playwright `page.route()` matching: `**/path`, `*.gif`, regex inside CSS.
20
+
21
+ ## Simulating failure
22
+
23
+ ```gherkin
24
+ Given the URL "**/api/login" returns status 401 with body "Unauthorized"
25
+ Given the URL "**/analytics.js" is blocked
26
+ Given the URL "**/api/**" is delayed by 1500 ms
27
+ Given the network is offline
28
+ Given the network is online
29
+ ```
30
+
31
+ ## Recording requests
32
+
33
+ ```gherkin
34
+ Given I start recording network requests
35
+ When I click "Buy now"
36
+ Then a POST request to "**/api/checkout" should have been made
37
+ And no request to "**/tracking" should have been made
38
+ ```
39
+
40
+ The matcher converts `*` to `.*` so URL patterns stay BDD-friendly.
41
+
42
+ ## Browser dialogs
43
+
44
+ Native `alert`/`confirm`/`prompt` dialogs block tests until handled. Attach a handler **before** the action that triggers the dialog:
45
+
46
+ ```gherkin
47
+ Given I will accept the next dialog
48
+ When I click "Delete"
49
+ Then the last dialog message should contain "Are you sure"
50
+
51
+ Given I will dismiss the next dialog
52
+ When I click "Leave page"
53
+
54
+ Given I will accept the next dialog with "user@example.com"
55
+ When I click "Reset password"
56
+ Then the last dialog type should be "prompt"
57
+ ```
58
+
59
+ The most recent dialog is captured on `this._lastDialog` for inspection inside custom step definitions.
60
+
61
+ For scenarios that trigger many confirmation dialogs in a row, use a persistent handler instead of a single-shot `will accept the next dialog`:
62
+
63
+ ```gherkin
64
+ Given I accept all confirmation dialogs
65
+ # … many clicks that each fire a confirm() …
66
+ Given I do not accept any confirmation dialogs
67
+ ```
68
+
69
+ When recording requests you can match either any method or a specific verb:
70
+
71
+ ```gherkin
72
+ Then a request to "**/api/users" should have been made
73
+ And a GET request to "**/api/users" should have been made
74
+ ```
75
+
76
+ ## When to stub vs hit a real backend
77
+
78
+ | Stub | Real backend |
79
+ | --- | --- |
80
+ | Third-party APIs (payments, mail, maps) | Your own happy-path flows |
81
+ | Slow/flaky external services | Schema validation tests |
82
+ | Edge cases (5xx, timeouts, malformed JSON) | End-to-end smoke tests |
83
+ | Tests run without internet | Pre-production smoke |
@@ -0,0 +1,75 @@
1
+ # Auth State
2
+
3
+ Logging in once per scenario adds 1–3 seconds per test. Varbase E2E uses Playwright's `storageState` API to **save the cookies + localStorage of an authenticated session** and replay it in later scenarios — instant sign-in, no UI flow.
4
+
5
+ ## Save once, restore everywhere
6
+
7
+ ### One-off setup feature
8
+
9
+ `tests/features/_setup-auth.feature`:
10
+
11
+ ```gherkin
12
+ @auth-setup
13
+ Feature: Auth state setup
14
+
15
+ Scenario: Save admin auth state
16
+ Given I am on "/login"
17
+ When I fill in "admin@example.com" for "Email"
18
+ And I fill in "secret" for "Password"
19
+ And I press "Sign in"
20
+ And I wait until the URL contains "/dashboard"
21
+ Then I save the auth state to "tests/auth/admin.json"
22
+ ```
23
+
24
+ Run once:
25
+
26
+ ```bash
27
+ npx cucumber-js --tags @auth-setup
28
+ ```
29
+
30
+ ### Use in regular scenarios
31
+
32
+ ```gherkin
33
+ Feature: Admin dashboard
34
+
35
+ Background:
36
+ Given I restore the auth state from "tests/auth/admin.json"
37
+ And I am on "/dashboard"
38
+
39
+ Scenario: Admin sees user list
40
+ Then "<#user-list>" should be visible
41
+ And "<#user-list>" should have a count of 5 within 5 seconds
42
+ ```
43
+
44
+ `I restore the auth state from "..."` swaps the current browser context for a fresh one with the saved cookies/localStorage. The tracker init script is reinstalled automatically so smart waits keep working.
45
+
46
+ ## Clearing auth
47
+
48
+ ```gherkin
49
+ Given I clear the auth state
50
+ ```
51
+
52
+ Removes cookies and clears `localStorage` / `sessionStorage` on the current page.
53
+
54
+ ## Multiple roles
55
+
56
+ Save one file per role:
57
+
58
+ - `tests/auth/admin.json`
59
+ - `tests/auth/editor.json`
60
+ - `tests/auth/customer.json`
61
+
62
+ Then pick a role per scenario:
63
+
64
+ ```gherkin
65
+ Scenario: Editor cannot delete
66
+ Given I restore the auth state from "tests/auth/editor.json"
67
+ When I am on "/admin/products"
68
+ Then the "Delete" button should not be visible
69
+ ```
70
+
71
+ ## Caveats
72
+
73
+ - Session keys signed against IP or User-Agent will reject the restored cookie. Use a longer session lifetime in test environments.
74
+ - CSRF tokens stored on form pages need to be re-fetched after restore. Use `Given I am on "/path"` after the restore step.
75
+ - Two-factor flows cannot be replayed — keep an environment-specific TOTP bypass behind a feature flag.
@@ -0,0 +1,59 @@
1
+ # Clock Mocking
2
+
3
+ Time-dependent UI is hard to test in real time: a "5 minutes ago" label takes 5 minutes to verify, a session-timeout warning sits idle for 14 minutes before firing. Varbase E2E wraps Playwright's `page.clock` API in BDD steps so scenarios can advance virtual time at full speed.
4
+
5
+ ## Install a fake clock
6
+
7
+ ```gherkin
8
+ Given the system time is "2026-05-08T10:00:00Z"
9
+ ```
10
+
11
+ After this step, `Date.now()` inside the page returns the fake time. Pending `setTimeout` and `setInterval` callbacks queue but do not fire until you advance the clock.
12
+
13
+ ## Advance time
14
+
15
+ ```gherkin
16
+ When I advance the clock by 500 ms
17
+ When I advance the clock by 30 seconds
18
+ When I advance the clock by 15 minutes
19
+ ```
20
+
21
+ Each advance fires every timer scheduled within the new interval, in order, in real-time speed (i.e. instantly).
22
+
23
+ ## Pause / resume / set
24
+
25
+ ```gherkin
26
+ When I pause the clock
27
+ When I resume the clock
28
+ When I set the system time to "2026-12-31T23:59:55Z"
29
+ ```
30
+
31
+ `pause` freezes time at the current value. `set` jumps to a new instant **without** firing the timers in between (use `advance` if you want them to fire).
32
+
33
+ ## Recipe: relative-time labels
34
+
35
+ ```gherkin
36
+ Scenario: "5 minutes ago" updates as time passes
37
+ Given the system time is "2026-05-08T10:00:00Z"
38
+ And I am on "/feed"
39
+ And "<.timestamp>" should have text "just now"
40
+ When I advance the clock by 5 minutes
41
+ Then "<.timestamp>" should have text "5 minutes ago"
42
+ ```
43
+
44
+ ## Recipe: session timeout
45
+
46
+ ```gherkin
47
+ Scenario: Idle warning fires at 14 minutes
48
+ Given the system time is "2026-05-08T10:00:00Z"
49
+ And I restore the auth state from "tests/auth/admin.json"
50
+ And I am on "/dashboard"
51
+ When I advance the clock by 14 minutes
52
+ Then "<#session-warning>" should be visible
53
+ ```
54
+
55
+ ## Caveats
56
+
57
+ - `requestAnimationFrame` and `MutationObserver` are not on the fake clock. Animations driven by `rAF` keep playing in real time.
58
+ - The Date constructor reads the fake clock, but server timestamps embedded at page load do not change.
59
+ - Install the clock **before** loading the page if you need scripts to see the fake time on first execution.
@@ -0,0 +1,114 @@
1
+ # API Testing
2
+
3
+ Varbase E2E scenarios can talk to an HTTP API directly without leaving the cucumber-js runtime. The browser context's cookie jar is shared, so a UI login can be followed by REST-level assertions in the same scenario.
4
+
5
+ ## Setting headers and base URL
6
+
7
+ ```gherkin
8
+ Given the API base URL is "https://api.example.com"
9
+ And I set the header "Authorization" to "Bearer abc123"
10
+ And I set the following headers:
11
+ | X-Request-ID | test-123 |
12
+ | Accept | application/json |
13
+ ```
14
+
15
+ ## Sending requests
16
+
17
+ ```gherkin
18
+ When I send a GET request to "/users"
19
+ When I send a POST request to "/users" with body:
20
+ """
21
+ {"name": "Alice", "email": "alice@example.com"}
22
+ """
23
+ When I send a PUT request to "/users/1" with form data:
24
+ """
25
+ name=Alice&role=admin
26
+ """
27
+ ```
28
+
29
+ ## Asserting responses
30
+
31
+ ```gherkin
32
+ Then the API response code should be 200
33
+ And the API response should contain "Alice"
34
+ And the API response should not contain "<script>"
35
+ And the response header "content-type" should contain "json"
36
+ And the response should be valid JSON
37
+ And the JSON property "user.name" should be "Alice"
38
+ And the JSON response should have property "user.id"
39
+ And the JSON response should not have property "password"
40
+ ```
41
+
42
+ ## Combining UI and API
43
+
44
+ ```gherkin
45
+ Scenario: Order placed via UI shows up in API
46
+ Given I restore the auth state from "tests/auth/customer.json"
47
+ And I am on "/cart"
48
+ When I press "Place Order"
49
+ And I wait until the URL contains "/orders/"
50
+ When I send a GET request to "/api/orders?latest=1"
51
+ Then the API response code should be 200
52
+ And the JSON property "orders.0.status" should be "Pending"
53
+ ```
54
+
55
+ ## Date placeholders
56
+
57
+ API bodies often need fresh dates. Use `[relative:OFFSET#FORMAT]` tokens — they're resolved before the request is sent:
58
+
59
+ ```gherkin
60
+ Given I set the request body to '{"start": "[relative:now#YYYY-MM-DD]", "end": "[relative:+7 days#YYYY-MM-DD]"}'
61
+ When I send a POST request to "/api/bookings"
62
+ Then the API response code should be 201
63
+ ```
64
+
65
+ ## Other request shapes
66
+
67
+ Use a data-table when the body is a flat key/value map:
68
+
69
+ ```gherkin
70
+ When I send a POST request to "/users" with values:
71
+ | name | Alice |
72
+ | email | alice@example.com |
73
+ ```
74
+
75
+ Assert against an exact JSON shape with a doc string:
76
+
77
+ ```gherkin
78
+ Then the API response should contain json:
79
+ """
80
+ {"id": 1, "name": "Alice"}
81
+ """
82
+ ```
83
+
84
+ Substitute placeholders captured from earlier responses or scenario data:
85
+
86
+ ```gherkin
87
+ Given I set placeholder "{{userId}}" to "42"
88
+ When I send a GET request to "/users/{{userId}}"
89
+ ```
90
+
91
+ For HTTP basic auth on the next page navigation, see also `path.steps.js`:
92
+
93
+ ```gherkin
94
+ Given the basic authentication with the username "admin" and the password "secret"
95
+ ```
96
+
97
+ ## Short-form REST steps
98
+
99
+ A parallel short-form lives in `rest.steps.js` for quick smoke tests:
100
+
101
+ ```gherkin
102
+ Given a REST header "Authorization" with value "Bearer abc123"
103
+ When I send a REST "GET" request to "/api/users"
104
+ Then the REST response status code should be 200
105
+ And the REST response should contain "Alice"
106
+ ```
107
+
108
+ ## Print response (debugging only)
109
+
110
+ ```gherkin
111
+ Then print API response
112
+ ```
113
+
114
+ Outputs status, headers, and body to stdout. Strip before committing.
@@ -0,0 +1,167 @@
1
+ # Accessibility (a11y)
2
+
3
+ Varbase E2E ships **two layers** of accessibility coverage:
4
+
5
+ 1. **Custom JS probes** — fast, dependency-free assertions for POUR
6
+ fundamentals (Perceivable, Operable, Understandable, Robust). Each
7
+ probe maps to a specific WCAG 2.1 / 2.2 success criterion.
8
+ 2. **axe-core full audit** — official Deque engine (`@axe-core/playwright`
9
+ + `axe-core`). Runs ~100 rules covering WCAG 2.0 / 2.1 / 2.2 levels
10
+ A, AA, AAA plus best-practice and experimental rules. Each violation
11
+ carries an `impact` (`minor` / `moderate` / `serious` / `critical`)
12
+ for triage.
13
+
14
+ ## Standards & references
15
+
16
+ * [WCAG 2.1](https://www.w3.org/TR/WCAG21/) — current baseline most laws cite.
17
+ * [WCAG 2.2](https://www.w3.org/TR/WCAG22/) — September 2023 update.
18
+ * [W3C WAI](https://www.w3.org/WAI/) — Web Accessibility Initiative overview.
19
+ * [W3C Evaluation Tools List](https://www.w3.org/WAI/test-evaluate/tools/list/)
20
+ * [MDN — Accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility)
21
+ * [axe-core rule descriptions](https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md)
22
+ * [Deque Labs](https://github.com/dequelabs/) — axe-core, axe-linter, IDE plugins.
23
+
24
+ ## Page structure
25
+
26
+ ```gherkin
27
+ Then the page should declare a language
28
+ And the page language should be "en"
29
+ And the page should have a main landmark
30
+ And the page should have a navigation landmark
31
+ And the page should have exactly one h1
32
+ ```
33
+
34
+ ## Images & form labels
35
+
36
+ ```gherkin
37
+ Then every image should have an alt attribute
38
+ And every form field should have an accessible label
39
+ ```
40
+
41
+ `every image` allows empty `alt=""` (decorative) and `role="presentation"`. Missing alt fails.
42
+
43
+ `every form field` counts as labelled when **any** of the following is true:
44
+ - An `aria-label` attribute is present
45
+ - An `aria-labelledby` attribute resolves to an element
46
+ - A `<label for="...">` matches the field's id
47
+ - The field is wrapped by a `<label>`
48
+
49
+ Submit/reset/button/image inputs and `type="hidden"` are exempt.
50
+
51
+ ## Focus assertions
52
+
53
+ ```gherkin
54
+ When I focus on the element "#email"
55
+ Then the focused element should match "#email"
56
+ And the focused element should be labeled "Email"
57
+ ```
58
+
59
+ The labeled assertion resolves the accessible name in priority order:
60
+ 1. `aria-label`
61
+ 2. `aria-labelledby` referenced element
62
+ 3. `<label for="...">` text
63
+ 4. Wrapping `<label>` text
64
+ 5. `value` / `placeholder` / `title` / `textContent`
65
+
66
+ ## Keyboard navigation
67
+
68
+ The `keyboard.steps.js` file exposes:
69
+
70
+ ```gherkin
71
+ When I press the "Tab" key
72
+ When I press the "Tab" key 3 times
73
+ When I press the "Enter" key
74
+ When I press the "Escape" key
75
+ When I press the "ArrowDown" key
76
+ ```
77
+
78
+ Combine with focus assertions:
79
+
80
+ ```gherkin
81
+ Scenario: Tab order is correct
82
+ Given I am on "/login"
83
+ And I focus on the element "body"
84
+ When I press the "Tab" key
85
+ Then the focused element should match "#email"
86
+ When I press the "Tab" key
87
+ Then the focused element should match "#password"
88
+ When I press the "Tab" key
89
+ Then the focused element should match "button[type=submit]"
90
+ ```
91
+
92
+ ## WCAG hygiene probes
93
+
94
+ Lightweight checks that map to specific WCAG criteria. No axe-core required.
95
+
96
+ ```gherkin
97
+ Then the page should have a title
98
+ And user zoom should be allowed
99
+ And the heading hierarchy should be valid
100
+ And the page should have a skip link
101
+ And every button should have an accessible name
102
+ And every link should have an accessible name
103
+ And no element should have a positive tabindex
104
+ And every ARIA reference should resolve
105
+ And every ARIA role should be valid
106
+ And required fields should be consistently marked
107
+ ```
108
+
109
+ | Step | WCAG SC |
110
+ | --- | --- |
111
+ | `the heading hierarchy should be valid` | 1.3.1, 2.4.6 |
112
+ | `the page should have a skip link` | 2.4.1 |
113
+ | `every button should have an accessible name` | 4.1.2 |
114
+ | `every link should have an accessible name` | 2.4.4, 4.1.2 |
115
+ | `no element should have a positive tabindex` | 2.4.3 |
116
+ | `every ARIA reference should resolve` | 4.1.2 |
117
+ | `every ARIA role should be valid` | 4.1.2 |
118
+ | `the page should have a title` | 2.4.2 |
119
+ | `user zoom should be allowed` | 1.4.4, 1.4.10 |
120
+ | `required fields should be consistently marked` | 3.3.2 |
121
+
122
+ ## axe-core full audit
123
+
124
+ ```gherkin
125
+ Then the page should pass an accessibility audit
126
+ And the page should pass an accessibility audit at level "AA"
127
+ And the page should pass an accessibility audit at level "AAA"
128
+ And the page should have no critical accessibility violations
129
+ And the page should have no serious accessibility violations
130
+ And the element "main" should pass an accessibility audit
131
+ And the page should pass an accessibility audit excluding "iframe.payment"
132
+ And the page should not violate the accessibility rule "color-contrast"
133
+ And the page should pass the accessibility rules "image-alt, label, button-name"
134
+ Then I print accessibility violations
135
+ ```
136
+
137
+ Default audit level is **AA** — required by EU Web Accessibility
138
+ Directive, US Section 508, UK PSBAR. Use `at level "AAA"` for stricter
139
+ gates.
140
+
141
+ Common axe rule ids worth pinning: `color-contrast`, `image-alt`,
142
+ `label`, `link-name`, `button-name`, `heading-order`, `landmark-one-main`,
143
+ `region`, `aria-valid-attr`, `tabindex`, `bypass`, `frame-title`,
144
+ `meta-viewport`, `valid-lang`, `duplicate-id-aria`, `list`, `listitem`.
145
+
146
+ ## Recommended baseline
147
+
148
+ For a public site under WCAG 2.1 AA obligations, gate every page on:
149
+
150
+ ```gherkin
151
+ Then the page should pass an accessibility audit at level "AA"
152
+ And the page should have a title
153
+ And the page should have a main landmark
154
+ And the heading hierarchy should be valid
155
+ And user zoom should be allowed
156
+ ```
157
+
158
+ For an admin / authenticated UI where some third-party widgets are
159
+ known-bad, gate on the impact-based step instead:
160
+
161
+ ```gherkin
162
+ Then the page should have no critical accessibility violations
163
+ And the page should have no serious accessibility violations
164
+ ```
165
+
166
+ Tag scenarios `@a11y` so CI can run the accessibility suite in
167
+ isolation: `npx cucumber-js --tags "@a11y"`.