@koenvanbelle/cypress-soft-assertions 2.1.0 → 2.1.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.
Files changed (2) hide show
  1. package/dist/index.js +24 -27
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -138,24 +138,13 @@ function patchedAssertionAssert(...args) {
138
138
  message: String((error === null || error === void 0 ? void 0 : error.message) || error),
139
139
  stack: error === null || error === void 0 ? void 0 : error.stack,
140
140
  });
141
- const now = Date.now();
142
141
  if (!retryFirstSeen.has(token)) {
143
- retryFirstSeen.set(token, now);
142
+ retryFirstSeen.set(token, Date.now());
144
143
  }
145
- const elapsed = now - retryFirstSeen.get(token);
146
- const timeout = getEffectiveTimeout();
147
- // Use 75% of the timeout as the retry window. This ensures the plugin
148
- // swallows the error before Cypress's own timeout fires (which would
149
- // route through the fail handler and prevent finalization).
150
- if (elapsed < timeout * 0.75) {
151
- // Still within the command timeout window — rethrow to let Cypress
152
- // retry the assertion. If it eventually passes, the token is cleared.
153
- throw error;
154
- }
155
- // Past the timeout budget — swallow so the command "succeeds" and
156
- // Cypress moves on to the next queued command. The token stays in the
157
- // Map and will be promoted to softAssertionErrors at finalization.
158
- return;
144
+ // Always rethrow to let Cypress use its full retry/timeout window.
145
+ // When the timeout expires, Cypress fires the fail event; our fail
146
+ // handler captures it and clears the staged entry to avoid duplicates.
147
+ throw error;
159
148
  }
160
149
  // No identifiable subject from the DOM. If we're inside a retryable
161
150
  // command (.should() / .and()), derive a token from the command ID so the
@@ -167,17 +156,11 @@ function patchedAssertionAssert(...args) {
167
156
  message: String((error === null || error === void 0 ? void 0 : error.message) || error),
168
157
  stack: error === null || error === void 0 ? void 0 : error.stack,
169
158
  });
170
- const now = Date.now();
171
159
  if (!retryFirstSeen.has(fallbackToken)) {
172
- retryFirstSeen.set(fallbackToken, now);
173
- }
174
- const elapsed = now - retryFirstSeen.get(fallbackToken);
175
- const timeout = getEffectiveTimeout();
176
- if (elapsed < timeout * 0.75) {
177
- throw error;
160
+ retryFirstSeen.set(fallbackToken, Date.now());
178
161
  }
179
- // Past retry budget swallow and let Cypress move on.
180
- return;
162
+ // Always rethrow to let Cypress use its full retry/timeout window.
163
+ throw error;
181
164
  }
182
165
  // Bare expect() in .then() callbacks — capture directly.
183
166
  captureSoftAssertion(error);
@@ -195,6 +178,16 @@ function setupSoftAssertions() {
195
178
  // Non-assertion command failures (e.g. element not found timeouts)
196
179
  // are captured as soft failures.
197
180
  captureSoftAssertion(error);
181
+ // Clear any matching retry-tracked entry to prevent double-counting
182
+ // at finalization (the fail handler is now the authoritative capture).
183
+ const errorMsg = (error === null || error === void 0 ? void 0 : error.message) || String(error);
184
+ for (const [token, entry] of retryAssertionFailures.entries()) {
185
+ if (entry.message === errorMsg) {
186
+ retryAssertionFailures.delete(token);
187
+ retryFirstSeen.delete(token);
188
+ break;
189
+ }
190
+ }
198
191
  return false;
199
192
  };
200
193
  Cypress.on('fail', activeFailHandler);
@@ -213,9 +206,13 @@ function restoreAssertions() {
213
206
  }
214
207
  }
215
208
  function buildSoftAssertionError() {
216
- // Promote any remaining retry-tracked failures.
209
+ // Promote any remaining retry-tracked failures that weren't already
210
+ // captured by the fail handler (dedup by message).
217
211
  for (const entry of retryAssertionFailures.values()) {
218
- captureSoftAssertion(entry);
212
+ const isDuplicate = softAssertionErrors.some(e => e.message === entry.message);
213
+ if (!isDuplicate) {
214
+ softAssertionErrors.push(entry);
215
+ }
219
216
  }
220
217
  retryAssertionFailures.clear();
221
218
  retryFirstSeen.clear();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koenvanbelle/cypress-soft-assertions",
3
- "version": "2.1.0",
3
+ "version": "2.1.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",