@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,216 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Cookie existence and value assertions (exact and partial matching) using
|
|
4
|
+
// Playwright's `BrowserContext.cookies()` API.
|
|
5
|
+
|
|
6
|
+
const { Then } = require('@cucumber/cucumber');
|
|
7
|
+
const assert = require('assert');
|
|
8
|
+
|
|
9
|
+
async function getCookies(world) {
|
|
10
|
+
return world.context ? await world.context.cookies() : [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function findByName(cookies, name) {
|
|
14
|
+
return cookies.find((c) => c.name === name);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function findByPartialName(cookies, partial) {
|
|
18
|
+
return cookies.find((c) => c.name.indexOf(partial) !== -1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Assert that a cookie with the exact name exists in the browser context.
|
|
23
|
+
*
|
|
24
|
+
* Example #1: Then a cookie with the name "session_id" should exist
|
|
25
|
+
* Example #2: Then a cookie with the name "auth_token" should exist
|
|
26
|
+
* Example #3: And a cookie with the name "lang" should exist
|
|
27
|
+
* Example #4: Then a cookie with the name "consent" should exist
|
|
28
|
+
* Example #5: When I press "Sign in"
|
|
29
|
+
* Then a cookie with the name "session" should exist
|
|
30
|
+
*
|
|
31
|
+
*/
|
|
32
|
+
Then('a cookie with the name {string} should exist', async function (name) {
|
|
33
|
+
const cookies = await getCookies(this);
|
|
34
|
+
assert.ok(findByName(cookies, name), `Cookie "${name}" was not found.`);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Assert that a cookie with the exact name AND exact value exists.
|
|
39
|
+
*
|
|
40
|
+
* Example #1: Then a cookie with the name "lang" and the value "en" should exist
|
|
41
|
+
* Example #2: Then a cookie with the name "consent" and the value "accepted" should exist
|
|
42
|
+
* Example #3: And a cookie with the name "ab_bucket" and the value "variant-b" should exist
|
|
43
|
+
* Example #4: Then a cookie with the name "theme" and the value "dark" should exist
|
|
44
|
+
* Example #5: When I check "Remember me"
|
|
45
|
+
* And I press "Sign in"
|
|
46
|
+
* Then a cookie with the name "remember" and the value "1" should exist
|
|
47
|
+
*
|
|
48
|
+
*/
|
|
49
|
+
Then('a cookie with the name {string} and the value {string} should exist', async function (name, value) {
|
|
50
|
+
const cookies = await getCookies(this);
|
|
51
|
+
const c = findByName(cookies, name);
|
|
52
|
+
assert.ok(c, `Cookie "${name}" was not found.`);
|
|
53
|
+
assert.strictEqual(c.value, value, `Cookie "${name}" has value "${c.value}", expected "${value}".`);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Assert a cookie with the exact name has a value containing a substring.
|
|
58
|
+
*
|
|
59
|
+
* Example #1: Then a cookie with the name "session_id" and a value containing "abc" should exist
|
|
60
|
+
* Example #2: Then a cookie with the name "auth" and a value containing "Bearer" should exist
|
|
61
|
+
* Example #3: And a cookie with the name "preferences" and a value containing "darkmode" should exist
|
|
62
|
+
* Example #4: Then a cookie with the name "tracking" and a value containing "v2-" should exist
|
|
63
|
+
* Example #5: Then a cookie with the name "csrf" and a value containing "token=" should exist
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
Then('a cookie with the name {string} and a value containing {string} should exist', async function (name, partial) {
|
|
67
|
+
const cookies = await getCookies(this);
|
|
68
|
+
const c = findByName(cookies, name);
|
|
69
|
+
assert.ok(c, `Cookie "${name}" was not found.`);
|
|
70
|
+
assert.ok(c.value.indexOf(partial) !== -1, `Cookie "${name}" value "${c.value}" does not contain "${partial}".`);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Assert a cookie whose name contains a substring exists.
|
|
75
|
+
*
|
|
76
|
+
* Example #1: Then a cookie with a name containing "session" should exist
|
|
77
|
+
* Example #2: Then a cookie with a name containing "_csrf" should exist
|
|
78
|
+
* Example #3: And a cookie with a name containing "tracking" should exist
|
|
79
|
+
* Example #4: Then a cookie with a name containing "auth" should exist
|
|
80
|
+
* Example #5: Then a cookie with a name containing "lang_" should exist
|
|
81
|
+
*
|
|
82
|
+
*/
|
|
83
|
+
Then('a cookie with a name containing {string} should exist', async function (partial) {
|
|
84
|
+
const cookies = await getCookies(this);
|
|
85
|
+
assert.ok(findByPartialName(cookies, partial), `No cookie with name containing "${partial}" was found.`);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Assert a cookie whose name contains a substring has the exact value.
|
|
90
|
+
*
|
|
91
|
+
* Example #1: Then a cookie with a name containing "session" and the value "active" should exist
|
|
92
|
+
* Example #2: Then a cookie with a name containing "auth" and the value "1" should exist
|
|
93
|
+
* Example #3: And a cookie with a name containing "lang_" and the value "en" should exist
|
|
94
|
+
* Example #4: Then a cookie with a name containing "feature_" and the value "on" should exist
|
|
95
|
+
* Example #5: Then a cookie with a name containing "_pref" and the value "dark" should exist
|
|
96
|
+
*
|
|
97
|
+
*/
|
|
98
|
+
Then('a cookie with a name containing {string} and the value {string} should exist', async function (partial, value) {
|
|
99
|
+
const cookies = await getCookies(this);
|
|
100
|
+
const found = cookies.find((c) => c.name.indexOf(partial) !== -1 && c.value === value);
|
|
101
|
+
assert.ok(found, `No cookie with name containing "${partial}" and value "${value}" was found.`);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Assert a cookie whose name contains substring A has a value containing substring B.
|
|
106
|
+
*
|
|
107
|
+
* Example #1: Then a cookie with a name containing "session" and a value containing "active" should exist
|
|
108
|
+
* Example #2: Then a cookie with a name containing "auth" and a value containing "Bearer" should exist
|
|
109
|
+
* Example #3: And a cookie with a name containing "tracking" and a value containing "v2-" should exist
|
|
110
|
+
* Example #4: Then a cookie with a name containing "csrf" and a value containing "token=" should exist
|
|
111
|
+
* Example #5: Then a cookie with a name containing "_pref" and a value containing "dark" should exist
|
|
112
|
+
*
|
|
113
|
+
*/
|
|
114
|
+
Then('a cookie with a name containing {string} and a value containing {string} should exist', async function (partialName, partialValue) {
|
|
115
|
+
const cookies = await getCookies(this);
|
|
116
|
+
const found = cookies.find((c) => c.name.indexOf(partialName) !== -1 && c.value.indexOf(partialValue) !== -1);
|
|
117
|
+
assert.ok(found, `No cookie with name containing "${partialName}" and value containing "${partialValue}" was found.`);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Assert a cookie with the exact name does NOT exist.
|
|
122
|
+
*
|
|
123
|
+
* Example #1: Then a cookie with the name "session_id" should not exist
|
|
124
|
+
* Example #2: Then a cookie with the name "auth_token" should not exist
|
|
125
|
+
* Example #3: And a cookie with the name "tracking" should not exist
|
|
126
|
+
* Example #4: When I press "Logout"
|
|
127
|
+
* Then a cookie with the name "session" should not exist
|
|
128
|
+
* Example #5: Given all cookies are cleared
|
|
129
|
+
* Then a cookie with the name "lang" should not exist
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
132
|
+
Then('a cookie with the name {string} should not exist', async function (name) {
|
|
133
|
+
const cookies = await getCookies(this);
|
|
134
|
+
assert.ok(!findByName(cookies, name), `Cookie "${name}" should not exist but it does.`);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Assert a cookie with the exact name+value does NOT exist.
|
|
139
|
+
*
|
|
140
|
+
* Example #1: Then a cookie with the name "lang" and the value "fr" should not exist
|
|
141
|
+
* Example #2: Then a cookie with the name "consent" and the value "rejected" should not exist
|
|
142
|
+
* Example #3: And a cookie with the name "theme" and the value "dark" should not exist
|
|
143
|
+
* Example #4: Then a cookie with the name "ab_bucket" and the value "variant-c" should not exist
|
|
144
|
+
* Example #5: Then a cookie with the name "remember" and the value "0" should not exist
|
|
145
|
+
*
|
|
146
|
+
*/
|
|
147
|
+
Then('a cookie with the name {string} and the value {string} should not exist', async function (name, value) {
|
|
148
|
+
const cookies = await getCookies(this);
|
|
149
|
+
const c = findByName(cookies, name);
|
|
150
|
+
assert.ok(!c || c.value !== value, `Cookie "${name}" with value "${value}" should not exist.`);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Assert a cookie with the exact name does not contain a substring in its value.
|
|
155
|
+
*
|
|
156
|
+
* Example #1: Then a cookie with the name "preferences" and a value containing "lightmode" should not exist
|
|
157
|
+
* Example #2: Then a cookie with the name "tracking" and a value containing "v1-" should not exist
|
|
158
|
+
* Example #3: And a cookie with the name "auth" and a value containing "Basic" should not exist
|
|
159
|
+
* Example #4: Then a cookie with the name "session" and a value containing "expired" should not exist
|
|
160
|
+
* Example #5: Then a cookie with the name "csrf" and a value containing "invalid" should not exist
|
|
161
|
+
*
|
|
162
|
+
*/
|
|
163
|
+
Then('a cookie with the name {string} and a value containing {string} should not exist', async function (name, partial) {
|
|
164
|
+
const cookies = await getCookies(this);
|
|
165
|
+
const c = findByName(cookies, name);
|
|
166
|
+
assert.ok(!c || c.value.indexOf(partial) === -1, `Cookie "${name}" should not contain value "${partial}".`);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Assert no cookie name contains a substring.
|
|
171
|
+
*
|
|
172
|
+
* Example #1: Then a cookie with a name containing "old_" should not exist
|
|
173
|
+
* Example #2: Then a cookie with a name containing "_legacy" should not exist
|
|
174
|
+
* Example #3: And a cookie with a name containing "deprecated" should not exist
|
|
175
|
+
* Example #4: Given all cookies are cleared
|
|
176
|
+
* Then a cookie with a name containing "session" should not exist
|
|
177
|
+
* Example #5: When I press "Logout"
|
|
178
|
+
* Then a cookie with a name containing "auth" should not exist
|
|
179
|
+
*
|
|
180
|
+
*/
|
|
181
|
+
Then('a cookie with a name containing {string} should not exist', async function (partial) {
|
|
182
|
+
const cookies = await getCookies(this);
|
|
183
|
+
assert.ok(!findByPartialName(cookies, partial), `Cookie with name containing "${partial}" should not exist.`);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Assert no cookie name+value pair (with partial name) matches.
|
|
188
|
+
*
|
|
189
|
+
* Example #1: Then a cookie with a name containing "session" and the value "expired" should not exist
|
|
190
|
+
* Example #2: Then a cookie with a name containing "auth" and the value "anonymous" should not exist
|
|
191
|
+
* Example #3: And a cookie with a name containing "feature_" and the value "off" should not exist
|
|
192
|
+
* Example #4: Then a cookie with a name containing "lang_" and the value "xx" should not exist
|
|
193
|
+
* Example #5: Then a cookie with a name containing "_pref" and the value "default" should not exist
|
|
194
|
+
*
|
|
195
|
+
*/
|
|
196
|
+
Then('a cookie with a name containing {string} and the value {string} should not exist', async function (partial, value) {
|
|
197
|
+
const cookies = await getCookies(this);
|
|
198
|
+
const found = cookies.find((c) => c.name.indexOf(partial) !== -1 && c.value === value);
|
|
199
|
+
assert.ok(!found, `Cookie with name containing "${partial}" and value "${value}" should not exist.`);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Assert no cookie partial-name + partial-value pair matches.
|
|
204
|
+
*
|
|
205
|
+
* Example #1: Then a cookie with a name containing "session" and a value containing "old" should not exist
|
|
206
|
+
* Example #2: Then a cookie with a name containing "auth" and a value containing "Basic" should not exist
|
|
207
|
+
* Example #3: And a cookie with a name containing "tracking" and a value containing "v0-" should not exist
|
|
208
|
+
* Example #4: Then a cookie with a name containing "_pref" and a value containing "lightmode" should not exist
|
|
209
|
+
* Example #5: Then a cookie with a name containing "csrf" and a value containing "invalid" should not exist
|
|
210
|
+
*
|
|
211
|
+
*/
|
|
212
|
+
Then('a cookie with a name containing {string} and a value containing {string} should not exist', async function (partialName, partialValue) {
|
|
213
|
+
const cookies = await getCookies(this);
|
|
214
|
+
const found = cookies.find((c) => c.name.indexOf(partialName) !== -1 && c.value.indexOf(partialValue) !== -1);
|
|
215
|
+
assert.ok(!found, `Cookie with name containing "${partialName}" and value containing "${partialValue}" should not exist.`);
|
|
216
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Debug helpers — print current URL, full HTML response, etc. Use sparingly
|
|
4
|
+
// and strip before merging.
|
|
5
|
+
|
|
6
|
+
const { Then } = require('@cucumber/cucumber');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Print the current page URL to console (debug).
|
|
10
|
+
*
|
|
11
|
+
* Example #1: Then print current URL
|
|
12
|
+
* Example #2: When print current URL
|
|
13
|
+
* Example #3: And print current URL
|
|
14
|
+
*/
|
|
15
|
+
Then(/^print current URL$/, function () {
|
|
16
|
+
try {
|
|
17
|
+
console.log('\n--- Current URL ---');
|
|
18
|
+
console.log(` ${this.page.url()}`);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.log(`\n--- Current URL unavailable: ${e.message} ---`);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Print the full page HTML (last response) to console (debug).
|
|
26
|
+
*
|
|
27
|
+
* Example #1: Then print last response
|
|
28
|
+
* Example #2: When print last response
|
|
29
|
+
* Example #3: And print last response
|
|
30
|
+
*/
|
|
31
|
+
Then(/^print last response$/, async function () {
|
|
32
|
+
try {
|
|
33
|
+
const html = await this.page.content();
|
|
34
|
+
console.log('\n--- Last Response (HTML) ---');
|
|
35
|
+
console.log(html);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.log(`\n--- Last response unavailable: ${e.message} ---`);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Browser dialog handlers (alert / confirm / prompt / beforeunload).
|
|
4
|
+
// Mirrors Playwright's `page.on('dialog')` API with BDD-friendly phrasing.
|
|
5
|
+
//
|
|
6
|
+
// Attach a handler BEFORE the action that triggers the dialog. Handlers
|
|
7
|
+
// queue dialog messages onto `this._lastDialog` so assertions can inspect
|
|
8
|
+
// them after the action completes.
|
|
9
|
+
|
|
10
|
+
const { Given, Then } = require('@cucumber/cucumber');
|
|
11
|
+
const assert = require('assert');
|
|
12
|
+
|
|
13
|
+
// Single shared attach() — handles single-shot ("next") and persistent
|
|
14
|
+
// ("all") variants via the `once` flag.
|
|
15
|
+
function attach(world, action, promptInput, once) {
|
|
16
|
+
if (world._dialogHandler) {
|
|
17
|
+
try { world.page.off('dialog', world._dialogHandler); } catch { /* ignore */ }
|
|
18
|
+
}
|
|
19
|
+
world._lastDialog = null;
|
|
20
|
+
world._dialogHandler = async (dialog) => {
|
|
21
|
+
world._lastDialog = {
|
|
22
|
+
type: dialog.type(),
|
|
23
|
+
message: dialog.message(),
|
|
24
|
+
defaultValue: dialog.defaultValue(),
|
|
25
|
+
};
|
|
26
|
+
try {
|
|
27
|
+
if (action === 'accept') {
|
|
28
|
+
if (typeof promptInput === 'string' && dialog.type() === 'prompt') {
|
|
29
|
+
await dialog.accept(promptInput);
|
|
30
|
+
} else {
|
|
31
|
+
await dialog.accept();
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
await dialog.dismiss();
|
|
35
|
+
}
|
|
36
|
+
} catch { /* dialog may have closed already */ }
|
|
37
|
+
if (once) {
|
|
38
|
+
try { world.page.off('dialog', world._dialogHandler); } catch { /* ignore */ }
|
|
39
|
+
world._dialogHandler = null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
world.page.on('dialog', world._dialogHandler);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Auto-accept the next native browser dialog (alert / confirm / prompt).
|
|
47
|
+
*
|
|
48
|
+
* Example #1: Given I will accept the next dialog
|
|
49
|
+
* When I click "Delete"
|
|
50
|
+
* Example #2: Given we will accept the next dialog
|
|
51
|
+
* When I press "Confirm"
|
|
52
|
+
* Example #3: Given I will accept the next dialog
|
|
53
|
+
* When I click "Save changes"
|
|
54
|
+
* Then I should see "Saved"
|
|
55
|
+
* Example #4: Given I will accept the next dialog
|
|
56
|
+
* When I follow "Leave page"
|
|
57
|
+
* Example #5: Given I will accept the next dialog
|
|
58
|
+
* When I press "Reset password"
|
|
59
|
+
* Then the last dialog type should be "confirm"
|
|
60
|
+
*
|
|
61
|
+
*/
|
|
62
|
+
Given(/^(I |we )*will accept the next dialog$/, function () {
|
|
63
|
+
attach(this, 'accept', undefined, true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Auto-dismiss the next native browser dialog.
|
|
68
|
+
*
|
|
69
|
+
* Example #1: Given I will dismiss the next dialog
|
|
70
|
+
* When I click "Leave page"
|
|
71
|
+
* Example #2: Given we will dismiss the next dialog
|
|
72
|
+
* When I press "Cancel reset"
|
|
73
|
+
* Example #3: Given I will dismiss the next dialog
|
|
74
|
+
* When I follow "Other site"
|
|
75
|
+
* Then I should be on the homepage
|
|
76
|
+
* Example #4: Given I will dismiss the next dialog
|
|
77
|
+
* When I press "Delete"
|
|
78
|
+
* Then "<.row>" should still be visible
|
|
79
|
+
* Example #5: Given I will dismiss the next dialog
|
|
80
|
+
* When I close the tab
|
|
81
|
+
*
|
|
82
|
+
*/
|
|
83
|
+
Given(/^(I |we )*will dismiss the next dialog$/, function () {
|
|
84
|
+
attach(this, 'dismiss', undefined, true);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Auto-accept the next prompt with the supplied text input.
|
|
89
|
+
*
|
|
90
|
+
* Example #1: Given I will accept the next dialog with "alice@example.com"
|
|
91
|
+
* When I press "Reset password"
|
|
92
|
+
* Example #2: Given I will accept the next dialog with "Yes"
|
|
93
|
+
* When I click "Continue"
|
|
94
|
+
* Example #3: Given we will accept the next dialog with "Bug report"
|
|
95
|
+
* When I press "Open feedback prompt"
|
|
96
|
+
* Example #4: Given I will accept the next dialog with "12345"
|
|
97
|
+
* When I follow "Set order ID"
|
|
98
|
+
* Example #5: Given I will accept the next dialog with "https://example.com"
|
|
99
|
+
* When I press "Add link"
|
|
100
|
+
*
|
|
101
|
+
*/
|
|
102
|
+
Given(/^(I |we )*will accept the next dialog with "([^"]*)"$/, function (pronoun, input) {
|
|
103
|
+
attach(this, 'accept', input, true);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Assert the most recently captured dialog message equals an expected value.
|
|
108
|
+
*
|
|
109
|
+
* Example #1: Then the last dialog message should be "Are you sure?"
|
|
110
|
+
* Example #2: Then the last dialog message should be "Delete this item?"
|
|
111
|
+
* Example #3: And the last dialog message should be "Leave site?"
|
|
112
|
+
* Example #4: Then the last dialog message should be "Save changes?"
|
|
113
|
+
* Example #5: When I press "Reset"
|
|
114
|
+
* Then the last dialog message should be "Reset all settings?"
|
|
115
|
+
*
|
|
116
|
+
*/
|
|
117
|
+
Then(/^the last dialog message should be "([^"]*)"$/, function (text) {
|
|
118
|
+
assert.ok(this._lastDialog, 'No dialog has been captured.');
|
|
119
|
+
assert.strictEqual(this._lastDialog.message, text,
|
|
120
|
+
`Expected dialog message "${text}", got "${this._lastDialog.message}".`);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Assert the most recently captured dialog message contains an expected substring.
|
|
125
|
+
*
|
|
126
|
+
* Example #1: Then the last dialog message should contain "Are you sure"
|
|
127
|
+
* Example #2: Then the last dialog message should contain "delete"
|
|
128
|
+
* Example #3: And the last dialog message should contain "leave"
|
|
129
|
+
* Example #4: Then the last dialog message should contain "save"
|
|
130
|
+
* Example #5: When I click "Cancel order"
|
|
131
|
+
* Then the last dialog message should contain "cancel"
|
|
132
|
+
*
|
|
133
|
+
*/
|
|
134
|
+
Then(/^the last dialog message should contain "([^"]*)"$/, function (text) {
|
|
135
|
+
assert.ok(this._lastDialog, 'No dialog has been captured.');
|
|
136
|
+
assert.ok(this._lastDialog.message.includes(text),
|
|
137
|
+
`Dialog message "${this._lastDialog.message}" does not contain "${text}".`);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Assert the most recently captured dialog type matches one of `alert`,
|
|
142
|
+
* `confirm`, `prompt`, or `beforeunload`.
|
|
143
|
+
*
|
|
144
|
+
* Example #1: Then the last dialog type should be "confirm"
|
|
145
|
+
* Example #2: Then the last dialog type should be "alert"
|
|
146
|
+
* Example #3: And the last dialog type should be "prompt"
|
|
147
|
+
* Example #4: Then the last dialog type should be "beforeunload"
|
|
148
|
+
* Example #5: When I press "Reset password"
|
|
149
|
+
* Then the last dialog type should be "prompt"
|
|
150
|
+
*
|
|
151
|
+
*/
|
|
152
|
+
Then(/^the last dialog type should be "([^"]*)"$/, function (type) {
|
|
153
|
+
assert.ok(this._lastDialog, 'No dialog has been captured.');
|
|
154
|
+
assert.strictEqual(this._lastDialog.type, type,
|
|
155
|
+
`Expected dialog type "${type}", got "${this._lastDialog.type}".`);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Auto-accept EVERY native browser dialog raised in this scenario.
|
|
160
|
+
*
|
|
161
|
+
* Persistent variant of "I will accept the next dialog" — handler stays
|
|
162
|
+
* attached for the rest of the scenario.
|
|
163
|
+
*
|
|
164
|
+
* Example #1: Given I accept all confirmation dialogs
|
|
165
|
+
* Example #2: Given we accept all confirmation dialogs
|
|
166
|
+
* When I click "Delete all"
|
|
167
|
+
* Example #3: And I accept all confirmation dialogs
|
|
168
|
+
* Example #4: Given I accept all confirmation dialogs
|
|
169
|
+
* When I press "Reset settings"
|
|
170
|
+
* Example #5: Given I accept all confirmation dialogs
|
|
171
|
+
* When I follow "Discard changes"
|
|
172
|
+
*
|
|
173
|
+
*/
|
|
174
|
+
Given(/^(I |we )*accept all confirmation dialogs$/, function () {
|
|
175
|
+
attach(this, 'accept', undefined, false);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Auto-dismiss EVERY native browser dialog raised in this scenario.
|
|
180
|
+
*
|
|
181
|
+
* Example #1: Given I do not accept any confirmation dialogs
|
|
182
|
+
* Example #2: Given we do not accept any confirmation dialogs
|
|
183
|
+
* When I click "Delete"
|
|
184
|
+
* Example #3: And I do not accept any confirmation dialogs
|
|
185
|
+
* Example #4: Given I do not accept any confirmation dialogs
|
|
186
|
+
* When I press "Cancel reset"
|
|
187
|
+
* Example #5: Given I do not accept any confirmation dialogs
|
|
188
|
+
* When I follow "Leave page"
|
|
189
|
+
*
|
|
190
|
+
*/
|
|
191
|
+
Given(/^(I |we )*do not accept any confirmation dialogs$/, function () {
|
|
192
|
+
attach(this, 'dismiss', undefined, false);
|
|
193
|
+
});
|