@koenvanbelle/cypress-soft-assertions 2.4.3 → 2.4.4

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/dist/index.js CHANGED
@@ -81,7 +81,13 @@ function patchChaiAssertions() {
81
81
  assertionProto.assert = patchedAssertionAssert;
82
82
  }
83
83
  function resolveStableToken(assertionContext, args) {
84
- return (0, utils_1.resolveToken)((0, utils_1.getAssertionToken)(assertionContext, args), getRetryableCommandId(), args);
84
+ const assertionToken = (0, utils_1.getAssertionToken)(assertionContext, args);
85
+ if (assertionToken)
86
+ return assertionToken;
87
+ const commandId = getRetryableCommandId();
88
+ if (commandId)
89
+ return (0, utils_1.resolveToken)('', commandId, args);
90
+ return '';
85
91
  }
86
92
  function isRunningHookContext() {
87
93
  var _a;
@@ -95,23 +101,24 @@ function isRunningHookContext() {
95
101
  }
96
102
  }
97
103
  function patchedAssertionAssert(...args) {
104
+ var _a;
98
105
  if (!originalChaiAssert)
99
106
  return;
107
+ // Fast path for non-soft tests: avoid try/catch and token logic entirely.
108
+ if (!isInSoftTest) {
109
+ return originalChaiAssert.apply(this, args);
110
+ }
100
111
  try {
101
112
  const result = originalChaiAssert.apply(this, args);
102
113
  // Assertion passed — clear any staged failure for this token.
103
- if (isInSoftTest) {
104
- const token = resolveStableToken(this, args);
105
- if (token) {
106
- retryAssertionFailures.delete(token);
107
- retryFirstSeen.delete(token);
108
- }
114
+ const token = resolveStableToken(this, args);
115
+ if (token) {
116
+ retryAssertionFailures.delete(token);
117
+ retryFirstSeen.delete(token);
109
118
  }
110
119
  return result;
111
120
  }
112
121
  catch (error) {
113
- if (!isInSoftTest)
114
- throw error;
115
122
  if (isRunningHookContext())
116
123
  throw error;
117
124
  const errorEntry = {
@@ -120,22 +127,30 @@ function patchedAssertionAssert(...args) {
120
127
  };
121
128
  const token = resolveStableToken(this, args);
122
129
  if (token) {
123
- // Track when we first saw this failure.
124
- if (!retryFirstSeen.has(token)) {
125
- retryFirstSeen.set(token, Date.now());
126
- }
127
130
  // Stage the failure so it can be cleared if a later retry succeeds.
128
131
  retryAssertionFailures.set(token, errorEntry);
129
- // Check if the retry window has expired. Swallow slightly before
130
- // Cypress's own timeout to prevent it from firing the fail event.
131
- // Cypress retries every ~50ms, so subtracting 100ms ensures we
132
- // catch at least 1-2 more retries before the deadline.
133
- const elapsed = Date.now() - retryFirstSeen.get(token);
132
+ const current = cy.state('current');
133
+ const wallClockStartedAt = (_a = current === null || current === void 0 ? void 0 : current.get) === null || _a === void 0 ? void 0 : _a.call(current, 'wallClockStartedAt');
134
134
  const timeout = getEffectiveTimeout();
135
- const swallowAt = Math.max(timeout - 100, timeout * 0.9);
136
- if (elapsed < swallowAt) {
137
- // Still within the retry window rethrow so Cypress retries.
138
- throw error;
135
+ if (typeof wallClockStartedAt === 'number') {
136
+ const totalElapsed = Date.now() - wallClockStartedAt;
137
+ // Swallow only when very close to the actual command timeout.
138
+ // A 20ms buffer maximizes retry attempts while still preventing
139
+ // Cypress's global fail handler from aborting the test queue.
140
+ if (totalElapsed < timeout - 20) {
141
+ throw error;
142
+ }
143
+ }
144
+ else {
145
+ // Fallback for cases where wallClockStartedAt is missing.
146
+ if (!retryFirstSeen.has(token)) {
147
+ retryFirstSeen.set(token, Date.now());
148
+ }
149
+ const elapsed = Date.now() - retryFirstSeen.get(token);
150
+ const swallowAt = Math.max(timeout - 100, timeout * 0.9);
151
+ if (elapsed < swallowAt) {
152
+ throw error;
153
+ }
139
154
  }
140
155
  // Retry window expired. Swallow the error: Cypress considers the
141
156
  // assertion "passed", the command resolves, and the queue continues.
package/dist/utils.js CHANGED
@@ -84,10 +84,11 @@ function appendUniqueError(errors, message, stack) {
84
84
  */
85
85
  function mergeRetryFailures(softErrors, retryFailures) {
86
86
  const result = [...softErrors];
87
+ const seenMessages = new Set(result.map(e => e.message));
87
88
  for (const entry of retryFailures.values()) {
88
- const isDuplicate = result.some(e => e.message === entry.message);
89
- if (!isDuplicate) {
89
+ if (!seenMessages.has(entry.message)) {
90
90
  result.push(entry);
91
+ seenMessages.add(entry.message);
91
92
  }
92
93
  }
93
94
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koenvanbelle/cypress-soft-assertions",
3
- "version": "2.4.3",
3
+ "version": "2.4.4",
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",