@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,848 @@
1
+ # Selector registry steps
2
+
3
+ 24 steps, defined in `tests/step-definitions/selectors.steps.js`.
4
+
5
+ Cucumber-js loads every `*.steps.js` in that directory automatically — you never `require()` a step file from a feature.
6
+
7
+ | # | Step |
8
+ | --- | --- |
9
+ | 1 | `When I add "mobile logo" selector for "header img#logo" css selector` |
10
+ | 2 | `When I add "page title" selector for "//h1[contains(@class,'page-header')]" xpath selector` |
11
+ | 3 | `When I add selectors from "selectors.json" file` |
12
+ | 4 | `Then I print css selectors` |
13
+ | 5 | `Then I print xpath selectors` |
14
+ | 6 | `/^(I \|we )*define css selectors:$/` |
15
+ | 7 | `/^(I \|we )*define xpath selectors:$/` |
16
+ | 8 | `Given I am viewing the site on a xl screen` |
17
+ | 9 | `Then I see header above footer` |
18
+ | 10 | `Then I see footer below header` |
19
+ | 11 | `Then I see logo to the left of nav` |
20
+ | 12 | `Then I see nav to the right of logo` |
21
+ | 13 | `Then I see logo inside of header` |
22
+ | 14 | `Then I see header outside of logo` |
23
+ | 15 | `Then I see modal over content` |
24
+ | 16 | `Then I see header not over content` |
25
+ | 17 | `Then I see visible header` |
26
+ | 18 | `Then I don't see modal` |
27
+ | 19 | `Then I see search has focus` |
28
+ | 20 | `When I move focus to "Title" field` |
29
+ | 21 | `When I select all text in "Title" field` |
30
+ | 22 | `When I select from 0 to 5 text in "Title" field` |
31
+ | 23 | `When I select "title name" text in "Title" field` |
32
+ | 24 | `When I click nav` |
33
+
34
+ ---
35
+
36
+ ## 1. When I add "mobile logo" selector for "header img#logo" css selector
37
+
38
+ Register a named CSS selector at runtime.
39
+
40
+ **Keyword**: `When`
41
+
42
+ **Pattern**
43
+
44
+ ```js
45
+ /^(I |we )*add "([^"]*)" selector for "([^"]*)" css selector$/
46
+ ```
47
+
48
+ **Examples**
49
+
50
+ ```gherkin
51
+ When I add "mobile logo" selector for "header img#logo" css selector
52
+ When I add "breadcrumb" selector for ".breadcrumb" css selector
53
+ When I add "breadcrumb first link" selector for ".breadcrumb li:nth-child(1) a" css selector
54
+ When I add "cta button" selector for ".cta .btn-primary" css selector
55
+ When I add "page header" selector for "header.page-header" css selector
56
+ When I add "main nav" selector for "nav[role='navigation']" css selector
57
+ When I add "hero image" selector for ".hero img" css selector
58
+ When I add "footer links" selector for "footer a" css selector
59
+ When I add "search field" selector for "input[type='search']" css selector
60
+ When I add "submit button" selector for "button[type='submit']" css selector
61
+
62
+ Advanced:
63
+ Later override same name → latest wins:
64
+ When I add "target" selector for "h1" css selector
65
+ And I add "target" selector for "ul" css selector
66
+ Component (CSS) takes precedence over CSS registry with same name:
67
+ When I add "shared" selector for "ul" css selector
68
+ And I define css selectors:
69
+ | shared | h1 |
70
+ Combine with XPath registration and use together:
71
+ When I add "cta" selector for ".cta" css selector
72
+ And I add "cta link" selector for "//a[contains(@class,'cta')]" xpath selector
73
+ ```
74
+
75
+ ## 2. When I add "page title" selector for "//h1[contains(@class,'page-header')]" xpath selector
76
+
77
+ Register a named XPath selector at runtime.
78
+
79
+ **Keyword**: `When`
80
+
81
+ **Pattern**
82
+
83
+ ```js
84
+ /^(I |we )*add "([^"]*)" selector for "([^"]*)" xpath selector$/
85
+ ```
86
+
87
+ **Examples**
88
+
89
+ ```gherkin
90
+ When I add "page title" selector for "//h1[contains(@class,'page-header')]" xpath selector
91
+ When I add "Dashboard" selector for "//*[@id='navbar-link-admin-dashboard']" xpath selector
92
+ When I add "Vertical orientation" selector for "//*[@id='navbar-item--2-tray']/div/div[2]/div/button" xpath selector
93
+ When I add "admin menu" selector for "//nav[contains(@class,'admin-menu')]" xpath selector
94
+ When I add "first table row" selector for "//table/tbody/tr[1]" xpath selector
95
+ When I add "active tab" selector for "//li[contains(@class,'active')]/a" xpath selector
96
+ When I add "error message" selector for "//*[contains(@class,'error')]" xpath selector
97
+ When I add "site name" selector for "//a[contains(@class,'site-name')]" xpath selector
98
+ When I add "user menu" selector for "//*[@id='user-menu']" xpath selector
99
+ When I add "language switcher" selector for "//ul[contains(@class,'language-switcher')]" xpath selector
100
+
101
+ Advanced:
102
+ Axis predicates — first match only (locator.first() is applied):
103
+ When I add "first row" selector for "//table//tr[1]" xpath selector
104
+ Text contains — name by rendered label:
105
+ When I add "login link" selector for "//a[contains(normalize-space(.),'Login')]" xpath selector
106
+ Attribute + position — last nav item:
107
+ When I add "last nav item" selector for "//nav[@role='navigation']//a[last()]" xpath selector
108
+ ```
109
+
110
+ ## 3. When I add selectors from "selectors.json" file
111
+
112
+ Load CSS and XPath selectors from a JSON file.
113
+ File path is relative to worldParameters.selectors.filesPath.
114
+
115
+ **Keyword**: `When`
116
+
117
+ **Pattern**
118
+
119
+ ```js
120
+ /^(I |we )*add selectors from "([^"]*)" file$/
121
+ ```
122
+
123
+ **Examples**
124
+
125
+ ```gherkin
126
+ When I add selectors from "selectors.json" file
127
+ When I add selectors from "admin-selectors.json" file
128
+ When I add selectors from "frontend.json" file
129
+ When I add selectors from "theme-selectors.json" file
130
+ When I add selectors from "components.json" file
131
+ When we add selectors from "shared.json" file
132
+ When add selectors from "backend.json" file
133
+ When I add selectors from "page-selectors.json" file
134
+ When I add selectors from "module-selectors.json" file
135
+ When we add selectors from "mobile.json" file
136
+
137
+ Advanced:
138
+ Load a file then override a single entry inline:
139
+ When I add selectors from "homepage-selectors.json" file
140
+ And I add "homepage heading" selector for "header h1" css selector
141
+ Load multiple files — later files override earlier keys:
142
+ When I add selectors from "front-end-selectors.json" file
143
+ And I add selectors from "back-end-selectors.json" file
144
+ File + inline xpath + component — all three registries merged:
145
+ When I add selectors from "homepage-selectors.json" file
146
+ And I add "extra link" selector for "//a[@rel='canonical']" xpath selector
147
+ And I define css selectors:
148
+ | wrapper | #main |
149
+ ```
150
+
151
+ ## 4. Then I print css selectors
152
+
153
+ Print all registered CSS selectors to console (debug/inspection).
154
+
155
+ **Keyword**: `Then`
156
+
157
+ **Pattern**
158
+
159
+ ```js
160
+ /^(I |we )*print css selectors$/
161
+ ```
162
+
163
+ **Examples**
164
+
165
+ ```gherkin
166
+ Then I print css selectors
167
+ When I print css selectors
168
+ Then we print css selectors
169
+ When we print css selectors
170
+ Then print css selectors
171
+ When print css selectors
172
+ And I print css selectors
173
+ And we print css selectors
174
+ Given I print css selectors
175
+ But I print css selectors
176
+ ```
177
+
178
+ ## 5. Then I print xpath selectors
179
+
180
+ Print all registered XPath selectors to console (debug/inspection).
181
+
182
+ **Keyword**: `Then`
183
+
184
+ **Pattern**
185
+
186
+ ```js
187
+ /^(I |we )*print xpath selectors$/
188
+ ```
189
+
190
+ **Examples**
191
+
192
+ ```gherkin
193
+ Then I print xpath selectors
194
+ When I print xpath selectors
195
+ Then we print xpath selectors
196
+ When we print xpath selectors
197
+ Then print xpath selectors
198
+ When print xpath selectors
199
+ And I print xpath selectors
200
+ And we print xpath selectors
201
+ Given I print xpath selectors
202
+ But I print xpath selectors
203
+ ```
204
+
205
+ ## 6. /^(I |we )*define css selectors:$/
206
+
207
+ Define named CSS selectors in bulk for the current scenario.
208
+
209
+ **Keyword**: `Given`
210
+
211
+ **Pattern**
212
+
213
+ ```js
214
+ /^(I |we )*define css selectors:$/
215
+ ```
216
+
217
+ **Examples**
218
+
219
+ ```gherkin
220
+ Given I define css selectors:
221
+ | header | #header |
222
+ | nav | nav.primary |
223
+ | footer | footer |
224
+
225
+ Given I define css selectors:
226
+ | logo | .site-logo |
227
+ | search | #search-input |
228
+
229
+ Given I define css selectors:
230
+ | hero | .hero-banner |
231
+ | content | .main-content |
232
+ | sidebar | .sidebar |
233
+
234
+ Given I define css selectors:
235
+ | menu | ul.menu |
236
+ | button | .cta-button |
237
+
238
+ Given I define css selectors:
239
+ | top bar | .top-bar |
240
+ | page | #page-wrapper |
241
+ | footer | .site-footer |
242
+
243
+ Given we define css selectors:
244
+ | modal | .modal-dialog |
245
+ | overlay | .modal-backdrop |
246
+
247
+ When I define css selectors:
248
+ | input | input[name=q] |
249
+ | button | button[type=submit] |
250
+
251
+ And I define css selectors:
252
+ | card | .card |
253
+ | title | .card-title |
254
+
255
+ Given define css selectors:
256
+ | heading | h1 |
257
+ | list | ul |
258
+
259
+ Given I define css selectors:
260
+ | left | .col-left |
261
+ | center | .col-center |
262
+ | right | .col-right |
263
+
264
+ Advanced:
265
+ Later entry with same name overrides earlier:
266
+ When I add "shared" selector for "ul" css selector
267
+ Given I define css selectors:
268
+ | shared | h1 |
269
+ Then I see visible shared # resolves to h1 (latest wins).
270
+
271
+ Define + use in position + visibility asserts:
272
+ Given I define css selectors:
273
+ | heading | h1 |
274
+ | list | ul |
275
+ Then I see visible heading, list
276
+ And I see heading above list
277
+
278
+ Layered page-shell selectors:
279
+ Given I define css selectors:
280
+ | topbar | .topbar |
281
+ | header | header.site |
282
+ | nav | nav[role=navigation] |
283
+ | main | main |
284
+ | footer | footer |
285
+ ```
286
+
287
+ ## 7. /^(I |we )*define xpath selectors:$/
288
+
289
+ Define named XPath selectors in bulk for the current scenario.
290
+
291
+ **Keyword**: `Given`
292
+
293
+ **Pattern**
294
+
295
+ ```js
296
+ /^(I |we )*define xpath selectors:$/
297
+ ```
298
+
299
+ **Examples**
300
+
301
+ ```gherkin
302
+ Given I define xpath selectors:
303
+ | first heading | //h1[1] |
304
+ | first subline | //h3[1] |
305
+ Given we define xpath selectors:
306
+ | active tab | //li[contains(@class,'active')]/a |
307
+ Given define xpath selectors:
308
+ | last nav item | //nav//a[last()] |
309
+ And I define xpath selectors:
310
+ | login link | //a[contains(normalize-space(.),'Login')] |
311
+ When I define xpath selectors:
312
+ | error message | //*[contains(@class,'error')] |
313
+ Given I define xpath selectors:
314
+ | first table row | //table/tbody/tr[1] |
315
+ | first table cell| //table/tbody/tr[1]/td[1] |
316
+ Given I define xpath selectors:
317
+ | page title | //h1[contains(@class,'page-header')] |
318
+ Given I define xpath selectors:
319
+ | admin menu | //nav[contains(@class,'admin-menu')] |
320
+ Given I define xpath selectors:
321
+ | language switcher | //ul[contains(@class,'language-switcher')] |
322
+ Given I define xpath selectors:
323
+ | user menu | //*[@id='user-menu'] |
324
+ ```
325
+
326
+ ## 8. Given I am viewing the site on a xl screen
327
+
328
+ Resize viewport to a named breakpoint.
329
+ Built-in names: xs, sm, md, lg, xl, xxl, xxxl.
330
+
331
+ xs 375 x 667 phone portrait
332
+ sm 576 x 800 large phone / phablet
333
+ md 768 x 1024 tablet portrait
334
+ lg 992 x 768 small laptop / tablet landscape
335
+ xl 1200 x 900 desktop (default)
336
+ xxl 1400 x 900 wide desktop / HD
337
+ xxxl 1920 x 1080 Full HD / large monitor
338
+
339
+ **Keyword**: `Given`
340
+
341
+ **Pattern**
342
+
343
+ ```js
344
+ /^(I am |we are )?viewing the site on a (?:"([^"]+)"|([a-zA-Z0-9 _,]+)) (?:screen|device)$/
345
+ ```
346
+
347
+ **Examples**
348
+
349
+ ```gherkin
350
+ Given I am viewing the site on a xl screen
351
+ Given I am viewing the site on a xs screen
352
+ Given I am viewing the site on a md screen
353
+ Given I am viewing the site on a "xl" screen
354
+ Given I am viewing the site on a lg device
355
+ Given I am viewing the site on a "sm" device
356
+ Given I am viewing the site on a xxl screen
357
+ Given I am viewing the site on a "xxxl" screen
358
+ Given I am viewing the site on a xxxl device
359
+ Given I am viewing the site on a "xxl" device
360
+ Given we are viewing the site on a xs screen
361
+ Given viewing the site on a lg screen
362
+ ```
363
+
364
+ ## 9. Then I see header above footer
365
+
366
+ Assert a subject locator is above one or more others (absolute page coordinates).
367
+
368
+ **Keyword**: `Then`
369
+
370
+ **Pattern**
371
+
372
+ ```js
373
+ /^(I |we )*see ([a-zA-Z0-9 ,\-]+) above ([a-zA-Z0-9 ,\-]+)$/
374
+ ```
375
+
376
+ **Examples**
377
+
378
+ ```gherkin
379
+ Then I see header above footer
380
+ Then I see logo above search
381
+ Then I see nav above content, footer
382
+ Then I see hero above sidebar and footer
383
+ Then I see top bar above nav, content and footer
384
+ Then I see heading above subline
385
+ Then I see nav above content
386
+ Then I see search above results
387
+ Then I see banner above body
388
+ Then I see menu above page
389
+
390
+ Advanced — multi-subject / multi-target dispatch:
391
+ Single subject, many targets (comma + "and"):
392
+ Then I see heading above subline, list and footer
393
+ Many subjects, single target:
394
+ Then I see heading, subline above list
395
+ Cartesian — many subjects × many targets:
396
+ Then I see heading, subline above list, footer
397
+ Combined with inline xpath registration:
398
+ When I add "first heading xp" selector for "//h1[1]" xpath selector
399
+ Then I see first heading xp above list
400
+ ```
401
+
402
+ ## 10. Then I see footer below header
403
+
404
+ Assert a subject locator is below one or more others.
405
+
406
+ **Keyword**: `Then`
407
+
408
+ **Pattern**
409
+
410
+ ```js
411
+ /^(I |we )*see ([a-zA-Z0-9 ,\-]+) below ([a-zA-Z0-9 ,\-]+)$/
412
+ ```
413
+
414
+ **Examples**
415
+
416
+ ```gherkin
417
+ Then I see footer below header
418
+ Then I see content below nav
419
+ Then I see footer below header, nav and content
420
+ Then I see results below search
421
+ Then I see sidebar below hero
422
+ Then I see list below heading
423
+ Then I see nav below top bar
424
+ Then I see content below logo
425
+ Then I see page below menu
426
+ Then I see body below banner
427
+ ```
428
+
429
+ ## 11. Then I see logo to the left of nav
430
+
431
+ Assert a subject locator is to the left of one or more others.
432
+
433
+ **Keyword**: `Then`
434
+
435
+ **Pattern**
436
+
437
+ ```js
438
+ /^(I |we )*see ([a-zA-Z0-9 ,\-]+) to (?:the )?left of ([a-zA-Z0-9 ,\-]+)$/
439
+ ```
440
+
441
+ **Examples**
442
+
443
+ ```gherkin
444
+ Then I see logo to the left of nav
445
+ Then I see sidebar to left of content
446
+ Then I see search to the left of search button
447
+ Then I see menu to the left of cta
448
+ Then I see label to left of input
449
+ Then I see icon to the left of title
450
+ Then I see thumbnail to the left of description
451
+ Then I see avatar to left of username
452
+ Then I see back button to the left of forward button
453
+ Then I see flag to left of country name
454
+ ```
455
+
456
+ ## 12. Then I see nav to the right of logo
457
+
458
+ Assert a subject locator is to the right of one or more others.
459
+
460
+ **Keyword**: `Then`
461
+
462
+ **Pattern**
463
+
464
+ ```js
465
+ /^(I |we )*see ([a-zA-Z0-9 ,\-]+) to (?:the )?right of ([a-zA-Z0-9 ,\-]+)$/
466
+ ```
467
+
468
+ **Examples**
469
+
470
+ ```gherkin
471
+ Then I see nav to the right of logo
472
+ Then I see content to right of sidebar
473
+ Then I see search button to the right of search
474
+ Then I see cta to the right of menu
475
+ Then I see input to right of label
476
+ Then I see title to the right of icon
477
+ Then I see description to the right of thumbnail
478
+ Then I see username to right of avatar
479
+ Then I see forward button to the right of back button
480
+ Then I see country name to right of flag
481
+ ```
482
+
483
+ ## 13. Then I see logo inside of header
484
+
485
+ Assert a subject locator's bounding box is fully inside another's.
486
+
487
+ **Keyword**: `Then`
488
+
489
+ **Pattern**
490
+
491
+ ```js
492
+ /^(I |we )*see ([a-zA-Z0-9 ,\-]+) inside of ([a-zA-Z0-9 ,\-]+)$/
493
+ ```
494
+
495
+ **Examples**
496
+
497
+ ```gherkin
498
+ Then I see logo inside of header
499
+ Then I see nav inside of header
500
+ Then I see search inside of header
501
+ Then I see cta inside of hero
502
+ Then I see label inside of form
503
+ Then I see icon inside of button
504
+ Then I see title inside of banner
505
+ Then I see content inside of page
506
+ Then I see sidebar inside of page
507
+ Then I see footer inside of page
508
+ ```
509
+
510
+ ## 14. Then I see header outside of logo
511
+
512
+ Assert a subject locator's bounding box fully contains another's.
513
+
514
+ **Keyword**: `Then`
515
+
516
+ **Pattern**
517
+
518
+ ```js
519
+ /^(I |we )*see ([a-zA-Z0-9 ,\-]+) outside of ([a-zA-Z0-9 ,\-]+)$/
520
+ ```
521
+
522
+ **Examples**
523
+
524
+ ```gherkin
525
+ Then I see header outside of logo
526
+ Then I see header outside of nav
527
+ Then I see hero outside of cta
528
+ Then I see form outside of label
529
+ Then I see button outside of icon
530
+ Then I see banner outside of title
531
+ Then I see page outside of content
532
+ Then I see page outside of sidebar
533
+ Then I see page outside of footer
534
+ Then I see wrapper outside of inner
535
+ ```
536
+
537
+ ## 15. Then I see modal over content
538
+
539
+ Assert a subject locator overlaps another via intersection and z-index.
540
+
541
+ **Keyword**: `Then`
542
+
543
+ **Pattern**
544
+
545
+ ```js
546
+ /^(I |we )*see ((?:[a-zA-Z0-9 ,\-](?!not))+) over ([a-zA-Z0-9 ,\-]+)$/
547
+ ```
548
+
549
+ **Examples**
550
+
551
+ ```gherkin
552
+ Then I see modal over content
553
+ Then I see dropdown over nav
554
+ Then I see tooltip over label
555
+ Then I see overlay over page
556
+ Then I see popup over hero
557
+ Then I see sticky header over content
558
+ Then I see cookie banner over footer
559
+ Then I see dialog over sidebar
560
+ Then I see notification over header
561
+ Then I see lightbox over page
562
+ ```
563
+
564
+ ## 16. Then I see header not over content
565
+
566
+ Assert a subject locator does NOT overlap another element.
567
+
568
+ **Keyword**: `Then`
569
+
570
+ **Pattern**
571
+
572
+ ```js
573
+ /^(I |we )*see ([a-zA-Z0-9 ,\-]+) not over ([a-zA-Z0-9 ,\-]+)$/
574
+ ```
575
+
576
+ **Examples**
577
+
578
+ ```gherkin
579
+ Then I see header not over content
580
+ Then I see nav not over sidebar
581
+ Then I see footer not over content
582
+ Then I see logo not over search
583
+ Then I see sidebar not over footer
584
+ Then I see menu not over hero
585
+ Then I see label not over input
586
+ Then I see icon not over title
587
+ Then I see button not over form
588
+ Then I see nav not over page
589
+ ```
590
+
591
+ ## 17. Then I see visible header
592
+
593
+ Assert one or more named locators are visible.
594
+
595
+ **Keyword**: `Then`
596
+
597
+ **Pattern**
598
+
599
+ ```js
600
+ /^(I |we )*see visible ([a-zA-Z0-9 ,\-]+)$/
601
+ ```
602
+
603
+ **Examples**
604
+
605
+ ```gherkin
606
+ Then I see visible header
607
+ Then I see visible nav, footer
608
+ Then I see visible logo and search
609
+ Then I see visible cta
610
+ Then I see visible hero, content and sidebar
611
+ Then I see visible menu
612
+ Then I see visible search button
613
+ Then I see visible banner
614
+ Then I see visible footer
615
+ Then I see visible top bar, nav and content
616
+
617
+ Advanced:
618
+ Mix of components, inline CSS, inline XPath — all resolve:
619
+ When I add "page heading" selector for "h1" css selector
620
+ And I add "first para" selector for "//p[1]" xpath selector
621
+ Then I see visible page heading, first para
622
+ After breakpoint resize — assert still visible:
623
+ Given I am viewing the site on a xs screen
624
+ Then I see visible heading, list
625
+ After loading a selector file — names from file are visible:
626
+ When I add selectors from "homepage-selectors.json" file
627
+ Then I see visible homepage heading, homepage first heading
628
+ ```
629
+
630
+ ## 18. Then I don't see modal
631
+
632
+ Assert one or more named locators are hidden.
633
+
634
+ **Keyword**: `Then`
635
+
636
+ **Pattern**
637
+
638
+ ```js
639
+ /^(I |we )*(don't|do not) see ([a-zA-Z0-9 ,\-]+)$/
640
+ ```
641
+
642
+ **Examples**
643
+
644
+ ```gherkin
645
+ Then I don't see modal
646
+ Then I don't see dropdown, tooltip
647
+ Then I don't see overlay
648
+ Then I don't see cookie banner
649
+ Then I don't see popup
650
+ Then I don't see notification
651
+ Then I don't see lightbox
652
+ Then I don't see sticky header
653
+ Then I don't see dialog
654
+ Then I don't see sidebar, overlay and popup
655
+ ```
656
+
657
+ ## 19. Then I see search has focus
658
+
659
+ Assert a named locator has keyboard focus.
660
+
661
+ **Keyword**: `Then`
662
+
663
+ **Pattern**
664
+
665
+ ```js
666
+ /^(I |we )*see ([a-zA-Z0-9 ,\-]+) has focus$/
667
+ ```
668
+
669
+ **Examples**
670
+
671
+ ```gherkin
672
+ Then I see search has focus
673
+ Then I see email input has focus
674
+ Then we see submit button has focus
675
+ Then I see username has focus
676
+ Then I see password has focus
677
+ Then we see search button has focus
678
+ Then I see first link has focus
679
+ Then I see skip link has focus
680
+ Then I see close button has focus
681
+ Then I see modal heading has focus
682
+ ```
683
+
684
+ ## 20. When I move focus to "Title" field
685
+
686
+ Move keyboard focus to a field by label, name, or id.
687
+
688
+ **Keyword**: `When`
689
+
690
+ **Pattern**
691
+
692
+ ```js
693
+ /^(I |we )*move focus to "([^"]*)" field$/
694
+ ```
695
+
696
+ **Examples**
697
+
698
+ ```gherkin
699
+ When I move focus to "Title" field
700
+ When I move focus to "Body" field
701
+ When I move focus to "Email" field
702
+ When I move focus to "Search" field
703
+ When I move focus to "Username" field
704
+ When I move focus to "Password" field
705
+ When I move focus to "First name" field
706
+ When I move focus to "Last name" field
707
+ When I move focus to "Description" field
708
+ When I move focus to "Phone" field
709
+ ```
710
+
711
+ ## 21. When I select all text in "Title" field
712
+
713
+ Select all text inside a field by label, name, or id.
714
+
715
+ **Keyword**: `When`
716
+
717
+ **Pattern**
718
+
719
+ ```js
720
+ /^(I |we )*select all text in "([^"]*)" field$/
721
+ ```
722
+
723
+ **Examples**
724
+
725
+ ```gherkin
726
+ When I select all text in "Title" field
727
+ When I select all text in "Description" field
728
+ When I select all text in "Body" field
729
+ When I select all text in "Email" field
730
+ When I select all text in "Username" field
731
+ When I select all text in "Search" field
732
+ When I select all text in "Name" field
733
+ When I select all text in "Notes" field
734
+ When I select all text in "Address" field
735
+ When I select all text in "Message" field
736
+ ```
737
+
738
+ ## 22. When I select from 0 to 5 text in "Title" field
739
+
740
+ Select a character range (from..to) inside a field.
741
+
742
+ **Keyword**: `When`
743
+
744
+ **Pattern**
745
+
746
+ ```js
747
+ /^(I |we )*select from (\d+) to (\d+) text in "([^"]*)" field$/
748
+ ```
749
+
750
+ **Examples**
751
+
752
+ ```gherkin
753
+ When I select from 0 to 5 text in "Title" field
754
+ When I select from 0 to 10 text in "Body" field
755
+ When I select from 3 to 8 text in "Description" field
756
+ When I select from 0 to 5 text in "Email" field
757
+ When I select from 2 to 6 text in "Username" field
758
+ When we select from 0 to 4 text in "Name" field
759
+ When select from 1 to 7 text in "Search" field
760
+ When I select from 0 to 20 text in "Notes" field
761
+ When I select from 5 to 15 text in "Address" field
762
+ When we select from 0 to 3 text in "Phone" field
763
+
764
+ Advanced:
765
+ Select first word after fill:
766
+ And I fill in "Title" with "Release 2.0 notes"
767
+ When I select from 0 to 7 text in "Title" field
768
+ Select middle substring by index range:
769
+ And I fill in "Body" with "abcdefghij"
770
+ When I select from 3 to 6 text in "Body" field
771
+ Chain — fill, focus, range-select, assert focus:
772
+ And I fill in "Notes" with "hello world"
773
+ When I move focus to "Notes" field
774
+ And I select from 0 to 5 text in "Notes" field
775
+ Then I see Notes has focus
776
+ ```
777
+
778
+ ## 23. When I select "title name" text in "Title" field
779
+
780
+ Select a specific substring of text inside a field.
781
+
782
+ **Keyword**: `When`
783
+
784
+ **Pattern**
785
+
786
+ ```js
787
+ /^(I |we )*select "([^"]*)" text in "([^"]*)" field$/
788
+ ```
789
+
790
+ **Examples**
791
+
792
+ ```gherkin
793
+ When I select "title name" text in "Title" field
794
+ When I select "some content" text in "Description" field
795
+ When I select "hello" text in "Body" field
796
+ When I select "admin" text in "Username" field
797
+ When I select "example" text in "Email" field
798
+ When we select "varbase-e2e" text in "Search" field
799
+ When select "lorem" text in "Notes" field
800
+ When I select "street" text in "Address" field
801
+ When we select "555" text in "Phone" field
802
+ When I select "summary" text in "Message" field
803
+ ```
804
+
805
+ ## 24. When I click nav
806
+
807
+ Click one or more named components — uses locator.click() which auto-scrolls.
808
+
809
+ The negative lookahead keeps three phrasings out of this greedy pattern —
810
+ "the delete button", "on tasks in the toolbar" and "next button in tour" —
811
+ because drupal-core / drupal-moderation / varbase own those exact steps and
812
+ cucumber-js has no notion of a more-specific match winning.
813
+
814
+ **Keyword**: `When`
815
+
816
+ **Pattern**
817
+
818
+ ```js
819
+ /^(I |we )*click (?!the delete button$|on tasks in the toolbar$|next button in tour$)(?:on |a )?([a-zA-Z0-9 ,\-]+)$/
820
+ ```
821
+
822
+ **Examples**
823
+
824
+ ```gherkin
825
+ When I click nav
826
+ When I click search button
827
+ When click cta
828
+ When I click on logo
829
+ When I click menu
830
+ When I click on submit button
831
+ When I click close button
832
+ When click back button
833
+ When I click on forward button
834
+ When I click hero, cta
835
+
836
+ Advanced:
837
+ Click via XPath-registered selector:
838
+ When I add "login link xp" selector for "//a[contains(.,'Login')]" xpath selector
839
+ And I click login link xp
840
+ Click a sequence — comma-separated names:
841
+ Given I define css selectors:
842
+ | tab 1 | [data-tab='1'] |
843
+ | tab 2 | [data-tab='2'] |
844
+ When I click tab 1, tab 2
845
+ Register with CSS then click — no components needed:
846
+ When I add "cta primary" selector for ".cta .btn-primary" css selector
847
+ And I click cta primary
848
+ ```