cypress-rerun-failed-specs-sid-g 1.0.7
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 +167 -0
- package/bin/cli.js +89 -0
- package/issues +1 -0
- package/package.json +30 -0
- package/src/index.js +89 -0
- package/types/index.d.ts +14 -0
package/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# ⭐ cypress-rerun-failed-specs-sid-g
|
|
2
|
+
|
|
3
|
+
A Cypress plugin and CLI tool that automatically **reruns only failed spec files** from the previous Cypress run.
|
|
4
|
+
It helps reduce flaky failures, saves CI time, and avoids rerunning the entire test suite.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## ❓ What problem does this solve?
|
|
9
|
+
|
|
10
|
+
In real-world Cypress projects:
|
|
11
|
+
|
|
12
|
+
- Tests can be **flaky**
|
|
13
|
+
- CI pipelines fail even when reruns would pass
|
|
14
|
+
- Rerunning the **entire suite** is slow and expensive
|
|
15
|
+
|
|
16
|
+
### ✅ This plugin solves that by:
|
|
17
|
+
- Detecting **only failed spec files**
|
|
18
|
+
- Rerunning **only those specs**
|
|
19
|
+
- Optionally auto‑rerunning in CI (opt‑in, safe by default)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 📦 Installation
|
|
24
|
+
|
|
25
|
+
Install as a dev dependency:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install cypress-rerun-failed-specs-sid-g --save-dev
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## JavaScript cypress.config.js
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
const rerunFailed = require("cypress-rerun-failed-specs-sid-g");
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
e2e: {
|
|
38
|
+
setupNodeEvents(on, config) {
|
|
39
|
+
rerunFailed(on, config);
|
|
40
|
+
return config;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
## TypeScript (cypress.config.ts)
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
import rerunFailed from "cypress-rerun-failed-specs-sid-g";
|
|
49
|
+
import { defineConfig } from "cypress";
|
|
50
|
+
|
|
51
|
+
export default defineConfig({
|
|
52
|
+
e2e: {
|
|
53
|
+
setupNodeEvents(on, config) {
|
|
54
|
+
rerunFailed(on, config);
|
|
55
|
+
return config;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
▶️ How to Use
|
|
62
|
+
Step 1: Run Cypress normally
|
|
63
|
+
```
|
|
64
|
+
npx cypress run
|
|
65
|
+
```
|
|
66
|
+
If any specs fail, the plugin generates:
|
|
67
|
+
```
|
|
68
|
+
cypress/failed-specs.json
|
|
69
|
+
```
|
|
70
|
+
Step 2: Rerun only failed specs
|
|
71
|
+
```
|
|
72
|
+
npx cypress-rerun-failed
|
|
73
|
+
```
|
|
74
|
+
Only the failed spec files from the last run are executed.
|
|
75
|
+
|
|
76
|
+
⚙️ CLI Commands & Options
|
|
77
|
+
```
|
|
78
|
+
npx cypress-rerun-failed [options]
|
|
79
|
+
```
|
|
80
|
+
Available Options
|
|
81
|
+
Option Description
|
|
82
|
+
```
|
|
83
|
+
--browser <name> Run in a specific browser (chrome, firefox, edge)
|
|
84
|
+
--headed Run Cypress in headed (UI) mode
|
|
85
|
+
--retries <number> Retry failed specs N times
|
|
86
|
+
--help Show CLI help
|
|
87
|
+
```
|
|
88
|
+
Example Commands
|
|
89
|
+
# Basic rerun
|
|
90
|
+
```
|
|
91
|
+
npx cypress-rerun-failed
|
|
92
|
+
```
|
|
93
|
+
# Run in Chrome
|
|
94
|
+
```
|
|
95
|
+
npx cypress-rerun-failed --browser chrome
|
|
96
|
+
```
|
|
97
|
+
# Headed mode
|
|
98
|
+
```
|
|
99
|
+
npx cypress-rerun-failed --headed
|
|
100
|
+
```
|
|
101
|
+
# Retry failed specs twice
|
|
102
|
+
```
|
|
103
|
+
npx cypress-rerun-failed --retries 2
|
|
104
|
+
```
|
|
105
|
+
# Combine options
|
|
106
|
+
```
|
|
107
|
+
npx cypress-rerun-failed --browser chrome --headed --retries 2
|
|
108
|
+
```
|
|
109
|
+
🔁 CI Usage (Optional & Safe)
|
|
110
|
+
Auto‑rerun is disabled by default.
|
|
111
|
+
|
|
112
|
+
Enable via environment variables
|
|
113
|
+
macOS / Linux
|
|
114
|
+
```
|
|
115
|
+
export CYPRESS_RERUN_FAILED=true
|
|
116
|
+
export CYPRESS_RERUN_MAX_ATTEMPTS=2
|
|
117
|
+
```
|
|
118
|
+
Windows (PowerShell)
|
|
119
|
+
```
|
|
120
|
+
$env:CYPRESS_RERUN_FAILED="true"
|
|
121
|
+
$env:CYPRESS_RERUN_MAX_ATTEMPTS="2"
|
|
122
|
+
```
|
|
123
|
+
Example: GitHub Actions
|
|
124
|
+
```
|
|
125
|
+
env:
|
|
126
|
+
CYPRESS_RERUN_FAILED: "true"
|
|
127
|
+
CYPRESS_RERUN_MAX_ATTEMPTS: "2"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
CI Behavior
|
|
131
|
+
|
|
132
|
+
Initial Cypress run executes
|
|
133
|
+
|
|
134
|
+
Failed specs are detected
|
|
135
|
+
|
|
136
|
+
Only failed specs are rerun
|
|
137
|
+
|
|
138
|
+
Stops after max retry attempts
|
|
139
|
+
|
|
140
|
+
Proper exit codes for CI pipelines
|
|
141
|
+
|
|
142
|
+
📂 Generated Files
|
|
143
|
+
```
|
|
144
|
+
cypress/results/*.json Mochawesome JSON reports
|
|
145
|
+
|
|
146
|
+
cypress/failed-specs.json List of failed spec files
|
|
147
|
+
```
|
|
148
|
+
🛡️ Why this plugin is safe
|
|
149
|
+
Auto‑rerun is opt‑in
|
|
150
|
+
|
|
151
|
+
Max retry protection (no infinite loops)
|
|
152
|
+
|
|
153
|
+
No network calls
|
|
154
|
+
|
|
155
|
+
No postinstall scripts
|
|
156
|
+
|
|
157
|
+
Cross‑platform (Windows / macOS / Linux)
|
|
158
|
+
|
|
159
|
+
🧩 TypeScript Support
|
|
160
|
+
TypeScript typings are included.
|
|
161
|
+
|
|
162
|
+
import rerunFailed from "cypress-rerun-failed-specs-sid-g";
|
|
163
|
+
📄 License
|
|
164
|
+
MIT
|
|
165
|
+
|
|
166
|
+
👤 Author
|
|
167
|
+
Siddhant Gadakh
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawnSync } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const { getFailedSpecs } = require("../src");
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
|
|
11
|
+
function getArg(flag) {
|
|
12
|
+
const index = args.indexOf(flag);
|
|
13
|
+
return index !== -1 ? args[index + 1] : null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
18
|
+
console.log(`
|
|
19
|
+
sid-cypress-rerun-failed
|
|
20
|
+
|
|
21
|
+
Usage:
|
|
22
|
+
npx cypress-rerun-failed [options]
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--browser <name> Run in specific browser (chrome, firefox, edge)
|
|
26
|
+
--headed Run Cypress in headed mode
|
|
27
|
+
--retries <number> Retry failed specs
|
|
28
|
+
--help, -h Show this help message
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
npx cypress-rerun-failed
|
|
32
|
+
npx cypress-rerun-failed --browser chrome
|
|
33
|
+
npx cypress-rerun-failed --headed --retries 2
|
|
34
|
+
`);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// --------------------
|
|
39
|
+
// SUPPORTED FLAGS
|
|
40
|
+
// --------------------
|
|
41
|
+
const browser = getArg("--browser");
|
|
42
|
+
const headed = args.includes("--headed");
|
|
43
|
+
const retries = getArg("--retries");
|
|
44
|
+
|
|
45
|
+
// --------------------
|
|
46
|
+
// CONFIG
|
|
47
|
+
// --------------------
|
|
48
|
+
const REPORT_DIR = path.join(process.cwd(), "cypress", "results");
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
console.log("Searching for failed spec files...");
|
|
52
|
+
|
|
53
|
+
if (!fs.existsSync(REPORT_DIR)) {
|
|
54
|
+
throw new Error(`Report directory not found: ${REPORT_DIR}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const failedSpecs = getFailedSpecs(REPORT_DIR);
|
|
58
|
+
|
|
59
|
+
if (!failedSpecs.length) {
|
|
60
|
+
console.log("No failed spec files found");
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log("Failed spec files:");
|
|
65
|
+
failedSpecs.forEach((spec) => console.log(` - ${spec}`));
|
|
66
|
+
|
|
67
|
+
const spawnArgs = [
|
|
68
|
+
"cypress",
|
|
69
|
+
"run",
|
|
70
|
+
"--spec",
|
|
71
|
+
failedSpecs.join(","),
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
if (browser) spawnArgs.push("--browser", browser);
|
|
75
|
+
if (headed) spawnArgs.push("--headed");
|
|
76
|
+
if (retries) spawnArgs.push("--retries", retries);
|
|
77
|
+
|
|
78
|
+
console.log("Rerunning failed spec files...\n");
|
|
79
|
+
|
|
80
|
+
const result = spawnSync("npx", spawnArgs, {
|
|
81
|
+
stdio: "inherit",
|
|
82
|
+
shell: process.platform === "win32",
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
process.exit(result.status ?? 0);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error("Error:", error.message);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
package/issues
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
please tell me the issues or bug you find
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cypress-rerun-failed-specs-sid-g",
|
|
3
|
+
"version": "1.0.7",
|
|
4
|
+
"description": "Rerun failed Cypress spec files from previous run",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"types": "types/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"cypress-rerun-failed": "bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"cypress",
|
|
12
|
+
"cypress-plugin",
|
|
13
|
+
"rerun",
|
|
14
|
+
"failed-specs",
|
|
15
|
+
"ci"
|
|
16
|
+
],
|
|
17
|
+
"author": "Siddhant Arjun Gadakh",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=16"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/SourceCode-code/sid-cypress-rerun-failed"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/SourceCode-code/sid-cypress-rerun-failed/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/SourceCode-code/sid-cypress-rerun-failed#readme"
|
|
30
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
function getFailedSpecs(reportDir) {
|
|
5
|
+
if (!fs.existsSync(reportDir)) {
|
|
6
|
+
throw new Error(`Report directory not found: ${reportDir}`);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const failedSpecs = new Set();
|
|
10
|
+
const files = fs.readdirSync(reportDir).filter(f => f.endsWith('.json'));
|
|
11
|
+
|
|
12
|
+
if (!files.length) {
|
|
13
|
+
throw new Error('No JSON report files found in report directory');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for (const file of files) {
|
|
17
|
+
const reportPath = path.join(reportDir, file);
|
|
18
|
+
let report;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
|
|
22
|
+
} catch (err) {
|
|
23
|
+
console.warn(`Skipping invalid JSON report: ${file}`);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!report.results) continue;
|
|
28
|
+
|
|
29
|
+
for (const result of report.results) {
|
|
30
|
+
let hasFailure = false;
|
|
31
|
+
|
|
32
|
+
(function walkSuites(suites = []) {
|
|
33
|
+
for (const suite of suites) {
|
|
34
|
+
suite.tests?.forEach(test => {
|
|
35
|
+
if (test.state === 'failed') {
|
|
36
|
+
hasFailure = true;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
walkSuites(suite.suites);
|
|
40
|
+
}
|
|
41
|
+
})(result.suites);
|
|
42
|
+
|
|
43
|
+
if (hasFailure && result.file) {
|
|
44
|
+
failedSpecs.add(result.file);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return Array.from(failedSpecs);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Cypress plugin entry point
|
|
54
|
+
*/
|
|
55
|
+
function cypressRerunFailed(on, config) {
|
|
56
|
+
console.log('cypress-rerun-failed initialized');
|
|
57
|
+
|
|
58
|
+
on('after:run', () => {
|
|
59
|
+
const reportDir = path.join(
|
|
60
|
+
config.projectRoot,
|
|
61
|
+
'cypress',
|
|
62
|
+
'results'
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const failedSpecs = getFailedSpecs(reportDir);
|
|
67
|
+
|
|
68
|
+
if (!failedSpecs.length) {
|
|
69
|
+
console.log('No failed specs found');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const outputPath = path.join(
|
|
74
|
+
config.projectRoot,
|
|
75
|
+
'cypress',
|
|
76
|
+
'failed-specs.json'
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
fs.writeFileSync(outputPath, JSON.stringify(failedSpecs, null, 2));
|
|
80
|
+
console.log('Failed specs saved to:', outputPath);
|
|
81
|
+
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.warn('Failed spec detection skipped:', err.message);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = cypressRerunFailed;
|
|
89
|
+
module.exports.getFailedSpecs = getFailedSpecs;
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare module "sid-cypress-rerun-failed" {
|
|
2
|
+
import { PluginEvents, PluginConfigOptions } from "cypress";
|
|
3
|
+
|
|
4
|
+
type CypressPlugin = (
|
|
5
|
+
on: PluginEvents,
|
|
6
|
+
config: PluginConfigOptions
|
|
7
|
+
) => void;
|
|
8
|
+
|
|
9
|
+
const rerunFailed: CypressPlugin;
|
|
10
|
+
|
|
11
|
+
export function getFailedSpecs(reportDir: string): string[];
|
|
12
|
+
|
|
13
|
+
export default rerunFailed;
|
|
14
|
+
}
|