artes 1.3.1 → 1.4.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 +3 -0
- package/cucumber.config.js +5 -2
- package/docs/stepDefinitions.md +1 -0
- package/executer.js +6 -2
- package/index.js +4 -1
- package/package.json +1 -1
- package/src/helper/contextManager/browserManager.js +7 -3
- package/src/helper/controller/pomCollector.js +22 -11
- package/src/helper/executers/helper.js +3 -0
- package/src/helper/executers/projectCreator.js +1 -0
- package/src/helper/executers/testRunner.js +10 -14
- package/src/helper/imports/commons.js +2 -2
- package/src/helper/stepFunctions/APIActions.js +30 -14
- package/src/helper/stepFunctions/assertions.js +579 -272
- package/src/helper/stepFunctions/elementInteractions.js +40 -20
- package/src/helper/stepFunctions/frameActions.js +43 -21
- package/src/helper/stepFunctions/keyboardActions.js +41 -23
- package/src/helper/stepFunctions/mouseActions.js +41 -108
- package/src/helper/stepFunctions/pageActions.js +24 -12
- package/src/hooks/hooks.js +13 -19
- package/src/stepDefinitions/API.steps.js +18 -1
- package/src/stepDefinitions/keyboardActions.steps.js +18 -26
- package/src/stepDefinitions/mouseActions.steps.js +98 -31
package/README.md
CHANGED
|
@@ -126,6 +126,7 @@ npx artes [options]
|
|
|
126
126
|
| 🎭 `--dryRun` | Perform a dry run without executing tests | `artes --dryRun` |
|
|
127
127
|
| 📈 `--percentage` | Set minimum success percentage to pass test run (default is 0) | `artes --percentage 85` |
|
|
128
128
|
| 🌍 `--browser` | Specify browser to use (`chromium`, `firefox`, or `webkit`) | `artes --browser chromium` |
|
|
129
|
+
| `--offline` | Run browser in offline mode | `artes --offline` |
|
|
129
130
|
| 📱 `--device` | Emulate specific device (e.g., "iPhone 13") | `artes --device "iPhone 13"` |
|
|
130
131
|
| 🔗 `--baseURL` | Set base URL for the tests | `artes --baseURL "https://example.com"` |
|
|
131
132
|
| 🖥️ `--maxScreen` | Maximize browser window on launch | `artes --maxScreen` |
|
|
@@ -589,6 +590,8 @@ Artes supports environment-specific configurations through environment variables
|
|
|
589
590
|
| `browserType` | `"chrome"` | Browser type (`"chrome"`, `"firefox"`, or `"webkit"`). |
|
|
590
591
|
| `viewport` | `{ width: 1280, height: 720 }` | Browser viewport size. |
|
|
591
592
|
| `headless` | `true` | Run browser in headless mode (`true` or `false`). |
|
|
593
|
+
| `offline` | `false` | Run browser in offline mode (`true` or `false`). |
|
|
594
|
+
|
|
592
595
|
|
|
593
596
|
### Device Configuration
|
|
594
597
|
|
package/cucumber.config.js
CHANGED
|
@@ -164,8 +164,11 @@ module.exports = {
|
|
|
164
164
|
? JSON.parse(process.env.BROWSER)
|
|
165
165
|
: artesConfig?.browser || "chrome",
|
|
166
166
|
device: process.env.DEVICE
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
? JSON.parse(process.env.DEVICE)
|
|
168
|
+
: artesConfig?.device || null,
|
|
169
|
+
offline: process.env.OFFLINE
|
|
170
|
+
? JSON.parse(process.env.OFFLINE)
|
|
171
|
+
: artesConfig?.offline || false,
|
|
169
172
|
viewport: {
|
|
170
173
|
width: process.env.WIDTH
|
|
171
174
|
? Number(process.env.WIDTH)
|
package/docs/stepDefinitions.md
CHANGED
package/executer.js
CHANGED
|
@@ -7,7 +7,7 @@ const {
|
|
|
7
7
|
generateReport,
|
|
8
8
|
cleanUp,
|
|
9
9
|
} = require("./src/helper/executers/exporter");
|
|
10
|
-
const { logPomWarnings }
|
|
10
|
+
const { logPomWarnings } = require("./src/helper/controller/pomCollector");
|
|
11
11
|
const fs = require("fs");
|
|
12
12
|
const path = require("path");
|
|
13
13
|
|
|
@@ -44,6 +44,7 @@ const flags = {
|
|
|
44
44
|
dryRun: args.includes("--dryRun"),
|
|
45
45
|
percentage: args.includes("--percentage"),
|
|
46
46
|
browser: args.includes("--browser"),
|
|
47
|
+
offline: args.includes("--offline"),
|
|
47
48
|
device: args.includes("--device"),
|
|
48
49
|
baseURL: args.includes("--baseURL"),
|
|
49
50
|
maximizeScreen: args.includes("--maxScreen"),
|
|
@@ -123,6 +124,9 @@ flags.percentage ? (process.env.PERCENTAGE = percentage) : "";
|
|
|
123
124
|
flags.browser && console.log("Running browser:", browser);
|
|
124
125
|
flags.browser ? (process.env.BROWSER = JSON.stringify(browser)) : "";
|
|
125
126
|
|
|
127
|
+
flags.browser && console.log("Running mode:", flags.offline && "Offline");
|
|
128
|
+
flags.offline ? (process.env.OFFLINE = true) : "";
|
|
129
|
+
|
|
126
130
|
flags.device && console.log("Running device:", device);
|
|
127
131
|
flags.device ? (process.env.DEVICE = JSON.stringify(device)) : "";
|
|
128
132
|
|
|
@@ -148,7 +152,7 @@ function main() {
|
|
|
148
152
|
if (flags.create) return createProject(flags.createYes, flags.noDeps);
|
|
149
153
|
|
|
150
154
|
runTests();
|
|
151
|
-
|
|
155
|
+
|
|
152
156
|
logPomWarnings();
|
|
153
157
|
|
|
154
158
|
if (
|
package/index.js
CHANGED
|
@@ -8,12 +8,13 @@ const {
|
|
|
8
8
|
selector,
|
|
9
9
|
saveVar,
|
|
10
10
|
extractVarsFromResponse,
|
|
11
|
-
|
|
11
|
+
browserPage,
|
|
12
12
|
request,
|
|
13
13
|
random,
|
|
14
14
|
time,
|
|
15
15
|
resolveVariable,
|
|
16
16
|
} = require("./src/helper/imports/commons");
|
|
17
|
+
|
|
17
18
|
const {
|
|
18
19
|
keyboard,
|
|
19
20
|
mouse,
|
|
@@ -21,6 +22,7 @@ const {
|
|
|
21
22
|
assert,
|
|
22
23
|
elementInteractions,
|
|
23
24
|
api,
|
|
25
|
+
page,
|
|
24
26
|
} = require("./src/helper/stepFunctions/exporter");
|
|
25
27
|
|
|
26
28
|
module.exports = {
|
|
@@ -34,6 +36,7 @@ module.exports = {
|
|
|
34
36
|
extractVarsFromResponse,
|
|
35
37
|
resolveVariable,
|
|
36
38
|
context,
|
|
39
|
+
browserPage,
|
|
37
40
|
api,
|
|
38
41
|
random,
|
|
39
42
|
time,
|
package/package.json
CHANGED
|
@@ -19,7 +19,9 @@ const invokeBrowser = async () => {
|
|
|
19
19
|
args: [cucumberConfig.browser.maximizeScreen ? "--start-maximized" : ""],
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const browserType = cucumberConfig.browser.device
|
|
22
|
+
const browserType = cucumberConfig.browser.device
|
|
23
|
+
? "webkit"
|
|
24
|
+
: cucumberConfig.browser.browserType.toLowerCase() || "chrome";
|
|
23
25
|
|
|
24
26
|
const browserContextOptions = {
|
|
25
27
|
baseURL: baseURL,
|
|
@@ -35,6 +37,7 @@ const invokeBrowser = async () => {
|
|
|
35
37
|
size: cucumberConfig.browser.viewport,
|
|
36
38
|
},
|
|
37
39
|
ignoreHTTPSErrors: true,
|
|
40
|
+
offline: cucumberConfig.browser.offline,
|
|
38
41
|
};
|
|
39
42
|
|
|
40
43
|
switch (browserType) {
|
|
@@ -53,9 +56,10 @@ const invokeBrowser = async () => {
|
|
|
53
56
|
);
|
|
54
57
|
}
|
|
55
58
|
|
|
56
|
-
|
|
57
59
|
const context = await browser.newContext({
|
|
58
|
-
...(cucumberConfig.browser.device
|
|
60
|
+
...(cucumberConfig.browser.device
|
|
61
|
+
? devices[cucumberConfig.browser.device]
|
|
62
|
+
: {}),
|
|
59
63
|
...browserContextOptions,
|
|
60
64
|
});
|
|
61
65
|
|
|
@@ -4,7 +4,6 @@ const fs = require("fs");
|
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const { moduleConfig } = require("../../helper/imports/commons");
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
const duplicateWarnings = [];
|
|
9
8
|
const keyRegistry = {};
|
|
10
9
|
|
|
@@ -27,7 +26,7 @@ function pomCollector() {
|
|
|
27
26
|
Object.keys(parsed).forEach((key) => {
|
|
28
27
|
if (keyRegistry[key]) {
|
|
29
28
|
duplicateWarnings.push(
|
|
30
|
-
`${key} in ${file} has the same key with ${key} in ${keyRegistry[key]}
|
|
29
|
+
`${key} in ${file} has the same key with ${key} in ${keyRegistry[key]}`,
|
|
31
30
|
);
|
|
32
31
|
} else {
|
|
33
32
|
keyRegistry[key] = file;
|
|
@@ -37,35 +36,47 @@ function pomCollector() {
|
|
|
37
36
|
addElements(parsed);
|
|
38
37
|
});
|
|
39
38
|
|
|
40
|
-
const duplicationFilePath = path.join(
|
|
39
|
+
const duplicationFilePath = path.join(
|
|
40
|
+
moduleConfig.projectPath,
|
|
41
|
+
"node_modules",
|
|
42
|
+
"artes",
|
|
43
|
+
"pomDuplicateWarnings.json",
|
|
44
|
+
);
|
|
41
45
|
|
|
42
46
|
if (duplicateWarnings.length > 0) {
|
|
43
47
|
fs.mkdirSync(path.dirname(duplicationFilePath), { recursive: true });
|
|
44
48
|
fs.writeFileSync(
|
|
45
49
|
duplicationFilePath,
|
|
46
50
|
JSON.stringify(duplicateWarnings, null, 2),
|
|
47
|
-
"utf8"
|
|
51
|
+
"utf8",
|
|
48
52
|
);
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
function logPomWarnings() {
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
if (
|
|
58
|
+
!fs.existsSync(
|
|
59
|
+
path.join(moduleConfig.modulePath, "pomDuplicateWarnings.json"),
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
return;
|
|
55
63
|
|
|
56
64
|
const duplicateWarnings = JSON.parse(
|
|
57
|
-
fs.readFileSync(
|
|
65
|
+
fs.readFileSync(
|
|
66
|
+
path.join(moduleConfig.modulePath, "pomDuplicateWarnings.json"),
|
|
67
|
+
"utf8",
|
|
68
|
+
),
|
|
58
69
|
);
|
|
59
70
|
|
|
60
71
|
console.warn(
|
|
61
|
-
"\n\x1b[33m[WARNING] POM DUPLICATE KEY WARNINGS: This may break your tests or cause flaky behavior."
|
|
62
|
-
);
|
|
63
|
-
|
|
72
|
+
"\n\x1b[33m[WARNING] POM DUPLICATE KEY WARNINGS: This may break your tests or cause flaky behavior.",
|
|
73
|
+
);
|
|
74
|
+
|
|
64
75
|
duplicateWarnings.forEach((warning) => {
|
|
65
76
|
console.warn(`- ${warning}`);
|
|
66
77
|
});
|
|
67
78
|
|
|
68
|
-
console.log("\x1b[0m")
|
|
79
|
+
console.log("\x1b[0m");
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
module.exports = { pomCollector, logPomWarnings };
|
|
@@ -75,6 +75,9 @@ function showHelp() {
|
|
|
75
75
|
|
|
76
76
|
🌐 --browser Specify browser to use (chromium, firefox, webkit)
|
|
77
77
|
Usage: artes --browser chromium
|
|
78
|
+
|
|
79
|
+
--offline Run browser in offline mode
|
|
80
|
+
Usage: artes --offline
|
|
78
81
|
|
|
79
82
|
📱 --device Emulate specific device (e.g., "iPhone 13")
|
|
80
83
|
Usage: artes --device "iPhone 13"
|
|
@@ -66,6 +66,7 @@ function createProject(createYes, noDeps) {
|
|
|
66
66
|
// backtrace: false, // boolean - Show full backtrace for errors
|
|
67
67
|
// dryRun: false, // boolean - Prepare test run without execution
|
|
68
68
|
// browser: "chrome", // "chrome", "firefox", "webkit"
|
|
69
|
+
// offline: false, // boolean - Run browser in offline mode
|
|
69
70
|
// device: "", // string - Emulate specific device (e.g., "iPhone 13", for more devices look at the documentation)
|
|
70
71
|
// width: 1280, // number - Browser width
|
|
71
72
|
// height: 720, // number - Browser height
|
|
@@ -5,21 +5,17 @@ function runTests() {
|
|
|
5
5
|
try {
|
|
6
6
|
console.log("🧪 Running tests...");
|
|
7
7
|
|
|
8
|
-
spawnSync(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
FORCE_TTY: "1",
|
|
18
|
-
FORCE_COLOR: "1",
|
|
19
|
-
CI: "false",
|
|
20
|
-
},
|
|
8
|
+
spawnSync("cucumber-js", ["--config=cucumber.config.js"], {
|
|
9
|
+
cwd: moduleConfig.modulePath,
|
|
10
|
+
stdio: "inherit",
|
|
11
|
+
shell: true,
|
|
12
|
+
env: {
|
|
13
|
+
...process.env,
|
|
14
|
+
FORCE_TTY: "1",
|
|
15
|
+
FORCE_COLOR: "1",
|
|
16
|
+
CI: "false",
|
|
21
17
|
},
|
|
22
|
-
);
|
|
18
|
+
});
|
|
23
19
|
console.log("✅ Tests running completed successfully!");
|
|
24
20
|
} catch (error) {
|
|
25
21
|
console.error("❌ Test execution failed:", error);
|
|
@@ -14,7 +14,7 @@ const dayjs = require("dayjs");
|
|
|
14
14
|
|
|
15
15
|
const element = getElement;
|
|
16
16
|
const selector = getSelector;
|
|
17
|
-
const
|
|
17
|
+
const browserPage = context.page;
|
|
18
18
|
const request = context.request;
|
|
19
19
|
|
|
20
20
|
const random = faker;
|
|
@@ -50,7 +50,7 @@ module.exports = {
|
|
|
50
50
|
resolveVariable,
|
|
51
51
|
random,
|
|
52
52
|
time,
|
|
53
|
-
|
|
53
|
+
browserPage,
|
|
54
54
|
request,
|
|
55
55
|
context,
|
|
56
56
|
moduleConfig,
|
|
@@ -197,9 +197,11 @@ async function responseMaker(request, response, duration, curlCommand) {
|
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
const api = {
|
|
200
|
-
get: async (url, payload) => {
|
|
200
|
+
get: async (url, payload, options) => {
|
|
201
201
|
const URL = await selector(url);
|
|
202
202
|
|
|
203
|
+
options = options ?? {};
|
|
204
|
+
|
|
203
205
|
const resolvedPayload = (await payload) && resolveVariable(payload);
|
|
204
206
|
const payloadJSON = (await resolvedPayload) && JSON.parse(resolvedPayload);
|
|
205
207
|
|
|
@@ -207,7 +209,7 @@ const api = {
|
|
|
207
209
|
|
|
208
210
|
const requestStarts = performance.now();
|
|
209
211
|
|
|
210
|
-
const res = await context.request.get(URL, req);
|
|
212
|
+
const res = await context.request.get(URL, req, options);
|
|
211
213
|
|
|
212
214
|
const duration = performance.now() - requestStarts;
|
|
213
215
|
|
|
@@ -223,12 +225,14 @@ const api = {
|
|
|
223
225
|
|
|
224
226
|
context.response = await response;
|
|
225
227
|
},
|
|
226
|
-
head: async (url) => {
|
|
228
|
+
head: async (url, options) => {
|
|
227
229
|
const URL = await selector(url);
|
|
228
230
|
|
|
231
|
+
options = options ?? {};
|
|
232
|
+
|
|
229
233
|
const requestStarts = performance.now();
|
|
230
234
|
|
|
231
|
-
const res = await context.request.head(URL);
|
|
235
|
+
const res = await context.request.head(URL, options);
|
|
232
236
|
|
|
233
237
|
const duration = performance.now() - requestStarts;
|
|
234
238
|
|
|
@@ -238,9 +242,11 @@ const api = {
|
|
|
238
242
|
|
|
239
243
|
context.response = await response;
|
|
240
244
|
},
|
|
241
|
-
post: async (url, payload, requestDataType) => {
|
|
245
|
+
post: async (url, payload, requestDataType, options) => {
|
|
242
246
|
const URL = await selector(url);
|
|
243
247
|
|
|
248
|
+
options = options ?? {};
|
|
249
|
+
|
|
244
250
|
const resolvedPayload = (await payload) && resolveVariable(payload);
|
|
245
251
|
const payloadJSON = (await resolvedPayload) && JSON.parse(resolvedPayload);
|
|
246
252
|
|
|
@@ -285,7 +291,7 @@ const api = {
|
|
|
285
291
|
|
|
286
292
|
const requestStarts = performance.now();
|
|
287
293
|
|
|
288
|
-
const res = await context.request.post(URL, req);
|
|
294
|
+
const res = await context.request.post(URL, req, options);
|
|
289
295
|
|
|
290
296
|
const duration = performance.now() - requestStarts;
|
|
291
297
|
|
|
@@ -306,9 +312,11 @@ const api = {
|
|
|
306
312
|
|
|
307
313
|
context.response = response;
|
|
308
314
|
},
|
|
309
|
-
put: async (url, payload, requestDataType) => {
|
|
315
|
+
put: async (url, payload, requestDataType, options) => {
|
|
310
316
|
const URL = await selector(url);
|
|
311
317
|
|
|
318
|
+
options = options ?? {};
|
|
319
|
+
|
|
312
320
|
const resolvedPayload = (await payload) && resolveVariable(payload);
|
|
313
321
|
const payloadJSON = (await resolvedPayload) && JSON.parse(resolvedPayload);
|
|
314
322
|
|
|
@@ -353,7 +361,7 @@ const api = {
|
|
|
353
361
|
|
|
354
362
|
const requestStarts = performance.now();
|
|
355
363
|
|
|
356
|
-
const res = await context.request.put(URL, req);
|
|
364
|
+
const res = await context.request.put(URL, req, options);
|
|
357
365
|
|
|
358
366
|
const duration = performance.now() - requestStarts;
|
|
359
367
|
|
|
@@ -374,9 +382,11 @@ const api = {
|
|
|
374
382
|
|
|
375
383
|
context.response = response;
|
|
376
384
|
},
|
|
377
|
-
patch: async (url, payload, requestDataType) => {
|
|
385
|
+
patch: async (url, payload, requestDataType, options) => {
|
|
378
386
|
const URL = await selector(url);
|
|
379
387
|
|
|
388
|
+
options = options ?? {};
|
|
389
|
+
|
|
380
390
|
const resolvedPayload = (await payload) && resolveVariable(payload);
|
|
381
391
|
const payloadJSON = (await resolvedPayload) && JSON.parse(resolvedPayload);
|
|
382
392
|
|
|
@@ -421,7 +431,7 @@ const api = {
|
|
|
421
431
|
|
|
422
432
|
const requestStarts = performance.now();
|
|
423
433
|
|
|
424
|
-
const res = await context.request.patch(URL, req);
|
|
434
|
+
const res = await context.request.patch(URL, req, options);
|
|
425
435
|
|
|
426
436
|
const duration = performance.now() - requestStarts;
|
|
427
437
|
|
|
@@ -442,9 +452,11 @@ const api = {
|
|
|
442
452
|
|
|
443
453
|
context.response = response;
|
|
444
454
|
},
|
|
445
|
-
delete: async (url, payload) => {
|
|
455
|
+
delete: async (url, payload, options) => {
|
|
446
456
|
const URL = await selector(url);
|
|
447
457
|
|
|
458
|
+
options = options ?? {};
|
|
459
|
+
|
|
448
460
|
const resolvedPayload = (await payload) && resolveVariable(payload);
|
|
449
461
|
const payloadJSON = (await resolvedPayload) && JSON.parse(resolvedPayload);
|
|
450
462
|
|
|
@@ -455,7 +467,7 @@ const api = {
|
|
|
455
467
|
|
|
456
468
|
const requestStarts = performance.now();
|
|
457
469
|
|
|
458
|
-
const res = await context.request.delete(URL, req);
|
|
470
|
+
const res = await context.request.delete(URL, req, options);
|
|
459
471
|
|
|
460
472
|
const duration = performance.now() - requestStarts;
|
|
461
473
|
|
|
@@ -471,8 +483,12 @@ const api = {
|
|
|
471
483
|
|
|
472
484
|
context.response = await response;
|
|
473
485
|
},
|
|
474
|
-
vars: () => {
|
|
475
|
-
|
|
486
|
+
vars: (variable) => {
|
|
487
|
+
if(!variable){
|
|
488
|
+
return context.vars;
|
|
489
|
+
}else{
|
|
490
|
+
return { [variable]: context.vars[variable] };
|
|
491
|
+
}
|
|
476
492
|
},
|
|
477
493
|
};
|
|
478
494
|
|