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.
- package/README.md +781 -779
- package/assets/styles.css +4 -4
- package/cucumber.config.js +253 -253
- package/docs/ciExecutors.md +198 -198
- package/docs/emulationDevicesList.md +152 -152
- package/docs/functionDefinitions.md +2401 -2401
- package/docs/stepDefinitions.md +435 -433
- package/executer.js +266 -264
- package/index.js +50 -50
- package/package.json +56 -56
- package/src/helper/contextManager/browserManager.js +74 -74
- package/src/helper/contextManager/requestManager.js +23 -23
- package/src/helper/controller/elementController.js +210 -210
- package/src/helper/controller/findDuplicateTestNames.js +69 -69
- package/src/helper/controller/getEnvInfo.js +94 -94
- package/src/helper/controller/getExecutor.js +109 -109
- package/src/helper/controller/pomCollector.js +83 -83
- package/src/helper/controller/reportCustomizer.js +485 -485
- package/src/helper/controller/screenComparer.js +97 -108
- package/src/helper/controller/status-formatter.js +137 -137
- package/src/helper/controller/testCoverageCalculator.js +111 -111
- package/src/helper/executers/cleaner.js +23 -23
- package/src/helper/executers/exporter.js +19 -19
- package/src/helper/executers/helper.js +193 -191
- package/src/helper/executers/projectCreator.js +226 -222
- package/src/helper/executers/reportGenerator.js +91 -91
- package/src/helper/executers/testRunner.js +28 -28
- package/src/helper/executers/versionChecker.js +31 -31
- package/src/helper/imports/commons.js +65 -65
- package/src/helper/stepFunctions/APIActions.js +495 -495
- package/src/helper/stepFunctions/assertions.js +986 -986
- package/src/helper/stepFunctions/browserActions.js +87 -87
- package/src/helper/stepFunctions/elementInteractions.js +60 -60
- package/src/helper/stepFunctions/exporter.js +19 -19
- package/src/helper/stepFunctions/frameActions.js +72 -72
- package/src/helper/stepFunctions/keyboardActions.js +66 -66
- package/src/helper/stepFunctions/mouseActions.js +84 -84
- package/src/helper/stepFunctions/pageActions.js +43 -43
- package/src/hooks/context.js +15 -15
- package/src/hooks/hooks.js +287 -279
- package/src/stepDefinitions/API.steps.js +310 -310
- package/src/stepDefinitions/assertions.steps.js +1303 -1280
- package/src/stepDefinitions/browser.steps.js +74 -74
- package/src/stepDefinitions/frameActions.steps.js +76 -76
- package/src/stepDefinitions/keyboardActions.steps.js +264 -264
- package/src/stepDefinitions/mouseActions.steps.js +378 -378
- package/src/stepDefinitions/page.steps.js +71 -71
- 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 };
|