@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,98 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Inspect HTTP response headers using Playwright's request API on the current page URL.
|
|
4
|
+
|
|
5
|
+
const { Then, Before } = require('@cucumber/cucumber');
|
|
6
|
+
const assert = require('assert');
|
|
7
|
+
|
|
8
|
+
// Capture response headers from navigation events, with page.request fallback.
|
|
9
|
+
Before({ order: 100 }, async function () {
|
|
10
|
+
if (!this.page) return;
|
|
11
|
+
this._lastResponseHeaders = null;
|
|
12
|
+
this._lastResponseStatus = null;
|
|
13
|
+
this.page.on('response', (resp) => {
|
|
14
|
+
try {
|
|
15
|
+
if (resp.request().isNavigationRequest() && resp.frame() === this.page.mainFrame()) {
|
|
16
|
+
this._lastResponseHeaders = resp.headers();
|
|
17
|
+
this._lastResponseStatus = resp.status();
|
|
18
|
+
}
|
|
19
|
+
} catch (e) { /* ignore */ }
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
async function getHeaders(world) {
|
|
24
|
+
if (world._lastResponseHeaders) return world._lastResponseHeaders;
|
|
25
|
+
// Fallback: fetch current URL via Playwright request context to get headers.
|
|
26
|
+
const url = world.page.url();
|
|
27
|
+
if (!url || url === 'about:blank') return {};
|
|
28
|
+
try {
|
|
29
|
+
const resp = await world.page.request.get(url);
|
|
30
|
+
return resp.headers();
|
|
31
|
+
} catch (e) {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Assert the most recent navigation response carried a header (case-insensitive).
|
|
38
|
+
*
|
|
39
|
+
* Example #1: Then the response should contain the header "content-type"
|
|
40
|
+
* Example #2: Then the response should contain the header "cache-control"
|
|
41
|
+
* Example #3: And the response should contain the header "x-frame-options"
|
|
42
|
+
* Example #4: Then the response should contain the header "set-cookie"
|
|
43
|
+
* Example #5: Then the response should contain the header "etag"
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
Then('the response should contain the header {string}', async function (name) {
|
|
47
|
+
const h = await getHeaders(this);
|
|
48
|
+
assert.ok(Object.keys(h).map((k) => k.toLowerCase()).includes(name.toLowerCase()), `Header "${name}" not present.`);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Assert the most recent navigation response did NOT carry a header.
|
|
53
|
+
*
|
|
54
|
+
* Example #1: Then the response should not contain the header "x-fake-header"
|
|
55
|
+
* Example #2: Then the response should not contain the header "x-powered-by"
|
|
56
|
+
* Example #3: And the response should not contain the header "server"
|
|
57
|
+
* Example #4: Then the response should not contain the header "x-aspnet-version"
|
|
58
|
+
* Example #5: Then the response should not contain the header "x-debug-token"
|
|
59
|
+
*
|
|
60
|
+
*/
|
|
61
|
+
Then('the response should not contain the header {string}', async function (name) {
|
|
62
|
+
const h = await getHeaders(this);
|
|
63
|
+
assert.ok(!Object.keys(h).map((k) => k.toLowerCase()).includes(name.toLowerCase()), `Header "${name}" should not be present.`);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Assert a header's value contains a substring.
|
|
68
|
+
*
|
|
69
|
+
* Example #1: Then the response header "content-type" should contain the value "html"
|
|
70
|
+
* Example #2: Then the response header "cache-control" should contain the value "no-cache"
|
|
71
|
+
* Example #3: And the response header "content-type" should contain the value "charset=utf-8"
|
|
72
|
+
* Example #4: Then the response header "set-cookie" should contain the value "session="
|
|
73
|
+
* Example #5: Then the response header "x-frame-options" should contain the value "DENY"
|
|
74
|
+
*
|
|
75
|
+
*/
|
|
76
|
+
Then('the response header {string} should contain the value {string}', async function (name, value) {
|
|
77
|
+
const h = await getHeaders(this);
|
|
78
|
+
const key = Object.keys(h).find((k) => k.toLowerCase() === name.toLowerCase());
|
|
79
|
+
assert.ok(key, `Header "${name}" not present.`);
|
|
80
|
+
assert.ok(String(h[key]).indexOf(value) !== -1, `Header "${name}"="${h[key]}" does not contain "${value}".`);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Assert a header's value does NOT contain a substring (or the header is absent).
|
|
85
|
+
*
|
|
86
|
+
* Example #1: Then the response header "content-type" should not contain the value "application/json"
|
|
87
|
+
* Example #2: Then the response header "cache-control" should not contain the value "public"
|
|
88
|
+
* Example #3: And the response header "content-type" should not contain the value "xml"
|
|
89
|
+
* Example #4: Then the response header "set-cookie" should not contain the value "Domain=other"
|
|
90
|
+
* Example #5: Then the response header "x-frame-options" should not contain the value "ALLOW"
|
|
91
|
+
*
|
|
92
|
+
*/
|
|
93
|
+
Then('the response header {string} should not contain the value {string}', async function (name, value) {
|
|
94
|
+
const h = await getHeaders(this);
|
|
95
|
+
const key = Object.keys(h).find((k) => k.toLowerCase() === name.toLowerCase());
|
|
96
|
+
if (!key) return;
|
|
97
|
+
assert.ok(String(h[key]).indexOf(value) === -1, `Header "${name}" should not contain "${value}".`);
|
|
98
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { friendly } = require('./varbase-e2e');
|
|
4
|
+
|
|
5
|
+
// Set viewport dimensions and named breakpoints.
|
|
6
|
+
|
|
7
|
+
const { Given, When } = require('@cucumber/cucumber');
|
|
8
|
+
|
|
9
|
+
const DEFAULT_BREAKPOINTS = {
|
|
10
|
+
xs: { width: 375, height: 667 },
|
|
11
|
+
sm: { width: 576, height: 800 },
|
|
12
|
+
md: { width: 768, height: 1024 },
|
|
13
|
+
lg: { width: 992, height: 768 },
|
|
14
|
+
xl: { width: 1200, height: 900 },
|
|
15
|
+
xxl: { width: 1400, height: 900 },
|
|
16
|
+
xxxl: { width: 1920, height: 1080 },
|
|
17
|
+
mobile: { width: 375, height: 667 },
|
|
18
|
+
tablet: { width: 768, height: 1024 },
|
|
19
|
+
desktop: { width: 1200, height: 900 },
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function getBreakpoints(world) {
|
|
23
|
+
if (!world._breakpoints) {
|
|
24
|
+
const cfg = (world.parameters && world.parameters.selectors && world.parameters.selectors.breakpoints) || {};
|
|
25
|
+
world._breakpoints = { ...DEFAULT_BREAKPOINTS, ...cfg };
|
|
26
|
+
}
|
|
27
|
+
return world._breakpoints;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Replace the breakpoint registry for the current scenario from a data table.
|
|
32
|
+
*
|
|
33
|
+
* Example #1: Given the following responsive breakpoints:
|
|
34
|
+
* | mobile | 375 | 667 |
|
|
35
|
+
* | tablet | 768 | 1024 |
|
|
36
|
+
* | desktop | 1200 | 900 |
|
|
37
|
+
* Example #2: Given the following responsive breakpoints:
|
|
38
|
+
* | watch | 280 | 280 |
|
|
39
|
+
* | phablet | 414 | 896 |
|
|
40
|
+
* Example #3: And the following responsive breakpoints:
|
|
41
|
+
* | xs | 320 | 480 |
|
|
42
|
+
* | sm | 480 | 800 |
|
|
43
|
+
* Example #4: Given the following responsive breakpoints:
|
|
44
|
+
* | hd | 1280 | 720 |
|
|
45
|
+
* | full-hd | 1920 | 1080 |
|
|
46
|
+
* Example #5: Given the following responsive breakpoints:
|
|
47
|
+
* | a11y | 320 | 480 |
|
|
48
|
+
* | print | 794 | 1123 |
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
Given('the following responsive breakpoints:', async function (table) {
|
|
52
|
+
const map = {};
|
|
53
|
+
for (const row of table.raw()) {
|
|
54
|
+
const [name, w, h] = row;
|
|
55
|
+
map[name] = { width: parseInt(w, 10), height: parseInt(h, 10) };
|
|
56
|
+
}
|
|
57
|
+
this._breakpoints = { ...DEFAULT_BREAKPOINTS, ...map };
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Resize the viewport to a registered named breakpoint.
|
|
62
|
+
*
|
|
63
|
+
* Built-in names: `xs`, `sm`, `md`, `lg`, `xl`, `xxl`, `xxxl`, `mobile`,
|
|
64
|
+
* `tablet`, `desktop`. Project-defined names override built-ins.
|
|
65
|
+
*
|
|
66
|
+
* Example #1: When I set the viewport to the "mobile" breakpoint
|
|
67
|
+
* Example #2: When I set the viewport to the "tablet" breakpoint
|
|
68
|
+
* Example #3: And we set the viewport to the "desktop" breakpoint
|
|
69
|
+
* Example #4: When I set the viewport to the "xl" breakpoint
|
|
70
|
+
* Example #5: When I set the viewport to the "xxxl" breakpoint
|
|
71
|
+
*
|
|
72
|
+
*/
|
|
73
|
+
When(/^(I |we )*set the viewport to the "([^"]*)" breakpoint$/, async function (pronoun, name) {
|
|
74
|
+
const bps = getBreakpoints(this);
|
|
75
|
+
const bp = bps[name];
|
|
76
|
+
if (!bp) throw friendly(`Unknown breakpoint "${name}".`);
|
|
77
|
+
await this.page.setViewportSize({ width: bp.width, height: bp.height });
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Resize the viewport width while keeping the current height.
|
|
82
|
+
*
|
|
83
|
+
* Example #1: When I set the viewport width to 1200
|
|
84
|
+
* Example #2: When I set the viewport width to 375
|
|
85
|
+
* Example #3: And we set the viewport width to 1920
|
|
86
|
+
* Example #4: When I set the viewport width to 768
|
|
87
|
+
* Example #5: When I set the viewport width to 1024
|
|
88
|
+
*
|
|
89
|
+
*/
|
|
90
|
+
When(/^(I |we )*set the viewport width to (\d+)$/, async function (pronoun, w) {
|
|
91
|
+
w = parseInt(w, 10);
|
|
92
|
+
const cur = this.page.viewportSize() || { height: 800 };
|
|
93
|
+
await this.page.setViewportSize({ width: w, height: cur.height });
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Resize the viewport height while keeping the current width.
|
|
98
|
+
*
|
|
99
|
+
* Example #1: When I set the viewport height to 800
|
|
100
|
+
* Example #2: When I set the viewport height to 1024
|
|
101
|
+
* Example #3: And we set the viewport height to 1080
|
|
102
|
+
* Example #4: When I set the viewport height to 667
|
|
103
|
+
* Example #5: When I set the viewport height to 900
|
|
104
|
+
*
|
|
105
|
+
*/
|
|
106
|
+
When(/^(I |we )*set the viewport height to (\d+)$/, async function (pronoun, h) {
|
|
107
|
+
h = parseInt(h, 10);
|
|
108
|
+
const cur = this.page.viewportSize() || { width: 1200 };
|
|
109
|
+
await this.page.setViewportSize({ width: cur.width, height: h });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Resize the viewport to an explicit width-by-height pair.
|
|
114
|
+
*
|
|
115
|
+
* Example #1: When I set the viewport to 1200 by 800
|
|
116
|
+
* Example #2: When I set the viewport to 375 by 667
|
|
117
|
+
* Example #3: And we set the viewport to 1920 by 1080
|
|
118
|
+
* Example #4: When I set the viewport to 768 by 1024
|
|
119
|
+
* Example #5: When I set the viewport to 1024 by 768
|
|
120
|
+
*
|
|
121
|
+
*/
|
|
122
|
+
When(/^(I |we )*set the viewport to (\d+) by (\d+)$/, async function (pronoun, w, h) {
|
|
123
|
+
w = parseInt(w, 10); h = parseInt(h, 10);
|
|
124
|
+
await this.page.setViewportSize({ width: w, height: h });
|
|
125
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Lightweight REST testing — distinct from the existing api.steps.js steps
|
|
4
|
+
// Preserves exact step phrasing for compatibility.
|
|
5
|
+
|
|
6
|
+
const { Given, When, Then } = require('@cucumber/cucumber');
|
|
7
|
+
const assert = require('assert');
|
|
8
|
+
const axios = require('axios');
|
|
9
|
+
|
|
10
|
+
function ensureState(world) {
|
|
11
|
+
if (!world._rest) world._rest = { headers: {}, response: null };
|
|
12
|
+
return world._rest;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Add an HTTP header to subsequent REST requests.
|
|
17
|
+
*
|
|
18
|
+
* Example #1: Given a REST header "Authorization" with value "Bearer abc123"
|
|
19
|
+
* Example #2: Given a REST header "Accept" with value "application/json"
|
|
20
|
+
* Example #3: And a REST header "X-Request-ID" with value "req-001"
|
|
21
|
+
* Example #4: Given a REST header "Content-Type" with value "application/json"
|
|
22
|
+
* Example #5: Given a REST header "X-API-Key" with value "key-xyz"
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
25
|
+
Given('a REST header {string} with value {string}', async function (name, value) {
|
|
26
|
+
ensureState(this).headers[name] = value;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Send an HTTP request without a body.
|
|
31
|
+
*
|
|
32
|
+
* Example #1: When I send a REST "GET" request to "/api/users"
|
|
33
|
+
* Example #2: When I send a REST "DELETE" request to "/api/orders/1"
|
|
34
|
+
* Example #3: And we send a REST "GET" request to "https://example.com/api/health"
|
|
35
|
+
* Example #4: When I send a REST "GET" request to "/api/me"
|
|
36
|
+
* Example #5: When I send a REST "DELETE" request to "/api/cart/items/42"
|
|
37
|
+
*
|
|
38
|
+
*/
|
|
39
|
+
When(/^(I |we )*send a REST "([^"]*)" request to "([^"]*)"$/, async function (pronoun, method, url) {
|
|
40
|
+
const s = ensureState(this);
|
|
41
|
+
const target = url.startsWith('http') ? url : (this.launchUrl || '') + url;
|
|
42
|
+
s.response = await axios.request({
|
|
43
|
+
method, url: target, headers: s.headers, validateStatus: () => true,
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Send an HTTP request with a doc-string body (raw text, JSON, or form-encoded).
|
|
49
|
+
*
|
|
50
|
+
* Example #1: When I send a REST "POST" request to "/api/users" with body:
|
|
51
|
+
* """
|
|
52
|
+
* {"name": "Alice"}
|
|
53
|
+
* """
|
|
54
|
+
* Example #2: When I send a REST "PUT" request to "/api/users/1" with body:
|
|
55
|
+
* """
|
|
56
|
+
* {"role": "admin"}
|
|
57
|
+
* """
|
|
58
|
+
* Example #3: And we send a REST "PATCH" request to "/api/orders/1" with body:
|
|
59
|
+
* """
|
|
60
|
+
* {"status": "shipped"}
|
|
61
|
+
* """
|
|
62
|
+
* Example #4: When I send a REST "POST" request to "/api/login" with body:
|
|
63
|
+
* """
|
|
64
|
+
* username=alice&password=s3cret
|
|
65
|
+
* """
|
|
66
|
+
* Example #5: When I send a REST "POST" request to "/webhooks/event" with body:
|
|
67
|
+
* """
|
|
68
|
+
* {"event": "ping"}
|
|
69
|
+
* """
|
|
70
|
+
*
|
|
71
|
+
*/
|
|
72
|
+
When(/^(I |we )*send a REST "([^"]*)" request to "([^"]*)" with body:$/, async function (pronoun, method, url, body) {
|
|
73
|
+
const s = ensureState(this);
|
|
74
|
+
const target = url.startsWith('http') ? url : (this.launchUrl || '') + url;
|
|
75
|
+
s.response = await axios.request({
|
|
76
|
+
method, url: target, headers: s.headers, data: body, validateStatus: () => true,
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Assert the most recent REST response carried an expected status code.
|
|
82
|
+
*
|
|
83
|
+
* Example #1: Then the REST response status code should be 200
|
|
84
|
+
* Example #2: Then the REST response status code should be 201
|
|
85
|
+
* Example #3: And the REST response status code should be 401
|
|
86
|
+
* Example #4: Then the REST response status code should be 404
|
|
87
|
+
* Example #5: Then the REST response status code should be 500
|
|
88
|
+
*
|
|
89
|
+
*/
|
|
90
|
+
Then('the REST response status code should be {int}', async function (code) {
|
|
91
|
+
const s = ensureState(this);
|
|
92
|
+
assert.ok(s.response, 'No REST response captured.');
|
|
93
|
+
assert.strictEqual(s.response.status, code);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Assert the most recent REST response body contains a substring.
|
|
98
|
+
*
|
|
99
|
+
* Example #1: Then the REST response should contain "Alice"
|
|
100
|
+
* Example #2: Then the REST response should contain "id"
|
|
101
|
+
* Example #3: And the REST response should contain "shipped"
|
|
102
|
+
* Example #4: Then the REST response should contain "ok"
|
|
103
|
+
* Example #5: Then the REST response should contain "Welcome"
|
|
104
|
+
*
|
|
105
|
+
*/
|
|
106
|
+
Then('the REST response should contain {string}', async function (text) {
|
|
107
|
+
const s = ensureState(this);
|
|
108
|
+
assert.ok(s.response, 'No REST response captured.');
|
|
109
|
+
const body = typeof s.response.data === 'string' ? s.response.data : JSON.stringify(s.response.data);
|
|
110
|
+
assert.ok(body.indexOf(text) !== -1, `REST response does not contain "${text}".`);
|
|
111
|
+
});
|