@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,255 @@
1
+ # Recipes Cookbook
2
+
3
+ 20 paste-and-go scenarios covering the most common testing needs. Drop
4
+ them straight into a `.feature` file, swap selectors / text for your
5
+ app, run.
6
+
7
+ ---
8
+
9
+ ## 1. Sign in (happy path)
10
+
11
+ ```gherkin
12
+ Scenario: Sign in with valid credentials
13
+ Given I am on "/login"
14
+ When I fill in "Email" with "alice@example.com"
15
+ And I fill in "Password" with "s3cret"
16
+ And I press "Sign in"
17
+ Then I should see "Dashboard"
18
+ ```
19
+
20
+ ## 2. Sign in (validation error)
21
+
22
+ ```gherkin
23
+ Scenario: Sign in fails with empty password
24
+ Given I am on "/login"
25
+ When I fill in "Email" with "alice@example.com"
26
+ And I press "Sign in"
27
+ Then I should see "Password is required"
28
+ And I should be on "/login"
29
+ ```
30
+
31
+ ## 3. Sign up with required fields
32
+
33
+ ```gherkin
34
+ Scenario: Sign up
35
+ Given I am on "/signup"
36
+ When I fill in the following:
37
+ | Name | Alice |
38
+ | Email | alice@example.com |
39
+ | Password | s3cret |
40
+ And I check "I agree to terms"
41
+ And I press "Create account"
42
+ Then I should see "Welcome, Alice"
43
+ ```
44
+
45
+ ## 4. Search
46
+
47
+ ```gherkin
48
+ Scenario: Find a product by keyword
49
+ Given I am on the homepage
50
+ When I fill in "Search" with "laptop"
51
+ And I press the key "Enter"
52
+ Then ".product-card" should have a count of 12 within 5 seconds
53
+ And I should see "Results for \"laptop\""
54
+ ```
55
+
56
+ ## 5. Logout
57
+
58
+ ```gherkin
59
+ Scenario: Logout returns to homepage
60
+ Given I restore the auth state from "tests/auth/admin.json"
61
+ And I am on "/dashboard"
62
+ When I click "Sign out"
63
+ Then I should be on the homepage
64
+ And I should see "Sign in"
65
+ ```
66
+
67
+ ## 6. Add to cart
68
+
69
+ ```gherkin
70
+ Scenario: Add a product to cart
71
+ Given I am on "/products/laptop-pro"
72
+ When I press "Add to cart"
73
+ And I follow "View cart"
74
+ Then I should see "Laptop Pro" in the "Cart" element
75
+ And the URL should match "/cart"
76
+ ```
77
+
78
+ ## 7. Modal open + close
79
+
80
+ ```gherkin
81
+ Scenario: Open and close the help modal
82
+ Given I am on the homepage
83
+ When I click "Help"
84
+ And I wait for the modal to appear
85
+ Then I should see "How can we help?" in the modal
86
+ When I close the modal
87
+ Then I should not see the modal
88
+ ```
89
+
90
+ ## 8. Native confirm dialog
91
+
92
+ ```gherkin
93
+ Scenario: Confirm deletion
94
+ Given I am on "/admin/users"
95
+ And I will accept the next dialog
96
+ When I click "Delete" in the "alice@example.com" row
97
+ Then the last dialog message should contain "delete"
98
+ And I should see "User removed"
99
+ ```
100
+
101
+ ## 9. Pagination
102
+
103
+ ```gherkin
104
+ Scenario: Navigate to second page of results
105
+ Given I am on "/blog"
106
+ When I follow "Next"
107
+ Then current url should have the "page" parameter with the "2" value
108
+ And ".post" should have a count of 10
109
+ ```
110
+
111
+ ## 10. Sortable table
112
+
113
+ ```gherkin
114
+ Scenario: Sort orders by total descending
115
+ Given I restore the auth state from "tests/auth/admin.json"
116
+ And I am on "/admin/orders"
117
+ When I click "Total"
118
+ And I click "Total"
119
+ Then the table "#orders" should be sorted by "Total" in "descending" order
120
+ ```
121
+
122
+ ## 11. Form file upload
123
+
124
+ ```gherkin
125
+ Scenario: Upload a profile photo
126
+ Given I restore the auth state from "tests/auth/customer.json"
127
+ And I am on "/account"
128
+ When I attach the file "avatar.png" to "#avatar"
129
+ And I press "Save"
130
+ Then I should see "Avatar updated"
131
+ ```
132
+
133
+ ## 12. API mock + UI assertion
134
+
135
+ ```gherkin
136
+ Scenario: Dashboard renders mocked user list
137
+ Given the URL "**/api/users" returns the JSON:
138
+ """
139
+ {"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}
140
+ """
141
+ When I am on "/users"
142
+ Then ".user" should have a count of 2 within 5 seconds
143
+ And I should see "Alice"
144
+ And I should see "Bob"
145
+ ```
146
+
147
+ ## 13. Block third-party tracking
148
+
149
+ ```gherkin
150
+ Scenario: Page renders without tracking scripts
151
+ Given the URL "**/google-analytics.com/**" is blocked
152
+ And I start recording network requests
153
+ When I am on the homepage
154
+ Then no request to "**/google-analytics.com/**" should have been made
155
+ ```
156
+
157
+ ## 14. Mobile viewport smoke
158
+
159
+ ```gherkin
160
+ Scenario: Mobile menu collapses
161
+ Given I am on the homepage
162
+ When I set the viewport to the "mobile" breakpoint
163
+ Then "<nav .mobile-toggle>" should be visible
164
+ And "<nav .desktop-menu>" should not be visible
165
+ ```
166
+
167
+ ## 15. Accessibility AA gate
168
+
169
+ ```gherkin
170
+ @a11y
171
+ Scenario: Page meets WCAG 2.1 AA
172
+ Given I am on "/checkout"
173
+ Then the page should pass an accessibility audit at level "AA"
174
+ And the page should have a title
175
+ And user zoom should be allowed
176
+ ```
177
+
178
+ ## 16. Keyboard navigation
179
+
180
+ ```gherkin
181
+ Scenario: Tab order is correct on the login form
182
+ Given I am on "/login"
183
+ And I focus on the element "body"
184
+ When I press the key "Tab"
185
+ Then the focused element should match "#email"
186
+ When I press the key "Tab"
187
+ Then the focused element should match "#password"
188
+ When I press the key "Tab"
189
+ Then the focused element should match "button[type=submit]"
190
+ ```
191
+
192
+ ## 17. SPA navigation without full reload
193
+
194
+ ```gherkin
195
+ Scenario: SPA route changes without full page load
196
+ Given I am on the homepage
197
+ When I follow "Pricing"
198
+ And I wait until the URL contains "/pricing"
199
+ Then I should see "Plans"
200
+ And the page should have exactly one h1
201
+ ```
202
+
203
+ ## 18. Wait for AJAX-loaded content
204
+
205
+ ```gherkin
206
+ Scenario: Live search returns results
207
+ Given I am on "/search"
208
+ When I fill in "Search" with "laptops"
209
+ Then I wait until at least 1 element matches ".result"
210
+ And I should see "results"
211
+ ```
212
+
213
+ ## 19. JSON-API response check
214
+
215
+ ```gherkin
216
+ Scenario: Health endpoint returns OK
217
+ When I send a GET request to "/api/health"
218
+ Then the API response code should be 200
219
+ And the JSON property "status" should be "ok"
220
+ ```
221
+
222
+ ## 20. End-to-end checkout (composite)
223
+
224
+ ```gherkin
225
+ Scenario: Customer completes checkout
226
+ Given I restore the auth state from "tests/auth/customer.json"
227
+ And I am on "/products/laptop-pro"
228
+ When I press "Add to cart"
229
+ And I follow "Checkout"
230
+ And I fill in the following:
231
+ | Card number | 4242 4242 4242 4242 |
232
+ | Expiry | 12/30 |
233
+ | CVV | 123 |
234
+ And I press "Place order"
235
+ And I wait until the URL contains "/orders/"
236
+ Then I should see "Order confirmed"
237
+ And I send a GET request to "/api/orders?latest=1"
238
+ And the API response code should be 200
239
+ And the JSON property "orders.0.status" should be "Pending"
240
+ ```
241
+
242
+ ---
243
+
244
+ ## How to adapt these
245
+
246
+ 1. Find the scenario closest to your goal.
247
+ 2. Swap selectors (`#email`, `.product-card`, …) for your real ones.
248
+ 3. Swap text labels (`"Sign in"`, `"Add to cart"`) for your real copy.
249
+ 4. Run. Fix any red. Iterate.
250
+
251
+ If you find yourself rewriting the same setup three times, extract it
252
+ into a `Background:` block. If you find yourself rewriting the same
253
+ selector three times, register it in `tests/selectors/your-app.json`.
254
+
255
+ That's the entire cookbook.
@@ -0,0 +1,76 @@
1
+ # Tag Conventions
2
+
3
+ Tags drive what runs in CI, what gets retried, what's currently broken.
4
+ Keep them consistent across the suite.
5
+
6
+ ## Standard tags
7
+
8
+ | Tag | Meaning |
9
+ | --- | --- |
10
+ | `@critical` | Must pass on every PR. Smoke set. Run with `--tags "@critical"` first in CI. |
11
+ | `@smoke` | Synonym for `@critical` when feature owners prefer it. Pick one and stick with it. |
12
+ | `@auth` | Touches authentication / sessions. |
13
+ | `@security` | Asserts a Safeguard (CSRF, rate limit, token expiry). |
14
+ | `@a11y` | Accessibility check (axe-core, focus order, ARIA). Run with `--tags "@a11y"` to gate the a11y suite. |
15
+ | `@i18n` | Multi-locale check (Arabic / RTL / French / etc). |
16
+ | `@perf` | Performance budget (page load, request count). |
17
+ | `@flaky` | Known-unstable. CI retries it once via `--retry` + `--retryTagFilter "@flaky"`. **Never** ship long-term `@flaky` — fix the root cause. |
18
+ | `@wip` | Work in progress. CI excludes with `--tags "not @wip"`. |
19
+ | `@desktop` / `@mobile` | Viewport-locked variants. |
20
+ | `@external` | Hits a third-party service. Skip in offline test runs. |
21
+ | `@auth-setup` | One-shot scenarios that produce auth state files. Run manually after credential rotation. |
22
+
23
+ ## How to apply
24
+
25
+ Tags go on `Feature:` (apply to every scenario) or on a single
26
+ `Scenario:`.
27
+
28
+ ```gherkin
29
+ @auth
30
+ Feature: Sign in
31
+
32
+ @critical
33
+ Scenario: Successful login
34
+ Given I am on "/login"
35
+ ...
36
+
37
+ @flaky
38
+ Scenario: Concurrent login from two devices
39
+ ...
40
+
41
+ @wip
42
+ Scenario: Sign in with Apple
43
+ ...
44
+ ```
45
+
46
+ ## Recommended CI lanes
47
+
48
+ ```bash
49
+ # Smoke gate — every PR.
50
+ npx cucumber-js --tags "@critical and not @wip"
51
+
52
+ # Full suite — main branch / nightly.
53
+ npx cucumber-js --tags "not @wip and not @auth-setup"
54
+
55
+ # Accessibility lane.
56
+ npx cucumber-js --tags "@a11y"
57
+
58
+ # Flaky lane — separate report, allowed to fail without blocking.
59
+ npx cucumber-js --tags "@flaky" --retry 2
60
+
61
+ # Pre-release security gate.
62
+ npx cucumber-js --tags "@security or @auth"
63
+ ```
64
+
65
+ ## Tag hygiene rules
66
+
67
+ 1. **No `@skip`.** If a scenario should not run, fix it or delete it.
68
+ `@wip` is a temporary excuse, not a bin.
69
+ 2. **`@flaky` is a debt marker.** Each `@flaky` should have an open
70
+ issue. Removing the tag is part of the fix.
71
+ 3. **Don't tag what's obvious.** Every scenario in `auth.feature`
72
+ doesn't need `@auth` — tag the file.
73
+ 4. **One source of truth.** Don't invent project-specific synonyms
74
+ (`@blocker`, `@must-pass`, `@p0`). Pick `@critical` and stick with it.
75
+ 5. **Document custom tags.** If your project needs a tag not in this
76
+ list, add a row to this page.
@@ -0,0 +1,90 @@
1
+ # CI / CD setup
2
+
3
+ Varbase E2E ships one ready-to-use CI config: **GitHub Actions**. The pattern is
4
+ install Node 20, install Playwright's chromium with its system deps, start the
5
+ fixture server on port 8080, run `npm test`. No build step — `tsx` transpiles
6
+ `.ts` step files on the fly.
7
+
8
+ | Provider | File | Account needed | Badge |
9
+ | --- | --- | --- | --- |
10
+ | GitHub Actions | `.github/workflows/github-actions.yml` | GitHub | yes |
11
+
12
+ ---
13
+
14
+ ## GitHub Actions
15
+
16
+ **File**: `.github/workflows/github-actions.yml`.
17
+
18
+ GitHub's native CI/CD. Free tier: 2,000 minutes per month for private repos,
19
+ **unlimited** for public repos. Linux minutes count 1:1, macOS 10:1, Windows 2:1.
20
+
21
+ ### Setup steps — open account + connect repo
22
+
23
+ 1. **Sign up for GitHub** at <https://github.com/signup>. Free.
24
+ 2. **Fork or push the repo**. Workflows under `.github/workflows/` are picked up automatically — no UI step needed.
25
+ 3. **Enable Actions** if you forked: `repo → Settings → Actions → General → Allow all actions`. New repos have Actions enabled by default.
26
+ 4. **Add secrets** (optional, only if a step needs them): `Settings → Secrets and variables → Actions → New repository secret`. None are required for the shipped workflow.
27
+
28
+ ### Workflow contents
29
+
30
+ Single job `build` on `ubuntu-latest`:
31
+
32
+ 1. `actions/checkout@v4` — pulls the repo.
33
+ 2. `actions/setup-node@v4` — Node 20.x.
34
+ 3. `npm install`.
35
+ 4. `npx playwright install --with-deps chromium`.
36
+ 5. `npm start &` — backgrounds the fixture server.
37
+ 6. `sleep 3`.
38
+ 7. `npm test`.
39
+ 8. `actions/upload-artifact@v4` — the HTML/JSON report and the failure screenshots, on every run.
40
+
41
+ Triggers: `push`, `pull_request` and `workflow_dispatch`. The `pull_request` trigger is what puts a check on a PR; `workflow_dispatch` lets you start a run from the Actions tab or over the API.
42
+
43
+ `FORCE_COLOR=1` is set on the job so cucumber-js v10 emits ANSI colours.
44
+
45
+ ### Badge
46
+
47
+ Already shipped in `README.md`:
48
+
49
+ ```markdown
50
+ [![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)
51
+ ```
52
+
53
+ The badge follows the workflow file name and branch — no extra setup.
54
+
55
+ ### Reports
56
+
57
+ The workflow uploads a `cucumber-report` artifact on every run, pass or fail:
58
+
59
+ ```yaml
60
+ - name: Upload the report and screenshots
61
+ if: always()
62
+ uses: actions/upload-artifact@v4
63
+ with:
64
+ name: cucumber-report
65
+ path: |
66
+ tests/reports/cucumber_report.html
67
+ tests/reports/cucumber_report.json
68
+ screenshots/
69
+ if-no-files-found: ignore
70
+ ```
71
+
72
+ ### Notes
73
+
74
+ - **A fork does not run workflows until someone says so.** If this repository is still a fork, GitHub blocks every run until the owner presses "I understand my workflows, go ahead and enable them" once in the Actions tab. There is no API for that button, and enabling Actions in the repository settings does not replace it.
75
+ - The fixture server is a tiny `http-server` static site on port 8080 — no Docker daemon required on the runner.
76
+ - For a per-browser matrix: add `strategy.matrix.browser: [chromium, firefox, webkit]` + `BROWSER: ${{ matrix.browser }}` to the env block, and replace `chromium` in the playwright install line with `${{ matrix.browser }}`.
77
+
78
+ ### Running the suite on another provider
79
+
80
+ Nothing in Varbase E2E is GitHub-specific. Any runner that can do
81
+
82
+ ```bash
83
+ npm install
84
+ npx playwright install --with-deps chromium
85
+ npm start &
86
+ npm test
87
+ ```
88
+
89
+ on Node 20+ will work — GitLab CI, CircleCI, Jenkins, Azure Pipelines and the
90
+ rest only need that four-line shape translated into their own YAML.
package/docs/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # Varbase E2E Documentation
2
+
3
+ Varbase E2E is a BDD-first browser-automation harness built on Playwright + Cucumber-js. Feature files in plain Gherkin; selectors that survive redesigns; smart waits that never sleep.
4
+
5
+ **495 built-in steps** across **44 step files**, including the Drupal and Varbase packs. **282 example scenarios / 1,372 step executions** in the bundled suite, all green on chromium.
6
+
7
+ The full step catalogue — one page per category, generated from the step definitions themselves — is in **[`steps/`](steps/README.md)**.
8
+
9
+ ## Reading order
10
+
11
+ ### Varbase E2E essentials (custom)
12
+
13
+ | Doc | Topic |
14
+ | --- | --- |
15
+ | [00 Quick start](00-quick-start.md) | 5-minute path for newcomers |
16
+ | [01 Getting started](01-getting-started.md) | Install, project layout, run modes |
17
+ | [02 BBR smart waits](02-bbr-smart-waits.md) | Why we never `sleep N seconds` |
18
+ | [03 Selector registry](03-selector-registry.md) | Named selectors + CMS / framework presets |
19
+ | [04 Step reference](04-step-reference.md) | Every built-in step, by topic (full catalogue: [`steps/`](steps/README.md)) |
20
+ | [05 Web-first assertions](05-web-first-assertions.md) | Auto-retrying matchers |
21
+ | [06 Networking & dialogs](06-network-and-dialogs.md) | Request mocking, alerts, prompts |
22
+ | [07 Auth state](07-auth-state.md) | Save / restore login |
23
+ | [08 Clock mocking](08-clock-mocking.md) | Control time |
24
+ | [09 API testing](09-api-testing.md) | Direct HTTP from BDD |
25
+ | [10 Accessibility](10-accessibility.md) | POUR smoke checks |
26
+ | [11 Debugging](11-debugging.md) | Screenshots, headed, traces, reports |
27
+ | [12 AI agent guide](12-ai-agent-guide.md) | Wisdom + recipes from the Recipes book v1.0.30 (TDD AI / SPDD / Three Amigos / golden rules) |
28
+ | [13 FAQ](13-faq.md) | Common questions for newcomers |
29
+ | [14 Recipes cookbook](14-recipes-cookbook.md) | 20 paste-and-go scenarios |
30
+ | [15 Tag conventions](15-tag-conventions.md) | Standard tags + CI lane patterns |
31
+ | [16 CI / CD setup](16-ci-cd.md) | GitHub Actions setup steps and config notes |
32
+
33
+ ### Reference
34
+
35
+ | Doc | Topic |
36
+ | --- | --- |
37
+ | [Overview](overview.md) | Varbase E2E v2.0.x at a glance |
38
+ | [Install](install-varbase-e2e.md) | Install Varbase E2E |
39
+ | [Install — DDEV](install-varbase-e2e/ddev-varbase-e2e.md) | DDEV-Varbase-E2E variant |
40
+ | [Global settings](global-settings.md) | `cucumber.js` `worldParameters` reference |
41
+ | [Step definitions](step-definitions.md) | Step-definition hub — what a step is, the rules, where the catalogue lives |
42
+ | [Step catalogue](steps/README.md) | All 495 steps, 44 category pages under `steps/`, generated from the source |
43
+ | [API step definitions](api-step-definitions.md) | REST step definitions |
44
+ | [Advanced screenshots](advanced-screenshots.md) | Per-size, full-page, named (3 sub-pages under `advanced-screenshots/`) |
45
+ | [Advanced selectors](advanced-selectors.md) | Named selector registry, position assertions |
46
+
47
+ > **Visual regression moved out.** The Diffy step-pack now ships as its own
48
+ > plugin, [`diffy-steps`](https://github.com/webship/diffy-steps) — install it
49
+ > alongside varbase-e2e and add its step-definition path to `cucumber.js`.
50
+
51
+ ## At a glance
52
+
53
+ ```gherkin
54
+ Feature: Smoke
55
+
56
+ Background:
57
+ Given I restore the auth state from "tests/auth/admin.json"
58
+
59
+ @javascript
60
+ Scenario: Dashboard renders without JS errors
61
+ Given I am on "/dashboard"
62
+ And I wait until the network is idle
63
+ Then the page should have a main landmark
64
+ And "<#user-list>" should have a count of 5 within 5 seconds
65
+ And "<.notification>" should not be visible
66
+ ```
67
+
68
+ ## Source layout
69
+
70
+ ```
71
+ varbase-e2e/
72
+ ├── docs/ <— You are here
73
+ ├── tests/
74
+ │ ├── features/ <— Your *.feature files
75
+ │ ├── selectors/ <— CMS / framework JSON presets
76
+ │ └── step-definitions/ <— Built-in steps (auto-loaded)
77
+ │ ├── varbase-e2e.js # World setup, hooks, shared helpers (smartSettle, modal, selectors, date tokens)
78
+ │ ├── a11y.steps.js (26) # axe-core audits + WCAG hygiene probes
79
+ │ ├── action.steps.js (7) # press / click / follow / attach
80
+ │ ├── api.steps.js (22) # REST long form (base URL, headers, query, body, JSON Pointer)
81
+ │ ├── assertion.steps.js (14) # see / not see, in row, in element, response, count
82
+ │ ├── auth.steps.js (3) # save / restore / clear storageState
83
+ │ ├── clock.steps.js (7) # install / advance / pause / set system time
84
+ │ ├── cookie.steps.js (12) # cookie exists / equals / contains
85
+ │ ├── debug.steps.js (2) # print URL / last response (diagnostic)
86
+ │ ├── dialog.steps.js (8) # native alert / confirm / prompt
87
+ │ ├── element.steps.js (19) # focus / scroll-to / dispatch / count / position
88
+ │ ├── field.steps.js (27) # field state, checkbox, radio, select-list
89
+ │ ├── file-download.steps.js (8) # capture + assert filename / mime / path
90
+ │ ├── form.steps.js (13) # fill / select / check / uncheck / radio
91
+ │ ├── iframe.steps.js (10) # frameLocator switch + scoped click / fill / assert
92
+ │ ├── input.steps.js (9) # hover / drag / dbl / right-click / tap / viewport
93
+ │ ├── javascript.steps.js (4) # JS error tracker + assertion (warn / fail / off)
94
+ │ ├── keyboard.steps.js (4) # single key + combos with alias normalisation
95
+ │ ├── link.steps.js (9) # href / title / target / rel
96
+ │ ├── metatag.steps.js (3) # description / keywords / OG / Twitter
97
+ │ ├── modal.steps.js (9) # HTML modal visibility / content / interactions
98
+ │ ├── navigation.steps.js (11) # homepage / paths / history / URL assertions
99
+ │ ├── network.steps.js (10) # route stubs / mocks / delays / offline
100
+ │ ├── path.steps.js (8) # URL path / query / fragment
101
+ │ ├── response.steps.js (4) # response header inspection
102
+ │ ├── responsive.steps.js (5) # named breakpoints + explicit viewport
103
+ │ ├── rest.steps.js (5) # REST short form
104
+ │ ├── screenshot.steps.js (6) # manual + auto-on-failure + per-step capture
105
+ │ ├── scroll.steps.js (12) # page + scoped element scroll
106
+ │ ├── selectors.steps.js (22) # named CSS / XPath registry + 22 CMS / framework presets
107
+ │ ├── storage.steps.js (9) # local / session storage
108
+ │ ├── table.steps.js (8) # data-table row / column assertions
109
+ │ ├── video.steps.js (4) # start / stop / save webm recording
110
+ │ ├── wait.steps.js (21) # every wait phrasing — all BBR-backed
111
+ │ ├── web-first.steps.js (12) # auto-retrying matchers (`within N seconds`)
112
+ │ ├── drupal-canvas.steps.js (12) # Canvas editor + authoring API
113
+ │ ├── drupal-ckeditor.steps.js (4) # CKEditor 5 write / append / command button / Linkit
114
+ │ ├── drupal-core.steps.js (27) # Drupal core: session, rows, operations, breadcrumbs, waits
115
+ │ ├── drupal-layout-builder.steps.js (17) # Layout Builder sections + their form controls
116
+ │ ├── drupal-media.steps.js (4) # media library open / select / insert
117
+ │ ├── drupal-moderation.steps.js (3) # moderation sidebar open + assertions
118
+ │ ├── drupal-paragraphs.steps.js (1) # choose a paragraph component
119
+ │ ├── varbase.steps.js (14) # Varbase users, tour, theme settings, a11y checker
120
+ │ ├── xml.steps.js (20) # XPath equals / contains / count / attr
121
+ │ └── yaml.steps.js (38) # multi-doc + types + numerics + JSON Schema + diff
122
+ ├── examples/ <— Static HTML fixtures
123
+ ├── cucumber.js <— Profiles + worldParameters
124
+ └── playwright.config.ts <— Browser launch + context options
125
+ ```
@@ -0,0 +1,36 @@
1
+
2
+ # Then I save fullscreen screenshot
3
+
4
+ ## Step Definition
5
+
6
+ ```
7
+ Then (I |we )*save fullscreen screenshot
8
+ ```
9
+
10
+ ## Description
11
+
12
+ "Save a full-page screenshot (entire scrollable area)."
13
+
14
+ ## Examples
15
+
16
+ **Example #1:**
17
+ ```
18
+ Then I save fullscreen screenshot
19
+ ```
20
+
21
+ **Example #2:**
22
+ ```
23
+ Then save fullscreen screenshot
24
+ ```
25
+
26
+ **Example #3:**
27
+ ```
28
+ Given I am on "/news"
29
+ Then I save fullscreen screenshot
30
+ ```
31
+
32
+ **Example #4:**
33
+ ```
34
+ Given we are on homepage
35
+ Then we save fullscreen screenshot
36
+ ```
@@ -0,0 +1,34 @@
1
+
2
+ # Then I save "width" x "height" screenshot
3
+
4
+ ## Description
5
+ Resize the viewport to specified dimensions and capture a screenshot.
6
+
7
+ ## Gherkin Syntax
8
+ ```
9
+ Then (I |we )*save (\d+) x (\d+) screenshot
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ **Example #1:**
15
+ ```
16
+ Then I save 1440 x 900 screenshot
17
+ ```
18
+
19
+ **Example #2:**
20
+ ```
21
+ Then we save 1200 x 800 screenshot
22
+ ```
23
+
24
+ **Example #3:**
25
+ ```
26
+ Given I am on "/about-us"
27
+ Then I save 1440 x 900 screenshot
28
+ ```
29
+
30
+ ## Parameters
31
+ - First numeric parameter: viewport width (in pixels)
32
+ - Second numeric parameter: viewport height (in pixels)
33
+
34
+ The step adjusts the browser window to the specified dimensions before capturing the screenshot.
@@ -0,0 +1,45 @@
1
+
2
+ # When I save screenshot with name "filename"
3
+
4
+ ## Description
5
+ Save a screenshot using an explicit filename (tokens supported).
6
+
7
+ ## Gherkin Step Syntax
8
+ ```
9
+ When (I |we )*save screenshot with name "([^"]*)"
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ **Example #1:**
15
+ ```
16
+ When I save screenshot with name "homepage.png"
17
+ ```
18
+
19
+ **Example #2:**
20
+ ```
21
+ When we save screenshot with name "varbase-e2e-home"
22
+ ```
23
+
24
+ **Example #3:**
25
+ ```
26
+ When save screenshot with name "un-landing-{datetime}.png"
27
+ ```
28
+
29
+ **Example #4:**
30
+ ```
31
+ Given I am on "/news"
32
+ When I save screenshot with name "news-latest.png"
33
+ ```
34
+
35
+ **Example #5:**
36
+ ```
37
+ Given I am on "/un.org"
38
+ When I save screenshot with name "un-home.png"
39
+ ```
40
+
41
+ ## Key Features
42
+ - Supports explicit filename specification
43
+ - Allows optional "I" or "we" pronouns
44
+ - Supports token substitution (e.g., `{datetime}`)
45
+ - Flexible filename formats (with or without extensions)