@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,411 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { friendly } = require('./varbase-e2e');
|
|
4
|
+
|
|
5
|
+
// Parse and assert against an XML response loaded from a file or doc string.
|
|
6
|
+
|
|
7
|
+
const { Given, Then, When } = require('@cucumber/cucumber');
|
|
8
|
+
const assert = require('assert');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
let DOMParser;
|
|
13
|
+
try { ({ DOMParser } = require('@xmldom/xmldom')); }
|
|
14
|
+
catch (e) {
|
|
15
|
+
try { ({ DOMParser } = require('xmldom')); }
|
|
16
|
+
catch (e2) { /* will throw on use */ }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function ensureXml(world) {
|
|
20
|
+
if (!DOMParser) throw friendly('XML steps require an XML DOM parser. Install @xmldom/xmldom.');
|
|
21
|
+
if (!world._xml) throw friendly('No XML response has been set.');
|
|
22
|
+
return world._xml;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function evalXPath(doc, xpath) {
|
|
26
|
+
// Minimal XPath: support /a/b and /a/b[@attr] and /a/b/text()
|
|
27
|
+
// For richer XPath, users can install xpath module.
|
|
28
|
+
let xpathLib;
|
|
29
|
+
try { xpathLib = require('xpath'); } catch (e) { xpathLib = null; }
|
|
30
|
+
if (xpathLib) return xpathLib.select(xpath, doc);
|
|
31
|
+
// Fallback simple traversal
|
|
32
|
+
const parts = xpath.split('/').filter(Boolean);
|
|
33
|
+
let nodes = [doc.documentElement].filter((n) => n && n.nodeName === parts[0]);
|
|
34
|
+
for (const part of parts.slice(1)) {
|
|
35
|
+
const next = [];
|
|
36
|
+
for (const n of nodes) {
|
|
37
|
+
const children = Array.from(n.childNodes || []).filter((c) => c.nodeType === 1 && c.nodeName === part);
|
|
38
|
+
next.push(...children);
|
|
39
|
+
}
|
|
40
|
+
nodes = next;
|
|
41
|
+
}
|
|
42
|
+
return nodes;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Load XML response content from a file under `tests/assets/`.
|
|
47
|
+
*
|
|
48
|
+
* Example #1: Given the response content from the file "feed.xml"
|
|
49
|
+
* Example #2: Given the response content from the file "rss.xml"
|
|
50
|
+
* Example #3: And the response content from the file "sitemap.xml"
|
|
51
|
+
* Example #4: Given the response content from the file "soap-response.xml"
|
|
52
|
+
* Example #5: Given the response content from the file "/tmp/sample.xml"
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
Given('the response content from the file {string}', async function (filename) {
|
|
56
|
+
const p = path.isAbsolute(filename) ? filename : path.join(this.assetsFolder || './tests/assets', filename);
|
|
57
|
+
const content = fs.readFileSync(p, 'utf-8');
|
|
58
|
+
this._rawResponse = content;
|
|
59
|
+
this._xml = new DOMParser().parseFromString(content, 'text/xml');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Set XML response content inline from a Gherkin doc string.
|
|
64
|
+
*
|
|
65
|
+
* Example #1: Given the response content is the following:
|
|
66
|
+
* """
|
|
67
|
+
* <root><item id="1">Hello</item></root>
|
|
68
|
+
* """
|
|
69
|
+
* Example #2: Given the response content is the following:
|
|
70
|
+
* """
|
|
71
|
+
* <feed><entry><title>Sample feed</title></entry></feed>
|
|
72
|
+
* """
|
|
73
|
+
* Example #3: And the response content is the following:
|
|
74
|
+
* """
|
|
75
|
+
* <orders><order id="1"><status>shipped</status></order></orders>
|
|
76
|
+
* """
|
|
77
|
+
* Example #4: Given the response content is the following:
|
|
78
|
+
* """
|
|
79
|
+
* <products><product><name>Laptop</name></product></products>
|
|
80
|
+
* """
|
|
81
|
+
* Example #5: Given the response content is the following:
|
|
82
|
+
* """
|
|
83
|
+
* <error code="404">Not found</error>
|
|
84
|
+
* """
|
|
85
|
+
*
|
|
86
|
+
*/
|
|
87
|
+
Given('the response content is the following:', async function (docString) {
|
|
88
|
+
this._rawResponse = docString;
|
|
89
|
+
this._xml = new DOMParser().parseFromString(docString, 'text/xml');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Assert the loaded response parses as XML.
|
|
94
|
+
*
|
|
95
|
+
* Example #1: Then the response should be in XML format
|
|
96
|
+
* Example #2: Given the response content from the file "rss.xml"
|
|
97
|
+
* Then the response should be in XML format
|
|
98
|
+
* Example #3: And the response should be in XML format
|
|
99
|
+
* Example #4: Given the response content is the following:
|
|
100
|
+
* """
|
|
101
|
+
* <root/>
|
|
102
|
+
* """
|
|
103
|
+
* Then the response should be in XML format
|
|
104
|
+
* Example #5: Then the response should be in XML format
|
|
105
|
+
* And the XML element "/root" should exist
|
|
106
|
+
*
|
|
107
|
+
*/
|
|
108
|
+
Then('the response should be in XML format', async function () {
|
|
109
|
+
assert.ok(this._rawResponse, 'No response content set.');
|
|
110
|
+
const doc = new DOMParser().parseFromString(this._rawResponse, 'text/xml');
|
|
111
|
+
assert.ok(doc && doc.documentElement, 'Response is not valid XML.');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Assert the loaded response is NOT XML.
|
|
116
|
+
*
|
|
117
|
+
* Example #1: Then the response should not be in XML format
|
|
118
|
+
* Example #2: Given the response content is the following:
|
|
119
|
+
* """
|
|
120
|
+
* {"hello": "world"}
|
|
121
|
+
* """
|
|
122
|
+
* Then the response should not be in XML format
|
|
123
|
+
* Example #3: And the response should not be in XML format
|
|
124
|
+
* Example #4: Given the response content is the following:
|
|
125
|
+
* """
|
|
126
|
+
* plain text
|
|
127
|
+
* """
|
|
128
|
+
* Then the response should not be in XML format
|
|
129
|
+
* Example #5: Then the response should not be in XML format
|
|
130
|
+
* And I print last XML response
|
|
131
|
+
*
|
|
132
|
+
*/
|
|
133
|
+
Then('the response should not be in XML format', async function () {
|
|
134
|
+
if (!this._rawResponse) return;
|
|
135
|
+
try {
|
|
136
|
+
const doc = new DOMParser().parseFromString(this._rawResponse, 'text/xml');
|
|
137
|
+
assert.ok(!doc || !doc.documentElement || doc.getElementsByTagName('parsererror').length > 0, 'Response is XML.');
|
|
138
|
+
} catch (e) { /* good */ }
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Assert at least one XML element matches an XPath.
|
|
143
|
+
*
|
|
144
|
+
* Example #1: Then the XML element "/root/item" should exist
|
|
145
|
+
* Example #2: Then the XML element "//book/title" should exist
|
|
146
|
+
* Example #3: And the XML element "/order/customer" should exist
|
|
147
|
+
* Example #4: Then the XML element "//status" should exist
|
|
148
|
+
* Example #5: Then the XML element "/feed/entry[2]" should exist
|
|
149
|
+
*
|
|
150
|
+
*/
|
|
151
|
+
Then('the XML element {string} should exist', async function (xpath) {
|
|
152
|
+
const doc = ensureXml(this);
|
|
153
|
+
const nodes = evalXPath(doc, xpath);
|
|
154
|
+
assert.ok(nodes && nodes.length > 0, `XML element "${xpath}" not found.`);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Assert NO XML element matches an XPath.
|
|
159
|
+
*
|
|
160
|
+
* Example #1: Then the XML element "/root/missing" should not exist
|
|
161
|
+
* Example #2: Then the XML element "//error" should not exist
|
|
162
|
+
* Example #3: And the XML element "/feed/legacy" should not exist
|
|
163
|
+
* Example #4: Then the XML element "//deprecated" should not exist
|
|
164
|
+
* Example #5: Then the XML element "/order/refund" should not exist
|
|
165
|
+
*
|
|
166
|
+
*/
|
|
167
|
+
Then('the XML element {string} should not exist', async function (xpath) {
|
|
168
|
+
const doc = ensureXml(this);
|
|
169
|
+
const nodes = evalXPath(doc, xpath);
|
|
170
|
+
assert.ok(!nodes || nodes.length === 0, `XML element "${xpath}" should not exist.`);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Assert an XML element's text content equals an expected value (trimmed).
|
|
175
|
+
*
|
|
176
|
+
* Example #1: Then the XML element "/root/item" should be equal to "Hello"
|
|
177
|
+
* Example #2: Then the XML element "//status" should be equal to "shipped"
|
|
178
|
+
* Example #3: And the XML element "/order/customer/name" should be equal to "Alice"
|
|
179
|
+
* Example #4: Then the XML element "/book/title" should be equal to "Sample title"
|
|
180
|
+
* Example #5: Then the XML element "//count" should be equal to "5"
|
|
181
|
+
*
|
|
182
|
+
*/
|
|
183
|
+
Then('the XML element {string} should be equal to {string}', async function (xpath, text) {
|
|
184
|
+
const doc = ensureXml(this);
|
|
185
|
+
const nodes = evalXPath(doc, xpath);
|
|
186
|
+
assert.ok(nodes && nodes.length > 0, `XML element "${xpath}" not found.`);
|
|
187
|
+
const value = (nodes[0].textContent || '').trim();
|
|
188
|
+
assert.strictEqual(value, text);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Assert an XML element's text content is NOT equal to an expected value.
|
|
193
|
+
*
|
|
194
|
+
* Example #1: Then the XML element "/root/item" should not be equal to "Bye"
|
|
195
|
+
* Example #2: Then the XML element "//status" should not be equal to "cancelled"
|
|
196
|
+
* Example #3: And the XML element "/order/customer/name" should not be equal to "Anonymous"
|
|
197
|
+
* Example #4: Then the XML element "/book/title" should not be equal to "Untitled"
|
|
198
|
+
* Example #5: Then the XML element "//count" should not be equal to "0"
|
|
199
|
+
*
|
|
200
|
+
*/
|
|
201
|
+
Then('the XML element {string} should not be equal to {string}', async function (xpath, text) {
|
|
202
|
+
const doc = ensureXml(this);
|
|
203
|
+
const nodes = evalXPath(doc, xpath);
|
|
204
|
+
if (!nodes || nodes.length === 0) return;
|
|
205
|
+
assert.notStrictEqual((nodes[0].textContent || '').trim(), text);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Assert an XML element's text content contains a substring.
|
|
210
|
+
*
|
|
211
|
+
* Example #1: Then the XML element "/root/item" should contain "Hello"
|
|
212
|
+
* Example #2: Then the XML element "//status" should contain "ship"
|
|
213
|
+
* Example #3: And the XML element "/order/customer/name" should contain "Alice"
|
|
214
|
+
* Example #4: Then the XML element "/book/title" should contain "Varbase E2E"
|
|
215
|
+
* Example #5: Then the XML element "/feed/entry/summary" should contain "release"
|
|
216
|
+
*
|
|
217
|
+
*/
|
|
218
|
+
Then('the XML element {string} should contain {string}', async function (xpath, text) {
|
|
219
|
+
const doc = ensureXml(this);
|
|
220
|
+
const nodes = evalXPath(doc, xpath);
|
|
221
|
+
assert.ok(nodes && nodes.length > 0, `XML element "${xpath}" not found.`);
|
|
222
|
+
assert.ok((nodes[0].textContent || '').indexOf(text) !== -1);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Assert an XML element's text content does NOT contain a substring.
|
|
227
|
+
*
|
|
228
|
+
* Example #1: Then the XML element "/root/item" should not contain "Error"
|
|
229
|
+
* Example #2: Then the XML element "//status" should not contain "fail"
|
|
230
|
+
* Example #3: And the XML element "/order/customer/name" should not contain "Anonymous"
|
|
231
|
+
* Example #4: Then the XML element "/book/title" should not contain "Untitled"
|
|
232
|
+
* Example #5: Then the XML element "/feed/entry/summary" should not contain "TODO"
|
|
233
|
+
*
|
|
234
|
+
*/
|
|
235
|
+
Then('the XML element {string} should not contain {string}', async function (xpath, text) {
|
|
236
|
+
const doc = ensureXml(this);
|
|
237
|
+
const nodes = evalXPath(doc, xpath);
|
|
238
|
+
if (!nodes || nodes.length === 0) return;
|
|
239
|
+
assert.ok((nodes[0].textContent || '').indexOf(text) === -1);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Assert an XML element has the named attribute.
|
|
244
|
+
*
|
|
245
|
+
* Example #1: Then the XML attribute "id" on element "/root/item" should exist
|
|
246
|
+
* Example #2: Then the XML attribute "lang" on element "/feed" should exist
|
|
247
|
+
* Example #3: And the XML attribute "type" on element "//entry" should exist
|
|
248
|
+
* Example #4: Then the XML attribute "version" on element "/rss" should exist
|
|
249
|
+
* Example #5: Then the XML attribute "code" on element "/error" should exist
|
|
250
|
+
*
|
|
251
|
+
*/
|
|
252
|
+
Then('the XML attribute {string} on element {string} should exist', async function (attr, xpath) {
|
|
253
|
+
const doc = ensureXml(this);
|
|
254
|
+
const nodes = evalXPath(doc, xpath);
|
|
255
|
+
assert.ok(nodes && nodes.length > 0, `XML element "${xpath}" not found.`);
|
|
256
|
+
assert.ok(nodes[0].getAttribute && nodes[0].hasAttribute(attr), `Attribute "${attr}" not found on "${xpath}".`);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Assert an XML element does NOT have the named attribute.
|
|
261
|
+
*
|
|
262
|
+
* Example #1: Then the XML attribute "deprecated" on element "/root/item" should not exist
|
|
263
|
+
* Example #2: Then the XML attribute "internal" on element "/feed" should not exist
|
|
264
|
+
* Example #3: And the XML attribute "secret" on element "//entry" should not exist
|
|
265
|
+
* Example #4: Then the XML attribute "private" on element "/rss" should not exist
|
|
266
|
+
* Example #5: Then the XML attribute "debug" on element "/error" should not exist
|
|
267
|
+
*
|
|
268
|
+
*/
|
|
269
|
+
Then('the XML attribute {string} on element {string} should not exist', async function (attr, xpath) {
|
|
270
|
+
const doc = ensureXml(this);
|
|
271
|
+
const nodes = evalXPath(doc, xpath);
|
|
272
|
+
if (!nodes || nodes.length === 0) return;
|
|
273
|
+
assert.ok(!nodes[0].hasAttribute(attr), `Attribute "${attr}" should not exist on "${xpath}".`);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Assert an XML attribute equals an expected value.
|
|
278
|
+
*
|
|
279
|
+
* Example #1: Then the XML attribute "id" on element "/root/item" should be equal to "1"
|
|
280
|
+
* Example #2: Then the XML attribute "lang" on element "/feed" should be equal to "en"
|
|
281
|
+
* Example #3: And the XML attribute "type" on element "//entry" should be equal to "html"
|
|
282
|
+
* Example #4: Then the XML attribute "version" on element "/rss" should be equal to "2.0"
|
|
283
|
+
* Example #5: Then the XML attribute "code" on element "/error" should be equal to "404"
|
|
284
|
+
*
|
|
285
|
+
*/
|
|
286
|
+
Then('the XML attribute {string} on element {string} should be equal to {string}', async function (attr, xpath, text) {
|
|
287
|
+
const doc = ensureXml(this);
|
|
288
|
+
const nodes = evalXPath(doc, xpath);
|
|
289
|
+
assert.ok(nodes && nodes.length > 0, `XML element "${xpath}" not found.`);
|
|
290
|
+
assert.strictEqual(nodes[0].getAttribute(attr), text);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Assert an XML attribute is NOT equal to an expected value.
|
|
295
|
+
*
|
|
296
|
+
* Example #1: Then the XML attribute "id" on element "/root/item" should not be equal to "0"
|
|
297
|
+
* Example #2: Then the XML attribute "lang" on element "/feed" should not be equal to "xx"
|
|
298
|
+
* Example #3: And the XML attribute "type" on element "//entry" should not be equal to "binary"
|
|
299
|
+
* Example #4: Then the XML attribute "version" on element "/rss" should not be equal to "0.9"
|
|
300
|
+
* Example #5: Then the XML attribute "code" on element "/error" should not be equal to "200"
|
|
301
|
+
*
|
|
302
|
+
*/
|
|
303
|
+
Then('the XML attribute {string} on element {string} should not be equal to {string}', async function (attr, xpath, text) {
|
|
304
|
+
const doc = ensureXml(this);
|
|
305
|
+
const nodes = evalXPath(doc, xpath);
|
|
306
|
+
if (!nodes || nodes.length === 0) return;
|
|
307
|
+
assert.notStrictEqual(nodes[0].getAttribute(attr), text);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Assert an XML attribute contains a substring.
|
|
312
|
+
*
|
|
313
|
+
* Example #1: Then the XML attribute "id" on element "/root/item" should contain "abc"
|
|
314
|
+
* Example #2: Then the XML attribute "href" on element "//link" should contain "example.com"
|
|
315
|
+
* Example #3: And the XML attribute "type" on element "//entry" should contain "html"
|
|
316
|
+
* Example #4: Then the XML attribute "version" on element "/rss" should contain "2"
|
|
317
|
+
* Example #5: Then the XML attribute "code" on element "/error" should contain "4"
|
|
318
|
+
*
|
|
319
|
+
*/
|
|
320
|
+
Then('the XML attribute {string} on element {string} should contain {string}', async function (attr, xpath, text) {
|
|
321
|
+
const doc = ensureXml(this);
|
|
322
|
+
const nodes = evalXPath(doc, xpath);
|
|
323
|
+
assert.ok(nodes && nodes.length > 0, `XML element "${xpath}" not found.`);
|
|
324
|
+
assert.ok((nodes[0].getAttribute(attr) || '').indexOf(text) !== -1);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Assert an XML attribute does NOT contain a substring.
|
|
329
|
+
*
|
|
330
|
+
* Example #1: Then the XML attribute "id" on element "/root/item" should not contain "old"
|
|
331
|
+
* Example #2: Then the XML attribute "href" on element "//link" should not contain "tracking"
|
|
332
|
+
* Example #3: And the XML attribute "type" on element "//entry" should not contain "binary"
|
|
333
|
+
* Example #4: Then the XML attribute "version" on element "/rss" should not contain "alpha"
|
|
334
|
+
* Example #5: Then the XML attribute "code" on element "/error" should not contain "5"
|
|
335
|
+
*
|
|
336
|
+
*/
|
|
337
|
+
Then('the XML attribute {string} on element {string} should not contain {string}', async function (attr, xpath, text) {
|
|
338
|
+
const doc = ensureXml(this);
|
|
339
|
+
const nodes = evalXPath(doc, xpath);
|
|
340
|
+
if (!nodes || nodes.length === 0) return;
|
|
341
|
+
assert.ok((nodes[0].getAttribute(attr) || '').indexOf(text) === -1);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Assert exactly N elements match an XPath.
|
|
346
|
+
*
|
|
347
|
+
* Example #1: Then the XML element "//entry" should have 5 elements
|
|
348
|
+
* Example #2: Then the XML element "/root/item" should have 1 element
|
|
349
|
+
* Example #3: And the XML element "//error" should have 0 elements
|
|
350
|
+
* Example #4: Then the XML element "/feed/entry" should have 10 elements
|
|
351
|
+
* Example #5: Then the XML element "/orders/order" should have 3 elements
|
|
352
|
+
*
|
|
353
|
+
*/
|
|
354
|
+
Then('the XML element {string} should have {int} element(s)', async function (xpath, count) {
|
|
355
|
+
const doc = ensureXml(this);
|
|
356
|
+
const nodes = evalXPath(doc, xpath);
|
|
357
|
+
assert.strictEqual((nodes || []).length, count);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Assert the XML root declares an `xmlns:*` namespace URI.
|
|
362
|
+
*
|
|
363
|
+
* Example #1: Then the XML should use the namespace "http://www.w3.org/2005/Atom"
|
|
364
|
+
* Example #2: Then the XML should use the namespace "http://www.sitemaps.org/schemas/sitemap/0.9"
|
|
365
|
+
* Example #3: And the XML should use the namespace "http://schemas.xmlsoap.org/soap/envelope/"
|
|
366
|
+
* Example #4: Then the XML should use the namespace "http://www.w3.org/1999/xhtml"
|
|
367
|
+
* Example #5: Then the XML should use the namespace "http://www.opengis.net/gml"
|
|
368
|
+
*
|
|
369
|
+
*/
|
|
370
|
+
Then('the XML should use the namespace {string}', async function (ns) {
|
|
371
|
+
const doc = ensureXml(this);
|
|
372
|
+
const root = doc.documentElement;
|
|
373
|
+
const found = Array.from(root.attributes || []).some((a) => a.value === ns);
|
|
374
|
+
assert.ok(found, `Namespace "${ns}" not declared.`);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Assert the XML root does NOT declare a namespace URI.
|
|
379
|
+
*
|
|
380
|
+
* Example #1: Then the XML should not use the namespace "http://example.com/legacy"
|
|
381
|
+
* Example #2: Then the XML should not use the namespace "http://example.com/internal"
|
|
382
|
+
* Example #3: And the XML should not use the namespace "http://example.com/v1"
|
|
383
|
+
* Example #4: Then the XML should not use the namespace "http://example.com/deprecated"
|
|
384
|
+
* Example #5: Then the XML should not use the namespace "http://example.com/private"
|
|
385
|
+
*
|
|
386
|
+
*/
|
|
387
|
+
Then('the XML should not use the namespace {string}', async function (ns) {
|
|
388
|
+
const doc = ensureXml(this);
|
|
389
|
+
const root = doc.documentElement;
|
|
390
|
+
const found = Array.from(root.attributes || []).some((a) => a.value === ns);
|
|
391
|
+
assert.ok(!found, `Namespace "${ns}" should not be declared.`);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Print the most recently set raw XML response to stdout (debug aid).
|
|
396
|
+
*
|
|
397
|
+
* Example #1: When I print last XML response
|
|
398
|
+
* Example #2: When I send a REST "GET" request to "/api/feed"
|
|
399
|
+
* And I print last XML response
|
|
400
|
+
* Example #3: And I print last XML response
|
|
401
|
+
* Example #4: Given the response content is the following:
|
|
402
|
+
* """
|
|
403
|
+
* <root/>
|
|
404
|
+
* """
|
|
405
|
+
* When I print last XML response
|
|
406
|
+
* Example #5: When I print last XML response
|
|
407
|
+
*
|
|
408
|
+
*/
|
|
409
|
+
When(/^(I |we )*print last XML response$/, async function () {
|
|
410
|
+
console.log(this._rawResponse || '(no response)');
|
|
411
|
+
});
|