artes 1.7.11 → 1.7.14
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/index.js +1 -0
- package/package.json +1 -1
- package/src/helper/controller/getEnvInfo.js +3 -0
- package/src/helper/stepFunctions/APIActions.js +115 -29
- package/src/stepDefinitions/API.steps.js +97 -5
- package/src/stepDefinitions/assertions.steps.js +47 -0
- package/src/stepDefinitions/mouseActions.steps.js +3 -7
- package/src/stepDefinitions/report.steps.js +5 -0
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -27,6 +27,9 @@ async function getEnvInfo() {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const environment = {
|
|
30
|
+
// ── ARTES Version ───────────────────────
|
|
31
|
+
ARTES_Version: require(moduleConfig.modulePackageJsonPath).version,
|
|
32
|
+
|
|
30
33
|
// ── System ──────────────────────────────
|
|
31
34
|
OS_Name: os.type(),
|
|
32
35
|
OS_Version: os.release(),
|
|
@@ -48,6 +48,10 @@ function curlExtractor(url, method, headers, body, requestDataType) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
break;
|
|
51
|
+
case "xml":
|
|
52
|
+
curlCommand += ` \\\n -H 'Content-Type: application/xml'`;
|
|
53
|
+
curlCommand += ` \\\n --data-raw '${data}'`;
|
|
54
|
+
break;
|
|
51
55
|
|
|
52
56
|
case "urlencoded":
|
|
53
57
|
case "application/x-www-form-urlencoded":
|
|
@@ -106,28 +110,37 @@ function processForm(requestBody) {
|
|
|
106
110
|
}
|
|
107
111
|
}
|
|
108
112
|
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
(value
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
113
|
+
if (typeof value === "string") {
|
|
114
|
+
|
|
115
|
+
const normalizedValue = path.normalize(value);
|
|
116
|
+
|
|
117
|
+
const looksLikeFilePath =
|
|
118
|
+
normalizedValue.endsWith(".pdf") ||
|
|
119
|
+
normalizedValue.endsWith(".jpg") ||
|
|
120
|
+
normalizedValue.endsWith(".jpeg") ||
|
|
121
|
+
normalizedValue.endsWith(".png") ||
|
|
122
|
+
normalizedValue.endsWith(".txt") ||
|
|
123
|
+
normalizedValue.endsWith(".doc") ||
|
|
124
|
+
normalizedValue.endsWith(".docx") ||
|
|
125
|
+
normalizedValue.includes(path.sep);
|
|
126
|
+
|
|
127
|
+
if (looksLikeFilePath) {
|
|
128
|
+
try {
|
|
129
|
+
const filePath = path.isAbsolute(normalizedValue)
|
|
130
|
+
? normalizedValue
|
|
131
|
+
: path.join(moduleConfig.projectPath, normalizedValue);
|
|
132
|
+
|
|
133
|
+
if (fs.existsSync(filePath)) {
|
|
134
|
+
formData[key] = {
|
|
135
|
+
name: path.basename(filePath),
|
|
136
|
+
mimeType: getMimeType(filePath),
|
|
137
|
+
buffer: fs.readFileSync(filePath),
|
|
138
|
+
};
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.log(error);
|
|
128
143
|
}
|
|
129
|
-
} catch (error) {
|
|
130
|
-
console.log(error);
|
|
131
144
|
}
|
|
132
145
|
}
|
|
133
146
|
|
|
@@ -145,6 +158,12 @@ async function requestMaker(headers, data, requestDataType) {
|
|
|
145
158
|
case "multipart":
|
|
146
159
|
Object.assign(request, { multipart: data });
|
|
147
160
|
break;
|
|
161
|
+
case "xml":
|
|
162
|
+
Object.assign(request, {
|
|
163
|
+
headers: { ...headers, "Content-Type": "application/xml" },
|
|
164
|
+
data: data,
|
|
165
|
+
});
|
|
166
|
+
break;
|
|
148
167
|
case "urlencoded":
|
|
149
168
|
case "application/x-www-form-urlencoded":
|
|
150
169
|
const urlEncodedData = new URLSearchParams(data).toString();
|
|
@@ -264,6 +283,14 @@ const api = {
|
|
|
264
283
|
);
|
|
265
284
|
bodyForCurl = formRequest;
|
|
266
285
|
break;
|
|
286
|
+
case "xml":
|
|
287
|
+
req = await requestMaker(
|
|
288
|
+
payloadJSON?.headers || {},
|
|
289
|
+
payloadJSON?.body || {},
|
|
290
|
+
requestDataType,
|
|
291
|
+
);
|
|
292
|
+
bodyForCurl = payloadJSON?.body || {};
|
|
293
|
+
break;
|
|
267
294
|
case "urlencoded":
|
|
268
295
|
case "application/x-www-form-urlencoded":
|
|
269
296
|
req = await requestMaker(
|
|
@@ -334,6 +361,14 @@ const api = {
|
|
|
334
361
|
);
|
|
335
362
|
bodyForCurl = formRequest;
|
|
336
363
|
break;
|
|
364
|
+
case "xml":
|
|
365
|
+
req = await requestMaker(
|
|
366
|
+
payloadJSON?.headers || {},
|
|
367
|
+
payloadJSON?.body || {},
|
|
368
|
+
requestDataType,
|
|
369
|
+
);
|
|
370
|
+
bodyForCurl = payloadJSON?.body || {};
|
|
371
|
+
break;
|
|
337
372
|
case "urlencoded":
|
|
338
373
|
case "application/x-www-form-urlencoded":
|
|
339
374
|
req = await requestMaker(
|
|
@@ -404,6 +439,14 @@ const api = {
|
|
|
404
439
|
);
|
|
405
440
|
bodyForCurl = formRequest;
|
|
406
441
|
break;
|
|
442
|
+
case "xml":
|
|
443
|
+
req = await requestMaker(
|
|
444
|
+
payloadJSON?.headers || {},
|
|
445
|
+
payloadJSON?.body || {},
|
|
446
|
+
requestDataType,
|
|
447
|
+
);
|
|
448
|
+
bodyForCurl = payloadJSON?.body || {};
|
|
449
|
+
break;
|
|
407
450
|
case "urlencoded":
|
|
408
451
|
case "application/x-www-form-urlencoded":
|
|
409
452
|
req = await requestMaker(
|
|
@@ -452,7 +495,7 @@ const api = {
|
|
|
452
495
|
|
|
453
496
|
context.response = response;
|
|
454
497
|
},
|
|
455
|
-
|
|
498
|
+
delete: async (url, payload, requestDataType, options) => {
|
|
456
499
|
const URL = await selector(url);
|
|
457
500
|
|
|
458
501
|
options = options ?? {};
|
|
@@ -460,10 +503,53 @@ const api = {
|
|
|
460
503
|
const resolvedPayload = (await payload) && resolveVariable(payload);
|
|
461
504
|
const payloadJSON = (await resolvedPayload) && JSON.parse(resolvedPayload);
|
|
462
505
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
)
|
|
506
|
+
let req;
|
|
507
|
+
let bodyForCurl = payloadJSON?.body || {};
|
|
508
|
+
|
|
509
|
+
switch (requestDataType) {
|
|
510
|
+
case "multipart":
|
|
511
|
+
const formRequest = processForm(payloadJSON?.body || {});
|
|
512
|
+
req = await requestMaker(
|
|
513
|
+
payloadJSON?.headers || {},
|
|
514
|
+
formRequest || {},
|
|
515
|
+
requestDataType,
|
|
516
|
+
);
|
|
517
|
+
bodyForCurl = formRequest;
|
|
518
|
+
break;
|
|
519
|
+
case "urlencoded":
|
|
520
|
+
case "application/x-www-form-urlencoded":
|
|
521
|
+
req = await requestMaker(
|
|
522
|
+
{
|
|
523
|
+
...payloadJSON?.headers,
|
|
524
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
525
|
+
},
|
|
526
|
+
payloadJSON?.body || {},
|
|
527
|
+
requestDataType,
|
|
528
|
+
);
|
|
529
|
+
break;
|
|
530
|
+
case "form":
|
|
531
|
+
req = await requestMaker(
|
|
532
|
+
payloadJSON?.headers || {},
|
|
533
|
+
payloadJSON?.body || {},
|
|
534
|
+
requestDataType,
|
|
535
|
+
);
|
|
536
|
+
break;
|
|
537
|
+
case "xml":
|
|
538
|
+
req = await requestMaker(
|
|
539
|
+
{
|
|
540
|
+
...payloadJSON?.headers,
|
|
541
|
+
"Content-Type": "application/xml",
|
|
542
|
+
},
|
|
543
|
+
payloadJSON?.body || {},
|
|
544
|
+
requestDataType,
|
|
545
|
+
);
|
|
546
|
+
break;
|
|
547
|
+
default:
|
|
548
|
+
req = await requestMaker(
|
|
549
|
+
payloadJSON?.headers || {},
|
|
550
|
+
payloadJSON?.body || {},
|
|
551
|
+
);
|
|
552
|
+
}
|
|
467
553
|
|
|
468
554
|
const requestStarts = performance.now();
|
|
469
555
|
|
|
@@ -474,9 +560,9 @@ const api = {
|
|
|
474
560
|
const curlCommand = curlExtractor(
|
|
475
561
|
res.url(),
|
|
476
562
|
"DELETE",
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
563
|
+
req.headers,
|
|
564
|
+
bodyForCurl,
|
|
565
|
+
requestDataType,
|
|
480
566
|
);
|
|
481
567
|
|
|
482
568
|
const response = responseMaker(payloadJSON, res, duration, curlCommand);
|
|
@@ -88,6 +88,21 @@ When(
|
|
|
88
88
|
},
|
|
89
89
|
);
|
|
90
90
|
|
|
91
|
+
When(
|
|
92
|
+
"User sends xml POST request to {string} with payload:",
|
|
93
|
+
async (url, payload) => {
|
|
94
|
+
await api.post(url, payload, "xml");
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
When(
|
|
99
|
+
"User sends xml POST request to {string} with payload and saves {string} variables",
|
|
100
|
+
async (url, vars, payload) => {
|
|
101
|
+
await api.post(url, payload, "xml");
|
|
102
|
+
await extractVarsFromResponse(context.response["Response Body"], vars);
|
|
103
|
+
},
|
|
104
|
+
);
|
|
105
|
+
|
|
91
106
|
When(
|
|
92
107
|
"User sends PUT request to {string} with payload:",
|
|
93
108
|
async function (url, payload) {
|
|
@@ -133,6 +148,21 @@ When(
|
|
|
133
148
|
},
|
|
134
149
|
);
|
|
135
150
|
|
|
151
|
+
When(
|
|
152
|
+
"User sends xml PUT request to {string} with payload:",
|
|
153
|
+
async (url, payload) => {
|
|
154
|
+
await api.put(url, payload, "xml");
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
When(
|
|
159
|
+
"User sends xml PUT request to {string} with payload and saves {string} variables",
|
|
160
|
+
async (url, vars, payload) => {
|
|
161
|
+
await api.put(url, payload, "xml");
|
|
162
|
+
await extractVarsFromResponse(context.response["Response Body"], vars);
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
|
|
136
166
|
When(
|
|
137
167
|
"User sends PATCH request to {string} with payload:",
|
|
138
168
|
async function (url, payload) {
|
|
@@ -178,6 +208,21 @@ When(
|
|
|
178
208
|
},
|
|
179
209
|
);
|
|
180
210
|
|
|
211
|
+
When(
|
|
212
|
+
"User sends xml PATCH request to {string} with payload:",
|
|
213
|
+
async (url, payload) => {
|
|
214
|
+
await api.patch(url, payload, "xml");
|
|
215
|
+
},
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
When(
|
|
219
|
+
"User sends xml PATCH request to {string} with payload and saves {string} variables",
|
|
220
|
+
async (url, vars, payload) => {
|
|
221
|
+
await api.patch(url, payload, "xml");
|
|
222
|
+
await extractVarsFromResponse(context.response["Response Body"], vars);
|
|
223
|
+
},
|
|
224
|
+
);
|
|
225
|
+
|
|
181
226
|
When("User sends DELETE request to {string}", async function (url) {
|
|
182
227
|
await api.delete(url);
|
|
183
228
|
});
|
|
@@ -205,6 +250,21 @@ When(
|
|
|
205
250
|
},
|
|
206
251
|
);
|
|
207
252
|
|
|
253
|
+
When(
|
|
254
|
+
"User sends xml DELETE request to {string} with payload:",
|
|
255
|
+
async (url, payload) => {
|
|
256
|
+
await api.delete(url, payload, "xml");
|
|
257
|
+
},
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
When(
|
|
261
|
+
"User sends xml DELETE request to {string} with payload and saves {string} variables",
|
|
262
|
+
async (url, vars, payload) => {
|
|
263
|
+
await api.delete(url, payload, "xml");
|
|
264
|
+
await extractVarsFromResponse(context.response["Response Body"], vars);
|
|
265
|
+
},
|
|
266
|
+
);
|
|
267
|
+
|
|
208
268
|
When(
|
|
209
269
|
"User saves {string} variable from response as {string}",
|
|
210
270
|
async function (vars, customVarName) {
|
|
@@ -223,6 +283,33 @@ When(
|
|
|
223
283
|
},
|
|
224
284
|
);
|
|
225
285
|
|
|
286
|
+
When(
|
|
287
|
+
'User sets {int} year from current year as {string}',
|
|
288
|
+
async function (year, yearName) {
|
|
289
|
+
const targetYear = time().add(year, 'year').year();
|
|
290
|
+
context.vars[yearName] = targetYear.toString();
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
When(
|
|
295
|
+
'User sets {int} month from current month as {string}',
|
|
296
|
+
async function (month, monthName) {
|
|
297
|
+
const targetMonth = time().add(month, 'month').month() + 1;
|
|
298
|
+
|
|
299
|
+
context.vars[monthName] = targetMonth.toString().padStart(2, '0');
|
|
300
|
+
}
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
When(
|
|
304
|
+
"User saves request time in ISO format as {string}",
|
|
305
|
+
async (request_time) => {
|
|
306
|
+
context.vars[request_time] = new Date(
|
|
307
|
+
context.response["Response Headers"].date,
|
|
308
|
+
).toISOString();
|
|
309
|
+
allure.attachment("Request Time", context.vars[request_time], "text/plain");
|
|
310
|
+
},
|
|
311
|
+
);
|
|
312
|
+
|
|
226
313
|
When("User wants to see saved variables", async function () {
|
|
227
314
|
console.log("\nVariables:", api.vars(null), "\n");
|
|
228
315
|
});
|
|
@@ -302,9 +389,14 @@ When(
|
|
|
302
389
|
async (file, variable) => {
|
|
303
390
|
file = await resolveVariable(file);
|
|
304
391
|
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
const
|
|
308
|
-
|
|
392
|
+
const normalizedFile = path.normalize(file);
|
|
393
|
+
|
|
394
|
+
const filePath = path.isAbsolute(normalizedFile)
|
|
395
|
+
? normalizedFile
|
|
396
|
+
: path.join(moduleConfig.projectPath, normalizedFile);
|
|
397
|
+
|
|
398
|
+
const fileData = fs.readFileSync(filePath);
|
|
399
|
+
const base64Data = fileData.toString("base64");
|
|
400
|
+
context.vars[variable] = base64Data;
|
|
309
401
|
},
|
|
310
|
-
);
|
|
402
|
+
);
|
|
@@ -1264,6 +1264,15 @@ Then(
|
|
|
1264
1264
|
},
|
|
1265
1265
|
);
|
|
1266
1266
|
|
|
1267
|
+
Then(
|
|
1268
|
+
"User expects that {string} array has {int} items",
|
|
1269
|
+
async (field, count) => {
|
|
1270
|
+
extractVarsFromResponse(context.response["Response Body"], field);
|
|
1271
|
+
const key = pathToCamelCase(field);
|
|
1272
|
+
expect(context.vars[key].length).toEqual(count);
|
|
1273
|
+
},
|
|
1274
|
+
);
|
|
1275
|
+
|
|
1267
1276
|
Then(
|
|
1268
1277
|
"User expects that {string} should match {string}",
|
|
1269
1278
|
async (value1, value2) => {
|
|
@@ -1303,3 +1312,41 @@ Then(
|
|
|
1303
1312
|
expect(actualStatusCode).toBe(expectedStatusCode);
|
|
1304
1313
|
},
|
|
1305
1314
|
);
|
|
1315
|
+
|
|
1316
|
+
|
|
1317
|
+
Then("User expects that response should have {string} field", async (field) => {
|
|
1318
|
+
extractVarsFromResponse(context.response["Response Body"], field);
|
|
1319
|
+
const key = pathToCamelCase(field);
|
|
1320
|
+
const varToString = JSON.stringify(context.vars[field]);
|
|
1321
|
+
expect(varToString).toBeDefined();
|
|
1322
|
+
});
|
|
1323
|
+
|
|
1324
|
+
Then(
|
|
1325
|
+
"User expects that response should not have {string} field",
|
|
1326
|
+
async (field) => {
|
|
1327
|
+
extractVarsFromResponse(context.response["Response Body"], field);
|
|
1328
|
+
const key = pathToCamelCase(field);
|
|
1329
|
+
const varToString = JSON.stringify(context.vars[field]);
|
|
1330
|
+
expect(varToString).not.toBeDefined();
|
|
1331
|
+
},
|
|
1332
|
+
);
|
|
1333
|
+
|
|
1334
|
+
Then(
|
|
1335
|
+
"User expects that {string} array has items more than {int}",
|
|
1336
|
+
(field, count) => {
|
|
1337
|
+
extractVarsFromResponse(context.response["Response Body"], field);
|
|
1338
|
+
const key = pathToCamelCase(field);
|
|
1339
|
+
const resolvedCount = resolveVariable(count)
|
|
1340
|
+
expect(context.vars[key].length).toBeLessThan(resolvedCount);
|
|
1341
|
+
},
|
|
1342
|
+
);
|
|
1343
|
+
|
|
1344
|
+
Then(
|
|
1345
|
+
"User expects that {string} array has items less than {int}",
|
|
1346
|
+
(field, count) => {
|
|
1347
|
+
extractVarsFromResponse(context.response["Response Body"], field);
|
|
1348
|
+
const key = pathToCamelCase(field);
|
|
1349
|
+
const resolvedCount = resolveVariable(count)
|
|
1350
|
+
expect(context.vars[key].length).toBeLessThan(resolvedCount);
|
|
1351
|
+
},
|
|
1352
|
+
);
|
|
@@ -60,7 +60,7 @@ When(
|
|
|
60
60
|
When("User clicks at {int}, {int} coordinates", async function (x, y) {
|
|
61
61
|
x = await resolveVariable(x);
|
|
62
62
|
y = await resolveVariable(y);
|
|
63
|
-
await context.page.click(
|
|
63
|
+
await context.page.mouse.click(x, y);
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
// User clicks at specific coordinates with click count and delay
|
|
@@ -69,11 +69,7 @@ When(
|
|
|
69
69
|
async function (x, y, clickCount, delay) {
|
|
70
70
|
x = await resolveVariable(x);
|
|
71
71
|
y = await resolveVariable(y);
|
|
72
|
-
await context.page.click({
|
|
73
|
-
position: { x: x, y: y },
|
|
74
|
-
clickCount: clickCount,
|
|
75
|
-
delay: delay,
|
|
76
|
-
});
|
|
72
|
+
await context.page.mouse.click(x, y, { clickCount: clickCount, delay: delay });
|
|
77
73
|
},
|
|
78
74
|
);
|
|
79
75
|
|
|
@@ -83,7 +79,7 @@ When(
|
|
|
83
79
|
async function (x, y) {
|
|
84
80
|
x = await resolveVariable(x);
|
|
85
81
|
y = await resolveVariable(y);
|
|
86
|
-
context.page.click(
|
|
82
|
+
await context.page.mouse.click(x, y, { force: true });
|
|
87
83
|
},
|
|
88
84
|
);
|
|
89
85
|
|