@koenvanbelle/cypress-soft-assertions 2.0.0 → 2.0.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 +9 -0
- package/dist/index.js +36 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -158,6 +158,15 @@ SOFT ASSERTION FAILURES (3 failed):
|
|
|
158
158
|
- **Retriable assertions are retried**: `.should()` and `.and()` assertions are retried by Cypress before being captured as soft failures. Assertions that eventually pass are not reported.
|
|
159
159
|
- **Non-assertion errors still stop execution**: Network errors, visit timeouts, and other command errors are captured as soft failures but may prevent subsequent commands from running.
|
|
160
160
|
- **State resets between tests**: Each `soft_it()` test starts with a clean slate — failures from one test never leak into another.
|
|
161
|
+
- **Timeout-aware retries**: The plugin respects Cypress's `defaultCommandTimeout` and per-command `{ timeout }` overrides. Retriable assertions (`.should()`, `.and()`) are retried for up to 75% of the effective timeout before being captured as soft failures. For slow applications, increase the timeout to give assertions more time to pass:
|
|
162
|
+
```typescript
|
|
163
|
+
// Global: set in cypress.config.ts
|
|
164
|
+
e2e: { defaultCommandTimeout: 10000 }
|
|
165
|
+
|
|
166
|
+
// Per-command: override on individual commands
|
|
167
|
+
cy.get('.slow-element', { timeout: 15000 }).should('be.visible');
|
|
168
|
+
```
|
|
169
|
+
- **Cypress Studio / Command Log**: When a soft assertion fails definitively, the plugin swallows the error so the test can continue. Cypress treats the command as resolved, which means it may not appear as a failed step in the Cypress Studio command log or may look like the assertion was skipped. The assertions **do** execute and failures **are** captured — they just don't show visually in the command log. Check the final `SoftAssertionError` report for the complete list of failures.
|
|
161
170
|
|
|
162
171
|
## License
|
|
163
172
|
|
package/dist/index.js
CHANGED
|
@@ -9,15 +9,26 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
let softAssertionErrors = [];
|
|
11
11
|
let retryAssertionFailures = new Map();
|
|
12
|
-
let
|
|
12
|
+
let retryFirstSeen = new Map();
|
|
13
13
|
let isInSoftTest = false;
|
|
14
14
|
let activeFailHandler = null;
|
|
15
15
|
let originalChaiAssert = null;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
16
|
+
function getEffectiveTimeout() {
|
|
17
|
+
var _a;
|
|
18
|
+
try {
|
|
19
|
+
const current = cy.state('current');
|
|
20
|
+
const perCommand = (_a = current === null || current === void 0 ? void 0 : current.get) === null || _a === void 0 ? void 0 : _a.call(current, 'timeout');
|
|
21
|
+
if (typeof perCommand === 'number')
|
|
22
|
+
return perCommand;
|
|
23
|
+
}
|
|
24
|
+
catch ( /* ignore */_b) { /* ignore */ }
|
|
25
|
+
try {
|
|
26
|
+
return Cypress.config('defaultCommandTimeout') || 4000;
|
|
27
|
+
}
|
|
28
|
+
catch (_c) {
|
|
29
|
+
return 4000;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
21
32
|
function captureSoftAssertion(error) {
|
|
22
33
|
const message = (error === null || error === void 0 ? void 0 : error.message) || String(error);
|
|
23
34
|
const stack = error === null || error === void 0 ? void 0 : error.stack;
|
|
@@ -81,7 +92,7 @@ function patchedAssertionAssert(...args) {
|
|
|
81
92
|
const token = getAssertionToken(this, args);
|
|
82
93
|
if (token) {
|
|
83
94
|
retryAssertionFailures.delete(token);
|
|
84
|
-
|
|
95
|
+
retryFirstSeen.delete(token);
|
|
85
96
|
}
|
|
86
97
|
}
|
|
87
98
|
return result;
|
|
@@ -97,17 +108,23 @@ function patchedAssertionAssert(...args) {
|
|
|
97
108
|
message: String((error === null || error === void 0 ? void 0 : error.message) || error),
|
|
98
109
|
stack: error === null || error === void 0 ? void 0 : error.stack,
|
|
99
110
|
});
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
if (!retryFirstSeen.has(token)) {
|
|
113
|
+
retryFirstSeen.set(token, now);
|
|
114
|
+
}
|
|
115
|
+
const elapsed = now - retryFirstSeen.get(token);
|
|
116
|
+
const timeout = getEffectiveTimeout();
|
|
117
|
+
// Use 75% of the timeout as the retry window. This ensures the plugin
|
|
118
|
+
// swallows the error before Cypress's own timeout fires (which would
|
|
119
|
+
// route through the fail handler and prevent finalization).
|
|
120
|
+
if (elapsed < timeout * 0.75) {
|
|
121
|
+
// Still within the command timeout window — rethrow to let Cypress
|
|
122
|
+
// retry the assertion. If it eventually passes, the token is cleared.
|
|
106
123
|
throw error;
|
|
107
124
|
}
|
|
108
|
-
// Past the
|
|
109
|
-
// moves on to the next queued command. The token stays in the
|
|
110
|
-
// will be promoted to softAssertionErrors at finalization.
|
|
125
|
+
// Past the timeout budget — swallow so the command "succeeds" and
|
|
126
|
+
// Cypress moves on to the next queued command. The token stays in the
|
|
127
|
+
// Map and will be promoted to softAssertionErrors at finalization.
|
|
111
128
|
return;
|
|
112
129
|
}
|
|
113
130
|
// No identifiable subject — capture directly (e.g. bare expect() calls
|
|
@@ -150,7 +167,7 @@ function buildSoftAssertionError() {
|
|
|
150
167
|
captureSoftAssertion(entry);
|
|
151
168
|
}
|
|
152
169
|
retryAssertionFailures.clear();
|
|
153
|
-
|
|
170
|
+
retryFirstSeen.clear();
|
|
154
171
|
if (softAssertionErrors.length > 0) {
|
|
155
172
|
const errorMessages = softAssertionErrors
|
|
156
173
|
.map((entry, index) => ` ${index + 1}. ${entry.message}`)
|
|
@@ -180,7 +197,7 @@ function abortSoftTest() {
|
|
|
180
197
|
isInSoftTest = false;
|
|
181
198
|
restoreAssertions();
|
|
182
199
|
retryAssertionFailures.clear();
|
|
183
|
-
|
|
200
|
+
retryFirstSeen.clear();
|
|
184
201
|
}
|
|
185
202
|
function createSoftIt(baseIt) {
|
|
186
203
|
return function (title, fn) {
|
|
@@ -188,7 +205,7 @@ function createSoftIt(baseIt) {
|
|
|
188
205
|
isInSoftTest = true;
|
|
189
206
|
softAssertionErrors = [];
|
|
190
207
|
retryAssertionFailures.clear();
|
|
191
|
-
|
|
208
|
+
retryFirstSeen.clear();
|
|
192
209
|
setupSoftAssertions();
|
|
193
210
|
let result;
|
|
194
211
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koenvanbelle/cypress-soft-assertions",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "A Cypress plugin that provides soft_it() for soft assertions - all assertions continue on failure and are reported together",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|