@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,149 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset='utf-8'>
|
|
5
|
+
<title>Scrolling Functionality Test</title>
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
margin: 0;
|
|
9
|
+
padding: 20px;
|
|
10
|
+
font-family: Arial, sans-serif;
|
|
11
|
+
}
|
|
12
|
+
.indicator {
|
|
13
|
+
display: none;
|
|
14
|
+
font-size: 22px;
|
|
15
|
+
font-weight: bold;
|
|
16
|
+
color: #007bff;
|
|
17
|
+
padding: 12px 20px;
|
|
18
|
+
margin: 10px 0;
|
|
19
|
+
border: 2px solid #007bff;
|
|
20
|
+
background-color: #e7f3ff;
|
|
21
|
+
border-radius: 4px;
|
|
22
|
+
}
|
|
23
|
+
.content-block {
|
|
24
|
+
height: 300px;
|
|
25
|
+
background: #f0f4f8;
|
|
26
|
+
border: 1px solid #ccc;
|
|
27
|
+
margin: 10px 0;
|
|
28
|
+
padding: 20px;
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
font-size: 18px;
|
|
33
|
+
color: #555;
|
|
34
|
+
}
|
|
35
|
+
#scrollable-container {
|
|
36
|
+
width: 100%;
|
|
37
|
+
height: 150px;
|
|
38
|
+
overflow-y: scroll;
|
|
39
|
+
border: 2px solid #333;
|
|
40
|
+
margin: 20px 0;
|
|
41
|
+
padding: 10px;
|
|
42
|
+
background-color: #f9f9f9;
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
}
|
|
45
|
+
.scrollable-inner {
|
|
46
|
+
height: 500px;
|
|
47
|
+
background: linear-gradient(to bottom, #ff9999, #99ff99, #9999ff);
|
|
48
|
+
padding: 10px;
|
|
49
|
+
}
|
|
50
|
+
#element-scroll-top { display: none; font-size: 18px; font-weight: bold; padding: 8px; }
|
|
51
|
+
#element-scroll-bottom { display: none; font-size: 18px; font-weight: bold; padding: 8px; }
|
|
52
|
+
</style>
|
|
53
|
+
</head>
|
|
54
|
+
<body>
|
|
55
|
+
<h1>Scrolling Functionality Test Page</h1>
|
|
56
|
+
|
|
57
|
+
<div id="basic-scroll-down" class="indicator">Basic scroll down works</div>
|
|
58
|
+
<div id="basic-scroll-up" class="indicator">Basic scroll up works</div>
|
|
59
|
+
<div id="custom-scroll-down" class="indicator">Custom scroll down works</div>
|
|
60
|
+
<div id="custom-scroll-up" class="indicator">Custom scroll up works</div>
|
|
61
|
+
<div id="scroll-to-top" class="indicator">Scroll to top works</div>
|
|
62
|
+
<div id="scroll-to-bottom" class="indicator">Scroll to bottom works</div>
|
|
63
|
+
|
|
64
|
+
<div class="content-block">Section 1 - Scroll down to see more</div>
|
|
65
|
+
<div class="content-block">Section 2</div>
|
|
66
|
+
<div class="content-block">Section 3</div>
|
|
67
|
+
<div class="content-block">Section 4</div>
|
|
68
|
+
<div class="content-block">Section 5</div>
|
|
69
|
+
<div class="content-block">Section 6</div>
|
|
70
|
+
<div class="content-block">Section 7</div>
|
|
71
|
+
<div class="content-block">Section 8</div>
|
|
72
|
+
<div class="content-block">Section 9</div>
|
|
73
|
+
<div class="content-block">Section 10 - Near the bottom</div>
|
|
74
|
+
|
|
75
|
+
<h2>Scrollable Element Container</h2>
|
|
76
|
+
<div id="scrollable-container">
|
|
77
|
+
<div class="scrollable-inner">
|
|
78
|
+
<div id="element-scroll-top">Element scroll to top works</div>
|
|
79
|
+
<p>Scrollable content - scroll this container to see indicators</p>
|
|
80
|
+
<div id="element-scroll-bottom">Element scroll to bottom works</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div class="content-block">End of page content</div>
|
|
85
|
+
|
|
86
|
+
<script>
|
|
87
|
+
var lastScrollY = 0;
|
|
88
|
+
var wasAtBottom = false;
|
|
89
|
+
var everScrolledDown = false;
|
|
90
|
+
|
|
91
|
+
window.addEventListener('scroll', function () {
|
|
92
|
+
var scrollY = window.scrollY;
|
|
93
|
+
var docHeight = document.documentElement.scrollHeight;
|
|
94
|
+
var winHeight = window.innerHeight;
|
|
95
|
+
var maxScroll = docHeight - winHeight;
|
|
96
|
+
var atBottom = scrollY >= maxScroll - 10;
|
|
97
|
+
var atTop = scrollY <= 0;
|
|
98
|
+
var goingDown = scrollY > lastScrollY;
|
|
99
|
+
|
|
100
|
+
document.getElementById('basic-scroll-down').style.display = 'none';
|
|
101
|
+
document.getElementById('basic-scroll-up').style.display = 'none';
|
|
102
|
+
document.getElementById('custom-scroll-down').style.display = 'none';
|
|
103
|
+
document.getElementById('custom-scroll-up').style.display = 'none';
|
|
104
|
+
document.getElementById('scroll-to-top').style.display = 'none';
|
|
105
|
+
document.getElementById('scroll-to-bottom').style.display = 'none';
|
|
106
|
+
|
|
107
|
+
if (atTop && everScrolledDown) {
|
|
108
|
+
document.getElementById('scroll-to-top').style.display = 'block';
|
|
109
|
+
} else if (atBottom) {
|
|
110
|
+
document.getElementById('scroll-to-bottom').style.display = 'block';
|
|
111
|
+
wasAtBottom = true;
|
|
112
|
+
everScrolledDown = true;
|
|
113
|
+
} else if (wasAtBottom && !goingDown) {
|
|
114
|
+
var distFromBottom = maxScroll - scrollY;
|
|
115
|
+
if (distFromBottom >= 340) {
|
|
116
|
+
document.getElementById('basic-scroll-up').style.display = 'block';
|
|
117
|
+
} else {
|
|
118
|
+
document.getElementById('custom-scroll-up').style.display = 'block';
|
|
119
|
+
}
|
|
120
|
+
} else if (scrollY >= 450) {
|
|
121
|
+
document.getElementById('custom-scroll-down').style.display = 'block';
|
|
122
|
+
} else if (scrollY > 0) {
|
|
123
|
+
document.getElementById('basic-scroll-down').style.display = 'block';
|
|
124
|
+
everScrolledDown = true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
lastScrollY = scrollY;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
var scrollContainer = document.getElementById('scrollable-container');
|
|
131
|
+
var containerWasAtBottom = false;
|
|
132
|
+
|
|
133
|
+
scrollContainer.addEventListener('scroll', function () {
|
|
134
|
+
var scrollTop = this.scrollTop;
|
|
135
|
+
var maxScrollTop = this.scrollHeight - this.clientHeight;
|
|
136
|
+
|
|
137
|
+
document.getElementById('element-scroll-top').style.display = 'none';
|
|
138
|
+
document.getElementById('element-scroll-bottom').style.display = 'none';
|
|
139
|
+
|
|
140
|
+
if (scrollTop >= maxScrollTop - 5) {
|
|
141
|
+
document.getElementById('element-scroll-bottom').style.display = 'block';
|
|
142
|
+
containerWasAtBottom = true;
|
|
143
|
+
} else if (scrollTop <= 0 && containerWasAtBottom) {
|
|
144
|
+
document.getElementById('element-scroll-top').style.display = 'block';
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
</script>
|
|
148
|
+
</body>
|
|
149
|
+
</html>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset='utf-8'>
|
|
5
|
+
<title>Select Option</title>
|
|
6
|
+
<style>
|
|
7
|
+
.style{
|
|
8
|
+
height: 50px;
|
|
9
|
+
font-size: 26px;
|
|
10
|
+
line-height: 50px;
|
|
11
|
+
}
|
|
12
|
+
</style>
|
|
13
|
+
<script>
|
|
14
|
+
function onClick(){
|
|
15
|
+
const cars = document.getElementById("cars");
|
|
16
|
+
const selectedOption = cars.options[cars.selectedIndex].text;
|
|
17
|
+
const element = document.getElementById("result");
|
|
18
|
+
element.innerText = "Option ( " + selectedOption + " ) has been selected successfully";
|
|
19
|
+
}
|
|
20
|
+
</script>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<h1>Select Option</h1>
|
|
24
|
+
<label for="cars">Choose a car:</label>
|
|
25
|
+
|
|
26
|
+
<select name="cars" id="cars">
|
|
27
|
+
<option value="volvo">Volvo</option>
|
|
28
|
+
<option value="saab">Saab</option>
|
|
29
|
+
<option value="mercedes">Mercedes</option>
|
|
30
|
+
<option value="audi">Audi</option>
|
|
31
|
+
</select>
|
|
32
|
+
<input id="btnClick" class="btnClick" name="btnClick" type="button" value="Submit" onclick="onClick()">
|
|
33
|
+
<div id="result" class="style"></div><br/>
|
|
34
|
+
</body>
|
|
35
|
+
</html>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset='utf-8'>
|
|
6
|
+
<title>Select Radio Button</title>
|
|
7
|
+
<style>
|
|
8
|
+
.style {
|
|
9
|
+
height: 50px;
|
|
10
|
+
font-size: 26px;
|
|
11
|
+
line-height: 50px;
|
|
12
|
+
}
|
|
13
|
+
.section {
|
|
14
|
+
margin: 20px 0;
|
|
15
|
+
padding: 15px;
|
|
16
|
+
border: 1px solid #ccc;
|
|
17
|
+
}
|
|
18
|
+
</style>
|
|
19
|
+
<script>
|
|
20
|
+
function onGenderSubmit() {
|
|
21
|
+
var genderForm = document.forms[0];
|
|
22
|
+
var selectedGender = "";
|
|
23
|
+
for (var i = 0; i < genderForm.length; i++) {
|
|
24
|
+
if (genderForm[i].type === 'radio' && genderForm[i].checked) {
|
|
25
|
+
selectedGender = genderForm[i].value;
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const element = document.getElementById("gender-result");
|
|
30
|
+
element.innerText = "Selected: " + selectedGender;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function onPlanSubmit() {
|
|
34
|
+
var planForm = document.forms[2];
|
|
35
|
+
var selectedPlan = "";
|
|
36
|
+
for (var i = 0; i < planForm.length; i++) {
|
|
37
|
+
if (planForm[i].type === 'radio' && planForm[i].checked) {
|
|
38
|
+
selectedPlan = planForm[i].value;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const element = document.getElementById("plan-result");
|
|
43
|
+
element.innerText = "Plan: " + selectedPlan;
|
|
44
|
+
}
|
|
45
|
+
</script>
|
|
46
|
+
</head>
|
|
47
|
+
|
|
48
|
+
<body>
|
|
49
|
+
<h1>Select Radio Button Options</h1>
|
|
50
|
+
|
|
51
|
+
<div class="section">
|
|
52
|
+
<h2>Gender Selection (by Label)</h2>
|
|
53
|
+
<form>
|
|
54
|
+
<input type="radio" id="gender-male" name="gender" value="Male">
|
|
55
|
+
<label for="gender-male">Male</label><br>
|
|
56
|
+
<input type="radio" id="gender-female" name="gender" value="Female">
|
|
57
|
+
<label for="gender-female">Female</label><br>
|
|
58
|
+
<input type="radio" id="gender-other" name="gender" value="Other">
|
|
59
|
+
<label for="gender-other">Other</label><br>
|
|
60
|
+
</form>
|
|
61
|
+
<input type="button" value="Submit" onclick="onGenderSubmit()">
|
|
62
|
+
<div id="gender-result" class="style"></div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="section">
|
|
66
|
+
<h2>Color Selection (by Value)</h2>
|
|
67
|
+
<form>
|
|
68
|
+
<label>
|
|
69
|
+
<input type="radio" name="color" value="red"> Red
|
|
70
|
+
</label><br>
|
|
71
|
+
<label>
|
|
72
|
+
<input type="radio" name="color" value="blue"> Blue
|
|
73
|
+
</label><br>
|
|
74
|
+
<label>
|
|
75
|
+
<input type="radio" name="color" value="green"> Green
|
|
76
|
+
</label><br>
|
|
77
|
+
</form>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div class="section">
|
|
81
|
+
<h2>Plan Selection (by ID Selector)</h2>
|
|
82
|
+
<form>
|
|
83
|
+
<input type="radio" id="plan-basic" name="plan" value="Basic">
|
|
84
|
+
<label for="plan-basic">Basic Plan</label><br>
|
|
85
|
+
<input type="radio" id="plan-premium" name="plan" value="Premium">
|
|
86
|
+
<label for="plan-premium">Premium Plan</label><br>
|
|
87
|
+
<input type="radio" id="plan-enterprise" name="plan" value="Enterprise">
|
|
88
|
+
<label for="plan-enterprise">Enterprise Plan</label><br>
|
|
89
|
+
</form>
|
|
90
|
+
<input type="button" value="Plan Submit" onclick="onPlanSubmit()">
|
|
91
|
+
<div id="plan-result" class="style"></div>
|
|
92
|
+
</div>
|
|
93
|
+
</body>
|
|
94
|
+
|
|
95
|
+
</html>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset='utf-8'>
|
|
6
|
+
<title>I wait time</title>
|
|
7
|
+
<style>
|
|
8
|
+
.container,
|
|
9
|
+
.container input,
|
|
10
|
+
.container button {
|
|
11
|
+
font-size: 26px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.style {
|
|
15
|
+
font-size: 22px;
|
|
16
|
+
line-height: 50px;
|
|
17
|
+
}
|
|
18
|
+
</style>
|
|
19
|
+
|
|
20
|
+
</head>
|
|
21
|
+
|
|
22
|
+
<body>
|
|
23
|
+
<h1>Waiting Max number of Time</h1>
|
|
24
|
+
|
|
25
|
+
<div class="container">
|
|
26
|
+
<b><div id="result" class="style">Waiting . . .</div></b>
|
|
27
|
+
</div>
|
|
28
|
+
</body>
|
|
29
|
+
|
|
30
|
+
<script>
|
|
31
|
+
const element = document.getElementById("result");
|
|
32
|
+
const timeWate = 3;
|
|
33
|
+
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
element.innerText = 'Welcome with waiting until page load';
|
|
36
|
+
}, timeWate * 1000);
|
|
37
|
+
|
|
38
|
+
</script>
|
|
39
|
+
</html>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset='utf-8'>
|
|
6
|
+
<title>I wait page until is loaded</title>
|
|
7
|
+
<style>
|
|
8
|
+
.container,
|
|
9
|
+
.container input,
|
|
10
|
+
.container button {
|
|
11
|
+
font-size: 26px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.style {
|
|
15
|
+
font-size: 22px;
|
|
16
|
+
line-height: 30px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#complete{
|
|
20
|
+
font-size: 32px;
|
|
21
|
+
line-height: 30px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
</style>
|
|
25
|
+
|
|
26
|
+
</head>
|
|
27
|
+
|
|
28
|
+
<body>
|
|
29
|
+
<h1>Waiting for the page to load</h1>
|
|
30
|
+
<div id="complete">
|
|
31
|
+
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div id="container">
|
|
35
|
+
|
|
36
|
+
</div>
|
|
37
|
+
</body>
|
|
38
|
+
|
|
39
|
+
<script>
|
|
40
|
+
|
|
41
|
+
for(var i=0; i<2000; i++){
|
|
42
|
+
document.getElementById("container").innerHTML += '<p class="style">' + i + '</p>';
|
|
43
|
+
}
|
|
44
|
+
document.getElementById("complete").innerHTML += "The waiting process was completed successfully.";
|
|
45
|
+
|
|
46
|
+
</script>
|
|
47
|
+
</html>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset='utf-8'>
|
|
6
|
+
<title>I wait time</title>
|
|
7
|
+
<style>
|
|
8
|
+
.container,
|
|
9
|
+
.container input,
|
|
10
|
+
.container button {
|
|
11
|
+
font-size: 26px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.style {
|
|
15
|
+
font-size: 22px;
|
|
16
|
+
line-height: 50px;
|
|
17
|
+
}
|
|
18
|
+
</style>
|
|
19
|
+
|
|
20
|
+
</head>
|
|
21
|
+
|
|
22
|
+
<body>
|
|
23
|
+
<h1>Waiting a Specific number of Time</h1>
|
|
24
|
+
|
|
25
|
+
<div class="container">
|
|
26
|
+
<b><div id="result" class="style">Waiting . . .</div></b>
|
|
27
|
+
</div>
|
|
28
|
+
</body>
|
|
29
|
+
|
|
30
|
+
<script>
|
|
31
|
+
const element = document.getElementById("result");
|
|
32
|
+
const timeWate = 3;
|
|
33
|
+
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
element.innerText = 'Welcome with waiting full time';
|
|
36
|
+
}, timeWate * 1000);
|
|
37
|
+
|
|
38
|
+
</script>
|
|
39
|
+
</html>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset='utf-8'>
|
|
5
|
+
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
|
6
|
+
<title>Test Acceptable URL Path</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
Example for test acceptable URL path that have "-" between words.
|
|
10
|
+
</body>
|
|
11
|
+
</html>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>🎬 Video Demo</title>
|
|
6
|
+
<style>
|
|
7
|
+
body { font-family: system-ui, sans-serif; max-width: 720px; margin: 2rem auto; padding: 1rem; background: linear-gradient(180deg, #fdf6e3 0%, #eee8d5 100%); color: #073642; }
|
|
8
|
+
h1 { font-size: 2rem; }
|
|
9
|
+
main { background: #fff; border-radius: 12px; padding: 2rem; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
|
|
10
|
+
button { font-size: 1.1rem; padding: 0.6rem 1.2rem; background: #268bd2; color: #fff; border: 0; border-radius: 8px; cursor: pointer; margin-right: 0.5rem; }
|
|
11
|
+
button:hover { background: #2aa198; }
|
|
12
|
+
.status { font-size: 1.4rem; padding: 1rem; margin-top: 1rem; border-radius: 8px; background: #fdf6e3; min-height: 2rem; }
|
|
13
|
+
.smile { font-size: 3rem; }
|
|
14
|
+
</style>
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<h1>🎬 Varbase E2E Video Demo</h1>
|
|
18
|
+
<main role="main">
|
|
19
|
+
<p>Click a button below — the recording captures the page state change.</p>
|
|
20
|
+
<button id="wave">👋 Wave</button>
|
|
21
|
+
<button id="rocket">🚀 Launch</button>
|
|
22
|
+
<button id="party">🎉 Celebrate</button>
|
|
23
|
+
<div class="status" id="status">Ready to record ⏺️</div>
|
|
24
|
+
<div class="smile" id="smile"></div>
|
|
25
|
+
</main>
|
|
26
|
+
<script>
|
|
27
|
+
const status = document.getElementById('status');
|
|
28
|
+
const smile = document.getElementById('smile');
|
|
29
|
+
document.getElementById('wave').addEventListener('click', () => {
|
|
30
|
+
status.textContent = 'Hello, world 👋';
|
|
31
|
+
smile.textContent = '😀';
|
|
32
|
+
});
|
|
33
|
+
document.getElementById('rocket').addEventListener('click', () => {
|
|
34
|
+
status.textContent = 'Liftoff! 🚀';
|
|
35
|
+
smile.textContent = '🌕';
|
|
36
|
+
});
|
|
37
|
+
document.getElementById('party').addEventListener('click', () => {
|
|
38
|
+
status.textContent = 'Party time 🎉';
|
|
39
|
+
smile.textContent = '🥳';
|
|
40
|
+
});
|
|
41
|
+
</script>
|
|
42
|
+
</body>
|
|
43
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vardot/varbase-e2e",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Varbase E2E automated functional testing.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"init-varbase-e2e": "./bin/init-varbase-e2e.js",
|
|
8
|
+
"generate-reports": "./bin/generate-reports.js"
|
|
9
|
+
},
|
|
10
|
+
"directories": {
|
|
11
|
+
"test": "test"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">= 20.0"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"postinstall": "node ./bin/postinstall.js",
|
|
18
|
+
"test": "cucumber-js --config cucumber.js",
|
|
19
|
+
"test:chromium": "BROWSER=chromium cucumber-js --config cucumber.js",
|
|
20
|
+
"test:firefox": "BROWSER=firefox cucumber-js --config cucumber.js",
|
|
21
|
+
"test:webkit": "BROWSER=webkit cucumber-js --config cucumber.js",
|
|
22
|
+
"test:headed": "HEADLESS=false cucumber-js --config cucumber.js",
|
|
23
|
+
"test:fast": "SLOW_MO=0 cucumber-js --config cucumber.js",
|
|
24
|
+
"generate-reports": "node ./bin/generate-reports.js",
|
|
25
|
+
"start": "http-server examples -p 8080 -s"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/Vardot/varbase-e2e.git"
|
|
30
|
+
},
|
|
31
|
+
"author": "Vardot",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/Vardot/varbase-e2e/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/Vardot/varbase-e2e",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@axe-core/playwright": "^4.11.3",
|
|
42
|
+
"@cucumber/cucumber": "*",
|
|
43
|
+
"@cucumber/pretty-formatter": "~1",
|
|
44
|
+
"@types/node": "~20",
|
|
45
|
+
"ajv": "^8.20.0",
|
|
46
|
+
"ajv-formats": "^3.0.1",
|
|
47
|
+
"axe-core": "^4.11.4",
|
|
48
|
+
"axios": "~1",
|
|
49
|
+
"cucumber-html-reporter": "^6.0.0",
|
|
50
|
+
"http-server": "^14.1.1",
|
|
51
|
+
"js-yaml": "^4.1.1",
|
|
52
|
+
"playwright": "^1.58.2",
|
|
53
|
+
"tsx": "^4.19.2",
|
|
54
|
+
"typescript": "~5"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { LaunchOptions, BrowserContextOptions } from 'playwright';
|
|
2
|
+
|
|
3
|
+
type BrowserName = 'chromium' | 'firefox' | 'webkit';
|
|
4
|
+
|
|
5
|
+
const browser = (process.env.BROWSER || 'chromium') as BrowserName;
|
|
6
|
+
|
|
7
|
+
const chromiumArgs: string[] = [
|
|
8
|
+
'--no-sandbox',
|
|
9
|
+
'--disable-dev-shm-usage',
|
|
10
|
+
'--disable-setuid-sandbox',
|
|
11
|
+
'--disable-web-security',
|
|
12
|
+
'--ignore-certificate-errors',
|
|
13
|
+
'--disable-extensions',
|
|
14
|
+
'--incognito',
|
|
15
|
+
'--disable-infobars',
|
|
16
|
+
'--start-maximized',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
interface PlaywrightConfig {
|
|
20
|
+
browser: BrowserName;
|
|
21
|
+
launchOptions: LaunchOptions;
|
|
22
|
+
contextOptions: BrowserContextOptions;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const config: PlaywrightConfig = {
|
|
26
|
+
browser,
|
|
27
|
+
launchOptions: {
|
|
28
|
+
headless: process.env.HEADLESS !== 'false',
|
|
29
|
+
// SLOW_MO env var: 0 in CI for speed, 800ms when watching headed runs.
|
|
30
|
+
slowMo: parseInt(process.env.SLOW_MO || (process.env.HEADLESS === 'false' ? '800' : '300'), 10),
|
|
31
|
+
args: browser === 'chromium' ? chromiumArgs : [],
|
|
32
|
+
},
|
|
33
|
+
contextOptions: {
|
|
34
|
+
viewport: null,
|
|
35
|
+
ignoreHTTPSErrors: true,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export = config;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
%PDF-1.4
|
|
2
|
+
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
|
|
3
|
+
2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj
|
|
4
|
+
3 0 obj<</Type/Page/MediaBox[0 0 612 792]/Parent 2 0 R>>endobj
|
|
5
|
+
xref
|
|
6
|
+
0 4
|
|
7
|
+
0000000000 65535 f
|
|
8
|
+
0000000009 00000 n
|
|
9
|
+
0000000058 00000 n
|
|
10
|
+
0000000115 00000 n
|
|
11
|
+
trailer<</Size 4/Root 1 0 R>>
|
|
12
|
+
startxref
|
|
13
|
+
190
|
|
14
|
+
%%EOF
|
|
Binary file
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
Feature: Accessibility (a11y) smoke checks
|
|
2
|
+
|
|
3
|
+
Scenario: Page-level landmarks and language
|
|
4
|
+
Given I am on "/a11y.html"
|
|
5
|
+
Then the page should declare a language
|
|
6
|
+
And the page language should be "en"
|
|
7
|
+
And the page should have a main landmark
|
|
8
|
+
And the page should have a navigation landmark
|
|
9
|
+
And the page should have exactly one h1
|
|
10
|
+
|
|
11
|
+
Scenario: Image alt text and form labels
|
|
12
|
+
Given I am on "/a11y.html"
|
|
13
|
+
Then every image should have an alt attribute
|
|
14
|
+
And every form field should have an accessible label
|
|
15
|
+
|
|
16
|
+
Scenario: Focused element assertions
|
|
17
|
+
Given I am on "/a11y.html"
|
|
18
|
+
When I focus on the element "#email"
|
|
19
|
+
Then the focused element should match "#email"
|
|
20
|
+
And the focused element should be labeled "Email"
|
|
21
|
+
|
|
22
|
+
Scenario: WCAG hygiene checks (custom probes)
|
|
23
|
+
Given I am on "/a11y.html"
|
|
24
|
+
Then the page should have a title
|
|
25
|
+
And user zoom should be allowed
|
|
26
|
+
And the heading hierarchy should be valid
|
|
27
|
+
And every button should have an accessible name
|
|
28
|
+
And every link should have an accessible name
|
|
29
|
+
And no element should have a positive tabindex
|
|
30
|
+
And every ARIA reference should resolve
|
|
31
|
+
And every ARIA role should be valid
|
|
32
|
+
And required fields should be consistently marked
|
|
33
|
+
|
|
34
|
+
Scenario: axe-core full WCAG audit
|
|
35
|
+
Given I am on "/a11y.html"
|
|
36
|
+
Then the page should have no critical accessibility violations
|
|
37
|
+
And the page should not violate the accessibility rule "image-alt"
|
|
38
|
+
And the page should not violate the accessibility rule "label"
|
|
39
|
+
And the page should pass the accessibility rules "image-alt, label, button-name"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Feature: AJAX Wait Examples
|
|
2
|
+
As a tester
|
|
3
|
+
I want to wait for AJAX requests to complete
|
|
4
|
+
So that I can verify content that loads asynchronously
|
|
5
|
+
|
|
6
|
+
Background:
|
|
7
|
+
Given I am on "/ajax-wait-examples.html"
|
|
8
|
+
|
|
9
|
+
# Example 1: Wait for AJAX to finish before verifying content
|
|
10
|
+
Scenario: Wait for AJAX to finish after search
|
|
11
|
+
When I fill in "laptop" for "#search-input" by attr
|
|
12
|
+
And I press "Search" button
|
|
13
|
+
And I wait for AJAX to finish
|
|
14
|
+
Then I should see "Search Results"
|
|
15
|
+
And I should see "Laptop Pro 15"
|
|
16
|
+
|
|
17
|
+
# Example 2: Wait for AJAX to finish after form submission
|
|
18
|
+
Scenario: Wait for AJAX to finish after submitting form
|
|
19
|
+
When I fill in "John Doe" for "#name-input" by attr
|
|
20
|
+
And I fill in "john@example.com" for "#email-input" by attr
|
|
21
|
+
And I press "Submit" button
|
|
22
|
+
And I wait for AJAX to finish
|
|
23
|
+
Then I should see "Form submitted successfully"
|
|
24
|
+
And I should see "Thank you, John Doe"
|