artes 1.5.11 → 1.6.1
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/README.md +2 -2
- package/docs/stepDefinitions.md +25 -0
- package/package.json +2 -1
- package/src/helper/controller/reportUploader.js +1 -1
- package/src/helper/controller/validateWCAGTags .js +52 -0
- package/src/helper/stepFunctions/browserActions.js +66 -1
- package/src/stepDefinitions/browser.steps.js +68 -1
package/README.md
CHANGED
|
@@ -627,7 +627,7 @@ Artes supports environment-specific configurations through environment variables
|
|
|
627
627
|
|
|
628
628
|
Artes can generate Allure reports. After running tests with the `-r` flag, the reports will be stored in the `report` folder in HTML format. You can view them in your browser after the tests complete.
|
|
629
629
|
|
|
630
|
-
|
|
630
|
+
### Integration with Artes Reporting System
|
|
631
631
|
|
|
632
632
|
Artes has a built-in integration with the Artes Reporting System. By configuring the options below, you can automatically upload your test reports and keep your pipeline stages clean and organized.
|
|
633
633
|
|
|
@@ -656,7 +656,7 @@ To achieve the best video recording quality, use the following command:
|
|
|
656
656
|
xvfb-run -a --server-args="-screen 0 3840x1180x24" --auto-servernum npx artes --width 1600 --height 900
|
|
657
657
|
```
|
|
658
658
|
|
|
659
|
-
###
|
|
659
|
+
### CI/CD Executor on Report
|
|
660
660
|
|
|
661
661
|
Artes automatically detects your CI/CD environment and displays executor information — pipeline name, build number, and a direct link to the build — on the generated report.
|
|
662
662
|
|
package/docs/stepDefinitions.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- [Mouse Actions](#mouse-actions)
|
|
6
6
|
- [Keyboard Actions](#keyboard-actions)
|
|
7
|
+
- [Browser Actions](#browser-actions)
|
|
7
8
|
- [Page Actions](#page-actions)
|
|
8
9
|
- [Frame Actions](#frame-actions)
|
|
9
10
|
- [API Actions](#api-actions)
|
|
@@ -107,6 +108,30 @@
|
|
|
107
108
|
- User releases `{string}`
|
|
108
109
|
- User presses `{string}`
|
|
109
110
|
|
|
111
|
+
# Browser Actions
|
|
112
|
+
|
|
113
|
+
## Cookie Actions
|
|
114
|
+
|
|
115
|
+
- User sets `{string}` cookies
|
|
116
|
+
|
|
117
|
+
## Accessibility Actions
|
|
118
|
+
|
|
119
|
+
### Full Page Checks
|
|
120
|
+
- User checks accessibility of current page
|
|
121
|
+
- User checks accessibility of `{string}` page
|
|
122
|
+
|
|
123
|
+
### Element Checks
|
|
124
|
+
- User checks accessibility of `{string}` element
|
|
125
|
+
- User checks accessibility of `{string}` element on the `{string}` page
|
|
126
|
+
|
|
127
|
+
### WCAG-Specific Checks
|
|
128
|
+
> For valid WCAG tags, refer to the [axe-core Tags Documentation](https://www.deque.com/axe/core-documentation/api-documentation/#axecore-tags)
|
|
129
|
+
|
|
130
|
+
- User checks accessibility of current page due to `{string}` WCAG
|
|
131
|
+
- User checks accessibility of `{string}` page due to `{string}` WCAG
|
|
132
|
+
- User checks accessibility of `{string}` element due to `{string}` WCAG
|
|
133
|
+
- User checks accessibility of `{string}` element on the `{string}` page due to `{string}` WCAG
|
|
134
|
+
|
|
110
135
|
---
|
|
111
136
|
|
|
112
137
|
# Page Actions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "artes",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "The simplest way to automate UI and API tests using Cucumber-style steps.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"dayjs": "1.11.13",
|
|
30
30
|
"deasync": "^0.1.31",
|
|
31
31
|
"playwright": "^1.58.2",
|
|
32
|
+
"@axe-core/playwright": "^4.11.1",
|
|
32
33
|
"ffmpeg-static": "^5.3.0",
|
|
33
34
|
"ffprobe-static": "^3.1.0",
|
|
34
35
|
"pixelmatch": "^5.3.0",
|
|
@@ -17,7 +17,7 @@ async function uploadReport({
|
|
|
17
17
|
formData.append("project", projectName);
|
|
18
18
|
formData.append("type", projectType);
|
|
19
19
|
|
|
20
|
-
const response = await fetch(
|
|
20
|
+
const response = await fetch(reporterURL, {
|
|
21
21
|
method: "POST",
|
|
22
22
|
body: formData,
|
|
23
23
|
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const EXACT_TAGS = new Set([
|
|
2
|
+
'wcag2a', 'wcag2aa', 'wcag2aaa',
|
|
3
|
+
'wcag21a', 'wcag21aa',
|
|
4
|
+
'wcag22aa',
|
|
5
|
+
'best-practice',
|
|
6
|
+
'wcag2a-obsolete',
|
|
7
|
+
'ACT',
|
|
8
|
+
'section508',
|
|
9
|
+
'TTv5',
|
|
10
|
+
'EN-301-549',
|
|
11
|
+
'RGAAv4',
|
|
12
|
+
'experimental'
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
const PATTERN_TAGS = [
|
|
16
|
+
/^wcag\d{3,}$/,
|
|
17
|
+
/^section508\.\d+\.\d+$/,
|
|
18
|
+
/^TT\d+\.\d+$/,
|
|
19
|
+
/^EN-9\.\d+(\.\d+)*$/,
|
|
20
|
+
/^RGAA-\d+\.\d+\.\d+$/,
|
|
21
|
+
/^cat\..+$/
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const isValidTag = (tag) => {
|
|
25
|
+
if (EXACT_TAGS.has(tag)) return true;
|
|
26
|
+
return PATTERN_TAGS.some(pattern => pattern.test(tag));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const validateWCAGTags = (tags) => {
|
|
30
|
+
const normalized = tags.split(",").map(tag => tag.trim());
|
|
31
|
+
|
|
32
|
+
if (normalized.length === 0) {
|
|
33
|
+
throw new Error('At least one WCAG tag must be provided.');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const invalid = normalized.filter(tag => !isValidTag(tag));
|
|
37
|
+
|
|
38
|
+
if (invalid.length > 0) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Invalid WCAG tag(s): "${invalid.join('", "')}"\n` +
|
|
41
|
+
`Valid tags: wcag2a, wcag2aa, wcag2aaa, wcag21a, wcag21aa, wcag22aa, ` +
|
|
42
|
+
`best-practice, wcag2a-obsolete, wcag111 (SC pattern), ACT, section508, ` +
|
|
43
|
+
`section508.x.x, TTv5, TT*.*, EN-301-549, EN-9.*, RGAAv4, RGAA-*.*.*, ` +
|
|
44
|
+
`experimental, cat.* `+
|
|
45
|
+
`For more information: https://www.deque.com/axe/core-documentation/api-documentation/#axecore-tags`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return normalized;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
module.exports = { validateWCAGTags };
|
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { page: p } = require("artes/src/helper/stepFunctions/pageActions");
|
|
2
|
+
const {
|
|
3
|
+
context,
|
|
4
|
+
resolveVariable,
|
|
5
|
+
expect,
|
|
6
|
+
selector,
|
|
7
|
+
} = require("../imports/commons");
|
|
8
|
+
const { AxeBuilder } = require("@axe-core/playwright");
|
|
9
|
+
const {
|
|
10
|
+
validateWCAGTags,
|
|
11
|
+
} = require("artes/src/helper/controller/validateWCAGTags ");
|
|
12
|
+
require("allure-cucumberjs");
|
|
13
|
+
const allure = require("allure-js-commons");
|
|
2
14
|
|
|
3
15
|
const browser = {
|
|
4
16
|
setCookies: async (cookies) => {
|
|
@@ -15,6 +27,59 @@ const browser = {
|
|
|
15
27
|
|
|
16
28
|
await context.browserContext.addCookies(cookieData);
|
|
17
29
|
},
|
|
30
|
+
checkAccessibilityOfPage: async (page, url, element) => {
|
|
31
|
+
if (url) {
|
|
32
|
+
await p.navigateTo(url);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (element) {
|
|
36
|
+
element = await selector(element);
|
|
37
|
+
await page.locator(element).waitFor();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const accessibilityScanResults = await new AxeBuilder({ page })
|
|
41
|
+
.include(element)
|
|
42
|
+
.analyze();
|
|
43
|
+
await allure.attachment(
|
|
44
|
+
"Accessibility Results",
|
|
45
|
+
JSON.stringify(accessibilityScanResults, null, 2),
|
|
46
|
+
"application/json",
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
expect(accessibilityScanResults.violations).toEqual([]);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
e.name = "AssertionError";
|
|
53
|
+
throw e;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
checkAccessibilityOfPageDueToWCAG: async (page, url, element, tags) => {
|
|
57
|
+
if (url) {
|
|
58
|
+
await p.navigateTo(url);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (element) {
|
|
62
|
+
element = await selector(element);
|
|
63
|
+
await page.locator(element).waitFor();
|
|
64
|
+
}
|
|
65
|
+
if (tags) {
|
|
66
|
+
tags = validateWCAGTags(tags);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
expect(accessibilityScanResults.violations).toEqual([]);
|
|
70
|
+
await allure.attachment(
|
|
71
|
+
"Accessibility Results",
|
|
72
|
+
JSON.stringify(accessibilityScanResults, null, 2),
|
|
73
|
+
"application/json",
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
expect(accessibilityScanResults.violations).toEqual([]);
|
|
78
|
+
} catch (e) {
|
|
79
|
+
e.name = "AssertionError";
|
|
80
|
+
throw e;
|
|
81
|
+
}
|
|
82
|
+
},
|
|
18
83
|
};
|
|
19
84
|
|
|
20
85
|
module.exports = {
|
|
@@ -1,7 +1,74 @@
|
|
|
1
|
-
const { When } = require("../helper/imports/commons");
|
|
1
|
+
const { When, context } = require("../helper/imports/commons");
|
|
2
2
|
const { browser } = require("../helper/stepFunctions/exporter");
|
|
3
3
|
|
|
4
4
|
// User sets cookies in json format
|
|
5
5
|
When("User sets {string} cookies", async function (cookies) {
|
|
6
6
|
await browser.setCookies(cookies);
|
|
7
7
|
});
|
|
8
|
+
|
|
9
|
+
When("User checks accessibility of current page", async function () {
|
|
10
|
+
await browser.checkAccessibilityOfPage(context.page, null, null);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
When("User checks accessibility of {string} page", async function (url) {
|
|
14
|
+
await browser.checkAccessibilityOfPage(context.page, url, null);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
When("User checks accessibility of {string} element", async function (element) {
|
|
18
|
+
await browser.checkAccessibilityOfPage(context.page, null, element);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
When(
|
|
22
|
+
"User checks accessibility of {string} element on the {string} page",
|
|
23
|
+
async function (element, url) {
|
|
24
|
+
await browser.checkAccessibilityOfPage(context.page, url, element);
|
|
25
|
+
},
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
When(
|
|
29
|
+
"User checks accessibility of current page due to {string} WCAG",
|
|
30
|
+
async function (wcag) {
|
|
31
|
+
await browser.checkAccessibilityOfPageDueToWCAG(
|
|
32
|
+
context.page,
|
|
33
|
+
null,
|
|
34
|
+
null,
|
|
35
|
+
wcag,
|
|
36
|
+
);
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
When(
|
|
41
|
+
"User checks accessibility of {string} page due to {string} WCAG",
|
|
42
|
+
async function (url, wcag) {
|
|
43
|
+
await browser.checkAccessibilityOfPageDueToWCAG(
|
|
44
|
+
context.page,
|
|
45
|
+
url,
|
|
46
|
+
null,
|
|
47
|
+
wcag,
|
|
48
|
+
);
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
When(
|
|
53
|
+
"User checks accessibility of {string} element due to {string} WCAG",
|
|
54
|
+
async function (element, wcag) {
|
|
55
|
+
await browser.checkAccessibilityOfPageDueToWCAG(
|
|
56
|
+
context.page,
|
|
57
|
+
null,
|
|
58
|
+
element,
|
|
59
|
+
wcag,
|
|
60
|
+
);
|
|
61
|
+
},
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
When(
|
|
65
|
+
"User checks accessibility of {string} element on the {string} page due to {string} WCAG",
|
|
66
|
+
async function (element, url, wcag) {
|
|
67
|
+
await browser.checkAccessibilityOfPageDueToWCAG(
|
|
68
|
+
context.page,
|
|
69
|
+
url,
|
|
70
|
+
element,
|
|
71
|
+
wcag,
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
);
|