@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,167 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// All "do an action" step definitions live here:
|
|
4
|
+
// press, click (text / attr / row / link follow), and file attach.
|
|
5
|
+
|
|
6
|
+
const { When } = require('@cucumber/cucumber');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { buildSelector, friendly } = require('./varbase-e2e');
|
|
9
|
+
|
|
10
|
+
// Wrap a Playwright action with a friendlier error pointing at the
|
|
11
|
+
// failing locator + Gherkin step. Pass `label` describing the step
|
|
12
|
+
// ("press button", "click link", ...) and the user-supplied target.
|
|
13
|
+
async function actOrExplain(label, target, fn) {
|
|
14
|
+
try {
|
|
15
|
+
await fn();
|
|
16
|
+
} catch (e) {
|
|
17
|
+
const msg = (e.message || '').split('\n')[0];
|
|
18
|
+
throw friendly(
|
|
19
|
+
`Failed to ${label} "${target}".\n` +
|
|
20
|
+
` ${msg}\n` +
|
|
21
|
+
` Hints:\n` +
|
|
22
|
+
` - Check the visible text matches exactly (case-sensitive).\n` +
|
|
23
|
+
` - Use the "by attr" variant if the element has no readable text.\n` +
|
|
24
|
+
` - Use "wait for ... to appear" if the element renders late.`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Press / click — by visible text
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Press a button, submit input, or link by its visible text.
|
|
35
|
+
*
|
|
36
|
+
* Example #1: When I press "Log In"
|
|
37
|
+
* Example #2: And I press the "Log In" button
|
|
38
|
+
* Example #3: And I press the "Save as" button
|
|
39
|
+
* Example #4: When we press "Submit"
|
|
40
|
+
* Example #5: And press "Cancel"
|
|
41
|
+
*
|
|
42
|
+
*/
|
|
43
|
+
When(/^(I |we )*press( the)* "([^"]*)?"( button)*$/, async function (pronounCase, theCase, element, buttonCase) {
|
|
44
|
+
const esc = element.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
45
|
+
const page = this.page;
|
|
46
|
+
await actOrExplain('press button', element, async () => {
|
|
47
|
+
await page.locator('button, input[type="button"], input[type="submit"], [role="button"], a')
|
|
48
|
+
.filter({ hasText: new RegExp('^' + esc + '$') })
|
|
49
|
+
.first()
|
|
50
|
+
.click();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Press a button by its attribute (id, class, name, placeholder, data-*).
|
|
56
|
+
*
|
|
57
|
+
* Example #1: When I press "btn-pressid" by attr
|
|
58
|
+
* Example #2: When I press "btn-pressid" by attribute
|
|
59
|
+
* Example #3: And I press "Your full name" by "placeholder" attribute
|
|
60
|
+
* Example #4: And I press "Your full name" by its "placeholder" attribute
|
|
61
|
+
* Example #5: And I press "save-name" by "data-selector" attr
|
|
62
|
+
*
|
|
63
|
+
*/
|
|
64
|
+
When(/^(I |we )*press "([^"]*)?" by( its)*(?: "([^"]*)?")* (attribute|attr)$/, async function (pronounCase, attrValue, itsCase, attr, attrWord) {
|
|
65
|
+
await this.page.locator(buildSelector(attrValue, attr)).first().click();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Click a link or button by its visible text.
|
|
70
|
+
*
|
|
71
|
+
* Example #1: When I click "Contact Us"
|
|
72
|
+
* Example #2: And I click "aboutUs"
|
|
73
|
+
* Example #3: When we click "Read more"
|
|
74
|
+
* Example #4: And click "Home"
|
|
75
|
+
*
|
|
76
|
+
*/
|
|
77
|
+
When(/^(I |we )*click "([^"]*)?"$/, async function (pronounCase, item) {
|
|
78
|
+
const esc = item.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
79
|
+
const page = this.page;
|
|
80
|
+
await actOrExplain('click', item, async () => {
|
|
81
|
+
await page.locator('a, button, [role="button"], input[type="button"], input[type="submit"]')
|
|
82
|
+
.filter({ hasText: new RegExp('^' + esc + '$') })
|
|
83
|
+
.first()
|
|
84
|
+
.click();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Click a link or button by its attribute (id, class, name, data-*).
|
|
90
|
+
*
|
|
91
|
+
* Example #1: When I click "#about-us-id" by attr
|
|
92
|
+
* Example #2: When I click "data-selector-about" by attribute
|
|
93
|
+
* Example #3: And I click "about-us-css" by "class" attr
|
|
94
|
+
* Example #4: And I click "about-us-id" by its "id" attribute
|
|
95
|
+
*
|
|
96
|
+
*/
|
|
97
|
+
When(/^(I |we )*click "([^"]*)?" by( its)*(?: "([^"]*)?")* (attribute|attr)$/, async function (pronounCase, attrValue, itsCase, attr, attrWord) {
|
|
98
|
+
await this.page.locator(buildSelector(attrValue, attr)).first().click();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Click a clickable element inside a table row identified by text.
|
|
103
|
+
*
|
|
104
|
+
* Example #1: When I click "Edit" in the "John Smith" row
|
|
105
|
+
* Example #2: When I click "Delete" in the "Product A" row
|
|
106
|
+
* Example #3: When we click "View Details" in the "Order #12345" row
|
|
107
|
+
* Example #4: And I click "Download" in the "Report 2024" row
|
|
108
|
+
*
|
|
109
|
+
*/
|
|
110
|
+
When(/^(I |we )*click "([^"]*)?" in( the)* "([^"]*)?" row$/, async function (pronounCase, clickText, theCase, rowIdentifier) {
|
|
111
|
+
const esc = clickText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
112
|
+
const row = this.page.locator('tr').filter({ hasText: rowIdentifier }).first();
|
|
113
|
+
const clickable = row.locator('a, button, [role="button"], input[type="submit"], input[type="button"]')
|
|
114
|
+
.filter({ hasText: new RegExp('^' + esc + '$') });
|
|
115
|
+
if (await clickable.count() > 0) {
|
|
116
|
+
await clickable.first().click();
|
|
117
|
+
} else {
|
|
118
|
+
await row.getByText(clickText, { exact: true }).first().click();
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Follow a link by its visible text.
|
|
124
|
+
* Uses Playwright's accessibility-first `getByRole('link', { name })` with a
|
|
125
|
+
* text-match fallback.
|
|
126
|
+
*
|
|
127
|
+
* Example #1: When I follow "Contact Us"
|
|
128
|
+
* Example #2: When I follow "About"
|
|
129
|
+
* Example #3: When we follow "Home"
|
|
130
|
+
* Example #4: And follow "Read more"
|
|
131
|
+
* Example #5: When I follow "Documentation"
|
|
132
|
+
* Example #6: When we follow "Sign in"
|
|
133
|
+
* Example #7: When I follow "Log out"
|
|
134
|
+
* Example #8: When I follow "Download report"
|
|
135
|
+
* Example #9: And I follow "Previous"
|
|
136
|
+
* Example #10: When I follow "Next"
|
|
137
|
+
*/
|
|
138
|
+
When(/^(I |we )*follow "([^"]*)"$/, async function (pronounCase, link) {
|
|
139
|
+
const esc = link.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
140
|
+
const page = this.page;
|
|
141
|
+
await actOrExplain('follow link', link, async () => {
|
|
142
|
+
const loc = page.getByRole('link', { name: link, exact: true }).or(
|
|
143
|
+
page.locator('a').filter({ hasText: new RegExp('^' + esc + '$') })
|
|
144
|
+
).first();
|
|
145
|
+
await loc.click();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Attach a file from tests/assets/ to a file input.
|
|
151
|
+
*
|
|
152
|
+
* The file path is resolved against `this.assetsFolder` (default
|
|
153
|
+
* `tests/assets/`). The target selector must address an `<input type="file">`.
|
|
154
|
+
*
|
|
155
|
+
* Example #1: When I attach the file "profile-icon.jpg" to "#profile-icon-upload"
|
|
156
|
+
* Example #2: When we attach file "resume.pdf" to "#resume"
|
|
157
|
+
* Example #3: And I attach the file "logo.svg" to "input[name=logo]"
|
|
158
|
+
* Example #4: When I attach file "report-2026-q1.csv" to "[data-testid=csv-upload]"
|
|
159
|
+
* Example #5: Given I am on "/upload"
|
|
160
|
+
* When I attach the file "video.mp4" to "#video-input"
|
|
161
|
+
* And I press "Upload"
|
|
162
|
+
* Then I should see "Upload complete"
|
|
163
|
+
*
|
|
164
|
+
*/
|
|
165
|
+
When(/^(I |we )*attach( the)* file "([^"]*)?" to "([^"]*)?"$/, async function (pronounCase, theCase, fileName, element) {
|
|
166
|
+
await this.page.locator(element).setInputFiles(path.resolve(this.assetsFolder, fileName));
|
|
167
|
+
});
|