wdio-rerun-service 2.0.7 โ 3.0.0
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/CHANGELOG.md +48 -0
- package/README.md +128 -42
- package/build/cjs/index.d.ts +6 -2
- package/build/cjs/index.js +60 -37
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.d.ts +6 -2
- package/build/esm/index.js +52 -21
- package/build/esm/index.js.map +1 -1
- package/eslint.config.js +78 -0
- package/package.json +69 -57
- package/test-output.log +526 -0
- package/vitest.config.ts +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -13,6 +13,54 @@ _Note: Gaps between patch versions are faulty, broken or test releases._
|
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
+
## v3.0.0 (2025-12-25)
|
|
17
|
+
|
|
18
|
+
#### :boom: Breaking Change
|
|
19
|
+
* **Node.js 20+ required** - Dropped support for Node.js 18 to leverage native APIs (`crypto.randomUUID()`, `util.parseArgs()`)
|
|
20
|
+
|
|
21
|
+
#### :house: Internal
|
|
22
|
+
* **Zero runtime dependencies** - Faster installs, smaller `node_modules`, no supply chain risk from transitive dependencies
|
|
23
|
+
* **Comprehensive E2E test suite** - 46 tests covering Cucumber (26), Jasmine (10), and Mocha (10) scenarios running real WebdriverIO processes, ensuring the service works correctly in actual usage
|
|
24
|
+
* **Cross-platform CI** - 12 GitHub Actions jobs testing Node 20/22/24 across macOS, Windows, and Linux, catching platform-specific bugs before release
|
|
25
|
+
* **ESLint v9** - Migrated to flat config with typescript-eslint unified tooling for modern, maintainable linting
|
|
26
|
+
|
|
27
|
+
#### :memo: Documentation
|
|
28
|
+
* Updated README with quality badges (coverage, E2E tests, zero deps)
|
|
29
|
+
|
|
30
|
+
#### Committers: 1
|
|
31
|
+
- [@esaari](https://github.com/esaari)
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## v2.1.0 (2025-12-22)
|
|
36
|
+
#### :rocket: New Feature
|
|
37
|
+
* Support for Cucumber scenarios nested inside `Rule:` blocks - line numbers are now correctly extracted for reruns
|
|
38
|
+
|
|
39
|
+
#### :bug: Bug Fix
|
|
40
|
+
* Fixed WebdriverIO v9 compatibility - updated `@cucumber/messages` enum comparison to work with both v8 and v9
|
|
41
|
+
|
|
42
|
+
#### :house: Internal
|
|
43
|
+
* Migrated from Jest to Vitest - faster test execution, no experimental flags needed
|
|
44
|
+
* Switched to pnpm for development (enforced via `packageManager` field)
|
|
45
|
+
* Updated all dependencies to latest versions
|
|
46
|
+
* Removed deprecated `@types/uuid` - uuid v13 includes its own types
|
|
47
|
+
* Achieved 100% unit test coverage
|
|
48
|
+
* Node.js 18+ required (compatible with both WDIO v8 and v9)
|
|
49
|
+
|
|
50
|
+
#### Committers: 1
|
|
51
|
+
- [@esaari](https://github.com/esaari)
|
|
52
|
+
|
|
53
|
+
## v2.0.7 (2023-7-24)
|
|
54
|
+
#### :bug: Bug Fix
|
|
55
|
+
* [[#67]](https://github.com/webdriverio-community/wdio-rerun-service/pull/67) Update some dependencies ([@esaari](https://github.com/esaari))
|
|
56
|
+
|
|
57
|
+
#### :memo: Documentation
|
|
58
|
+
* [[#63]](https://github.com/webdriverio-community/wdio-rerun-service/pull/63) Update Readme ([@mikesalvia](https://github.com/mikesalvia))
|
|
59
|
+
|
|
60
|
+
#### Committers: 3
|
|
61
|
+
- [@esaari](https://github.com/esaari)
|
|
62
|
+
- [@mikesalvia](https://github.com/mikesalvia)
|
|
63
|
+
|
|
16
64
|
## v2.0.6 (2023-1-19)
|
|
17
65
|
#### :bug: Bug Fix
|
|
18
66
|
* [[#56]](https://github.com/webdriverio-community/wdio-rerun-service/pull/56) [v8] Generate failure line number at Example data line ([@cesar-rivera](https://github.com/cesar-rivera), [@wenzhhu](https://github.com/wenzhhu))
|
package/README.md
CHANGED
|
@@ -1,27 +1,57 @@
|
|
|
1
|
-
WebdriverIO Re-run Service
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
](https://github.com/webdriverio-community/wdio-rerun-service/actions/workflows/test.yml)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
8
12
|
|
|
9
13
|
This service tracks failing Mocha or Jasmine tests and Cucumber scenarios executed within the [WebdriverIO](https://webdriver.io) test framework. It will allow failing or unstable tests or scenarios to be re-run.
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- ๐ Re-run failed Mocha, Jasmine, or Cucumber tests after the main test run completes
|
|
18
|
+
- ๐ฅ Full Cucumber support including scenarios inside `Rule:` blocks
|
|
19
|
+
- ๐ท๏ธ Filter out scenarios with specific tags from re-runs
|
|
20
|
+
- ๐ช Cross-platform support (generates `rerun.sh` on Unix, `rerun.bat` on Windows)
|
|
21
|
+
- โ๏ธ Configurable command prefix and custom parameters
|
|
22
|
+
|
|
23
|
+
## Quality & Reliability
|
|
24
|
+
|
|
25
|
+
- โ
**100% test coverage** โ comprehensive unit and E2E tests
|
|
26
|
+
- ๐งช **E2E tests** โ real WebdriverIO runs across Cucumber, Mocha, and Jasmine
|
|
27
|
+
- ๐ฅ๏ธ **Cross-platform CI** โ tested on macOS, Windows, and Linux
|
|
28
|
+
- ๐ฆ **Zero dependencies** โ only WebdriverIO peer dependencies, minimal footprint
|
|
29
|
+
- ๐ท **100% TypeScript** โ fully typed for great IDE support
|
|
30
|
+
- ๐ **Modern Node.js** โ uses native APIs (`crypto.randomUUID`, `util.parseArgs`)
|
|
31
|
+
|
|
32
|
+
## Compatibility
|
|
33
|
+
|
|
34
|
+
| wdio-rerun-service | WebdriverIO | Node.js |
|
|
35
|
+
|--------------------|-------------|---------|
|
|
36
|
+
| `^3.0.0` | `^8.0.0 \|\| ^9.0.0` | `>=20` |
|
|
37
|
+
| `^2.1.0` | `^8.0.0 \|\| ^9.0.0` | `>=18` |
|
|
38
|
+
| `^2.0.0` | `^8.0.0` | `>=18` |
|
|
39
|
+
| `^1.7.0` | `^7.0.0` | `>=14` |
|
|
12
40
|
|
|
13
41
|
## Re-run vs. Retry
|
|
14
42
|
|
|
15
|
-
The `retry` logic built into WebdriverIO for Cucumber and Mocha/Jasmine is helpful for handling flaky steps in Cucumber and Mocha/Jasmine. Retrying in each framework has caveats:
|
|
16
|
-
|
|
17
|
-
|
|
43
|
+
The `retry` logic built into WebdriverIO for Cucumber and Mocha/Jasmine is helpful for handling flaky steps in Cucumber and Mocha/Jasmine. Retrying in each framework has caveats:
|
|
44
|
+
|
|
45
|
+
- **Cucumber:** It does not take into account that some steps may not be able to be retried in the middle of a test. Running a step twice may break the rest of the Scenario or it may not be possible in the test context.
|
|
46
|
+
- **Mocha/Jasmine:** The `retry` logic may be applied to an individual test, however, this is still done in real-time and perhaps does not account for temporal issues or network connectivity problems.
|
|
18
47
|
|
|
19
48
|
The main distinctions of the `re-run`:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
49
|
+
|
|
50
|
+
- Will re-run an entire individual Cucumber Scenario and not just a single step
|
|
51
|
+
- Enables an entire spec file to be re-run after a main test execution is complete
|
|
52
|
+
- May be copied and executed locally (`retry` cannot)
|
|
53
|
+
- Can still be used in conjunction with `retry` methods
|
|
54
|
+
- Does not require any code change to apply `retry` logic to flaky or problematic tests
|
|
25
55
|
|
|
26
56
|
It is recommended to take some time to evaluate the options available. A hybrid solution may be the best solution to provide the best real and actionable test results.
|
|
27
57
|
|
|
@@ -33,12 +63,18 @@ Using `npm`:
|
|
|
33
63
|
npm install wdio-rerun-service
|
|
34
64
|
```
|
|
35
65
|
|
|
36
|
-
|
|
66
|
+
Using `yarn`:
|
|
37
67
|
|
|
38
68
|
```bash
|
|
39
69
|
yarn add wdio-rerun-service
|
|
40
70
|
```
|
|
41
71
|
|
|
72
|
+
Using `pnpm`:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pnpm add wdio-rerun-service
|
|
76
|
+
```
|
|
77
|
+
|
|
42
78
|
After package installation is complete, add it to `services` array in `wdio.conf.js`:
|
|
43
79
|
|
|
44
80
|
```js
|
|
@@ -46,52 +82,75 @@ After package installation is complete, add it to `services` array in `wdio.conf
|
|
|
46
82
|
import RerunService from 'wdio-rerun-service';
|
|
47
83
|
export const config = {
|
|
48
84
|
// ...
|
|
49
|
-
services: [
|
|
50
|
-
|
|
51
|
-
|
|
85
|
+
services: [
|
|
86
|
+
[RerunService, {
|
|
87
|
+
// Re-run service options here...
|
|
88
|
+
}]
|
|
89
|
+
],
|
|
90
|
+
// ...
|
|
52
91
|
};
|
|
53
92
|
```
|
|
54
93
|
|
|
55
|
-
Instructions on how to install `WebdriverIO` can be found [
|
|
94
|
+
Instructions on how to install `WebdriverIO` can be found in the [official documentation](https://webdriver.io/docs/gettingstarted.html).
|
|
56
95
|
|
|
57
96
|
## Usage
|
|
97
|
+
|
|
58
98
|
By design, this service does not automatically re-run failed tests.
|
|
59
99
|
|
|
60
|
-
After
|
|
100
|
+
After WebdriverIO has completed execution, if failures are found, a re-run script will be generated at **rerunScriptPath** (default: `./rerun.sh` on Unix, `./rerun.bat` on Windows).
|
|
101
|
+
|
|
102
|
+
You can then execute this script manually or integrate it into your CI pipeline.
|
|
103
|
+
|
|
104
|
+
### Disabling Re-run
|
|
105
|
+
|
|
106
|
+
Set the environment variable `DISABLE_RERUN=true` to disable the service (useful during re-run execution to prevent infinite loops).
|
|
61
107
|
|
|
62
108
|
### Conditional Re-run
|
|
63
|
-
Every teams re-run needs will differ execution could be based on any number of factors, this is an example of how to accomplish a conditional re-run based on # of failures.
|
|
64
109
|
|
|
65
|
-
|
|
66
|
-
|
|
110
|
+
Every team's re-run needs will differโexecution could be based on any number of factors. This is an example of how to accomplish a conditional re-run based on number of failures.
|
|
111
|
+
|
|
112
|
+
#### attemptRerun.sh
|
|
113
|
+
|
|
114
|
+
Executes `./rerun.sh` if less than 25 failures have been found in the last execution of WebdriverIO.
|
|
115
|
+
|
|
67
116
|
```sh
|
|
68
117
|
#!/usr/bin/env bash
|
|
69
118
|
MAX_TO_RERUN=${MAX_TO_RERUN:=25}
|
|
70
119
|
if [ -f "rerun.sh" ]; then
|
|
71
|
-
echo "[rerun.sh] file
|
|
120
|
+
echo "[rerun.sh] file exists, checking total failures."
|
|
72
121
|
NUMBER_OF_FAILURES=$(grep "\-\-spec" -o rerun.sh | wc -l | xargs)
|
|
73
|
-
|
|
122
|
+
if [ "$MAX_TO_RERUN" -gt "$NUMBER_OF_FAILURES" ]; then
|
|
74
123
|
echo "Re-running $NUMBER_OF_FAILURES failed scenarios!"
|
|
75
124
|
. ./rerun.sh
|
|
76
|
-
|
|
77
|
-
echo "Skipping re-run, expected < $MAX_TO_RERUN failures
|
|
78
|
-
|
|
125
|
+
else
|
|
126
|
+
echo "Skipping re-run, expected < $MAX_TO_RERUN failures."
|
|
127
|
+
echo "Got $NUMBER_OF_FAILURES failures."
|
|
128
|
+
fi
|
|
79
129
|
else
|
|
80
|
-
echo "No [rerun.sh] file
|
|
130
|
+
echo "No [rerun.sh] file exists, skipping re-run!"
|
|
81
131
|
fi
|
|
82
132
|
```
|
|
83
|
-
|
|
84
|
-
|
|
133
|
+
|
|
134
|
+
#### Bash Re-run Command
|
|
135
|
+
|
|
136
|
+
Execute in shell:
|
|
137
|
+
|
|
85
138
|
```sh
|
|
86
139
|
. ./attemptRerun.sh
|
|
87
140
|
```
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
141
|
+
|
|
142
|
+
#### Integrate with NPM
|
|
143
|
+
|
|
144
|
+
Add task in `package.json`:
|
|
145
|
+
|
|
146
|
+
```json
|
|
91
147
|
"attempt-rerun": ". ./attemptRerun.sh"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### NPM Re-run Command
|
|
151
|
+
|
|
152
|
+
Execute in shell:
|
|
153
|
+
|
|
95
154
|
```sh
|
|
96
155
|
npm run attempt-rerun
|
|
97
156
|
```
|
|
@@ -115,6 +174,7 @@ export const config = {
|
|
|
115
174
|
```
|
|
116
175
|
|
|
117
176
|
### rerunDataDir
|
|
177
|
+
|
|
118
178
|
Directory where all the re-run JSON data will be kept during execution.
|
|
119
179
|
|
|
120
180
|
Type: `String`
|
|
@@ -122,6 +182,7 @@ Type: `String`
|
|
|
122
182
|
Default: `./results/rerun`
|
|
123
183
|
|
|
124
184
|
Example:
|
|
185
|
+
|
|
125
186
|
```js
|
|
126
187
|
import RerunService from 'wdio-rerun-service';
|
|
127
188
|
export const config = {
|
|
@@ -136,13 +197,15 @@ export const config = {
|
|
|
136
197
|
```
|
|
137
198
|
|
|
138
199
|
### rerunScriptPath
|
|
139
|
-
|
|
200
|
+
|
|
201
|
+
Path to write the re-run script.
|
|
140
202
|
|
|
141
203
|
Type: `String`
|
|
142
204
|
|
|
143
|
-
Default: `./rerun.sh`
|
|
205
|
+
Default: `./rerun.sh` (Unix) or `./rerun.bat` (Windows)
|
|
144
206
|
|
|
145
207
|
Example:
|
|
208
|
+
|
|
146
209
|
```js
|
|
147
210
|
import RerunService from 'wdio-rerun-service';
|
|
148
211
|
export const config = {
|
|
@@ -157,6 +220,7 @@ export const config = {
|
|
|
157
220
|
```
|
|
158
221
|
|
|
159
222
|
### ignoredTags
|
|
223
|
+
|
|
160
224
|
(Cucumber-only) Set of Cucumber tags to exclude. If scenario contains a tag, the re-run service will skip analysis.
|
|
161
225
|
|
|
162
226
|
Type: `Array`
|
|
@@ -164,6 +228,7 @@ Type: `Array`
|
|
|
164
228
|
Default: `[]`
|
|
165
229
|
|
|
166
230
|
Example:
|
|
231
|
+
|
|
167
232
|
```js
|
|
168
233
|
import RerunService from 'wdio-rerun-service';
|
|
169
234
|
export const config = {
|
|
@@ -178,6 +243,7 @@ export const config = {
|
|
|
178
243
|
```
|
|
179
244
|
|
|
180
245
|
### commandPrefix
|
|
246
|
+
|
|
181
247
|
Prefix which will be added to the re-run command that is generated.
|
|
182
248
|
|
|
183
249
|
Type: `String`
|
|
@@ -185,6 +251,7 @@ Type: `String`
|
|
|
185
251
|
Default: `''`
|
|
186
252
|
|
|
187
253
|
Example:
|
|
254
|
+
|
|
188
255
|
```js
|
|
189
256
|
import RerunService from 'wdio-rerun-service';
|
|
190
257
|
export const config = {
|
|
@@ -199,6 +266,7 @@ export const config = {
|
|
|
199
266
|
```
|
|
200
267
|
|
|
201
268
|
### customParameters
|
|
269
|
+
|
|
202
270
|
Parameters which will be added to the re-run command that is generated.
|
|
203
271
|
Can be used with `commandPrefix`.
|
|
204
272
|
|
|
@@ -207,6 +275,7 @@ Type: `String`
|
|
|
207
275
|
Default: `''`
|
|
208
276
|
|
|
209
277
|
Example:
|
|
278
|
+
|
|
210
279
|
```js
|
|
211
280
|
import RerunService from 'wdio-rerun-service';
|
|
212
281
|
export const config = {
|
|
@@ -219,5 +288,22 @@ export const config = {
|
|
|
219
288
|
// ...
|
|
220
289
|
}
|
|
221
290
|
```
|
|
222
|
-
----
|
|
223
291
|
|
|
292
|
+
## Contributing
|
|
293
|
+
|
|
294
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
# Clone the repo
|
|
298
|
+
git clone https://github.com/webdriverio-community/wdio-rerun-service.git
|
|
299
|
+
|
|
300
|
+
# Install dependencies
|
|
301
|
+
pnpm install
|
|
302
|
+
|
|
303
|
+
# Run tests
|
|
304
|
+
pnpm test
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## License
|
|
308
|
+
|
|
309
|
+
MIT
|
package/build/cjs/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Logger } from '@wdio/logger';
|
|
2
|
+
import type { Frameworks, Services } from '@wdio/types';
|
|
2
3
|
type AfterScenario = NonNullable<WebdriverIO.HookFunctionExtension['afterScenario']>;
|
|
3
4
|
type AfterScenarioParameters = Parameters<AfterScenario>;
|
|
4
5
|
type World = AfterScenarioParameters[0];
|
|
@@ -12,6 +13,7 @@ interface RerunServiceOptions {
|
|
|
12
13
|
rerunScriptPath?: string;
|
|
13
14
|
commandPrefix?: string;
|
|
14
15
|
customParameters?: string;
|
|
16
|
+
platformName?: NodeJS.Platform;
|
|
15
17
|
}
|
|
16
18
|
export default class RerunService implements Services.ServiceInstance {
|
|
17
19
|
nonPassingItems: NonPassingItem[];
|
|
@@ -23,8 +25,10 @@ export default class RerunService implements Services.ServiceInstance {
|
|
|
23
25
|
customParameters: string;
|
|
24
26
|
specFile: string;
|
|
25
27
|
disabled: boolean;
|
|
28
|
+
platformName: NodeJS.Platform;
|
|
29
|
+
log: Logger;
|
|
26
30
|
constructor(options?: RerunServiceOptions);
|
|
27
|
-
before(_capabilities: Capabilities
|
|
31
|
+
before(_capabilities: WebdriverIO.Capabilities, specs: string[]): Promise<void>;
|
|
28
32
|
afterTest(_test: Frameworks.Test, _context: any, results: Frameworks.TestResult): void;
|
|
29
33
|
afterScenario(world: World): void;
|
|
30
34
|
after(): Promise<void>;
|
package/build/cjs/index.js
CHANGED
|
@@ -1,35 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const node_path_1 = require("node:path");
|
|
9
|
-
const node_process_1 = require("node:process");
|
|
10
|
-
const uuid_1 = require("uuid");
|
|
11
|
-
class RerunService {
|
|
1
|
+
import logger from '@wdio/logger';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { argv, env, platform } from 'node:process';
|
|
6
|
+
import { parseArgs } from 'node:util';
|
|
7
|
+
export default class RerunService {
|
|
12
8
|
constructor(options = {}) {
|
|
13
|
-
const { ignoredTags, rerunDataDir, rerunScriptPath, commandPrefix, customParameters, } = options;
|
|
9
|
+
const { ignoredTags, rerunDataDir, rerunScriptPath, commandPrefix, customParameters, platformName, } = options;
|
|
14
10
|
this.nonPassingItems = [];
|
|
15
11
|
this.serviceWorkerId = '';
|
|
16
12
|
this.ignoredTags = ignoredTags ?? [];
|
|
17
13
|
this.rerunDataDir = rerunDataDir ?? './results/rerun';
|
|
14
|
+
this.platformName = platformName ?? platform;
|
|
18
15
|
this.rerunScriptPath =
|
|
19
|
-
rerunScriptPath ??
|
|
16
|
+
rerunScriptPath ??
|
|
17
|
+
(this.platformName === 'win32' ? 'rerun.bat' : 'rerun.sh');
|
|
20
18
|
this.commandPrefix = commandPrefix ?? '';
|
|
21
19
|
this.customParameters = customParameters ?? '';
|
|
22
20
|
this.specFile = '';
|
|
23
|
-
this.disabled =
|
|
21
|
+
this.disabled = env['DISABLE_RERUN'] === 'true';
|
|
22
|
+
this.log = logger('@wdio/wdio-rerun-service');
|
|
24
23
|
}
|
|
25
24
|
async before(_capabilities, specs) {
|
|
26
25
|
if (this.disabled) {
|
|
27
26
|
return;
|
|
28
27
|
}
|
|
29
28
|
this.specFile = specs[0] ?? '';
|
|
30
|
-
|
|
31
|
-
await
|
|
32
|
-
this.serviceWorkerId = (
|
|
29
|
+
this.log.debug(`๐ Re-run service activated. Data directory: ${this.rerunDataDir}`);
|
|
30
|
+
await mkdir(this.rerunDataDir, { recursive: true });
|
|
31
|
+
this.serviceWorkerId = randomUUID();
|
|
33
32
|
}
|
|
34
33
|
afterTest(_test, _context, results) {
|
|
35
34
|
if (this.disabled) {
|
|
@@ -40,8 +39,8 @@ class RerunService {
|
|
|
40
39
|
if (passed || config.framework === 'cucumber') {
|
|
41
40
|
return;
|
|
42
41
|
}
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
this.log.debug(`๐ Inspecting non-passing test.`);
|
|
43
|
+
this.log.debug(`๐ Test location: ${this.specFile}`);
|
|
45
44
|
const error = results.error;
|
|
46
45
|
if (error?.message) {
|
|
47
46
|
this.nonPassingItems.push({
|
|
@@ -50,7 +49,7 @@ class RerunService {
|
|
|
50
49
|
});
|
|
51
50
|
}
|
|
52
51
|
else {
|
|
53
|
-
|
|
52
|
+
this.log.debug('โ ๏ธ Non-passing test did not contain an error message, skipping.');
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
// Executed after a Cucumber scenario ends.
|
|
@@ -65,14 +64,34 @@ class RerunService {
|
|
|
65
64
|
status === 'SKIPPED') {
|
|
66
65
|
return;
|
|
67
66
|
}
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
const { gherkinDocument, pickle } = world;
|
|
68
|
+
const featureChildren = gherkinDocument.feature?.children ?? [];
|
|
69
|
+
// Locate the matching scenario by searching feature children
|
|
70
|
+
// Scenarios can be at top-level OR nested within Rule blocks
|
|
71
|
+
const findMatchingScenario = () => {
|
|
72
|
+
for (const featureChild of featureChildren) {
|
|
73
|
+
// Direct scenario under feature
|
|
74
|
+
if (featureChild.scenario) {
|
|
75
|
+
if (pickle.astNodeIds.includes(featureChild.scenario.id)) {
|
|
76
|
+
return featureChild.scenario;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Scenario nested inside a Rule block
|
|
80
|
+
if (featureChild.rule?.children) {
|
|
81
|
+
const ruleScenario = featureChild.rule.children.find((ruleChild) => ruleChild.scenario &&
|
|
82
|
+
pickle.astNodeIds.includes(ruleChild.scenario.id))?.scenario;
|
|
83
|
+
if (ruleScenario)
|
|
84
|
+
return ruleScenario;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
};
|
|
89
|
+
const scenario = findMatchingScenario();
|
|
71
90
|
let scenarioLineNumber = scenario?.location.line ?? 0;
|
|
72
91
|
if (scenario && scenario.examples.length > 0) {
|
|
73
92
|
let exampleLineNumber = 0;
|
|
74
93
|
scenario.examples.find((example) => example.tableBody.find((row) => {
|
|
75
|
-
if (row.id ===
|
|
94
|
+
if (row.id === pickle.astNodeIds[1]) {
|
|
76
95
|
exampleLineNumber = row.location.line;
|
|
77
96
|
return true;
|
|
78
97
|
}
|
|
@@ -80,8 +99,8 @@ class RerunService {
|
|
|
80
99
|
}));
|
|
81
100
|
scenarioLineNumber = exampleLineNumber;
|
|
82
101
|
}
|
|
83
|
-
const scenarioLocation = `${
|
|
84
|
-
const tagsList =
|
|
102
|
+
const scenarioLocation = `${pickle.uri}:${scenarioLineNumber}`;
|
|
103
|
+
const tagsList = pickle.tags.map((tag) => tag.name);
|
|
85
104
|
if (!Array.isArray(this.ignoredTags) ||
|
|
86
105
|
!tagsList.some((ignoredTag) => this.ignoredTags.includes(ignoredTag))) {
|
|
87
106
|
this.nonPassingItems.push({
|
|
@@ -95,30 +114,35 @@ class RerunService {
|
|
|
95
114
|
return;
|
|
96
115
|
}
|
|
97
116
|
if (this.nonPassingItems.length === 0) {
|
|
98
|
-
|
|
117
|
+
this.log.debug('โ
No non-passing scenarios or tests detected.');
|
|
118
|
+
return;
|
|
99
119
|
}
|
|
100
|
-
await
|
|
120
|
+
await writeFile(join(this.rerunDataDir, `rerun-${this.serviceWorkerId}.json`), JSON.stringify(this.nonPassingItems));
|
|
101
121
|
}
|
|
102
122
|
async onComplete() {
|
|
103
123
|
if (this.disabled) {
|
|
104
124
|
return;
|
|
105
125
|
}
|
|
106
126
|
try {
|
|
107
|
-
const files = await
|
|
127
|
+
const files = await readdir(this.rerunDataDir);
|
|
108
128
|
const rerunFiles = files.filter((file) => file.endsWith('.json'));
|
|
109
129
|
if (rerunFiles.length === 0) {
|
|
110
130
|
return;
|
|
111
131
|
}
|
|
112
|
-
const
|
|
113
|
-
|
|
132
|
+
const { positionals } = parseArgs({
|
|
133
|
+
args: argv.slice(2),
|
|
134
|
+
allowPositionals: true,
|
|
135
|
+
strict: false,
|
|
136
|
+
});
|
|
137
|
+
const args = positionals[0] ? positionals[0] + ' ' : '';
|
|
114
138
|
const prefix = this.commandPrefix ? this.commandPrefix + ' ' : '';
|
|
115
|
-
const disableRerun =
|
|
139
|
+
const disableRerun = this.platformName === 'win32'
|
|
116
140
|
? 'set DISABLE_RERUN=true &&'
|
|
117
141
|
: 'DISABLE_RERUN=true';
|
|
118
142
|
let rerunCommand = `${prefix}${disableRerun} npx wdio ${args}${this.customParameters}`;
|
|
119
143
|
const failureLocations = new Set();
|
|
120
144
|
for (const file of rerunFiles) {
|
|
121
|
-
const json = JSON.parse(await
|
|
145
|
+
const json = JSON.parse(await readFile(join(this.rerunDataDir, file), 'utf8'));
|
|
122
146
|
json.forEach((failure) => {
|
|
123
147
|
failureLocations.add(failure.location.replace(/\\/g, '/'));
|
|
124
148
|
});
|
|
@@ -126,13 +150,12 @@ class RerunService {
|
|
|
126
150
|
failureLocations.forEach((failureLocation) => {
|
|
127
151
|
rerunCommand += ` --spec=${failureLocation}`;
|
|
128
152
|
});
|
|
129
|
-
await
|
|
130
|
-
|
|
153
|
+
await writeFile(this.rerunScriptPath, rerunCommand, { mode: 0o755 });
|
|
154
|
+
this.log.debug(`๐ Re-run script generated: ${this.rerunScriptPath}`);
|
|
131
155
|
}
|
|
132
156
|
catch (err) {
|
|
133
|
-
|
|
157
|
+
this.log.debug(`โ Failed to generate re-run script: ${JSON.stringify(err)}`);
|
|
134
158
|
}
|
|
135
159
|
}
|
|
136
160
|
}
|
|
137
|
-
exports.default = RerunService;
|
|
138
161
|
//# sourceMappingURL=index.js.map
|
package/build/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/build/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Logger } from '@wdio/logger';
|
|
2
|
+
import type { Frameworks, Services } from '@wdio/types';
|
|
2
3
|
type AfterScenario = NonNullable<WebdriverIO.HookFunctionExtension['afterScenario']>;
|
|
3
4
|
type AfterScenarioParameters = Parameters<AfterScenario>;
|
|
4
5
|
type World = AfterScenarioParameters[0];
|
|
@@ -12,6 +13,7 @@ interface RerunServiceOptions {
|
|
|
12
13
|
rerunScriptPath?: string;
|
|
13
14
|
commandPrefix?: string;
|
|
14
15
|
customParameters?: string;
|
|
16
|
+
platformName?: NodeJS.Platform;
|
|
15
17
|
}
|
|
16
18
|
export default class RerunService implements Services.ServiceInstance {
|
|
17
19
|
nonPassingItems: NonPassingItem[];
|
|
@@ -23,8 +25,10 @@ export default class RerunService implements Services.ServiceInstance {
|
|
|
23
25
|
customParameters: string;
|
|
24
26
|
specFile: string;
|
|
25
27
|
disabled: boolean;
|
|
28
|
+
platformName: NodeJS.Platform;
|
|
29
|
+
log: Logger;
|
|
26
30
|
constructor(options?: RerunServiceOptions);
|
|
27
|
-
before(_capabilities: Capabilities
|
|
31
|
+
before(_capabilities: WebdriverIO.Capabilities, specs: string[]): Promise<void>;
|
|
28
32
|
afterTest(_test: Frameworks.Test, _context: any, results: Frameworks.TestResult): void;
|
|
29
33
|
afterScenario(world: World): void;
|
|
30
34
|
after(): Promise<void>;
|