@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.
- package/AGENTS.md +148 -0
- package/CLAUDE.md +544 -0
- package/README.md +22 -0
- package/bin/generate-reports.js +363 -0
- package/bin/init-varbase-e2e.js +330 -0
- package/bin/postinstall.js +26 -0
- package/cucumber.js +125 -0
- package/docs/00-quick-start.md +102 -0
- package/docs/01-getting-started.md +102 -0
- package/docs/02-bbr-smart-waits.md +77 -0
- package/docs/03-selector-registry.md +95 -0
- package/docs/04-step-reference.md +801 -0
- package/docs/05-web-first-assertions.md +91 -0
- package/docs/06-network-and-dialogs.md +83 -0
- package/docs/07-auth-state.md +75 -0
- package/docs/08-clock-mocking.md +59 -0
- package/docs/09-api-testing.md +114 -0
- package/docs/10-accessibility.md +167 -0
- package/docs/11-debugging.md +129 -0
- package/docs/12-ai-agent-guide.md +338 -0
- package/docs/13-faq.md +236 -0
- package/docs/14-recipes-cookbook.md +255 -0
- package/docs/15-tag-conventions.md +76 -0
- package/docs/16-ci-cd.md +90 -0
- package/docs/README.md +125 -0
- package/docs/advanced-screenshots/then-i-save-fullscreen-screenshot.md +36 -0
- package/docs/advanced-screenshots/then-i-save-width-x-height-screenshot.md +34 -0
- package/docs/advanced-screenshots/when-i-save-screenshot-name-filename.md +45 -0
- package/docs/advanced-screenshots.md +52 -0
- package/docs/advanced-selectors.md +18 -0
- package/docs/api-step-definitions.md +45 -0
- package/docs/global-settings.md +267 -0
- package/docs/install-varbase-e2e/ddev-varbase-e2e.md +52 -0
- package/docs/install-varbase-e2e.md +34 -0
- package/docs/overview.md +40 -0
- package/docs/step-definitions/given-i-am-anonymous-user.md +67 -0
- package/docs/step-definitions/given-i-am-homepage.md +68 -0
- package/docs/step-definitions/given-i-am-specific-page.md +72 -0
- package/docs/step-definitions/then-i-should-be.md +56 -0
- package/docs/step-definitions/then-i-should-see.md +62 -0
- package/docs/step-definitions/then-item-checkbox.md +54 -0
- package/docs/step-definitions/then-item-link-should-contain-url.md +84 -0
- package/docs/step-definitions/then-item-should-contain.md +67 -0
- package/docs/step-definitions/then-radio-button-value-should-be-selected.md +68 -0
- package/docs/step-definitions/then-response-status-code-should-be-number.md +69 -0
- package/docs/step-definitions/then-value-radio-button-selected.md +62 -0
- package/docs/step-definitions/when-i-attach-file-file-name-element.md +71 -0
- package/docs/step-definitions/when-i-check-checkbox.md +60 -0
- package/docs/step-definitions/when-i-click-link.md +51 -0
- package/docs/step-definitions/when-i-click-operation-text-row.md +71 -0
- package/docs/step-definitions/when-i-fill.md +59 -0
- package/docs/step-definitions/when-i-go-homepage.md +60 -0
- package/docs/step-definitions/when-i-go-specific-page.md +67 -0
- package/docs/step-definitions/when-i-move-backward-one-page.md +49 -0
- package/docs/step-definitions/when-i-move-forward-one-page.md +58 -0
- package/docs/step-definitions/when-i-press-button.md +58 -0
- package/docs/step-definitions/when-i-reload-page.md +51 -0
- package/docs/step-definitions/when-i-scroll.md +73 -0
- package/docs/step-definitions/when-i-select-option-select-list.md +53 -0
- package/docs/step-definitions/when-i-select-radio-button-value.md +62 -0
- package/docs/step-definitions/when-i-uncheck-checkbox.md +57 -0
- package/docs/step-definitions/when-i-wait-ajax-finish.md +64 -0
- package/docs/step-definitions/when-i-wait.md +62 -0
- package/docs/step-definitions.md +82 -0
- package/docs/steps/README.md +137 -0
- package/docs/steps/a11y.md +731 -0
- package/docs/steps/action.md +181 -0
- package/docs/steps/api.md +679 -0
- package/docs/steps/assertion.md +328 -0
- package/docs/steps/auth.md +108 -0
- package/docs/steps/clock.md +171 -0
- package/docs/steps/cookie.md +293 -0
- package/docs/steps/debug.md +52 -0
- package/docs/steps/dialog.md +226 -0
- package/docs/steps/drupal-canvas.md +414 -0
- package/docs/steps/drupal-ckeditor.md +118 -0
- package/docs/steps/drupal-core.md +688 -0
- package/docs/steps/drupal-layout-builder.md +437 -0
- package/docs/steps/drupal-media.md +107 -0
- package/docs/steps/drupal-moderation.md +81 -0
- package/docs/steps/drupal-paragraphs.md +36 -0
- package/docs/steps/element.md +455 -0
- package/docs/steps/field.md +648 -0
- package/docs/steps/file-download.md +235 -0
- package/docs/steps/form.md +344 -0
- package/docs/steps/iframe.md +248 -0
- package/docs/steps/input.md +220 -0
- package/docs/steps/javascript.md +111 -0
- package/docs/steps/keyboard.md +107 -0
- package/docs/steps/link.md +217 -0
- package/docs/steps/metatag.md +99 -0
- package/docs/steps/modal.md +232 -0
- package/docs/steps/navigation.md +275 -0
- package/docs/steps/network.md +284 -0
- package/docs/steps/path.md +203 -0
- package/docs/steps/response.md +102 -0
- package/docs/steps/responsive.md +139 -0
- package/docs/steps/rest.md +140 -0
- package/docs/steps/screenshot.md +211 -0
- package/docs/steps/scroll.md +266 -0
- package/docs/steps/selectors.md +848 -0
- package/docs/steps/storage.md +254 -0
- package/docs/steps/table.md +216 -0
- package/docs/steps/varbase.md +391 -0
- package/docs/steps/video.md +111 -0
- package/docs/steps/wait.md +553 -0
- package/docs/steps/web-first.md +289 -0
- package/docs/steps/xml.md +505 -0
- package/docs/steps/yaml.md +951 -0
- package/examples/a11y.html +31 -0
- package/examples/about-us.html +11 -0
- package/examples/account.html +32 -0
- package/examples/ajax-wait-examples.html +147 -0
- package/examples/contact-us.html +10 -0
- package/examples/cookies.html +10 -0
- package/examples/date.html +12 -0
- package/examples/dynamic-examples.html +498 -0
- package/examples/element.html +11 -0
- package/examples/example-api.json +28 -0
- package/examples/existing-page.html +11 -0
- package/examples/field.html +24 -0
- package/examples/index.html +37 -0
- package/examples/keyboard.html +11 -0
- package/examples/links.html +9 -0
- package/examples/modal.html +14 -0
- package/examples/path.html +3 -0
- package/examples/table.html +13 -0
- package/examples/test--modal-dialogs.html +252 -0
- package/examples/test--then--i-should--not--see-text-in-element.html +48 -0
- package/examples/test--then--i-should--see-text-in-element.html +48 -0
- package/examples/test--then--i-should--see-text-matching-pattern.html +31 -0
- package/examples/test--then--i-should-see-text-in-table-row.html +232 -0
- package/examples/test--then--the-checkbox-checked.html +68 -0
- package/examples/test--then--the-element-should_not-contain-cssproperty.html +47 -0
- package/examples/test--then--the-link-should-contain.html +21 -0
- package/examples/test--when--i-additionally-select.html +27 -0
- package/examples/test--when--i-attach-file-to-feild.html +50 -0
- package/examples/test--when--i-check-uncheck-checkbox.html +47 -0
- package/examples/test--when--i-click-link.html +18 -0
- package/examples/test--when--i-click-text-in-table-row.html +178 -0
- package/examples/test--when--i-fill-in.html +48 -0
- package/examples/test--when--i-press-button.html +31 -0
- package/examples/test--when--i-reload-page.html +27 -0
- package/examples/test--when--i-scroll-functionality.html +177 -0
- package/examples/test--when--i-scroll-left-right-functionality.html +149 -0
- package/examples/test--when--i-select-option-from-dropdownlist.html +35 -0
- package/examples/test--when--i-select-radio-button.html +95 -0
- package/examples/test--when-i-wait-max-of-time.html +39 -0
- package/examples/test--when-i-wait-page-until-is-loaded.html +47 -0
- package/examples/test--when-i-wait-specific-time.html +39 -0
- package/examples/test-acceptable-url-path.html +11 -0
- package/examples/video-demo.html +43 -0
- package/package.json +56 -0
- package/playwright.config.ts +39 -0
- package/tests/assets/test-document.pdf +14 -0
- package/tests/assets/vardot.png +0 -0
- package/tests/features/a11y.feature +39 -0
- package/tests/features/ajax-wait-examples.feature +24 -0
- package/tests/features/api-step-definitions-individual.feature +185 -0
- package/tests/features/complete-api-testing-examples.feature +205 -0
- package/tests/features/cookie.feature +13 -0
- package/tests/features/date.feature +11 -0
- package/tests/features/dynamic-content-examples.feature +156 -0
- package/tests/features/element.feature +16 -0
- package/tests/features/field.feature +25 -0
- package/tests/features/keyboard.feature +10 -0
- package/tests/features/link.feature +11 -0
- package/tests/features/modal-advanced-example.feature +54 -0
- package/tests/features/modal-basic-example.feature +42 -0
- package/tests/features/modal-error-handling-example.feature +37 -0
- package/tests/features/modal.feature +11 -0
- package/tests/features/path.feature +16 -0
- package/tests/features/response.feature +8 -0
- package/tests/features/responsive.feature +10 -0
- package/tests/features/table.feature +18 -0
- package/tests/features/test--given--i-am-an-anonymous-user.feature +10 -0
- package/tests/features/test--given--i-am-on-homepage.feature +16 -0
- package/tests/features/test--then--i-save-screenshot.feature +33 -0
- package/tests/features/test--then--i-see-locator.feature +320 -0
- package/tests/features/test--then--i-should--not--see-text-in-element.feature +13 -0
- package/tests/features/test--then--i-should--see-text-in-element-by-attr.feature +10 -0
- package/tests/features/test--then--i-should--see-text-in-element.feature +10 -0
- package/tests/features/test--then--i-should--see-text-matching-pattern-in-element.feature +13 -0
- package/tests/features/test--then--i-should--see-text-matching-pattern.feature +18 -0
- package/tests/features/test--then--i-should-be-on-page.feature +10 -0
- package/tests/features/test--then--i-should-be-on-the-homepage.feature +10 -0
- package/tests/features/test--then--i-should-not-see-an-element-by-attr.feature +8 -0
- package/tests/features/test--then--i-should-not-see-an-element.feature +8 -0
- package/tests/features/test--then--i-should-see-an-element-by-attr.feature +8 -0
- package/tests/features/test--then--i-should-see-an-element.feature +8 -0
- package/tests/features/test--then--i-should-see-n-elements.feature +24 -0
- package/tests/features/test--then--i-should-see-text-in-table-row.feature +96 -0
- package/tests/features/test--then--print-current-url-and-response.feature +21 -0
- package/tests/features/test--then--the-checkbox-is-checked.feature +18 -0
- package/tests/features/test--then--the-checkbox-should-be-checked.feature +16 -0
- package/tests/features/test--then--the-element-should-contain-cssproperty.feature +9 -0
- package/tests/features/test--then--the-element-should-not-contain-cssproperty.feature +10 -0
- package/tests/features/test--then--the-field-should-contain-value.feature +11 -0
- package/tests/features/test--then--the-response-should-contain.feature +11 -0
- package/tests/features/test--then--the-response-status-code-should-be.feature +31 -0
- package/tests/features/test--then--the-url-should-match.feature +7 -0
- package/tests/features/test--then-the-link-should-contain-by-attribute.feature +18 -0
- package/tests/features/test--then-the-link-should-contain.feature +7 -0
- package/tests/features/test--when--i-additionally-select.feature +30 -0
- package/tests/features/test--when--i-attach-file-to-feild.feature +9 -0
- package/tests/features/test--when--i-check-checkbox.feature +21 -0
- package/tests/features/test--when--i-click-link-by-attribute.feature +21 -0
- package/tests/features/test--when--i-click-link.feature +9 -0
- package/tests/features/test--when--i-click-text-in-table-row.feature +37 -0
- package/tests/features/test--when--i-fill-in-by-attr.feature +31 -0
- package/tests/features/test--when--i-fill-in-table-by-attr.feature +19 -0
- package/tests/features/test--when--i-fill-in.feature +32 -0
- package/tests/features/test--when--i-follow.feature +22 -0
- package/tests/features/test--when--i-go-to-homepage.feature +9 -0
- package/tests/features/test--when--i-move-forward-backward-one-page.feature +14 -0
- package/tests/features/test--when--i-press-button-by-attribute.feature +18 -0
- package/tests/features/test--when--i-press-button.feature +13 -0
- package/tests/features/test--when--i-reload-page.feature +11 -0
- package/tests/features/test--when--i-scroll-left-right.feature +48 -0
- package/tests/features/test--when--i-scroll.feature +48 -0
- package/tests/features/test--when--i-select-option-from-dropdownlist.feature +21 -0
- package/tests/features/test--when--i-select-radio-button.feature +37 -0
- package/tests/features/test--when--i-wait-page-is-loaded.feature +8 -0
- package/tests/features/test--when--i-wait-time.feature +21 -0
- package/tests/features/video.feature +18 -0
- package/tests/features/wait.feature +7 -0
- package/tests/features/yaml.feature +102 -0
- package/tests/selectors/_canonical-keys.json +113 -0
- package/tests/selectors/back-end-selectors.json +19 -0
- package/tests/selectors/cms-contentful-admin.json +35 -0
- package/tests/selectors/cms-craft-admin.json +39 -0
- package/tests/selectors/cms-drupal-cms-gin.json +56 -0
- package/tests/selectors/cms-drupal-core-claro.json +50 -0
- package/tests/selectors/cms-generic-admin.json +34 -0
- package/tests/selectors/cms-ghost-admin.json +34 -0
- package/tests/selectors/cms-joomla-admin.json +41 -0
- package/tests/selectors/cms-magento2-admin.json +32 -0
- package/tests/selectors/cms-prestashop-admin.json +38 -0
- package/tests/selectors/cms-shopify-admin.json +25 -0
- package/tests/selectors/cms-strapi-admin.json +42 -0
- package/tests/selectors/cms-typo3-admin.json +41 -0
- package/tests/selectors/cms-woocommerce-front.json +50 -0
- package/tests/selectors/cms-wordpress-admin.json +31 -0
- package/tests/selectors/framework-ant-design.json +80 -0
- package/tests/selectors/framework-bootstrap.json +86 -0
- package/tests/selectors/framework-bulma.json +74 -0
- package/tests/selectors/framework-chakra.json +58 -0
- package/tests/selectors/framework-foundation.json +51 -0
- package/tests/selectors/framework-material-ui.json +72 -0
- package/tests/selectors/framework-shadcn.json +51 -0
- package/tests/selectors/framework-tailwind.json +40 -0
- package/tests/selectors/framework-vuetify.json +61 -0
- package/tests/selectors/front-end-selectors.json +16 -0
- package/tests/selectors/homepage-selectors.json +13 -0
- package/tests/step-definitions/a11y.steps.js +800 -0
- package/tests/step-definitions/action.steps.js +167 -0
- package/tests/step-definitions/api.steps.js +732 -0
- package/tests/step-definitions/assertion.steps.js +352 -0
- package/tests/step-definitions/auth.steps.js +126 -0
- package/tests/step-definitions/clock.steps.js +128 -0
- package/tests/step-definitions/cookie.steps.js +216 -0
- package/tests/step-definitions/debug.steps.js +39 -0
- package/tests/step-definitions/dialog.steps.js +193 -0
- package/tests/step-definitions/drupal-canvas.steps.js +764 -0
- package/tests/step-definitions/drupal-ckeditor.steps.js +108 -0
- package/tests/step-definitions/drupal-core.steps.js +665 -0
- package/tests/step-definitions/drupal-helpers.js +371 -0
- package/tests/step-definitions/drupal-layout-builder.steps.js +466 -0
- package/tests/step-definitions/drupal-media.steps.js +99 -0
- package/tests/step-definitions/drupal-moderation.steps.js +71 -0
- package/tests/step-definitions/drupal-paragraphs.steps.js +50 -0
- package/tests/step-definitions/element.steps.js +356 -0
- package/tests/step-definitions/field.steps.js +653 -0
- package/tests/step-definitions/file-download.steps.js +211 -0
- package/tests/step-definitions/form.steps.js +333 -0
- package/tests/step-definitions/iframe.steps.js +228 -0
- package/tests/step-definitions/input.steps.js +202 -0
- package/tests/step-definitions/javascript.steps.js +232 -0
- package/tests/step-definitions/keyboard.steps.js +112 -0
- package/tests/step-definitions/link.steps.js +142 -0
- package/tests/step-definitions/metatag.steps.js +91 -0
- package/tests/step-definitions/modal.steps.js +244 -0
- package/tests/step-definitions/navigation.steps.js +218 -0
- package/tests/step-definitions/network.steps.js +280 -0
- package/tests/step-definitions/path.steps.js +141 -0
- package/tests/step-definitions/response.steps.js +98 -0
- package/tests/step-definitions/responsive.steps.js +125 -0
- package/tests/step-definitions/rest.steps.js +111 -0
- package/tests/step-definitions/screenshot.steps.js +423 -0
- package/tests/step-definitions/scroll.steps.js +189 -0
- package/tests/step-definitions/selectors.steps.js +1003 -0
- package/tests/step-definitions/storage.steps.js +194 -0
- package/tests/step-definitions/table.steps.js +181 -0
- package/tests/step-definitions/varbase-e2e.js +897 -0
- package/tests/step-definitions/varbase.steps.js +458 -0
- package/tests/step-definitions/video.steps.js +178 -0
- package/tests/step-definitions/wait.steps.js +400 -0
- package/tests/step-definitions/web-first.steps.js +298 -0
- package/tests/step-definitions/xml.steps.js +411 -0
- package/tests/step-definitions/yaml.steps.js +913 -0
- 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.
|
package/docs/16-ci-cd.md
ADDED
|
@@ -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
|
+
[](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)
|