artes 1.7.4 → 1.7.6

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.
Files changed (48) hide show
  1. package/README.md +781 -779
  2. package/assets/styles.css +4 -4
  3. package/cucumber.config.js +253 -253
  4. package/docs/ciExecutors.md +198 -198
  5. package/docs/emulationDevicesList.md +152 -152
  6. package/docs/functionDefinitions.md +2401 -2401
  7. package/docs/stepDefinitions.md +435 -433
  8. package/executer.js +266 -264
  9. package/index.js +50 -50
  10. package/package.json +56 -56
  11. package/src/helper/contextManager/browserManager.js +74 -74
  12. package/src/helper/contextManager/requestManager.js +23 -23
  13. package/src/helper/controller/elementController.js +210 -210
  14. package/src/helper/controller/findDuplicateTestNames.js +69 -69
  15. package/src/helper/controller/getEnvInfo.js +94 -94
  16. package/src/helper/controller/getExecutor.js +109 -109
  17. package/src/helper/controller/pomCollector.js +83 -83
  18. package/src/helper/controller/reportCustomizer.js +485 -485
  19. package/src/helper/controller/screenComparer.js +97 -108
  20. package/src/helper/controller/status-formatter.js +137 -137
  21. package/src/helper/controller/testCoverageCalculator.js +111 -111
  22. package/src/helper/executers/cleaner.js +23 -23
  23. package/src/helper/executers/exporter.js +19 -19
  24. package/src/helper/executers/helper.js +193 -191
  25. package/src/helper/executers/projectCreator.js +226 -222
  26. package/src/helper/executers/reportGenerator.js +91 -91
  27. package/src/helper/executers/testRunner.js +28 -28
  28. package/src/helper/executers/versionChecker.js +31 -31
  29. package/src/helper/imports/commons.js +65 -65
  30. package/src/helper/stepFunctions/APIActions.js +495 -495
  31. package/src/helper/stepFunctions/assertions.js +986 -986
  32. package/src/helper/stepFunctions/browserActions.js +87 -87
  33. package/src/helper/stepFunctions/elementInteractions.js +60 -60
  34. package/src/helper/stepFunctions/exporter.js +19 -19
  35. package/src/helper/stepFunctions/frameActions.js +72 -72
  36. package/src/helper/stepFunctions/keyboardActions.js +66 -66
  37. package/src/helper/stepFunctions/mouseActions.js +84 -84
  38. package/src/helper/stepFunctions/pageActions.js +43 -43
  39. package/src/hooks/context.js +15 -15
  40. package/src/hooks/hooks.js +287 -279
  41. package/src/stepDefinitions/API.steps.js +310 -310
  42. package/src/stepDefinitions/assertions.steps.js +1303 -1280
  43. package/src/stepDefinitions/browser.steps.js +74 -74
  44. package/src/stepDefinitions/frameActions.steps.js +76 -76
  45. package/src/stepDefinitions/keyboardActions.steps.js +264 -264
  46. package/src/stepDefinitions/mouseActions.steps.js +378 -378
  47. package/src/stepDefinitions/page.steps.js +71 -71
  48. package/src/stepDefinitions/random.steps.js +191 -191
@@ -1,210 +1,210 @@
1
- const { context } = require("../../hooks/context");
2
-
3
- let elements = {};
4
-
5
- function addElements(newElements) {
6
- elements = { ...elements, ...newElements };
7
- }
8
-
9
- // async function locatorExistenceChecker(locator){
10
- // const locatorCount = await locator.count();
11
- // console.log(locator, locatorCount)
12
- // return locatorCount ==0 ? false : true;
13
- // }
14
-
15
- function selectorSeparator(element) {
16
- if (typeof element !== "string") return element;
17
-
18
- const selector = element?.split("=");
19
- const validTypes = [
20
- "xpath",
21
- "name",
22
- "placeholder",
23
- "text",
24
- "label",
25
- "role",
26
- "alt",
27
- "title",
28
- "testid",
29
- ];
30
-
31
- if (selector && validTypes.includes(selector[0]?.trim())) {
32
- return [
33
- selector[0].trim(),
34
- selector[1] !== undefined ? selector[1].trim() : "",
35
- ];
36
- } else {
37
- return selector.join("=");
38
- }
39
- }
40
-
41
- function getSelector(element) {
42
- element = resolveVariable(element);
43
-
44
- const selector =
45
- elements?.[element]?.selector || elements?.[element] || element;
46
- return resolveVariable(selectorSeparator(selector));
47
- }
48
-
49
- function getElement(element) {
50
- if (!context.page) {
51
- throw new Error("Page context is not initialized.");
52
- }
53
-
54
- const selector = getSelector(element);
55
- const waitTime = elements[element]?.waitTime * 1000 || 0;
56
-
57
- let locator;
58
- switch (selector[0]) {
59
- case "xpath":
60
- locator = context.page.locator(`xpath=${selector[1]}`, { exact: true });
61
- break;
62
- case "name":
63
- locator = context.page.locator(`[name="${selector[1]}"]`, {
64
- exact: true,
65
- });
66
- break;
67
- case "placeholder":
68
- locator = context.page.getByPlaceholder(selector[1], { exact: true });
69
- break;
70
- case "text":
71
- locator = context.page.getByText(selector[1], { exact: true });
72
- break;
73
- case "label":
74
- locator = context.page.getByLabel(selector[1], { exact: true });
75
- break;
76
- case "role":
77
- locator = context.page.getByRole(selector[1], { exact: true });
78
- break;
79
- case "alt":
80
- locator = context.page.getByAltText(selector[1], { exact: true });
81
- break;
82
- case "title":
83
- locator = context.page.getByTitle(selector[1], { exact: true });
84
- break;
85
- case "testid":
86
- locator = context.page.getByTestId(selector[1], { exact: true });
87
- break;
88
- default:
89
- locator = context.page.locator(selector, { exact: true });
90
- break;
91
- }
92
-
93
- return locator;
94
- }
95
-
96
- function extractVarsFromResponse(responseBody, vars, customVarNames) {
97
- function getValueByPath(obj, path) {
98
- const keys = path.split(".");
99
- let current = obj;
100
-
101
- if (typeof obj === "string") return obj;
102
-
103
- for (const key of keys) {
104
- if (current && typeof current === "object" && key in current) {
105
- current = current[key];
106
- } else {
107
- return undefined;
108
- }
109
- }
110
-
111
- return current;
112
- }
113
-
114
- function pathToCamelCase(path) {
115
- const parts = path.split(".");
116
- return parts
117
- .map((part, index) => {
118
- if (index === 0) return part;
119
- return part.charAt(0).toUpperCase() + part.slice(1);
120
- })
121
- .join("");
122
- }
123
-
124
- const varPaths = vars.split(",").map((v) => v.trim());
125
- let customNames = [];
126
-
127
- if (!customVarNames) {
128
- customNames = varPaths.map(pathToCamelCase);
129
- } else if (typeof customVarNames === "string") {
130
- customNames = customVarNames.split(",").map((n) => n.trim());
131
- } else if (Array.isArray(customVarNames)) {
132
- customNames = customVarNames;
133
- } else {
134
- throw new Error("customVarNames must be a string or an array");
135
- }
136
-
137
- if (customNames.length !== varPaths.length) {
138
- customNames = varPaths.map(pathToCamelCase);
139
- }
140
-
141
- varPaths.forEach((path, index) => {
142
- const value = getValueByPath(responseBody, path);
143
- if (value !== undefined) {
144
- saveVar(value, customNames[index], path);
145
- }
146
- });
147
- }
148
-
149
- function saveVar(value, customName, path) {
150
- if (!customName) {
151
- const flatKey = path
152
- .split(".")
153
- .map((part, i) =>
154
- i === 0 ? part : part[0].toUpperCase() + part.slice(1),
155
- )
156
- .join("");
157
-
158
- context.vars[flatKey] = value;
159
- } else {
160
- context.vars[customName] = value;
161
- }
162
- }
163
-
164
- function resolveVariable(template) {
165
- if (typeof template === "string") {
166
- return template.replace(/{{\s*(\w+)\s*}}/g, (_, varName) => {
167
- let value = context.vars[varName];
168
-
169
- if (value !== undefined) {
170
- if (typeof value !== "string") {
171
- try {
172
- value = JSON.stringify(value);
173
- } catch {
174
- value = String(value);
175
- }
176
- }
177
-
178
- return value
179
- .replace(/\n/g, "\\n")
180
- .replace(/\r/g, "\\r")
181
- .replace(/\t/g, "\\t");
182
- }
183
-
184
- return `{{${varName}}}`;
185
- });
186
- }
187
-
188
- if (Array.isArray(template)) {
189
- return template.map((item) => resolveVariable(item));
190
- }
191
-
192
- if (template && typeof template === "object") {
193
- const result = {};
194
- for (const key in template) {
195
- result[key] = resolveVariable(template[key]);
196
- }
197
- return result;
198
- }
199
-
200
- return template;
201
- }
202
-
203
- module.exports = {
204
- getElement,
205
- addElements,
206
- getSelector,
207
- extractVarsFromResponse,
208
- saveVar,
209
- resolveVariable,
210
- };
1
+ const { context } = require("../../hooks/context");
2
+
3
+ let elements = {};
4
+
5
+ function addElements(newElements) {
6
+ elements = { ...elements, ...newElements };
7
+ }
8
+
9
+ // async function locatorExistenceChecker(locator){
10
+ // const locatorCount = await locator.count();
11
+ // console.log(locator, locatorCount)
12
+ // return locatorCount ==0 ? false : true;
13
+ // }
14
+
15
+ function selectorSeparator(element) {
16
+ if (typeof element !== "string") return element;
17
+
18
+ const selector = element?.split("=");
19
+ const validTypes = [
20
+ "xpath",
21
+ "name",
22
+ "placeholder",
23
+ "text",
24
+ "label",
25
+ "role",
26
+ "alt",
27
+ "title",
28
+ "testid",
29
+ ];
30
+
31
+ if (selector && validTypes.includes(selector[0]?.trim())) {
32
+ return [
33
+ selector[0].trim(),
34
+ selector[1] !== undefined ? selector[1].trim() : "",
35
+ ];
36
+ } else {
37
+ return selector.join("=");
38
+ }
39
+ }
40
+
41
+ function getSelector(element) {
42
+ element = resolveVariable(element);
43
+
44
+ const selector =
45
+ elements?.[element]?.selector || elements?.[element] || element;
46
+ return resolveVariable(selectorSeparator(selector));
47
+ }
48
+
49
+ function getElement(element) {
50
+ if (!context.page) {
51
+ throw new Error("Page context is not initialized.");
52
+ }
53
+
54
+ const selector = getSelector(element);
55
+ const waitTime = elements[element]?.waitTime * 1000 || 0;
56
+
57
+ let locator;
58
+ switch (selector[0]) {
59
+ case "xpath":
60
+ locator = context.page.locator(`xpath=${selector[1]}`, { exact: true });
61
+ break;
62
+ case "name":
63
+ locator = context.page.locator(`[name="${selector[1]}"]`, {
64
+ exact: true,
65
+ });
66
+ break;
67
+ case "placeholder":
68
+ locator = context.page.getByPlaceholder(selector[1], { exact: true });
69
+ break;
70
+ case "text":
71
+ locator = context.page.getByText(selector[1], { exact: true });
72
+ break;
73
+ case "label":
74
+ locator = context.page.getByLabel(selector[1], { exact: true });
75
+ break;
76
+ case "role":
77
+ locator = context.page.getByRole(selector[1], { exact: true });
78
+ break;
79
+ case "alt":
80
+ locator = context.page.getByAltText(selector[1], { exact: true });
81
+ break;
82
+ case "title":
83
+ locator = context.page.getByTitle(selector[1], { exact: true });
84
+ break;
85
+ case "testid":
86
+ locator = context.page.getByTestId(selector[1], { exact: true });
87
+ break;
88
+ default:
89
+ locator = context.page.locator(selector, { exact: true });
90
+ break;
91
+ }
92
+
93
+ return locator;
94
+ }
95
+
96
+ function extractVarsFromResponse(responseBody, vars, customVarNames) {
97
+ function getValueByPath(obj, path) {
98
+ const keys = path.split(".");
99
+ let current = obj;
100
+
101
+ if (typeof obj === "string") return obj;
102
+
103
+ for (const key of keys) {
104
+ if (current && typeof current === "object" && key in current) {
105
+ current = current[key];
106
+ } else {
107
+ return undefined;
108
+ }
109
+ }
110
+
111
+ return current;
112
+ }
113
+
114
+ function pathToCamelCase(path) {
115
+ const parts = path.split(".");
116
+ return parts
117
+ .map((part, index) => {
118
+ if (index === 0) return part;
119
+ return part.charAt(0).toUpperCase() + part.slice(1);
120
+ })
121
+ .join("");
122
+ }
123
+
124
+ const varPaths = vars.split(",").map((v) => v.trim());
125
+ let customNames = [];
126
+
127
+ if (!customVarNames) {
128
+ customNames = varPaths.map(pathToCamelCase);
129
+ } else if (typeof customVarNames === "string") {
130
+ customNames = customVarNames.split(",").map((n) => n.trim());
131
+ } else if (Array.isArray(customVarNames)) {
132
+ customNames = customVarNames;
133
+ } else {
134
+ throw new Error("customVarNames must be a string or an array");
135
+ }
136
+
137
+ if (customNames.length !== varPaths.length) {
138
+ customNames = varPaths.map(pathToCamelCase);
139
+ }
140
+
141
+ varPaths.forEach((path, index) => {
142
+ const value = getValueByPath(responseBody, path);
143
+ if (value !== undefined) {
144
+ saveVar(value, customNames[index], path);
145
+ }
146
+ });
147
+ }
148
+
149
+ function saveVar(value, customName, path) {
150
+ if (!customName) {
151
+ const flatKey = path
152
+ .split(".")
153
+ .map((part, i) =>
154
+ i === 0 ? part : part[0].toUpperCase() + part.slice(1),
155
+ )
156
+ .join("");
157
+
158
+ context.vars[flatKey] = value;
159
+ } else {
160
+ context.vars[customName] = value;
161
+ }
162
+ }
163
+
164
+ function resolveVariable(template) {
165
+ if (typeof template === "string") {
166
+ return template.replace(/{{\s*(\w+)\s*}}/g, (_, varName) => {
167
+ let value = context.vars[varName];
168
+
169
+ if (value !== undefined) {
170
+ if (typeof value !== "string") {
171
+ try {
172
+ value = JSON.stringify(value);
173
+ } catch {
174
+ value = String(value);
175
+ }
176
+ }
177
+
178
+ return value
179
+ .replace(/\n/g, "\\n")
180
+ .replace(/\r/g, "\\r")
181
+ .replace(/\t/g, "\\t");
182
+ }
183
+
184
+ return `{{${varName}}}`;
185
+ });
186
+ }
187
+
188
+ if (Array.isArray(template)) {
189
+ return template.map((item) => resolveVariable(item));
190
+ }
191
+
192
+ if (template && typeof template === "object") {
193
+ const result = {};
194
+ for (const key in template) {
195
+ result[key] = resolveVariable(template[key]);
196
+ }
197
+ return result;
198
+ }
199
+
200
+ return template;
201
+ }
202
+
203
+ module.exports = {
204
+ getElement,
205
+ addElements,
206
+ getSelector,
207
+ extractVarsFromResponse,
208
+ saveVar,
209
+ resolveVariable,
210
+ };
@@ -1,69 +1,69 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
-
4
- function findDuplicateTestNames() {
5
- const testStatusFile = path.join(
6
- process.cwd(),
7
- "node_modules",
8
- "artes",
9
- "test-status",
10
- "test-status.txt",
11
- );
12
-
13
- if (!fs.existsSync(testStatusFile)) {
14
- console.error("test-status.txt not found");
15
- return;
16
- }
17
-
18
- const content = fs.readFileSync(testStatusFile, "utf8");
19
- const lines = content.split("\n").filter((line) => line.trim());
20
-
21
- const testNameToEntries = {};
22
-
23
- lines.forEach((line) => {
24
- const parts = line.split(" | ");
25
- if (parts.length < 5) return;
26
-
27
- const testName = parts[2].trim();
28
- const filePath = parts[4].trim();
29
- const uuid = parts[3].trim();
30
-
31
- if (!testNameToEntries[testName]) {
32
- testNameToEntries[testName] = [];
33
- }
34
-
35
- const alreadyExists = testNameToEntries[testName].some(
36
- (e) => e.uuid === uuid,
37
- );
38
- if (!alreadyExists) {
39
- testNameToEntries[testName].push({ filePath, uuid });
40
- }
41
- });
42
-
43
- const duplicates = {};
44
-
45
- Object.entries(testNameToEntries).forEach(([testName, entries]) => {
46
- if (entries.length > 1) {
47
- duplicates[testName] = entries.map((e) => e.filePath);
48
- }
49
- });
50
-
51
- if (Object.keys(duplicates).length > 0) {
52
- console.warn(
53
- "\n\x1b[33m[WARNING] Duplicate scenario names found: This will affect your reporting",
54
- );
55
- Object.entries(duplicates).forEach(([testName, files]) => {
56
- console.log(`\x1b[33m"${testName}" exists in:`);
57
- files.forEach((file) => {
58
- console.log(` - ${file}`);
59
- });
60
- console.log("");
61
- });
62
- console.log("\x1b[0m");
63
- console.log("");
64
- }
65
-
66
- return duplicates;
67
- }
68
-
69
- module.exports = { findDuplicateTestNames };
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ function findDuplicateTestNames() {
5
+ const testStatusFile = path.join(
6
+ process.cwd(),
7
+ "node_modules",
8
+ "artes",
9
+ "test-status",
10
+ "test-status.txt",
11
+ );
12
+
13
+ if (!fs.existsSync(testStatusFile)) {
14
+ console.error("test-status.txt not found");
15
+ return;
16
+ }
17
+
18
+ const content = fs.readFileSync(testStatusFile, "utf8");
19
+ const lines = content.split("\n").filter((line) => line.trim());
20
+
21
+ const testNameToEntries = {};
22
+
23
+ lines.forEach((line) => {
24
+ const parts = line.split(" | ");
25
+ if (parts.length < 5) return;
26
+
27
+ const testName = parts[2].trim();
28
+ const filePath = parts[4].trim();
29
+ const uuid = parts[3].trim();
30
+
31
+ if (!testNameToEntries[testName]) {
32
+ testNameToEntries[testName] = [];
33
+ }
34
+
35
+ const alreadyExists = testNameToEntries[testName].some(
36
+ (e) => e.uuid === uuid,
37
+ );
38
+ if (!alreadyExists) {
39
+ testNameToEntries[testName].push({ filePath, uuid });
40
+ }
41
+ });
42
+
43
+ const duplicates = {};
44
+
45
+ Object.entries(testNameToEntries).forEach(([testName, entries]) => {
46
+ if (entries.length > 1) {
47
+ duplicates[testName] = entries.map((e) => e.filePath);
48
+ }
49
+ });
50
+
51
+ if (Object.keys(duplicates).length > 0) {
52
+ console.warn(
53
+ "\n\x1b[33m[WARNING] Duplicate scenario names found: This will affect your reporting",
54
+ );
55
+ Object.entries(duplicates).forEach(([testName, files]) => {
56
+ console.log(`\x1b[33m"${testName}" exists in:`);
57
+ files.forEach((file) => {
58
+ console.log(` - ${file}`);
59
+ });
60
+ console.log("");
61
+ });
62
+ console.log("\x1b[0m");
63
+ console.log("");
64
+ }
65
+
66
+ return duplicates;
67
+ }
68
+
69
+ module.exports = { findDuplicateTestNames };