artes 1.4.3 → 1.4.5
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 +17 -5
- package/cucumber.config.js +20 -0
- package/executer.js +132 -14
- package/package.json +2 -1
- package/src/helper/executers/helper.js +3 -0
- package/src/helper/executers/projectCreator.js +2 -0
- package/src/helper/executers/reportGenerator.js +1 -1
- package/src/helper/imports/commons.js +1 -1
- package/src/hooks/hooks.js +35 -63
- package/src/stepDefinitions/assertions.steps.js +230 -6
- package/src/stepDefinitions/mouseActions.steps.js +35 -0
package/README.md
CHANGED
|
@@ -119,6 +119,7 @@ npx artes [options]
|
|
|
119
119
|
| 📜 `--stepDef` | Specify one or more step definition files' relative paths to use (comma-separated) | `artes --stepDef "tests/steps/login.js,tests/steps/home.js"` |
|
|
120
120
|
| 🔖 `--tags` | Run tests with specified Cucumber tags | `artes --tags "@smoke or @wip"` |
|
|
121
121
|
| 🌐 `--env` | Set the environment for the test run | `artes --env "dev"` |
|
|
122
|
+
| `--saveVar` | Set the variables from CLI | `artes --saveVar '{"armud":20,"banana":200}'` |
|
|
122
123
|
| 🕶️ `--headless` | Run browser in headless mode | `artes --headless` |
|
|
123
124
|
| ⚡ `--parallel` | Run tests in parallel mode | `artes --parallel 2` |
|
|
124
125
|
| 🔁 `--retry` | Retry failed tests | `artes --retry 3` |
|
|
@@ -482,23 +483,34 @@ You can configure Artes by editing the `artes.config.js` file. Below are the def
|
|
|
482
483
|
|
|
483
484
|
| **Option** | **Default Value** | **Description** |
|
|
484
485
|
| ----------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
486
|
+
| `headless` | `false` | Run browser in headless mode. |
|
|
487
|
+
| `env` | `""` | Environment name for tests. |
|
|
488
|
+
| `variables` | `{}` | Variables for tests. |
|
|
489
|
+
| `baseURL` | `""` | Base URL for API or web tests. |
|
|
485
490
|
| `timeout` | `30` | Default timeout in seconds. |
|
|
486
|
-
| `slowMo` | `0` | Default slow motion in seconds
|
|
491
|
+
| `slowMo` | `0` | Default slow motion in seconds. |
|
|
487
492
|
| `paths` | `[moduleConfig.featuresPath]` | Paths to feature files. |
|
|
488
493
|
| `require` | `[moduleConfig.stepsPath, "src/stepDefinitions/*.js", "src/hooks/hooks.js"]` | Support code paths (CommonJS). |
|
|
489
494
|
| `pomPath` | `moduleConfig.pomPath` | Path to Page Object Models. |
|
|
490
495
|
| `import` | `[]` | Support code paths. |
|
|
491
496
|
| `testPercentage` | `0` | Define test coverage percentage |
|
|
492
497
|
| `report` | `false` | Generate report |
|
|
493
|
-
| `
|
|
494
|
-
| `
|
|
495
|
-
| `
|
|
498
|
+
| `zip` | `false` | Generate zip of report |
|
|
499
|
+
| `reportSuccess` | `false` | Add screenshots and video records also for success test cases |
|
|
500
|
+
| `trace` | `false` | Enable tracing |
|
|
501
|
+
| `reportWithTrace` | `false` | Include trace in report |
|
|
496
502
|
| `format` | `["rerun:@rerun.txt", "allure-cucumberjs/reporter"]` | Formatter names/paths. |
|
|
497
503
|
| `formatOptions` | `{ "resultsDir": "allure-result" }` | Formatter options. |
|
|
498
504
|
| `parallel` | `1` | Number of parallel workers. |
|
|
505
|
+
| `browser` | `"chrome"` | Browser to use: "chrome", "firefox", "webkit". |
|
|
506
|
+
| `offline` | `false` | Run browser in offline mode. |
|
|
507
|
+
| `device` | `""` | Emulate specific device (e.g., "iPhone 13"). |
|
|
508
|
+
| `width` | `1280` | Browser width in pixels. |
|
|
509
|
+
| `height` | `720` | Browser height in pixels. |
|
|
510
|
+
| `maximizeScreen` | `true` | Maximize browser window on start. |
|
|
499
511
|
| `dryRun` | `false` | Prepare test run without execution. |
|
|
500
512
|
| `failFast` | `false` | Stop on first test failure. |
|
|
501
|
-
| `forceExit` | `false` | Force `process.exit()` after tests
|
|
513
|
+
| `forceExit` | `false` | Force `process.exit()` after tests |
|
|
502
514
|
| `strict` | `true` | Fail on pending steps. |
|
|
503
515
|
| `backtrace` | `false` | Show full backtrace for errors. |
|
|
504
516
|
| `tags` | `""` | Tag expression to filter scenarios. |
|
package/cucumber.config.js
CHANGED
|
@@ -51,6 +51,25 @@ function resolveEnv(artesConfig) {
|
|
|
51
51
|
}
|
|
52
52
|
const env = resolveEnv(artesConfig);
|
|
53
53
|
|
|
54
|
+
function loadVariables(cliVariables, artesConfigVariables) {
|
|
55
|
+
|
|
56
|
+
if (cliVariables) {
|
|
57
|
+
try {
|
|
58
|
+
cliVariables = JSON.parse(process.env.VARS);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error("Invalid JSON in process.env.VARS:", process.env.VARS);
|
|
61
|
+
envVars = {};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const mergedVars = {
|
|
66
|
+
...(artesConfigVariables || {}),
|
|
67
|
+
...cliVariables,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return mergedVars;
|
|
71
|
+
}
|
|
72
|
+
|
|
54
73
|
const resolveFeaturePaths = (basePath, value) => {
|
|
55
74
|
return value
|
|
56
75
|
.split(',')
|
|
@@ -162,6 +181,7 @@ module.exports = {
|
|
|
162
181
|
zip: process.env.ZIP == "true" ? true : artesConfig.zip ? true : false,
|
|
163
182
|
},
|
|
164
183
|
env: env,
|
|
184
|
+
variables: loadVariables(process.env.VARS, artesConfig.variables),
|
|
165
185
|
baseURL: process.env.BASE_URL
|
|
166
186
|
? JSON.parse(process.env.BASE_URL)
|
|
167
187
|
: artesConfig?.baseURL
|
package/executer.js
CHANGED
|
@@ -10,13 +10,14 @@ const {
|
|
|
10
10
|
const { logPomWarnings } = require("./src/helper/controller/pomCollector");
|
|
11
11
|
const fs = require("fs");
|
|
12
12
|
const path = require("path");
|
|
13
|
+
const { spawnSync } = require("child_process");
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
+
const artesConfigPath = path.resolve(process.cwd(), "artes.config.js");
|
|
15
16
|
|
|
16
17
|
let artesConfig = {};
|
|
17
18
|
|
|
18
|
-
if (fs.existsSync(
|
|
19
|
-
artesConfig = require(
|
|
19
|
+
if (fs.existsSync(artesConfigPath)) {
|
|
20
|
+
artesConfig = require(artesConfigPath);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
const args = process.argv.slice(2);
|
|
@@ -37,6 +38,7 @@ const flags = {
|
|
|
37
38
|
stepDef: args.includes("--stepDef"),
|
|
38
39
|
tags: args.includes("--tags"),
|
|
39
40
|
env: args.includes("--env"),
|
|
41
|
+
saveVar: args.includes("--saveVar"),
|
|
40
42
|
headless: args.includes("--headless"),
|
|
41
43
|
parallel: args.includes("--parallel"),
|
|
42
44
|
retry: args.includes("--retry"),
|
|
@@ -55,6 +57,7 @@ const flags = {
|
|
|
55
57
|
};
|
|
56
58
|
|
|
57
59
|
const env = args[args.indexOf("--env") + 1];
|
|
60
|
+
const vars = args[args.indexOf("--saveVar") + 1]
|
|
58
61
|
const featureFiles = args[args.indexOf("--features") + 1];
|
|
59
62
|
const features = flags.features && featureFiles;
|
|
60
63
|
const stepDef = args[args.indexOf("--stepDef") + 1];
|
|
@@ -73,6 +76,8 @@ const slowMo = args[args.indexOf("--slowMo") + 1];
|
|
|
73
76
|
|
|
74
77
|
flags.env ? (process.env.ENV = env) : "";
|
|
75
78
|
|
|
79
|
+
vars ? (process.env.VARS = vars) : "";
|
|
80
|
+
|
|
76
81
|
flags.reportWithTrace ||
|
|
77
82
|
artesConfig.reportWithTrace ||
|
|
78
83
|
flags.report ||
|
|
@@ -146,6 +151,83 @@ flags.timeout ? (process.env.TIMEOUT = timeout) : "";
|
|
|
146
151
|
|
|
147
152
|
flags.slowMo ? (process.env.SLOWMO = slowMo) : "";
|
|
148
153
|
|
|
154
|
+
|
|
155
|
+
function testCoverageCalculation(testStatusDir){
|
|
156
|
+
if(fs.existsSync(testStatusDir)){
|
|
157
|
+
const files = fs.readdirSync(testStatusDir);
|
|
158
|
+
|
|
159
|
+
const map = {};
|
|
160
|
+
const retriedTests = [];
|
|
161
|
+
const uuidRegex = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
|
|
162
|
+
|
|
163
|
+
files.forEach(file => {
|
|
164
|
+
const match = file.match(uuidRegex);
|
|
165
|
+
if (!match) return;
|
|
166
|
+
|
|
167
|
+
const id = match[0];
|
|
168
|
+
|
|
169
|
+
const beforeId = file.substring(0, file.indexOf(id) - 1);
|
|
170
|
+
const afterId = file.substring(file.indexOf(id) + id.length + 1);
|
|
171
|
+
|
|
172
|
+
const status = beforeId.split('-')[0];
|
|
173
|
+
const scenario = beforeId.substring(status.length + 1);
|
|
174
|
+
const timestamp = afterId;
|
|
175
|
+
|
|
176
|
+
if (!map[id]) {
|
|
177
|
+
map[id] = {
|
|
178
|
+
count: 1,
|
|
179
|
+
latest: { status, scenario, timestamp }
|
|
180
|
+
};
|
|
181
|
+
} else {
|
|
182
|
+
map[id].count++;
|
|
183
|
+
if (timestamp > map[id].latest.timestamp) {
|
|
184
|
+
map[id].latest = { status, scenario, timestamp };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
let total = 0;
|
|
190
|
+
let notPassed = 0;
|
|
191
|
+
|
|
192
|
+
Object.entries(map).forEach(([id, data]) => {
|
|
193
|
+
total++;
|
|
194
|
+
|
|
195
|
+
if (data.count > 1) {
|
|
196
|
+
retriedTests.push({
|
|
197
|
+
scenario: data.latest.scenario,
|
|
198
|
+
id,
|
|
199
|
+
count: data.count
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (data.latest.status !== 'PASSED') {
|
|
204
|
+
notPassed++;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
if (retriedTests.length > 0) {
|
|
209
|
+
console.warn('\n\x1b[33mRetried test cases:');
|
|
210
|
+
retriedTests.forEach(t => {
|
|
211
|
+
console.warn(`- "${t.scenario}" ran ${t.count} times`);
|
|
212
|
+
});
|
|
213
|
+
console.log("\x1b[0m");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
percentage : (total - notPassed)/total*100,
|
|
218
|
+
totalTests: total,
|
|
219
|
+
notPassed,
|
|
220
|
+
passed: total - notPassed,
|
|
221
|
+
latestStatuses: Object.fromEntries(
|
|
222
|
+
Object.entries(map).map(([id, data]) => [
|
|
223
|
+
id,
|
|
224
|
+
data.latest.status
|
|
225
|
+
])
|
|
226
|
+
)
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
149
231
|
function main() {
|
|
150
232
|
if (flags.help) return showHelp();
|
|
151
233
|
if (flags.version) return showVersion();
|
|
@@ -155,6 +237,35 @@ function main() {
|
|
|
155
237
|
|
|
156
238
|
logPomWarnings();
|
|
157
239
|
|
|
240
|
+
const testCoverage = testCoverageCalculation(path.join(process.cwd(), "node_modules", "artes" , "testsStatus"))
|
|
241
|
+
|
|
242
|
+
const testPercentage = (process.env.PERCENTAGE ? Number(process.env.PERCENTAGE) : artesConfig.testPercentage || 0)
|
|
243
|
+
|
|
244
|
+
if (testPercentage > 0) {
|
|
245
|
+
|
|
246
|
+
const meetsThreshold = testCoverage.percentage >= testPercentage
|
|
247
|
+
|
|
248
|
+
if (meetsThreshold) {
|
|
249
|
+
console.log(
|
|
250
|
+
`✅ Tests passed required ${testPercentage}% success rate with ${testCoverage.percentage.toFixed(2)}%!`,
|
|
251
|
+
);
|
|
252
|
+
process.env.EXIT_CODE = parseInt(0, 10);
|
|
253
|
+
} else {
|
|
254
|
+
console.log(
|
|
255
|
+
`❌ Tests failed required ${testPercentage}% success rate with ${testCoverage.percentage.toFixed(2)}%!`,
|
|
256
|
+
);
|
|
257
|
+
process.env.EXIT_CODE = parseInt(1, 10);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (fs.existsSync(path.join(process.cwd(), "node_modules", "artes" , "@rerun.txt"))) {
|
|
262
|
+
spawnSync("mv", ["@rerun.txt", process.cwd()], {
|
|
263
|
+
cwd: path.join(process.cwd(), "node_modules", "artes"),
|
|
264
|
+
stdio: "inherit",
|
|
265
|
+
shell: true,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
158
269
|
if (
|
|
159
270
|
flags.reportWithTrace ||
|
|
160
271
|
artesConfig.reportWithTrace ||
|
|
@@ -163,18 +274,25 @@ function main() {
|
|
|
163
274
|
)
|
|
164
275
|
generateReport();
|
|
165
276
|
|
|
166
|
-
if (
|
|
167
|
-
fs.existsSync(
|
|
168
|
-
path.join(process.cwd(), "node_modules", "artes", "EXIT_CODE.txt"),
|
|
169
|
-
)
|
|
170
|
-
) {
|
|
171
|
-
const data = fs.readFileSync(
|
|
172
|
-
path.join(process.cwd(), "node_modules", "artes", "EXIT_CODE.txt"),
|
|
173
|
-
"utf8",
|
|
174
|
-
);
|
|
175
|
-
process.env.EXIT_CODE = parseInt(data, 10);
|
|
176
|
-
}
|
|
177
277
|
|
|
278
|
+
if (!( process.env.TRACE === "true"
|
|
279
|
+
? process.env.TRACE
|
|
280
|
+
: artesConfig.trace || false)) {
|
|
281
|
+
spawnSync(
|
|
282
|
+
"npx",
|
|
283
|
+
[
|
|
284
|
+
"rimraf",
|
|
285
|
+
"--no-glob",
|
|
286
|
+
path.join(process.cwd(), "traces"),
|
|
287
|
+
],
|
|
288
|
+
{
|
|
289
|
+
cwd: process.cwd(),
|
|
290
|
+
stdio: "inherit",
|
|
291
|
+
shell: false,
|
|
292
|
+
},
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
178
296
|
cleanUp();
|
|
179
297
|
process.exit(process.env.EXIT_CODE);
|
|
180
298
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "artes",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.5",
|
|
4
4
|
"description": "The simplest way to automate UI and API tests using Cucumber-style steps.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"dayjs": "1.11.13",
|
|
31
31
|
"deasync": "^0.1.31",
|
|
32
32
|
"playwright": "^1.58.2",
|
|
33
|
+
"proper-lockfile": "^4.1.2",
|
|
33
34
|
"rimraf": "6.0.1"
|
|
34
35
|
},
|
|
35
36
|
"repository": {
|
|
@@ -54,6 +54,9 @@ function showHelp() {
|
|
|
54
54
|
|
|
55
55
|
🌐 --env Set environment for the test run
|
|
56
56
|
Usage: artes --env "dev"
|
|
57
|
+
|
|
58
|
+
--saveVar Set variables from cli
|
|
59
|
+
artes --saveVar '{"armud":20,"banana":200}'
|
|
57
60
|
|
|
58
61
|
🕶️ --headless Run browser in headless mode
|
|
59
62
|
Usage: artes --headless
|
|
@@ -47,6 +47,7 @@ function createProject(createYes, noDeps) {
|
|
|
47
47
|
|
|
48
48
|
// Configuration options:
|
|
49
49
|
// env: "", // string - Environment name for tests
|
|
50
|
+
// variables: {} // object - Variables for tests
|
|
50
51
|
// testPercentage: 0, // number - Minimum success rate percentage(Default: 0)
|
|
51
52
|
// baseURL: "", // string - Base URL for API tests
|
|
52
53
|
// paths: [], // string[] - Paths to feature files
|
|
@@ -56,6 +57,7 @@ function createProject(createYes, noDeps) {
|
|
|
56
57
|
// slowMo: 0, // number - Slow down test execution (Default: 0 seconds)
|
|
57
58
|
// parallel: 0, // number - Number of parallel workers
|
|
58
59
|
// report: true // boolean - Generate report
|
|
60
|
+
// zip: false // boolean - Generate zip of report
|
|
59
61
|
// reportSuccess: false, // boolean - Add screenshots and video records to report also for success test cases
|
|
60
62
|
// trace: false, // boolean - Enable tracing
|
|
61
63
|
// reportWithTrace: false, // boolean - Include trace in report
|
|
@@ -58,7 +58,7 @@ function generateReport() {
|
|
|
58
58
|
|
|
59
59
|
require("deasync").loopWhile(() => !done);
|
|
60
60
|
|
|
61
|
-
console.log(`🗜️ Zipped in ${moduleConfig.
|
|
61
|
+
console.log(`🗜️ Zipped in ${path.join( path.dirname(moduleConfig.reportPath), "report.zip" )}!`);
|
|
62
62
|
if (error) throw error;
|
|
63
63
|
}
|
|
64
64
|
} catch (err) {
|
|
@@ -35,7 +35,7 @@ const moduleConfig = {
|
|
|
35
35
|
stepsPath: path.join(projectPath, "/tests/steps/*.js"),
|
|
36
36
|
pomPath: path.join(projectPath, "/tests/POMs"),
|
|
37
37
|
cleanUpPaths:
|
|
38
|
-
"allure-result allure-results test-results @rerun.txt testsStatus
|
|
38
|
+
"allure-result allure-results test-results @rerun.txt testsStatus pomDuplicateWarnings.json",
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
module.exports = {
|
package/src/hooks/hooks.js
CHANGED
|
@@ -8,18 +8,16 @@ const {
|
|
|
8
8
|
BeforeStep,
|
|
9
9
|
AfterAll,
|
|
10
10
|
} = require("@cucumber/cucumber");
|
|
11
|
-
const { spawnSync } = require("child_process");
|
|
12
11
|
const { invokeBrowser } = require("../helper/contextManager/browserManager");
|
|
13
12
|
const { invokeRequest } = require("../helper/contextManager/requestManager");
|
|
14
13
|
const {
|
|
15
|
-
pomCollector
|
|
16
|
-
logPomWarnings,
|
|
14
|
+
pomCollector
|
|
17
15
|
} = require("../helper/controller/pomCollector");
|
|
18
16
|
const cucumberConfig = require("../../cucumber.config");
|
|
19
17
|
const { context } = require("./context");
|
|
20
18
|
const fs = require("fs");
|
|
21
19
|
const path = require("path");
|
|
22
|
-
const { moduleConfig } = require("artes/src/helper/imports/commons");
|
|
20
|
+
const { moduleConfig, saveVar } = require("artes/src/helper/imports/commons");
|
|
23
21
|
require("allure-cucumberjs");
|
|
24
22
|
const allure = require("allure-js-commons");
|
|
25
23
|
|
|
@@ -44,11 +42,26 @@ async function attachResponse(attachFn) {
|
|
|
44
42
|
}
|
|
45
43
|
|
|
46
44
|
function saveTestStatus(result, pickle) {
|
|
45
|
+
|
|
47
46
|
fs.mkdirSync(statusDir, { recursive: true });
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
|
|
48
|
+
const now = new Date();
|
|
49
|
+
const YYYY = now.getFullYear();
|
|
50
|
+
const MM = String(now.getMonth() + 1).padStart(2, '0');
|
|
51
|
+
const DD = String(now.getDate()).padStart(2, '0');
|
|
52
|
+
const hh = String(now.getHours()).padStart(2, '0');
|
|
53
|
+
const mm = String(now.getMinutes()).padStart(2, '0');
|
|
54
|
+
const ss = String(now.getSeconds()).padStart(2, '0');
|
|
55
|
+
const ms = String(now.getMilliseconds()).padStart(3, '0');
|
|
56
|
+
|
|
57
|
+
const timestamp = `${YYYY}${MM}${DD}-${hh}${mm}${ss}-${ms}`;
|
|
58
|
+
|
|
59
|
+
const fileName = `${result.status}-${pickle.name}-${pickle.id}-${timestamp}.txt`;
|
|
60
|
+
|
|
61
|
+
const filePath = path.join(statusDir, fileName);
|
|
62
|
+
|
|
63
|
+
fs.writeFileSync(filePath, "");
|
|
64
|
+
|
|
52
65
|
}
|
|
53
66
|
|
|
54
67
|
const projectHooksPath = path.resolve(
|
|
@@ -78,9 +91,18 @@ BeforeAll(async () => {
|
|
|
78
91
|
pomCollector();
|
|
79
92
|
});
|
|
80
93
|
|
|
81
|
-
Before(async function () {
|
|
94
|
+
Before(async function ({pickle}) {
|
|
82
95
|
context.vars = {};
|
|
83
96
|
|
|
97
|
+
const vars = await cucumberConfig.variables
|
|
98
|
+
|
|
99
|
+
if (vars && typeof vars === "object") {
|
|
100
|
+
for (let [key, value] of Object.entries(vars)) {
|
|
101
|
+
|
|
102
|
+
saveVar(value, key);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
84
106
|
const envFilePath = path.join(
|
|
85
107
|
moduleConfig.projectPath,
|
|
86
108
|
"tests",
|
|
@@ -110,6 +132,7 @@ Before(async function () {
|
|
|
110
132
|
|
|
111
133
|
if (cucumberConfig.default.reportWithTrace || cucumberConfig.default.trace) {
|
|
112
134
|
await browserContext.tracing.start({
|
|
135
|
+
title: pickle.name,
|
|
113
136
|
sources: true,
|
|
114
137
|
screenshots: true,
|
|
115
138
|
snapshots: true,
|
|
@@ -141,7 +164,7 @@ AfterStep(async function ({ pickleStep }) {
|
|
|
141
164
|
}
|
|
142
165
|
});
|
|
143
166
|
|
|
144
|
-
After(async function ({ pickle
|
|
167
|
+
After(async function ({result, pickle}) {
|
|
145
168
|
if (typeof projectHooks.After === "function") {
|
|
146
169
|
await projectHooks.After();
|
|
147
170
|
}
|
|
@@ -155,12 +178,12 @@ After(async function ({ pickle, result }) {
|
|
|
155
178
|
await allure.attachment("Screenshot", screenshotBuffer, "image/png");
|
|
156
179
|
}
|
|
157
180
|
|
|
158
|
-
saveTestStatus(result, pickle);
|
|
181
|
+
if(cucumberConfig.default.testPercentage>0) saveTestStatus(result, pickle);
|
|
159
182
|
|
|
160
183
|
if (cucumberConfig.default.reportWithTrace || cucumberConfig.default.trace) {
|
|
161
184
|
var tracePath = path.join(
|
|
162
185
|
moduleConfig.projectPath,
|
|
163
|
-
`./traces/${pickle.name.replaceAll(" ", "_")}.zip`,
|
|
186
|
+
`./traces/${pickle.name.replaceAll(" ", "_")}-${pickle.id}.zip`,
|
|
164
187
|
);
|
|
165
188
|
}
|
|
166
189
|
|
|
@@ -211,55 +234,4 @@ AfterAll(async () => {
|
|
|
211
234
|
await projectHooks.AfterAll();
|
|
212
235
|
}
|
|
213
236
|
|
|
214
|
-
logPomWarnings();
|
|
215
|
-
|
|
216
|
-
if (!cucumberConfig.default.trace) {
|
|
217
|
-
spawnSync(
|
|
218
|
-
"npx",
|
|
219
|
-
[
|
|
220
|
-
"rimraf",
|
|
221
|
-
"--no-glob",
|
|
222
|
-
path.join(moduleConfig.projectPath, "./traces"),
|
|
223
|
-
],
|
|
224
|
-
{
|
|
225
|
-
cwd: moduleConfig.projectPath,
|
|
226
|
-
stdio: "inherit",
|
|
227
|
-
shell: false,
|
|
228
|
-
},
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (!fs.existsSync(statusDir)) return;
|
|
233
|
-
|
|
234
|
-
const files = fs.readdirSync(statusDir);
|
|
235
|
-
const passedCount = files.filter((f) => f.split("-")[0] === "PASSED").length;
|
|
236
|
-
const totalTests = files.length;
|
|
237
|
-
const successPercentage = (passedCount / totalTests) * 100;
|
|
238
|
-
|
|
239
|
-
const failed = files.filter((f) => f.split("-")[0] === "FAILED").length;
|
|
240
|
-
|
|
241
|
-
if (failed > 0) {
|
|
242
|
-
spawnSync("mv", ["@rerun.txt", moduleConfig.projectPath], {
|
|
243
|
-
cwd: path.join(moduleConfig.projectPath, "node_modules", "artes"),
|
|
244
|
-
stdio: "ignore",
|
|
245
|
-
shell: true,
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (cucumberConfig.default.testPercentage > 0) {
|
|
250
|
-
const meetsThreshold =
|
|
251
|
-
successPercentage >= cucumberConfig.default.testPercentage;
|
|
252
|
-
|
|
253
|
-
if (meetsThreshold) {
|
|
254
|
-
console.log(
|
|
255
|
-
`✅ Tests passed required ${cucumberConfig.default.testPercentage}% success rate with ${successPercentage.toFixed(2)}%!`,
|
|
256
|
-
);
|
|
257
|
-
fs.writeFileSync(path.join(process.cwd(), "EXIT_CODE.txt"), "0");
|
|
258
|
-
} else {
|
|
259
|
-
console.log(
|
|
260
|
-
`❌ Tests failed required ${cucumberConfig.default.testPercentage}% success rate with ${successPercentage.toFixed(2)}%!`,
|
|
261
|
-
);
|
|
262
|
-
fs.writeFileSync(path.join(process.cwd(), "EXIT_CODE.txt"), "1");
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
237
|
});
|
|
@@ -15,41 +15,81 @@ Then("User expects {string} should be attached", async function (selector) {
|
|
|
15
15
|
await assert.shouldBeAttached(selector);
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
+
Then("User expects {int} th of {string} should be attached", async function (order, elements) {
|
|
19
|
+
const nthElement = await frame.nth(elements, order);
|
|
20
|
+
await assert.shouldBeAttached(nthElement);
|
|
21
|
+
});
|
|
22
|
+
|
|
18
23
|
// Check if a selector should be checked
|
|
19
24
|
Then("User expects {string} should be checked", async function (selector) {
|
|
20
25
|
await assert.shouldBeChecked(selector);
|
|
21
26
|
});
|
|
22
27
|
|
|
28
|
+
Then("User expects {int} th of {string} should be checked", async function (order, elements) {
|
|
29
|
+
const nthElement = await frame.nth(elements, order);
|
|
30
|
+
await assert.shouldBeChecked(nthElement);
|
|
31
|
+
});
|
|
32
|
+
|
|
23
33
|
// Check if a selector should be disabled
|
|
24
34
|
Then("User expects {string} should be disabled", async function (selector) {
|
|
25
35
|
await assert.shouldBeDisabled(selector);
|
|
26
36
|
});
|
|
27
37
|
|
|
38
|
+
Then("User expects {int} th of {string} should be disabled", async function (order, elements) {
|
|
39
|
+
const nthElement = await frame.nth(elements, order);
|
|
40
|
+
await assert.shouldBeDisabled(nthElement);
|
|
41
|
+
});
|
|
42
|
+
|
|
28
43
|
// Check if a selector should be editable
|
|
29
44
|
Then("User expects {string} should be editable", async function (selector) {
|
|
30
45
|
await assert.shouldBeEditable(selector);
|
|
31
46
|
});
|
|
32
47
|
|
|
48
|
+
Then("User expects {int} th of {string} should be editable", async function (order, elements) {
|
|
49
|
+
const nthElement = await frame.nth(elements, order);
|
|
50
|
+
await assert.shouldBeEditable(nthElement);
|
|
51
|
+
});
|
|
52
|
+
|
|
33
53
|
// Check if a selector should be empty
|
|
34
54
|
Then("User expects {string} should be empty", async function (selector) {
|
|
35
55
|
await assert.shouldBeEmpty(selector);
|
|
36
56
|
});
|
|
37
57
|
|
|
58
|
+
Then("User expects {int} th of {string} should be empty", async function (order, elements) {
|
|
59
|
+
const nthElement = await frame.nth(elements, order);
|
|
60
|
+
await assert.shouldBeEmpty(nthElement);
|
|
61
|
+
});
|
|
62
|
+
|
|
38
63
|
// Check if a selector should be enabled
|
|
39
64
|
Then("User expects {string} should be enabled", async function (selector) {
|
|
40
65
|
await assert.shouldBeEnabled(selector);
|
|
41
66
|
});
|
|
42
67
|
|
|
68
|
+
Then("User expects {int} th of {string} should be enabled", async function (order, elements) {
|
|
69
|
+
const nthElement = await frame.nth(elements, order);
|
|
70
|
+
await assert.shouldBeEnabled(nthElement);
|
|
71
|
+
});
|
|
72
|
+
|
|
43
73
|
// Check if a selector should be focused
|
|
44
74
|
Then("User expects {string} should be focused", async function (selector) {
|
|
45
75
|
await assert.shouldBeFocused(selector);
|
|
46
76
|
});
|
|
47
77
|
|
|
78
|
+
Then("User expects {int} th of {string} should be focused", async function (order, elements) {
|
|
79
|
+
const nthElement = await frame.nth(elements, order);
|
|
80
|
+
await assert.shouldBeFocused(nthElement);
|
|
81
|
+
});
|
|
82
|
+
|
|
48
83
|
// Check if a selector should be hidden
|
|
49
84
|
Then("User expects {string} should be hidden", async function (selector) {
|
|
50
85
|
await assert.shouldBeHidden(selector);
|
|
51
86
|
});
|
|
52
87
|
|
|
88
|
+
Then("User expects {int} th of {string} should be hidden", async function (order, elements) {
|
|
89
|
+
const nthElement = await frame.nth(elements, order);
|
|
90
|
+
await assert.shouldBeHidden(nthElement);
|
|
91
|
+
});
|
|
92
|
+
|
|
53
93
|
// Check if a selector should be in the viewport
|
|
54
94
|
Then(
|
|
55
95
|
"User expects {string} should be on the screen",
|
|
@@ -58,11 +98,29 @@ Then(
|
|
|
58
98
|
},
|
|
59
99
|
);
|
|
60
100
|
|
|
101
|
+
Then(
|
|
102
|
+
"User expects {int} th of {string} should be on the screen",
|
|
103
|
+
async function (order, elements) {
|
|
104
|
+
const nthElement = await frame.nth(elements, order);
|
|
105
|
+
await assert.shouldBeInViewport(nthElement);
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
Then("User expects {int} th of {string} should be screen", async function (order, elements) {
|
|
110
|
+
const nthElement = await frame.nth(elements, order);
|
|
111
|
+
await assert.shouldBeInViewport(nthElement);
|
|
112
|
+
});
|
|
113
|
+
|
|
61
114
|
// Check if a selector should be visible
|
|
62
115
|
Then("User expects {string} should be visible", async function (selector) {
|
|
63
116
|
await assert.shouldBeVisible(selector);
|
|
64
117
|
});
|
|
65
118
|
|
|
119
|
+
Then("User expects {int} th of {string} should be visible", async function (order, elements) {
|
|
120
|
+
const nthElement = await frame.nth(elements, order);
|
|
121
|
+
await assert.shouldBeVisible(nthElement);
|
|
122
|
+
});
|
|
123
|
+
|
|
66
124
|
// Check if a selector should contain specific text
|
|
67
125
|
Then(
|
|
68
126
|
"User expects {string} should have {string} text",
|
|
@@ -71,6 +129,11 @@ Then(
|
|
|
71
129
|
},
|
|
72
130
|
);
|
|
73
131
|
|
|
132
|
+
Then("User expects {int} th of {string} should have {string} text", async function (order, elements, text) {
|
|
133
|
+
const nthElement = await frame.nth(elements, order);
|
|
134
|
+
await assert.shouldContainText(nthElement, text);
|
|
135
|
+
});
|
|
136
|
+
|
|
74
137
|
Then(
|
|
75
138
|
"User expects default value of {string} should have {string} text",
|
|
76
139
|
async (selector, text) => {
|
|
@@ -79,6 +142,11 @@ Then(
|
|
|
79
142
|
},
|
|
80
143
|
);
|
|
81
144
|
|
|
145
|
+
Then("User expects default value of {int} th of {string} should have {string} text", async function (order, elements, text) {
|
|
146
|
+
const nthElement = await frame.nth(elements, order);
|
|
147
|
+
await assert.toContain(nthElement, text);
|
|
148
|
+
});
|
|
149
|
+
|
|
82
150
|
Then(
|
|
83
151
|
"User expects multiple {string} should have {string} text",
|
|
84
152
|
async (elements, expectedText) => {
|
|
@@ -94,6 +162,11 @@ Then(
|
|
|
94
162
|
},
|
|
95
163
|
);
|
|
96
164
|
|
|
165
|
+
Then("User expects {int} th of {string} should have {string} description", async function (order, elements, text) {
|
|
166
|
+
const nthElement = await frame.nth(elements, order);
|
|
167
|
+
await assert.shouldHaveAccessibleDescription(nthElement, text);
|
|
168
|
+
});
|
|
169
|
+
|
|
97
170
|
// Check if a selector should have an accessible name
|
|
98
171
|
Then(
|
|
99
172
|
"User expects {string} should have {string} name",
|
|
@@ -102,6 +175,11 @@ Then(
|
|
|
102
175
|
},
|
|
103
176
|
);
|
|
104
177
|
|
|
178
|
+
Then("User expects {int} th of {string} should have {string} name", async function (order, elements, text) {
|
|
179
|
+
const nthElement = await frame.nth(elements, order);
|
|
180
|
+
await assert.shouldHaveAccessibleName(nthElement, text);
|
|
181
|
+
});
|
|
182
|
+
|
|
105
183
|
// Check if a selector should have a specific attribute with a given value
|
|
106
184
|
Then(
|
|
107
185
|
"User expects {string} should have {string} attribute with {string} value",
|
|
@@ -110,6 +188,11 @@ Then(
|
|
|
110
188
|
},
|
|
111
189
|
);
|
|
112
190
|
|
|
191
|
+
Then("User expects {int} th of {string} should have {string} attribute with {string} value", async function (order, elements, attribute, value) {
|
|
192
|
+
const nthElement = await frame.nth(elements, order);
|
|
193
|
+
await assert.shouldHaveAttribute(nthElement, attribute, value);
|
|
194
|
+
});
|
|
195
|
+
|
|
113
196
|
// Check if a selector should have a specific class
|
|
114
197
|
Then(
|
|
115
198
|
"User expects {string} should have {string} class",
|
|
@@ -118,6 +201,11 @@ Then(
|
|
|
118
201
|
},
|
|
119
202
|
);
|
|
120
203
|
|
|
204
|
+
Then("User expects {int} th of {string} should have {string} class", async function (order, elements, className) {
|
|
205
|
+
const nthElement = await frame.nth(elements, order);
|
|
206
|
+
await assert.shouldHaveClass(nthElement, className);
|
|
207
|
+
});
|
|
208
|
+
|
|
121
209
|
// Check if a selector should have a specific count
|
|
122
210
|
Then(
|
|
123
211
|
"User expects count of {string} should be {int}",
|
|
@@ -134,6 +222,11 @@ Then(
|
|
|
134
222
|
},
|
|
135
223
|
);
|
|
136
224
|
|
|
225
|
+
Then("User expects {int} th of {string} should have {string} CSS property with {string} value", async function (order, elements, property, value) {
|
|
226
|
+
const nthElement = await frame.nth(elements, order);
|
|
227
|
+
await assert.shouldHaveCSS(nthElement, property, value);
|
|
228
|
+
});
|
|
229
|
+
|
|
137
230
|
// Check if a selector should have a specific id
|
|
138
231
|
Then(
|
|
139
232
|
"User expects {string} should have {string} id",
|
|
@@ -142,6 +235,11 @@ Then(
|
|
|
142
235
|
},
|
|
143
236
|
);
|
|
144
237
|
|
|
238
|
+
Then("User expects {int} th of {string} should have {string} id", async function (order, elements, id) {
|
|
239
|
+
const nthElement = await frame.nth(elements, order);
|
|
240
|
+
await assert.shouldHaveId(nthElement, id);
|
|
241
|
+
});
|
|
242
|
+
|
|
145
243
|
// Check if a selector should have a specific JavaScript property with a given value
|
|
146
244
|
Then(
|
|
147
245
|
"User expects {string} should have {string} JavaScript property with {string} value",
|
|
@@ -150,6 +248,11 @@ Then(
|
|
|
150
248
|
},
|
|
151
249
|
);
|
|
152
250
|
|
|
251
|
+
Then("User expects {int} th of {string} should have {string} JavaScript property with {string} value", async function (order, elements, property, value) {
|
|
252
|
+
const nthElement = await frame.nth(elements, order);
|
|
253
|
+
await assert.shouldHaveJSProperty(nthElement, property, value);
|
|
254
|
+
});
|
|
255
|
+
|
|
153
256
|
// Check if a selector should have a specific role
|
|
154
257
|
Then(
|
|
155
258
|
"User expects {string} should have {string} role",
|
|
@@ -158,6 +261,11 @@ Then(
|
|
|
158
261
|
},
|
|
159
262
|
);
|
|
160
263
|
|
|
264
|
+
Then("User expects {int} th of {string} should have {string} role", async function (order, elements, role) {
|
|
265
|
+
const nthElement = await frame.nth(elements, order);
|
|
266
|
+
await assert.shouldHaveId(nthElement, role);
|
|
267
|
+
});
|
|
268
|
+
|
|
161
269
|
// Check if a selector should have a screenshot
|
|
162
270
|
Then(
|
|
163
271
|
"User expects {string} should have a screenshot",
|
|
@@ -174,6 +282,11 @@ Then(
|
|
|
174
282
|
},
|
|
175
283
|
);
|
|
176
284
|
|
|
285
|
+
Then("User expects {int} th of {string} should match {string} text", async function (order, elements, text) {
|
|
286
|
+
const nthElement = await frame.nth(elements, order);
|
|
287
|
+
await assert.shouldHaveText(nthElement, text);
|
|
288
|
+
});
|
|
289
|
+
|
|
177
290
|
// Check if a selector should have a specific value
|
|
178
291
|
Then(
|
|
179
292
|
"User expects {string} should have {string} value",
|
|
@@ -182,6 +295,11 @@ Then(
|
|
|
182
295
|
},
|
|
183
296
|
);
|
|
184
297
|
|
|
298
|
+
Then("User expects {int} th of {string} should have {string} value", async function (order, elements, value) {
|
|
299
|
+
const nthElement = await frame.nth(elements, order);
|
|
300
|
+
await assert.shouldHaveValue(nthElement, value);
|
|
301
|
+
});
|
|
302
|
+
|
|
185
303
|
// Check if a selector should have specific values
|
|
186
304
|
Then(
|
|
187
305
|
"User expects {string} should have {string} values",
|
|
@@ -209,64 +327,115 @@ Then("User expects to be in {string} page", async function (url) {
|
|
|
209
327
|
await assert.shouldPageHaveURL(URL);
|
|
210
328
|
});
|
|
211
329
|
|
|
212
|
-
// Check if the response should be OK
|
|
213
|
-
Then("The response should be OK", async function (response) {
|
|
214
|
-
await assert.shouldResponseBeOK(response);
|
|
215
|
-
});
|
|
216
|
-
|
|
217
330
|
// Check if a selector should not be attached
|
|
218
331
|
Then("User expects {string} should not be attached", async function (selector) {
|
|
219
332
|
await assert.shouldNotBeAttached(selector);
|
|
220
333
|
});
|
|
221
334
|
|
|
335
|
+
Then("User expects {int} th of {string} should be not be attached", async function (order, elements) {
|
|
336
|
+
const nthElement = await frame.nth(elements, order);
|
|
337
|
+
await assert.shouldNotBeAttached(nthElement);
|
|
338
|
+
});
|
|
339
|
+
|
|
222
340
|
// Check if a selector should not be checked
|
|
223
341
|
Then("User expects {string} should not be checked", async function (selector) {
|
|
224
342
|
await assert.shouldNotBeChecked(selector);
|
|
225
343
|
});
|
|
226
344
|
|
|
345
|
+
Then("User expects {int} th of {string} should be not be checked", async function (order, elements) {
|
|
346
|
+
const nthElement = await frame.nth(elements, order);
|
|
347
|
+
await assert.shouldNotBeChecked(nthElement);
|
|
348
|
+
});
|
|
349
|
+
|
|
227
350
|
// Check if a selector should not be disabled
|
|
228
351
|
Then("User expects {string} should not be disabled", async function (selector) {
|
|
229
352
|
await assert.shouldNotBeDisabled(selector);
|
|
230
353
|
});
|
|
231
354
|
|
|
355
|
+
Then("User expects {int} th of {string} should be not be disabled", async function (order, elements) {
|
|
356
|
+
const nthElement = await frame.nth(elements, order);
|
|
357
|
+
await assert.shouldNotBeDisabled(nthElement);
|
|
358
|
+
});
|
|
359
|
+
|
|
232
360
|
// Check if a selector should not be editable
|
|
233
361
|
Then("User expects {string} should not be editable", async function (selector) {
|
|
234
362
|
await assert.shouldNotBeEditable(selector);
|
|
235
363
|
});
|
|
236
364
|
|
|
365
|
+
Then("User expects {int} th of {string} should be not be editable", async function (order, elements) {
|
|
366
|
+
const nthElement = await frame.nth(elements, order);
|
|
367
|
+
await assert.shouldNotBeEditable(nthElement);
|
|
368
|
+
});
|
|
369
|
+
|
|
237
370
|
// Check if a selector should not be empty
|
|
238
371
|
Then("User expects {string} should not be empty", async function (selector) {
|
|
239
372
|
await assert.shouldNotBeEmpty(selector);
|
|
240
373
|
});
|
|
241
374
|
|
|
375
|
+
Then("User expects {int} th of {string} should be not be empty", async function (order, elements) {
|
|
376
|
+
const nthElement = await frame.nth(elements, order);
|
|
377
|
+
await assert.shouldNotBeEmpty(nthElement);
|
|
378
|
+
});
|
|
379
|
+
|
|
242
380
|
// Check if a selector should not be enabled
|
|
243
381
|
Then("User expects {string} should not be enabled", async function (selector) {
|
|
244
382
|
await assert.shouldNotBeEnabled(selector);
|
|
245
383
|
});
|
|
246
384
|
|
|
385
|
+
Then("User expects {int} th of {string} should be not be enabled", async function (order, elements) {
|
|
386
|
+
const nthElement = await frame.nth(elements, order);
|
|
387
|
+
await assert.shouldNotBeEnabled(nthElement);
|
|
388
|
+
});
|
|
389
|
+
|
|
247
390
|
// Check if a selector should not be focused
|
|
248
391
|
Then("User expects {string} should not be focused", async function (selector) {
|
|
249
392
|
await assert.shouldNotBeFocused(selector);
|
|
250
393
|
});
|
|
251
394
|
|
|
395
|
+
Then("User expects {int} th of {string} should be not be focused", async function (order, elements) {
|
|
396
|
+
const nthElement = await frame.nth(elements, order);
|
|
397
|
+
await assert.shouldNotBeFocused(nthElement);
|
|
398
|
+
});
|
|
399
|
+
|
|
252
400
|
// Check if a selector should not be hidden
|
|
253
401
|
Then("User expects {string} should not be hidden", async function (selector) {
|
|
254
402
|
await assert.shouldNotBeHidden(selector);
|
|
255
403
|
});
|
|
256
404
|
|
|
405
|
+
Then("User expects {int} th of {string} should be not be hidden", async function (order, elements) {
|
|
406
|
+
const nthElement = await frame.nth(elements, order);
|
|
407
|
+
await assert.shouldNotBeHidden(nthElement);
|
|
408
|
+
});
|
|
409
|
+
|
|
257
410
|
// Check if a selector should not be in the viewport
|
|
258
411
|
Then(
|
|
259
|
-
"User expects {string} should not be on screen",
|
|
412
|
+
"User expects {string} should not be on the screen",
|
|
260
413
|
async function (selector) {
|
|
261
414
|
await assert.shouldNotBeInViewport(selector);
|
|
262
415
|
},
|
|
263
416
|
);
|
|
264
417
|
|
|
418
|
+
Then(
|
|
419
|
+
"User expects {int} th of {string} should not be on the screen",
|
|
420
|
+
async function (order, elements) {
|
|
421
|
+
const nthElement = await frame.nth(elements, order);
|
|
422
|
+
await assert.shouldNotBeInViewport(nthElement);
|
|
423
|
+
},
|
|
424
|
+
);
|
|
425
|
+
|
|
265
426
|
// Check if a selector should not be visible
|
|
266
427
|
Then("User expects {string} should not be visible", async function (selector) {
|
|
267
428
|
await assert.shouldNotBeVisible(selector);
|
|
268
429
|
});
|
|
269
430
|
|
|
431
|
+
Then(
|
|
432
|
+
"User expects {int} th of {string} should not be visible",
|
|
433
|
+
async function (order, elements) {
|
|
434
|
+
const nthElement = await frame.nth(elements, order);
|
|
435
|
+
await assert.shouldNotBeVisible(nthElement);
|
|
436
|
+
},
|
|
437
|
+
);
|
|
438
|
+
|
|
270
439
|
// Check if a selector should not contain specific text
|
|
271
440
|
Then(
|
|
272
441
|
"User expects {string} should not have {string} text",
|
|
@@ -275,6 +444,11 @@ Then(
|
|
|
275
444
|
},
|
|
276
445
|
);
|
|
277
446
|
|
|
447
|
+
Then("User expects {int} th of {string} should not have {string} text", async function (order, elements, text) {
|
|
448
|
+
const nthElement = await frame.nth(elements, order);
|
|
449
|
+
await assert.shouldNotContainText(nthElement, text);
|
|
450
|
+
});
|
|
451
|
+
|
|
278
452
|
// Check if a selector should not have an accessible description
|
|
279
453
|
Then(
|
|
280
454
|
"User expects {string} should not have {string} description",
|
|
@@ -283,6 +457,11 @@ Then(
|
|
|
283
457
|
},
|
|
284
458
|
);
|
|
285
459
|
|
|
460
|
+
Then("User expects {int} th of {string} should not have {string} description", async function (order, elements, text) {
|
|
461
|
+
const nthElement = await frame.nth(elements, order);
|
|
462
|
+
await assert.shouldNotHaveAccessibleDescription(nthElement, text);
|
|
463
|
+
});
|
|
464
|
+
|
|
286
465
|
// Check if a selector should not have an accessible name
|
|
287
466
|
Then(
|
|
288
467
|
"User expects {string} should not have {string} name",
|
|
@@ -291,6 +470,11 @@ Then(
|
|
|
291
470
|
},
|
|
292
471
|
);
|
|
293
472
|
|
|
473
|
+
Then("User expects {int} th of {string} should not have {string} name", async function (order, elements, text) {
|
|
474
|
+
const nthElement = await frame.nth(elements, order);
|
|
475
|
+
await assert.shouldNotHaveAccessibleName(nthElement, text);
|
|
476
|
+
});
|
|
477
|
+
|
|
294
478
|
// Check if a selector should not have a specific attribute with a given value
|
|
295
479
|
Then(
|
|
296
480
|
"User expects {string} should not have {string} attribute with {string} value",
|
|
@@ -299,6 +483,11 @@ Then(
|
|
|
299
483
|
},
|
|
300
484
|
);
|
|
301
485
|
|
|
486
|
+
Then("User expects {int} th of {string} should have {string} attribute with {string} value", async function (order, elements, attribute, value) {
|
|
487
|
+
const nthElement = await frame.nth(elements, order);
|
|
488
|
+
await assert.shouldNotHaveAttribute(nthElement, attribute, value);
|
|
489
|
+
});
|
|
490
|
+
|
|
302
491
|
// Check if a selector should not have a specific class
|
|
303
492
|
Then(
|
|
304
493
|
"User expects {string} should not have {string} class",
|
|
@@ -307,6 +496,11 @@ Then(
|
|
|
307
496
|
},
|
|
308
497
|
);
|
|
309
498
|
|
|
499
|
+
Then("User expects {int} th of {string} should not have {string} class", async function (order, elements, text) {
|
|
500
|
+
const nthElement = await frame.nth(elements, order);
|
|
501
|
+
await assert.shouldNotHaveClass(nthElement, text);
|
|
502
|
+
});
|
|
503
|
+
|
|
310
504
|
// Check if a selector should not have a specific count
|
|
311
505
|
Then(
|
|
312
506
|
"User expects count of {string} should not be {int}",
|
|
@@ -323,6 +517,11 @@ Then(
|
|
|
323
517
|
},
|
|
324
518
|
);
|
|
325
519
|
|
|
520
|
+
Then("User expects {int} th of {string} should not have {string} CSS property with {string} value", async function (order, elements, property, value) {
|
|
521
|
+
const nthElement = await frame.nth(elements, order);
|
|
522
|
+
await assert.shouldNotHaveCSS(nthElement, property, value);
|
|
523
|
+
});
|
|
524
|
+
|
|
326
525
|
// Check if a selector should not have a specific ID
|
|
327
526
|
Then(
|
|
328
527
|
"User expects {string} should not have {string} id",
|
|
@@ -331,6 +530,11 @@ Then(
|
|
|
331
530
|
},
|
|
332
531
|
);
|
|
333
532
|
|
|
533
|
+
Then("User expects {int} th of {string} should not have {string} id", async function (order, elements, text) {
|
|
534
|
+
const nthElement = await frame.nth(elements, order);
|
|
535
|
+
await assert.shouldNotHaveId(nthElement, text);
|
|
536
|
+
});
|
|
537
|
+
|
|
334
538
|
// Check if a selector should not have a specific JavaScript property with a given value
|
|
335
539
|
Then(
|
|
336
540
|
"User expects {string} should not have {string} JavaScript property with {string} value",
|
|
@@ -339,6 +543,11 @@ Then(
|
|
|
339
543
|
},
|
|
340
544
|
);
|
|
341
545
|
|
|
546
|
+
Then("User expects {int} th of {string} should not have {string} JavaScript property with {string} value", async function (order, elements, property, value) {
|
|
547
|
+
const nthElement = await frame.nth(elements, order);
|
|
548
|
+
await assert.shouldNotHaveJSProperty(nthElement, property, value);
|
|
549
|
+
});
|
|
550
|
+
|
|
342
551
|
// Check if a selector should not have a specific role
|
|
343
552
|
Then(
|
|
344
553
|
"User expects {string} should not have {string} role",
|
|
@@ -347,6 +556,11 @@ Then(
|
|
|
347
556
|
},
|
|
348
557
|
);
|
|
349
558
|
|
|
559
|
+
Then("User expects {int} th of {string} should not have {string} role", async function (order, elements, text) {
|
|
560
|
+
const nthElement = await frame.nth(elements, order);
|
|
561
|
+
await assert.shouldNotHaveRole(nthElement, text);
|
|
562
|
+
});
|
|
563
|
+
|
|
350
564
|
// Check if a selector should not have specific text
|
|
351
565
|
Then(
|
|
352
566
|
"User expects {string} should not match {string} text",
|
|
@@ -355,6 +569,11 @@ Then(
|
|
|
355
569
|
},
|
|
356
570
|
);
|
|
357
571
|
|
|
572
|
+
Then("User expects {int} th of {string} should not have {string} text", async function (order, elements, text) {
|
|
573
|
+
const nthElement = await frame.nth(elements, order);
|
|
574
|
+
await assert.shouldNotHaveText(nthElement, text);
|
|
575
|
+
});
|
|
576
|
+
|
|
358
577
|
// Check if a selector should not have a specific value
|
|
359
578
|
Then(
|
|
360
579
|
"User expects {string} should not have {string} value",
|
|
@@ -363,6 +582,11 @@ Then(
|
|
|
363
582
|
},
|
|
364
583
|
);
|
|
365
584
|
|
|
585
|
+
Then("User expects {int} th of {string} should not have {string} value", async function (order, elements, text) {
|
|
586
|
+
const nthElement = await frame.nth(elements, order);
|
|
587
|
+
await assert.shouldNotHaveValue(nthElement, text);
|
|
588
|
+
});
|
|
589
|
+
|
|
366
590
|
// Check if a selector should not have specific values
|
|
367
591
|
Then(
|
|
368
592
|
"User expects {string} should not have {string} values",
|
|
@@ -3,6 +3,7 @@ const {
|
|
|
3
3
|
element,
|
|
4
4
|
selector,
|
|
5
5
|
context,
|
|
6
|
+
resolveVariable
|
|
6
7
|
} = require("../helper/imports/commons");
|
|
7
8
|
const { mouse, frame, page } = require("../helper/stepFunctions/exporter");
|
|
8
9
|
|
|
@@ -39,6 +40,8 @@ When("User clicks {string} with force", async function (selector) {
|
|
|
39
40
|
When(
|
|
40
41
|
"User clicks {string} at {int}, {int} position",
|
|
41
42
|
async function (selector, x, y) {
|
|
43
|
+
x = await resolveVariable(x)
|
|
44
|
+
y = await resolveVariable(y)
|
|
42
45
|
await mouse.click(selector, { position: { x: x, y: y } });
|
|
43
46
|
},
|
|
44
47
|
);
|
|
@@ -47,12 +50,16 @@ When(
|
|
|
47
50
|
When(
|
|
48
51
|
"User clicks {string} at {int}, {int} position with force",
|
|
49
52
|
async function (selector, x, y) {
|
|
53
|
+
x = await resolveVariable(x)
|
|
54
|
+
y = await resolveVariable(y)
|
|
50
55
|
await mouse.click(selector, { force: true, position: { x: x, y: y } });
|
|
51
56
|
},
|
|
52
57
|
);
|
|
53
58
|
|
|
54
59
|
// User clicks at specific coordinates
|
|
55
60
|
When("User clicks at {int}, {int} coordinates", async function (x, y) {
|
|
61
|
+
x = await resolveVariable(x)
|
|
62
|
+
y = await resolveVariable(y)
|
|
56
63
|
await context.page.click({ position: { x: x, y: y } });
|
|
57
64
|
});
|
|
58
65
|
|
|
@@ -60,6 +67,8 @@ When("User clicks at {int}, {int} coordinates", async function (x, y) {
|
|
|
60
67
|
When(
|
|
61
68
|
"User clicks at {int}, {int} coordinates with click count {int} and delay {int}",
|
|
62
69
|
async function (x, y, clickCount, delay) {
|
|
70
|
+
x = await resolveVariable(x)
|
|
71
|
+
y = await resolveVariable(y)
|
|
63
72
|
await context.page.click({
|
|
64
73
|
position: { x: x, y: y },
|
|
65
74
|
clickCount: clickCount,
|
|
@@ -72,6 +81,8 @@ When(
|
|
|
72
81
|
When(
|
|
73
82
|
"User clicks at {int}, {int} coordinates with force",
|
|
74
83
|
async function (x, y) {
|
|
84
|
+
x = await resolveVariable(x)
|
|
85
|
+
y = await resolveVariable(y)
|
|
75
86
|
context.page.click({ position: { x: x, y: y }, force: true });
|
|
76
87
|
},
|
|
77
88
|
);
|
|
@@ -139,6 +150,8 @@ When("User double clicks {string} with force", async function (selector) {
|
|
|
139
150
|
When(
|
|
140
151
|
"User double clicks {string} at {int}, {int} position",
|
|
141
152
|
async function (selector, x, y) {
|
|
153
|
+
x = await resolveVariable(x)
|
|
154
|
+
y = await resolveVariable(y)
|
|
142
155
|
await mouse.doubleClick(selector, { position: { x: x, y: y } });
|
|
143
156
|
},
|
|
144
157
|
);
|
|
@@ -147,6 +160,8 @@ When(
|
|
|
147
160
|
When(
|
|
148
161
|
"User double clicks {string} at {int}, {int} position with force",
|
|
149
162
|
async function (selector, x, y) {
|
|
163
|
+
x = await resolveVariable(x)
|
|
164
|
+
y = await resolveVariable(y)
|
|
150
165
|
await mouse.doubleClick(selector, {
|
|
151
166
|
position: { x: x, y: y },
|
|
152
167
|
force: true,
|
|
@@ -156,6 +171,8 @@ When(
|
|
|
156
171
|
|
|
157
172
|
// User double clicks at specific coordinates
|
|
158
173
|
When("User double clicks at {int}, {int} coordinates", async function (x, y) {
|
|
174
|
+
x = await resolveVariable(x)
|
|
175
|
+
y = await resolveVariable(y)
|
|
159
176
|
await context.page.doubleClick({ position: { x: x, y: y } });
|
|
160
177
|
});
|
|
161
178
|
|
|
@@ -163,6 +180,8 @@ When("User double clicks at {int}, {int} coordinates", async function (x, y) {
|
|
|
163
180
|
When(
|
|
164
181
|
"User double clicks at {int}, {int} coordinates with click count {int} and delay {int}",
|
|
165
182
|
async function (x, y, clickCount, delay) {
|
|
183
|
+
x = await resolveVariable(x)
|
|
184
|
+
y = await resolveVariable(y)
|
|
166
185
|
await context.page.doubleClick({
|
|
167
186
|
position: { x: x, y: y },
|
|
168
187
|
clickCount: clickCount,
|
|
@@ -175,12 +194,16 @@ When(
|
|
|
175
194
|
When(
|
|
176
195
|
"User double clicks at {int}, {int} coordinates with force",
|
|
177
196
|
async function (x, y) {
|
|
197
|
+
x = await resolveVariable(x)
|
|
198
|
+
y = await resolveVariable(y)
|
|
178
199
|
await context.page.doubleClick({ position: { x: x, y: y }, force: true });
|
|
179
200
|
},
|
|
180
201
|
);
|
|
181
202
|
|
|
182
203
|
// User moves the mouse to specific coordinates
|
|
183
204
|
When("User moves to {int}, {int} coordinates", async function (x, y) {
|
|
205
|
+
x = await resolveVariable(x)
|
|
206
|
+
y = await resolveVariable(y)
|
|
184
207
|
await context.page.move({ position: { x: x, y: y } });
|
|
185
208
|
});
|
|
186
209
|
|
|
@@ -188,6 +211,8 @@ When("User moves to {int}, {int} coordinates", async function (x, y) {
|
|
|
188
211
|
When(
|
|
189
212
|
"User scrolls the mouse wheel at {int}, {int} coordinates",
|
|
190
213
|
async function (x, y) {
|
|
214
|
+
x = await resolveVariable(x)
|
|
215
|
+
y = await resolveVariable(y)
|
|
191
216
|
await context.page.wheel({ position: { x: x, y: y } });
|
|
192
217
|
},
|
|
193
218
|
);
|
|
@@ -206,6 +231,8 @@ When("User hovers over {string} with force", async function (selector) {
|
|
|
206
231
|
When(
|
|
207
232
|
"User hovers over {string} at {int}, {int} position",
|
|
208
233
|
async function (selector, x, y) {
|
|
234
|
+
x = await resolveVariable(x)
|
|
235
|
+
y = await resolveVariable(y)
|
|
209
236
|
await mouse.hover(selector, { position: { x: x, y: y } });
|
|
210
237
|
},
|
|
211
238
|
);
|
|
@@ -214,6 +241,8 @@ When(
|
|
|
214
241
|
When(
|
|
215
242
|
"User hovers over {string} at {int}, {int} position with force",
|
|
216
243
|
async function (selector, x, y) {
|
|
244
|
+
x = await resolveVariable(x)
|
|
245
|
+
y = await resolveVariable(y)
|
|
217
246
|
await mouse.hover(selector, { position: { x: x, y: y }, force: true });
|
|
218
247
|
},
|
|
219
248
|
);
|
|
@@ -232,6 +261,8 @@ When("User focuses on {string} with force", async function (selector) {
|
|
|
232
261
|
When(
|
|
233
262
|
"User focuses on {string} at {int}, {int} position",
|
|
234
263
|
async function (selector, x, y) {
|
|
264
|
+
x = await resolveVariable(x)
|
|
265
|
+
y = await resolveVariable(y)
|
|
235
266
|
await mouse.focus(selector, { position: { x: x, y: y } });
|
|
236
267
|
},
|
|
237
268
|
);
|
|
@@ -240,6 +271,8 @@ When(
|
|
|
240
271
|
When(
|
|
241
272
|
"User focuses on {string} at {int}, {int} position with force",
|
|
242
273
|
async function (selector, x, y) {
|
|
274
|
+
x = await resolveVariable(x)
|
|
275
|
+
y = await resolveVariable(y)
|
|
243
276
|
await mouse.focus(selector, { position: { x: x, y: y }, force: true });
|
|
244
277
|
},
|
|
245
278
|
);
|
|
@@ -256,6 +289,8 @@ When(
|
|
|
256
289
|
When(
|
|
257
290
|
"User drags {string} to {int}, {int} position",
|
|
258
291
|
async function (sourceSelector, x, y) {
|
|
292
|
+
x = await resolveVariable(x)
|
|
293
|
+
y = await resolveVariable(y)
|
|
259
294
|
await mouse.dragAndDrop(sourceSelector, { position: { x: x, y: y } });
|
|
260
295
|
},
|
|
261
296
|
);
|