vest 5.2.8 → 5.2.10

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.
@@ -140,18 +140,85 @@ function useIsOptionalFieldApplied(fieldName) {
140
140
  return ((_b = (_a = SuiteOptionalFields.getOptionalField(root, fieldName)) === null || _a === void 0 ? void 0 : _a.applied) !== null && _b !== void 0 ? _b : false);
141
141
  }
142
142
 
143
- var Events;
144
- (function (Events) {
145
- Events["TEST_RUN_STARTED"] = "test_run_started";
146
- Events["TEST_COMPLETED"] = "test_completed";
147
- Events["ALL_RUNNING_TESTS_FINISHED"] = "all_running_tests_finished";
148
- Events["REMOVE_FIELD"] = "remove_field";
149
- Events["RESET_FIELD"] = "reset_field";
150
- Events["RESET_SUITE"] = "reset_suite";
151
- Events["SUITE_RUN_STARTED"] = "suite_run_started";
152
- Events["SUITE_CALLBACK_RUN_FINISHED"] = "SUITE_CALLBACK_RUN_FINISHED";
153
- Events["DONE_TEST_OMISSION_PASS"] = "DONE_TEST_OMISSION_PASS";
154
- })(Events || (Events = {}));
143
+ var FocusModes;
144
+ (function (FocusModes) {
145
+ FocusModes[FocusModes["ONLY"] = 0] = "ONLY";
146
+ FocusModes[FocusModes["SKIP"] = 1] = "SKIP";
147
+ })(FocusModes || (FocusModes = {}));
148
+
149
+ function IsolateFocused(focusMode, match) {
150
+ return vestjsRuntime.Isolate.create(VestIsolateType.Focused, vestUtils.noop, {
151
+ focusMode,
152
+ match: vestUtils.asArray(match).filter(vestUtils.isStringValue),
153
+ matchAll: match === true,
154
+ });
155
+ }
156
+ class FocusSelectors {
157
+ static isSkipFocused(focus, fieldName) {
158
+ return ((focus === null || focus === void 0 ? void 0 : focus.data.focusMode) === FocusModes.SKIP &&
159
+ (hasFocus(focus, fieldName) || focus.data.matchAll === true));
160
+ }
161
+ static isOnlyFocused(focus, fieldName) {
162
+ return ((focus === null || focus === void 0 ? void 0 : focus.data.focusMode) === FocusModes.ONLY && hasFocus(focus, fieldName));
163
+ }
164
+ static isIsolateFocused(isolate) {
165
+ return vestjsRuntime.IsolateSelectors.isIsolateType(isolate, VestIsolateType.Focused);
166
+ }
167
+ }
168
+ /**
169
+ * Adds a field or a list of fields into the inclusion list
170
+ *
171
+ * @example
172
+ *
173
+ * only('username');
174
+ */
175
+ // @vx-allow use-use
176
+ function only(match) {
177
+ return IsolateFocused(FocusModes.ONLY, defaultMatch(match));
178
+ }
179
+ /**
180
+ * Adds a field or a list of fields into the exclusion list
181
+ *
182
+ * @example
183
+ *
184
+ * skip('username');
185
+ */
186
+ // @vx-allow use-use
187
+ function skip(match) {
188
+ return IsolateFocused(FocusModes.SKIP, defaultMatch(match));
189
+ }
190
+ function defaultMatch(match) {
191
+ return match === false ? [] : match;
192
+ }
193
+ function hasFocus(focus, fieldName) {
194
+ var _a, _b;
195
+ return (vestUtils.isNotEmpty(focus === null || focus === void 0 ? void 0 : focus.data.match) &&
196
+ (fieldName ? (_b = (_a = focus === null || focus === void 0 ? void 0 : focus.data.match) === null || _a === void 0 ? void 0 : _a.includes(fieldName)) !== null && _b !== void 0 ? _b : true : true));
197
+ }
198
+
199
+ function group(...args) {
200
+ const [callback, groupName] = args.reverse();
201
+ return vestjsRuntime.Isolate.create(VestIsolateType.Group, () => {
202
+ return SuiteContext.run(Object.assign({}, (groupName && { groupName })), callback);
203
+ });
204
+ }
205
+
206
+ var ErrorStrings;
207
+ (function (ErrorStrings) {
208
+ ErrorStrings["HOOK_CALLED_OUTSIDE"] = "hook called outside of a running suite.";
209
+ ErrorStrings["EXPECTED_VEST_TEST"] = "Expected value to be an instance of IsolateTest";
210
+ ErrorStrings["FIELD_NAME_REQUIRED"] = "Field name must be passed";
211
+ ErrorStrings["SUITE_MUST_BE_INITIALIZED_WITH_FUNCTION"] = "Suite must be initialized with a function";
212
+ ErrorStrings["PROMISIFY_REQUIRE_FUNCTION"] = "Vest.Promisify must be called with a function";
213
+ ErrorStrings["PARSER_EXPECT_RESULT_OBJECT"] = "Vest parser: expected argument at position 0 to be Vest's result object.";
214
+ ErrorStrings["WARN_MUST_BE_CALLED_FROM_TEST"] = "Warn must be called from within the body of a test function";
215
+ ErrorStrings["EACH_CALLBACK_MUST_BE_A_FUNCTION"] = "Each must be called with a function";
216
+ ErrorStrings["INVALID_PARAM_PASSED_TO_FUNCTION"] = "Incompatible params passed to {fn_name} function. \"{param}\" must be of type {expected}";
217
+ ErrorStrings["TESTS_CALLED_IN_DIFFERENT_ORDER"] = "Vest Critical Error: Tests called in different order than previous run.\n expected: {fieldName}\n received: {prevName}\n This can happen on one of two reasons:\n 1. You're using if/else statements to conditionally select tests. Instead, use \"skipWhen\".\n 2. You are iterating over a list of tests, and their order changed. Use \"each\" and a custom key prop so that Vest retains their state.";
218
+ ErrorStrings["UNEXPECTED_TEST_REGISTRATION_ERROR"] = "Unexpected error encountered during test registration.\n Please report this issue to Vest's Github repository.\n Test Object: {testObject}.\n Error: {error}.";
219
+ ErrorStrings["UNEXPECTED_TEST_RUN_ERROR"] = "Unexpected error encountered during test run. Please report this issue to Vest's Github repository.\n Test Object: {testObject}.";
220
+ ErrorStrings["INCLUDE_SELF"] = "Trying to call include.when on the same field.";
221
+ })(ErrorStrings || (ErrorStrings = {}));
155
222
 
156
223
  const suiteResultCache = vestUtils.cache();
157
224
  function useCreateVestState({ suiteName, VestReconciler, }) {
@@ -202,124 +269,6 @@ function useLoadSuite(rootNode) {
202
269
  useExpireSuiteResultCache();
203
270
  }
204
271
 
205
- const CommonStates = {
206
- PENDING: 'PENDING',
207
- INITIAL: 'INITIAL',
208
- };
209
- const State = {
210
- [CommonStates.PENDING]: CommonStates.PENDING,
211
- [CommonStates.INITIAL]: CommonStates.INITIAL,
212
- DONE: 'DONE',
213
- };
214
- const machine$1 = {
215
- initial: State.INITIAL,
216
- states: {
217
- [State.DONE]: {},
218
- [State.INITIAL]: {
219
- [State.PENDING]: State.PENDING,
220
- [State.DONE]: State.DONE,
221
- },
222
- [State.PENDING]: {
223
- [State.DONE]: State.DONE,
224
- },
225
- },
226
- };
227
- function transition(from, to) {
228
- return CommonStateMachine.staticTransition(from !== null && from !== void 0 ? from : State.INITIAL, to);
229
- }
230
- function setDone(isolate) {
231
- isolate.status = transition(isolate.status, State.DONE);
232
- }
233
- function setPending(isolate) {
234
- isolate.status = transition(isolate.status, State.PENDING);
235
- }
236
- const CommonStateMachine = vestUtils.StateMachine(machine$1);
237
-
238
- class VestIsolate {
239
- static getStatus(isolate) {
240
- var _a;
241
- return (_a = isolate.status) !== null && _a !== void 0 ? _a : CommonStates.INITIAL;
242
- }
243
- static setStatus(isolate, status, payload) {
244
- isolate.status = this.stateMachine.staticTransition(VestIsolate.getStatus(isolate), status, payload);
245
- }
246
- static statusEquals(isolate, status) {
247
- return VestIsolate.getStatus(isolate) === status;
248
- }
249
- static setPending(isolate) {
250
- this.setStatus(isolate, CommonStates.PENDING);
251
- }
252
- static isPending(isolate) {
253
- return VestIsolate.statusEquals(isolate, CommonStates.PENDING);
254
- }
255
- }
256
- VestIsolate.stateMachine = CommonStateMachine;
257
-
258
- var ErrorStrings;
259
- (function (ErrorStrings) {
260
- ErrorStrings["HOOK_CALLED_OUTSIDE"] = "hook called outside of a running suite.";
261
- ErrorStrings["EXPECTED_VEST_TEST"] = "Expected value to be an instance of IsolateTest";
262
- ErrorStrings["FIELD_NAME_REQUIRED"] = "Field name must be passed";
263
- ErrorStrings["SUITE_MUST_BE_INITIALIZED_WITH_FUNCTION"] = "Suite must be initialized with a function";
264
- ErrorStrings["PROMISIFY_REQUIRE_FUNCTION"] = "Vest.Promisify must be called with a function";
265
- ErrorStrings["PARSER_EXPECT_RESULT_OBJECT"] = "Vest parser: expected argument at position 0 to be Vest's result object.";
266
- ErrorStrings["WARN_MUST_BE_CALLED_FROM_TEST"] = "Warn must be called from within the body of a test function";
267
- ErrorStrings["EACH_CALLBACK_MUST_BE_A_FUNCTION"] = "Each must be called with a function";
268
- ErrorStrings["INVALID_PARAM_PASSED_TO_FUNCTION"] = "Incompatible params passed to {fn_name} function. \"{param}\" must be of type {expected}";
269
- ErrorStrings["TESTS_CALLED_IN_DIFFERENT_ORDER"] = "Vest Critical Error: Tests called in different order than previous run.\n expected: {fieldName}\n received: {prevName}\n This can happen on one of two reasons:\n 1. You're using if/else statements to conditionally select tests. Instead, use \"skipWhen\".\n 2. You are iterating over a list of tests, and their order changed. Use \"each\" and a custom key prop so that Vest retains their state.";
270
- ErrorStrings["UNEXPECTED_TEST_REGISTRATION_ERROR"] = "Unexpected error encountered during test registration.\n Please report this issue to Vest's Github repository.\n Test Object: {testObject}.\n Error: {error}.";
271
- ErrorStrings["UNEXPECTED_TEST_RUN_ERROR"] = "Unexpected error encountered during test run. Please report this issue to Vest's Github repository.\n Test Object: {testObject}.";
272
- ErrorStrings["INCLUDE_SELF"] = "Trying to call include.when on the same field.";
273
- })(ErrorStrings || (ErrorStrings = {}));
274
-
275
- const TestStatus = {
276
- [CommonStates.PENDING]: CommonStates.PENDING,
277
- CANCELED: 'CANCELED',
278
- FAILED: 'FAILED',
279
- OMITTED: 'OMITTED',
280
- PASSING: 'PASSING',
281
- SKIPPED: 'SKIPPED',
282
- UNTESTED: 'UNTESTED',
283
- WARNING: 'WARNING',
284
- };
285
- const TestAction = {
286
- RESET: 'RESET',
287
- };
288
- const machine = {
289
- initial: TestStatus.UNTESTED,
290
- states: {
291
- '*': {
292
- [TestStatus.OMITTED]: TestStatus.OMITTED,
293
- [TestAction.RESET]: TestStatus.UNTESTED,
294
- },
295
- [TestStatus.UNTESTED]: {
296
- [TestStatus.CANCELED]: TestStatus.CANCELED,
297
- [TestStatus.FAILED]: TestStatus.FAILED,
298
- [TestStatus.PASSING]: TestStatus.PASSING,
299
- [TestStatus.PENDING]: TestStatus.PENDING,
300
- [TestStatus.SKIPPED]: TestStatus.SKIPPED,
301
- [TestStatus.WARNING]: TestStatus.WARNING,
302
- },
303
- [TestStatus.PENDING]: {
304
- [TestStatus.CANCELED]: TestStatus.CANCELED,
305
- [TestStatus.FAILED]: TestStatus.FAILED,
306
- [TestStatus.PASSING]: TestStatus.PASSING,
307
- [TestStatus.SKIPPED]: [
308
- TestStatus.SKIPPED,
309
- (force) => force === true,
310
- ],
311
- [TestStatus.WARNING]: TestStatus.WARNING,
312
- },
313
- [TestStatus.SKIPPED]: {},
314
- [TestStatus.FAILED]: {},
315
- [TestStatus.WARNING]: {},
316
- [TestStatus.PASSING]: {},
317
- [TestStatus.CANCELED]: {},
318
- [TestStatus.OMITTED]: {},
319
- },
320
- };
321
- const IsolateTestStateMachine = vestUtils.StateMachine(machine);
322
-
323
272
  var Severity;
324
273
  (function (Severity) {
325
274
  Severity["WARNINGS"] = "warnings";
@@ -341,161 +290,449 @@ var TestSeverity;
341
290
  TestSeverity["Warning"] = "warning";
342
291
  })(TestSeverity || (TestSeverity = {}));
343
292
 
344
- class VestTest extends VestIsolate {
345
- // Read
346
- static getData(test) {
347
- vestUtils.invariant(test.data);
348
- return test.data;
349
- }
350
- static is(isolate) {
351
- return vestjsRuntime.IsolateSelectors.isIsolateType(isolate, VestIsolateType.Test);
352
- }
353
- static isX(isolate) {
354
- vestUtils.invariant(VestTest.is(isolate), ErrorStrings.EXPECTED_VEST_TEST);
293
+ // calls collectAll or getByFieldName depending on whether fieldName is provided
294
+ function gatherFailures(testGroup, severityKey, fieldName) {
295
+ return fieldName
296
+ ? getByFieldName(testGroup, severityKey, fieldName)
297
+ : collectAll(testGroup, severityKey);
298
+ }
299
+ function getByFieldName(testGroup, severityKey, fieldName) {
300
+ var _a;
301
+ return ((_a = testGroup === null || testGroup === void 0 ? void 0 : testGroup[fieldName]) === null || _a === void 0 ? void 0 : _a[severityKey]) || [];
302
+ }
303
+ function collectAll(testGroup, severityKey) {
304
+ const output = {};
305
+ const countKey = countKeyBySeverity(severityKey);
306
+ for (const field in testGroup) {
307
+ if (vestUtils.isPositive(testGroup[field][countKey])) {
308
+ // We will probably never get to the fallback array
309
+ // leaving it just in case the implementation changes
310
+ output[field] = testGroup[field][severityKey] || [];
311
+ }
355
312
  }
356
- static cast(isolate) {
357
- VestTest.isX(isolate);
358
- return isolate;
313
+ return output;
314
+ }
315
+
316
+ function nonMatchingFieldName(WithFieldName, fieldName) {
317
+ return !!fieldName && !matchingFieldName(WithFieldName, fieldName);
318
+ }
319
+ function matchingFieldName(WithFieldName, fieldName) {
320
+ return !!(fieldName && WithFieldName.fieldName === fieldName);
321
+ }
322
+ function matchesOrHasNoFieldName(WithFieldName, fieldName) {
323
+ if (fieldName) {
324
+ return matchingFieldName(WithFieldName, fieldName);
359
325
  }
360
- static warns(test) {
361
- return VestTest.getData(test).severity === TestSeverity.Warning;
362
- }
363
- static isOmitted(test) {
364
- return VestTest.statusEquals(test, TestStatus.OMITTED);
365
- }
366
- static isUntested(test) {
367
- return VestTest.statusEquals(test, TestStatus.UNTESTED);
368
- }
369
- static isFailing(test) {
370
- return VestTest.statusEquals(test, TestStatus.FAILED);
371
- }
372
- static isCanceled(test) {
373
- return VestTest.statusEquals(test, TestStatus.CANCELED);
374
- }
375
- static isSkipped(test) {
376
- return VestTest.statusEquals(test, TestStatus.SKIPPED);
377
- }
378
- static isPassing(test) {
379
- return VestTest.statusEquals(test, TestStatus.PASSING);
380
- }
381
- static isWarning(test) {
382
- return VestTest.statusEquals(test, TestStatus.WARNING);
326
+ return true;
327
+ }
328
+
329
+ function bindSuiteSelectors(get) {
330
+ return {
331
+ getError: (...args) => get().getError(...args),
332
+ getErrors: (...args) => get().getErrors(...args),
333
+ getErrorsByGroup: (...args) => get().getErrorsByGroup(...args),
334
+ getWarning: (...args) => get().getWarning(...args),
335
+ getWarnings: (...args) => get().getWarnings(...args),
336
+ getWarningsByGroup: (...args) => get().getWarningsByGroup(...args),
337
+ hasErrors: (...args) => get().hasErrors(...args),
338
+ hasErrorsByGroup: (...args) => get().hasErrorsByGroup(...args),
339
+ hasWarnings: (...args) => get().hasWarnings(...args),
340
+ hasWarningsByGroup: (...args) => get().hasWarningsByGroup(...args),
341
+ isPending: (...args) => {
342
+ return get().isPending(...args);
343
+ },
344
+ isTested: (...args) => get().isTested(...args),
345
+ isValid: (...args) => get().isValid(...args),
346
+ isValidByGroup: (...args) => get().isValidByGroup(...args),
347
+ };
348
+ }
349
+ // eslint-disable-next-line max-lines-per-function, max-statements
350
+ function suiteSelectors(summary) {
351
+ const selectors = {
352
+ getError,
353
+ getErrors,
354
+ getErrorsByGroup,
355
+ getWarning,
356
+ getWarnings,
357
+ getWarningsByGroup,
358
+ hasErrors,
359
+ hasErrorsByGroup,
360
+ hasWarnings,
361
+ hasWarningsByGroup,
362
+ isPending,
363
+ isTested,
364
+ isValid,
365
+ isValidByGroup,
366
+ };
367
+ return selectors;
368
+ // Booleans
369
+ function isValid(fieldName) {
370
+ var _a;
371
+ return fieldName ? Boolean((_a = summary.tests[fieldName]) === null || _a === void 0 ? void 0 : _a.valid) : summary.valid;
383
372
  }
384
- static hasFailures(test) {
385
- return VestTest.isFailing(test) || VestTest.isWarning(test);
373
+ function isValidByGroup(groupName, fieldName) {
374
+ const group = summary.groups[groupName];
375
+ if (!group) {
376
+ return false;
377
+ }
378
+ if (fieldName) {
379
+ return isFieldValid(group, fieldName);
380
+ }
381
+ for (const fieldName in group) {
382
+ if (!isFieldValid(group, fieldName)) {
383
+ return false;
384
+ }
385
+ }
386
+ return true;
386
387
  }
387
- static isNonActionable(test) {
388
- return (VestTest.isSkipped(test) ||
389
- VestTest.isOmitted(test) ||
390
- VestTest.isCanceled(test));
388
+ function hasWarnings(fieldName) {
389
+ return hasFailures(summary, SeverityCount.WARN_COUNT, fieldName);
391
390
  }
392
- static isTested(test) {
393
- return VestTest.hasFailures(test) || VestTest.isPassing(test);
391
+ function hasErrors(fieldName) {
392
+ return hasFailures(summary, SeverityCount.ERROR_COUNT, fieldName);
394
393
  }
395
- static awaitsResolution(test) {
396
- // Is the test in a state where it can still be run, or complete running
397
- // and its final status is indeterminate?
398
- return (VestTest.isSkipped(test) ||
399
- VestTest.isUntested(test) ||
400
- VestTest.isPending(test));
394
+ function isTested(fieldName) {
395
+ var _a;
396
+ return vestUtils.isPositive((_a = summary.tests[fieldName]) === null || _a === void 0 ? void 0 : _a.testCount);
401
397
  }
402
- static isAsyncTest(test) {
403
- return vestUtils.isPromise(VestTest.getData(test).asyncTest);
398
+ function hasWarningsByGroup(groupName, fieldName) {
399
+ return hasFailuresByGroup(summary, SeverityCount.WARN_COUNT, groupName, fieldName);
404
400
  }
405
- // Mutate
406
- // static setPending(test: TIsolateTest) {
407
- // this.setStatus(test, TestStatus.PENDING);
408
- // }
409
- static fail(test) {
410
- VestTest.setStatus(test, VestTest.warns(test) ? TestStatus.WARNING : TestStatus.FAILED);
401
+ function hasErrorsByGroup(groupName, fieldName) {
402
+ return hasFailuresByGroup(summary, SeverityCount.ERROR_COUNT, groupName, fieldName);
411
403
  }
412
- static pass(test) {
413
- VestTest.setStatus(test, TestStatus.PASSING);
404
+ function getWarnings(fieldName) {
405
+ return getFailures(summary, Severity.WARNINGS, fieldName);
414
406
  }
415
- static warn(test) {
416
- VestTest.setData(test, current => (Object.assign(Object.assign({}, current), { severity: TestSeverity.Warning })));
407
+ function getWarning(fieldName) {
408
+ return getFailure(Severity.WARNINGS, summary, fieldName);
417
409
  }
418
- static setData(test, setter) {
419
- test.data = vestUtils.optionalFunctionValue(setter, VestTest.getData(test));
410
+ function getErrors(fieldName) {
411
+ return getFailures(summary, Severity.ERRORS, fieldName);
420
412
  }
421
- static skip(test, force) {
422
- // Without this force flag, the test will be marked as skipped even if it is pending.
423
- // This means that it will not be counted in "allIncomplete" and its done callbacks
424
- // will not be called, or will be called prematurely.
425
- // What this mostly say is that when we have a pending test for one field, and we then
426
- // start typing in a different field - the pending test will be canceled, which
427
- // is usually an unwanted behavior.
428
- // The only scenario in which we DO want to cancel the async test regardless
429
- // is when we specifically skip a test with `skipWhen`, which is handled by the
430
- // "force" boolean flag.
431
- // I am not a fan of this flag, but it gets the job done.
432
- VestTest.setStatus(test, TestStatus.SKIPPED, force);
413
+ function getError(fieldName) {
414
+ return getFailure(Severity.ERRORS, summary, fieldName);
433
415
  }
434
- static cancel(test) {
435
- VestTest.setStatus(test, TestStatus.CANCELED);
436
- vestjsRuntime.IsolateMutator.abort(test, TestStatus.CANCELED);
416
+ function getErrorsByGroup(groupName, fieldName) {
417
+ return getFailuresByGroup(summary, Severity.ERRORS, groupName, fieldName);
437
418
  }
438
- static omit(test) {
439
- VestTest.setStatus(test, TestStatus.OMITTED);
419
+ function getWarningsByGroup(groupName, fieldName) {
420
+ return getFailuresByGroup(summary, Severity.WARNINGS, groupName, fieldName);
440
421
  }
441
- static reset(test) {
442
- VestTest.setStatus(test, TestAction.RESET);
422
+ function isPending(fieldName) {
423
+ var _a;
424
+ return fieldName
425
+ ? vestUtils.greaterThan((_a = summary.tests[fieldName]) === null || _a === void 0 ? void 0 : _a.pendingCount, 0)
426
+ : vestUtils.greaterThan(summary.pendingCount, 0);
443
427
  }
444
428
  }
445
- VestTest.stateMachine = IsolateTestStateMachine;
446
-
447
- function nonMatchingFieldName(WithFieldName, fieldName) {
448
- return !!fieldName && !matchingFieldName(WithFieldName, fieldName);
429
+ function getFailures(summary, severityKey, fieldName) {
430
+ return gatherFailures(summary.tests, severityKey, fieldName);
449
431
  }
450
- function matchingFieldName(WithFieldName, fieldName) {
451
- return !!(fieldName && WithFieldName.fieldName === fieldName);
432
+ // Gathers all failures of a given severity within a group
433
+ // With a fieldName, it will only gather failures for that field
434
+ function getFailuresByGroup(summary, severityKey, groupName, fieldName) {
435
+ return gatherFailures(summary.groups[groupName], severityKey, fieldName);
452
436
  }
453
- function matchesOrHasNoFieldName(WithFieldName, fieldName) {
437
+ // Checks if a field is valid within a container object - can be within a group or top level
438
+ function isFieldValid(testContainer, fieldName) {
439
+ var _a;
440
+ return !!((_a = testContainer[fieldName]) === null || _a === void 0 ? void 0 : _a.valid);
441
+ }
442
+ // Checks if a there are any failures of a given severity within a group
443
+ // If a fieldName is provided, it will only check for failures within that field
444
+ function hasFailuresByGroup(summary, severityCount, groupName, fieldName) {
445
+ var _a, _b;
446
+ const group = summary.groups[groupName];
447
+ if (!group) {
448
+ return false;
449
+ }
454
450
  if (fieldName) {
455
- return matchingFieldName(WithFieldName, fieldName);
451
+ return vestUtils.isPositive((_a = group[fieldName]) === null || _a === void 0 ? void 0 : _a[severityCount]);
456
452
  }
457
- return true;
458
- }
459
-
460
- class SuiteWalker {
461
- static hasPending(predicate) {
462
- const root = SuiteWalker.defaultRoot();
463
- if (!root) {
464
- return false;
453
+ for (const field in group) {
454
+ if (vestUtils.isPositive((_b = group[field]) === null || _b === void 0 ? void 0 : _b[severityCount])) {
455
+ return true;
465
456
  }
466
- return vestjsRuntime.Walker.some(root, vestUtils.Predicates.all(VestIsolate.isPending, predicate !== null && predicate !== void 0 ? predicate : true));
467
457
  }
468
- // Checks whether there are pending isolates in the tree.
469
- // If a fieldname is provided, will only check tests with a matching fieldname.
470
- static hasRemainingWithTestNameMatching(fieldName) {
471
- return SuiteWalker.hasPending(vestUtils.Predicates.any(vestUtils.isNullish(fieldName), vestUtils.Predicates.all(VestTest.is, (testObject) => {
472
- return matchesOrHasNoFieldName(VestTest.getData(testObject), fieldName);
473
- })));
458
+ return false;
459
+ }
460
+ // Checks if there are any failures of a given severity
461
+ // If a fieldName is provided, it will only check for failures within that field
462
+ function hasFailures(summary, countKey, fieldName) {
463
+ var _a;
464
+ const failureCount = fieldName
465
+ ? (_a = summary.tests[fieldName]) === null || _a === void 0 ? void 0 : _a[countKey]
466
+ : summary[countKey] || 0;
467
+ return vestUtils.isPositive(failureCount);
468
+ }
469
+ function getFailure(severity, summary, fieldName) {
470
+ var _a;
471
+ const summaryKey = summary[severity];
472
+ if (!fieldName) {
473
+ return summaryKey[0];
474
474
  }
475
+ return (_a = summaryKey.find((summaryFailure) => matchingFieldName(summaryFailure, fieldName))) === null || _a === void 0 ? void 0 : _a.message;
475
476
  }
476
- SuiteWalker.defaultRoot = vestjsRuntime.VestRuntime.useAvailableRoot;
477
477
 
478
- class TestWalker {
479
- static hasNoTests(root = TestWalker.defaultRoot()) {
480
- if (!root)
481
- return true;
482
- return !vestjsRuntime.Walker.has(root, VestTest.is);
483
- }
484
- static someTests(predicate, root = TestWalker.defaultRoot()) {
485
- if (!root)
486
- return false;
487
- return vestjsRuntime.Walker.some(root, isolate => {
488
- VestTest.isX(isolate);
489
- return predicate(isolate);
490
- }, VestTest.is);
478
+ var _a, _b;
479
+ class SummaryBase {
480
+ constructor() {
481
+ this.errorCount = 0;
482
+ this.warnCount = 0;
483
+ this.testCount = 0;
484
+ this.pendingCount = 0;
491
485
  }
492
- static everyTest(predicate, root = TestWalker.defaultRoot()) {
493
- if (!root)
494
- return false;
495
- return vestjsRuntime.Walker.every(root, isolate => {
496
- VestTest.isX(isolate);
497
- return predicate(isolate);
498
- }, VestTest.is);
486
+ }
487
+ class SuiteSummary extends SummaryBase {
488
+ constructor() {
489
+ super(...arguments);
490
+ this[_a] = [];
491
+ this[_b] = [];
492
+ this.groups = {};
493
+ this.tests = {};
494
+ this.valid = false;
495
+ }
496
+ }
497
+ _a = Severity.ERRORS, _b = Severity.WARNINGS;
498
+
499
+ const CommonStates = {
500
+ PENDING: 'PENDING',
501
+ INITIAL: 'INITIAL',
502
+ };
503
+ const State = {
504
+ [CommonStates.PENDING]: CommonStates.PENDING,
505
+ [CommonStates.INITIAL]: CommonStates.INITIAL,
506
+ DONE: 'DONE',
507
+ };
508
+ const machine$1 = {
509
+ initial: State.INITIAL,
510
+ states: {
511
+ [State.DONE]: {},
512
+ [State.INITIAL]: {
513
+ [State.PENDING]: State.PENDING,
514
+ [State.DONE]: State.DONE,
515
+ },
516
+ [State.PENDING]: {
517
+ [State.DONE]: State.DONE,
518
+ },
519
+ },
520
+ };
521
+ function transition(from, to) {
522
+ return CommonStateMachine.staticTransition(from !== null && from !== void 0 ? from : State.INITIAL, to);
523
+ }
524
+ function setDone(isolate) {
525
+ isolate.status = transition(isolate.status, State.DONE);
526
+ }
527
+ function setPending(isolate) {
528
+ isolate.status = transition(isolate.status, State.PENDING);
529
+ }
530
+ const CommonStateMachine = vestUtils.StateMachine(machine$1);
531
+
532
+ const TestStatus = {
533
+ [CommonStates.PENDING]: CommonStates.PENDING,
534
+ CANCELED: 'CANCELED',
535
+ FAILED: 'FAILED',
536
+ OMITTED: 'OMITTED',
537
+ PASSING: 'PASSING',
538
+ SKIPPED: 'SKIPPED',
539
+ UNTESTED: 'UNTESTED',
540
+ WARNING: 'WARNING',
541
+ };
542
+ const TestAction = {
543
+ RESET: 'RESET',
544
+ };
545
+ const machine = {
546
+ initial: TestStatus.UNTESTED,
547
+ states: {
548
+ '*': {
549
+ [TestStatus.OMITTED]: TestStatus.OMITTED,
550
+ [TestAction.RESET]: TestStatus.UNTESTED,
551
+ },
552
+ [TestStatus.UNTESTED]: {
553
+ [TestStatus.CANCELED]: TestStatus.CANCELED,
554
+ [TestStatus.FAILED]: TestStatus.FAILED,
555
+ [TestStatus.PASSING]: TestStatus.PASSING,
556
+ [TestStatus.PENDING]: TestStatus.PENDING,
557
+ [TestStatus.SKIPPED]: TestStatus.SKIPPED,
558
+ [TestStatus.WARNING]: TestStatus.WARNING,
559
+ },
560
+ [TestStatus.PENDING]: {
561
+ [TestStatus.CANCELED]: TestStatus.CANCELED,
562
+ [TestStatus.FAILED]: TestStatus.FAILED,
563
+ [TestStatus.PASSING]: TestStatus.PASSING,
564
+ [TestStatus.SKIPPED]: [
565
+ TestStatus.SKIPPED,
566
+ (force) => force === true,
567
+ ],
568
+ [TestStatus.WARNING]: TestStatus.WARNING,
569
+ },
570
+ [TestStatus.SKIPPED]: {},
571
+ [TestStatus.FAILED]: {},
572
+ [TestStatus.WARNING]: {},
573
+ [TestStatus.PASSING]: {},
574
+ [TestStatus.CANCELED]: {},
575
+ [TestStatus.OMITTED]: {},
576
+ },
577
+ };
578
+ const IsolateTestStateMachine = vestUtils.StateMachine(machine);
579
+
580
+ class VestIsolate {
581
+ static getStatus(isolate) {
582
+ var _a;
583
+ return (_a = isolate.status) !== null && _a !== void 0 ? _a : CommonStates.INITIAL;
584
+ }
585
+ static setStatus(isolate, status, payload) {
586
+ isolate.status = this.stateMachine.staticTransition(VestIsolate.getStatus(isolate), status, payload);
587
+ }
588
+ static statusEquals(isolate, status) {
589
+ return VestIsolate.getStatus(isolate) === status;
590
+ }
591
+ static setPending(isolate) {
592
+ this.setStatus(isolate, CommonStates.PENDING);
593
+ }
594
+ static isPending(isolate) {
595
+ return VestIsolate.statusEquals(isolate, CommonStates.PENDING);
596
+ }
597
+ }
598
+ VestIsolate.stateMachine = CommonStateMachine;
599
+
600
+ class VestTest extends VestIsolate {
601
+ // Read
602
+ static getData(test) {
603
+ vestUtils.invariant(test.data);
604
+ return test.data;
605
+ }
606
+ static is(isolate) {
607
+ return vestjsRuntime.IsolateSelectors.isIsolateType(isolate, VestIsolateType.Test);
608
+ }
609
+ static isX(isolate) {
610
+ vestUtils.invariant(VestTest.is(isolate), ErrorStrings.EXPECTED_VEST_TEST);
611
+ }
612
+ static cast(isolate) {
613
+ VestTest.isX(isolate);
614
+ return isolate;
615
+ }
616
+ static warns(test) {
617
+ return VestTest.getData(test).severity === TestSeverity.Warning;
618
+ }
619
+ static isOmitted(test) {
620
+ return VestTest.statusEquals(test, TestStatus.OMITTED);
621
+ }
622
+ static isUntested(test) {
623
+ return VestTest.statusEquals(test, TestStatus.UNTESTED);
624
+ }
625
+ static isFailing(test) {
626
+ return VestTest.statusEquals(test, TestStatus.FAILED);
627
+ }
628
+ static isCanceled(test) {
629
+ return VestTest.statusEquals(test, TestStatus.CANCELED);
630
+ }
631
+ static isSkipped(test) {
632
+ return VestTest.statusEquals(test, TestStatus.SKIPPED);
633
+ }
634
+ static isPassing(test) {
635
+ return VestTest.statusEquals(test, TestStatus.PASSING);
636
+ }
637
+ static isWarning(test) {
638
+ return VestTest.statusEquals(test, TestStatus.WARNING);
639
+ }
640
+ static hasFailures(test) {
641
+ return VestTest.isFailing(test) || VestTest.isWarning(test);
642
+ }
643
+ static isNonActionable(test) {
644
+ return (VestTest.isSkipped(test) ||
645
+ VestTest.isOmitted(test) ||
646
+ VestTest.isCanceled(test));
647
+ }
648
+ static isTested(test) {
649
+ return VestTest.hasFailures(test) || VestTest.isPassing(test);
650
+ }
651
+ static awaitsResolution(test) {
652
+ // Is the test in a state where it can still be run, or complete running
653
+ // and its final status is indeterminate?
654
+ return (VestTest.isSkipped(test) ||
655
+ VestTest.isUntested(test) ||
656
+ VestTest.isPending(test));
657
+ }
658
+ static isAsyncTest(test) {
659
+ return vestUtils.isPromise(VestTest.getData(test).asyncTest);
660
+ }
661
+ // Mutate
662
+ // static setPending(test: TIsolateTest) {
663
+ // this.setStatus(test, TestStatus.PENDING);
664
+ // }
665
+ static fail(test) {
666
+ VestTest.setStatus(test, VestTest.warns(test) ? TestStatus.WARNING : TestStatus.FAILED);
667
+ }
668
+ static pass(test) {
669
+ VestTest.setStatus(test, TestStatus.PASSING);
670
+ }
671
+ static warn(test) {
672
+ VestTest.setData(test, current => (Object.assign(Object.assign({}, current), { severity: TestSeverity.Warning })));
673
+ }
674
+ static setData(test, setter) {
675
+ test.data = vestUtils.optionalFunctionValue(setter, VestTest.getData(test));
676
+ }
677
+ static skip(test, force) {
678
+ // Without this force flag, the test will be marked as skipped even if it is pending.
679
+ // This means that it will not be counted in "allIncomplete" and its done callbacks
680
+ // will not be called, or will be called prematurely.
681
+ // What this mostly say is that when we have a pending test for one field, and we then
682
+ // start typing in a different field - the pending test will be canceled, which
683
+ // is usually an unwanted behavior.
684
+ // The only scenario in which we DO want to cancel the async test regardless
685
+ // is when we specifically skip a test with `skipWhen`, which is handled by the
686
+ // "force" boolean flag.
687
+ // I am not a fan of this flag, but it gets the job done.
688
+ VestTest.setStatus(test, TestStatus.SKIPPED, force);
689
+ }
690
+ static cancel(test) {
691
+ VestTest.setStatus(test, TestStatus.CANCELED);
692
+ vestjsRuntime.IsolateMutator.abort(test, TestStatus.CANCELED);
693
+ }
694
+ static omit(test) {
695
+ VestTest.setStatus(test, TestStatus.OMITTED);
696
+ }
697
+ static reset(test) {
698
+ VestTest.setStatus(test, TestAction.RESET);
699
+ }
700
+ }
701
+ VestTest.stateMachine = IsolateTestStateMachine;
702
+
703
+ class SummaryFailure {
704
+ constructor(fieldName, message, groupName) {
705
+ this.fieldName = fieldName;
706
+ this.message = message;
707
+ this.groupName = groupName;
708
+ }
709
+ static fromTestObject(testObject) {
710
+ const { fieldName, message, groupName } = VestTest.getData(testObject);
711
+ return new SummaryFailure(fieldName, message, groupName);
712
+ }
713
+ }
714
+
715
+ class TestWalker {
716
+ static hasNoTests(root = TestWalker.defaultRoot()) {
717
+ if (!root)
718
+ return true;
719
+ return !vestjsRuntime.Walker.has(root, VestTest.is);
720
+ }
721
+ static someTests(predicate, root = TestWalker.defaultRoot()) {
722
+ if (!root)
723
+ return false;
724
+ return vestjsRuntime.Walker.some(root, isolate => {
725
+ VestTest.isX(isolate);
726
+ return predicate(isolate);
727
+ }, VestTest.is);
728
+ }
729
+ static everyTest(predicate, root = TestWalker.defaultRoot()) {
730
+ if (!root)
731
+ return false;
732
+ return vestjsRuntime.Walker.every(root, isolate => {
733
+ VestTest.isX(isolate);
734
+ return predicate(isolate);
735
+ }, VestTest.is);
499
736
  }
500
737
  static walkTests(callback, root = TestWalker.defaultRoot()) {
501
738
  if (!root)
@@ -527,178 +764,23 @@ class TestWalker {
527
764
  }
528
765
  TestWalker.defaultRoot = vestjsRuntime.VestRuntime.useAvailableRoot;
529
766
 
530
- /**
531
- * This module gets triggered once the suite is done running its sync tests.
532
- *
533
- * It goes over all the tests in the state, and checks if they need to be omitted.
534
- */
535
- function useOmitOptionalFields() {
536
- const root = vestjsRuntime.VestRuntime.useAvailableRoot();
537
- const optionalFields = SuiteOptionalFields.getOptionalFields(root);
538
- // If there are no optional fields, we don't need to do anything
539
- if (vestUtils.isEmpty(optionalFields)) {
540
- return;
541
- }
542
- // Create an object to store the fields that need to be omitted
543
- const shouldOmit = new Set();
544
- // iterate over each of the tests in the state
545
- TestWalker.walkTests(testObject => {
546
- if (VestTest.isPending(testObject)) {
547
- return;
548
- }
549
- const { fieldName } = VestTest.getData(testObject);
550
- // If we already added the current field (not this test specifically)
551
- // no need for further checks, go and omit the test
552
- if (shouldOmit.has(fieldName)) {
553
- verifyAndOmit(testObject);
554
- }
555
- else {
556
- // check if the field has an optional function
557
- // if so, run it and verify/omit the test
558
- runOptionalConfig(testObject);
559
- }
560
- });
561
- vestjsRuntime.Bus.useEmit(Events.DONE_TEST_OMISSION_PASS);
562
- function verifyAndOmit(testObject) {
563
- const { fieldName } = VestTest.getData(testObject);
564
- if (shouldOmit.has(fieldName)) {
565
- VestTest.omit(testObject);
566
- SuiteOptionalFields.setOptionalField(root, fieldName, current => (Object.assign(Object.assign({}, current), { applied: true })));
567
- }
568
- }
569
- function runOptionalConfig(testObject) {
570
- const { fieldName } = VestTest.getData(testObject);
571
- // Ge the optional configuration for the given field
572
- const optionalConfig = SuiteOptionalFields.getOptionalField(root, fieldName);
573
- // If the optional was set to a function or a boolean, run it and verify/omit the test
574
- if (vestUtils.optionalFunctionValue(optionalConfig.rule) === true) {
575
- shouldOmit.add(fieldName);
576
- }
577
- verifyAndOmit(testObject);
578
- }
579
- }
580
-
581
- /**
582
- * Runs done callback per field when async tests are finished running.
583
- */
584
- function useRunFieldCallbacks(fieldName) {
585
- const [fieldCallbacks] = useFieldCallbacks();
586
- if (fieldName &&
587
- !SuiteWalker.hasRemainingWithTestNameMatching(fieldName) &&
588
- vestUtils.isArray(fieldCallbacks[fieldName])) {
589
- vestUtils.callEach(fieldCallbacks[fieldName]);
590
- }
591
- }
592
- /**
593
- * Runs unlabelled done callback when async tests are finished running.
594
- */
595
- function useRunDoneCallbacks() {
596
- const [doneCallbacks] = useDoneCallbacks();
597
- vestUtils.callEach(doneCallbacks);
598
- }
599
-
600
- // eslint-disable-next-line max-statements, max-lines-per-function
601
- function useInitVestBus() {
602
- const VestBus = vestjsRuntime.Bus.useBus();
603
- // Report a the completion of a test. There may be other tests with the same
604
- // name that are still running, or not yet started.
605
- on(Events.TEST_COMPLETED, (testObject) => {
606
- if (VestTest.isCanceled(testObject)) {
607
- return;
608
- }
609
- const { fieldName } = VestTest.getData(testObject);
610
- useRunFieldCallbacks(fieldName);
611
- });
612
- on(Events.TEST_RUN_STARTED, () => {
613
- /* Let's just invalidate the suite cache for now */
614
- });
615
- on(vestjsRuntime.RuntimeEvents.ISOLATE_PENDING, (isolate) => {
616
- if (VestTest.is(isolate)) {
617
- VestTest.setPending(isolate);
618
- }
619
- setPending(isolate);
620
- });
621
- on(vestjsRuntime.RuntimeEvents.ISOLATE_DONE, (isolate) => {
622
- if (VestTest.is(isolate)) {
623
- VestBus.emit(Events.TEST_COMPLETED, isolate);
624
- }
625
- setDone(isolate);
626
- if (!SuiteWalker.hasPending()) {
627
- // When no more tests are running, emit the done event
628
- VestBus.emit(Events.ALL_RUNNING_TESTS_FINISHED);
629
- }
630
- });
631
- on(Events.DONE_TEST_OMISSION_PASS, () => {
632
- /* We NEED to refresh the cache here. Don't ask */
633
- });
634
- // Called when all the tests, including async, are done running
635
- on(Events.ALL_RUNNING_TESTS_FINISHED, () => {
636
- // Small optimization. We don't need to run this if there are no async tests
637
- // The reason is that we run this function immediately after the suite callback
638
- // is run, so if the suite is only comprised of sync tests, we don't need to
639
- // run this function twice since we know for a fact the state is up to date
640
- if (TestWalker.someTests(VestTest.isAsyncTest)) {
641
- useOmitOptionalFields();
767
+ class SuiteWalker {
768
+ static hasPending(predicate) {
769
+ const root = SuiteWalker.defaultRoot();
770
+ if (!root) {
771
+ return false;
642
772
  }
643
- useRunDoneCallbacks();
644
- });
645
- on(Events.RESET_FIELD, (fieldName) => {
646
- TestWalker.resetField(fieldName);
647
- });
648
- on(Events.SUITE_RUN_STARTED, () => {
649
- useResetCallbacks();
650
- });
651
- on(Events.SUITE_CALLBACK_RUN_FINISHED, () => {
652
- useOmitOptionalFields();
653
- });
654
- on(Events.REMOVE_FIELD, (fieldName) => {
655
- TestWalker.removeTestByFieldName(fieldName);
656
- });
657
- on(Events.RESET_SUITE, () => {
658
- useResetSuite();
659
- });
660
- return {
661
- subscribe,
662
- };
663
- function subscribe(cb) {
664
- return VestBus.on('*', () => {
665
- cb();
666
- }).off;
667
- }
668
- function on(event, cb) {
669
- VestBus.on(event, (...args) => {
670
- // This is more concise, but it might be an overkill
671
- // if we're adding events that don't need to invalidate the cache
672
- useExpireSuiteResultCache();
673
- cb(...args);
674
- });
675
- }
676
- }
677
-
678
- class IsolateReconciler {
679
- static match(_currentNode, _historyNode) {
680
- return false;
681
- }
682
- static reconcile(currentNode, historyNode) {
683
- return (currentNode !== null && currentNode !== void 0 ? currentNode : historyNode);
773
+ return vestjsRuntime.Walker.some(root, vestUtils.Predicates.all(VestIsolate.isPending, predicate !== null && predicate !== void 0 ? predicate : true));
684
774
  }
685
- }
686
-
687
- function isSameProfileTest(testObject1, testObject2) {
688
- const { groupName: gn1 } = VestTest.getData(testObject1);
689
- const { groupName: gn2, fieldName: fn2 } = VestTest.getData(testObject2);
690
- return (matchingFieldName(VestTest.getData(testObject1), fn2) &&
691
- gn1 === gn2 &&
692
- testObject1.key === testObject2.key);
693
- }
694
-
695
- function cancelOverriddenPendingTest(prevRunTestObject, currentRunTestObject) {
696
- if (currentRunTestObject !== prevRunTestObject &&
697
- isSameProfileTest(prevRunTestObject, currentRunTestObject) &&
698
- VestTest.isPending(prevRunTestObject)) {
699
- VestTest.cancel(prevRunTestObject);
775
+ // Checks whether there are pending isolates in the tree.
776
+ // If a fieldname is provided, will only check tests with a matching fieldname.
777
+ static hasRemainingWithTestNameMatching(fieldName) {
778
+ return SuiteWalker.hasPending(vestUtils.Predicates.any(vestUtils.isNullish(fieldName), vestUtils.Predicates.all(VestTest.is, (testObject) => {
779
+ return matchesOrHasNoFieldName(VestTest.getData(testObject), fieldName);
780
+ })));
700
781
  }
701
782
  }
783
+ SuiteWalker.defaultRoot = vestjsRuntime.VestRuntime.useAvailableRoot;
702
784
 
703
785
  const nonMatchingGroupName = vestUtils.bindNot(matchingGroupName);
704
786
  function matchingGroupName(testObject, groupName) {
@@ -748,296 +830,46 @@ function hasFailuresByTestObject(testObject, severityKey, fieldName) {
748
830
  return true;
749
831
  }
750
832
 
751
- /**
752
- * Sets the current execution mode for the current suite.
753
- *
754
- * Supported modes:
755
- * - `EAGER` - (default) Runs all tests, but stops on first failure for each given field.
756
- * - `ALL` - Runs all tests, regardless of failures.
757
- * - `ONE` - Stops suite execution on first failure of any field.
758
- *
759
- * @example
760
- * ```js
761
- * import {Modes, create} from 'vest';
762
- *
763
- * const suite = create('suite_name', () => {
764
- * vest.mode(Modes.ALL);
765
- *
766
- * // ...
767
- * });
768
- * ```
769
- * @param 'ALL' | 'EAGER' | 'ONE' mode - The mode to set.
770
- */
771
- // @vx-allow use-use
772
- function mode(mode) {
773
- const [, setMode] = useMode();
774
- setMode(mode);
775
- }
776
- function useIsMode(mode) {
777
- const [currentMode] = useMode();
778
- return currentMode === mode;
779
- }
780
- function useIsEager() {
781
- return useIsMode(exports.Modes.EAGER);
782
- }
783
- function useIsOne() {
784
- return useIsMode(exports.Modes.ONE);
833
+ function useShouldAddValidProperty(fieldName) {
834
+ // Is the field optional, and the optional condition is applied
835
+ if (useIsOptionalFieldApplied(fieldName)) {
836
+ return true;
837
+ }
838
+ // Are there no tests?
839
+ if (TestWalker.hasNoTests()) {
840
+ return false;
841
+ }
842
+ // // Does the field have any tests with errors?
843
+ if (hasErrorsByTestObjects(fieldName)) {
844
+ return false;
845
+ }
846
+ // Does the given field have any pending tests that are not optional?
847
+ if (useHasNonOptionalIncomplete(fieldName)) {
848
+ return false;
849
+ }
850
+ // Does the field have no missing tests?
851
+ return useNoMissingTests(fieldName);
785
852
  }
786
- function useShouldSkipBasedOnMode(testData) {
787
- if (useIsOne()) {
788
- return hasErrorsByTestObjects();
853
+ function useShouldAddValidPropertyInGroup(groupName, fieldName) {
854
+ if (useIsOptionalFieldApplied(fieldName)) {
855
+ return true;
789
856
  }
790
- if (useIsEager()) {
791
- return hasErrorsByTestObjects(testData.fieldName);
857
+ if (hasGroupFailuresByTestObjects(Severity.ERRORS, groupName, fieldName)) {
858
+ return false;
792
859
  }
793
- return false;
860
+ // Do the given group/field have any pending tests that are not optional?
861
+ if (useHasNonOptionalIncompleteByGroup(groupName, fieldName)) {
862
+ return false;
863
+ }
864
+ return useNoMissingTestsByGroup(groupName, fieldName);
794
865
  }
795
-
796
- // calls collectAll or getByFieldName depending on whether fieldName is provided
797
- function gatherFailures(testGroup, severityKey, fieldName) {
798
- return fieldName
799
- ? getByFieldName(testGroup, severityKey, fieldName)
800
- : collectAll(testGroup, severityKey);
866
+ // Does the given field have any pending tests that are not optional?
867
+ function useHasNonOptionalIncomplete(fieldName) {
868
+ return SuiteWalker.hasPending(vestUtils.Predicates.all(VestTest.is, (testObject) => !nonMatchingFieldName(VestTest.getData(testObject), fieldName), () => !useIsOptionalFieldApplied(fieldName)));
801
869
  }
802
- function getByFieldName(testGroup, severityKey, fieldName) {
803
- var _a;
804
- return ((_a = testGroup === null || testGroup === void 0 ? void 0 : testGroup[fieldName]) === null || _a === void 0 ? void 0 : _a[severityKey]) || [];
805
- }
806
- function collectAll(testGroup, severityKey) {
807
- const output = {};
808
- const countKey = countKeyBySeverity(severityKey);
809
- for (const field in testGroup) {
810
- if (vestUtils.isPositive(testGroup[field][countKey])) {
811
- // We will probably never get to the fallback array
812
- // leaving it just in case the implementation changes
813
- output[field] = testGroup[field][severityKey] || [];
814
- }
815
- }
816
- return output;
817
- }
818
-
819
- function bindSuiteSelectors(get) {
820
- return {
821
- getError: (...args) => get().getError(...args),
822
- getErrors: (...args) => get().getErrors(...args),
823
- getErrorsByGroup: (...args) => get().getErrorsByGroup(...args),
824
- getWarning: (...args) => get().getWarning(...args),
825
- getWarnings: (...args) => get().getWarnings(...args),
826
- getWarningsByGroup: (...args) => get().getWarningsByGroup(...args),
827
- hasErrors: (...args) => get().hasErrors(...args),
828
- hasErrorsByGroup: (...args) => get().hasErrorsByGroup(...args),
829
- hasWarnings: (...args) => get().hasWarnings(...args),
830
- hasWarningsByGroup: (...args) => get().hasWarningsByGroup(...args),
831
- isPending: (...args) => {
832
- return get().isPending(...args);
833
- },
834
- isTested: (...args) => get().isTested(...args),
835
- isValid: (...args) => get().isValid(...args),
836
- isValidByGroup: (...args) => get().isValidByGroup(...args),
837
- };
838
- }
839
- // eslint-disable-next-line max-lines-per-function, max-statements
840
- function suiteSelectors(summary) {
841
- const selectors = {
842
- getError,
843
- getErrors,
844
- getErrorsByGroup,
845
- getWarning,
846
- getWarnings,
847
- getWarningsByGroup,
848
- hasErrors,
849
- hasErrorsByGroup,
850
- hasWarnings,
851
- hasWarningsByGroup,
852
- isPending,
853
- isTested,
854
- isValid,
855
- isValidByGroup,
856
- };
857
- return selectors;
858
- // Booleans
859
- function isValid(fieldName) {
860
- var _a;
861
- return fieldName ? Boolean((_a = summary.tests[fieldName]) === null || _a === void 0 ? void 0 : _a.valid) : summary.valid;
862
- }
863
- function isValidByGroup(groupName, fieldName) {
864
- const group = summary.groups[groupName];
865
- if (!group) {
866
- return false;
867
- }
868
- if (fieldName) {
869
- return isFieldValid(group, fieldName);
870
- }
871
- for (const fieldName in group) {
872
- if (!isFieldValid(group, fieldName)) {
873
- return false;
874
- }
875
- }
876
- return true;
877
- }
878
- function hasWarnings(fieldName) {
879
- return hasFailures(summary, SeverityCount.WARN_COUNT, fieldName);
880
- }
881
- function hasErrors(fieldName) {
882
- return hasFailures(summary, SeverityCount.ERROR_COUNT, fieldName);
883
- }
884
- function isTested(fieldName) {
885
- var _a;
886
- return vestUtils.isPositive((_a = summary.tests[fieldName]) === null || _a === void 0 ? void 0 : _a.testCount);
887
- }
888
- function hasWarningsByGroup(groupName, fieldName) {
889
- return hasFailuresByGroup(summary, SeverityCount.WARN_COUNT, groupName, fieldName);
890
- }
891
- function hasErrorsByGroup(groupName, fieldName) {
892
- return hasFailuresByGroup(summary, SeverityCount.ERROR_COUNT, groupName, fieldName);
893
- }
894
- function getWarnings(fieldName) {
895
- return getFailures(summary, Severity.WARNINGS, fieldName);
896
- }
897
- function getWarning(fieldName) {
898
- return getFailure(Severity.WARNINGS, summary, fieldName);
899
- }
900
- function getErrors(fieldName) {
901
- return getFailures(summary, Severity.ERRORS, fieldName);
902
- }
903
- function getError(fieldName) {
904
- return getFailure(Severity.ERRORS, summary, fieldName);
905
- }
906
- function getErrorsByGroup(groupName, fieldName) {
907
- return getFailuresByGroup(summary, Severity.ERRORS, groupName, fieldName);
908
- }
909
- function getWarningsByGroup(groupName, fieldName) {
910
- return getFailuresByGroup(summary, Severity.WARNINGS, groupName, fieldName);
911
- }
912
- function isPending(fieldName) {
913
- var _a;
914
- return fieldName
915
- ? vestUtils.greaterThan((_a = summary.tests[fieldName]) === null || _a === void 0 ? void 0 : _a.pendingCount, 0)
916
- : vestUtils.greaterThan(summary.pendingCount, 0);
917
- }
918
- }
919
- function getFailures(summary, severityKey, fieldName) {
920
- return gatherFailures(summary.tests, severityKey, fieldName);
921
- }
922
- // Gathers all failures of a given severity within a group
923
- // With a fieldName, it will only gather failures for that field
924
- function getFailuresByGroup(summary, severityKey, groupName, fieldName) {
925
- return gatherFailures(summary.groups[groupName], severityKey, fieldName);
926
- }
927
- // Checks if a field is valid within a container object - can be within a group or top level
928
- function isFieldValid(testContainer, fieldName) {
929
- var _a;
930
- return !!((_a = testContainer[fieldName]) === null || _a === void 0 ? void 0 : _a.valid);
931
- }
932
- // Checks if a there are any failures of a given severity within a group
933
- // If a fieldName is provided, it will only check for failures within that field
934
- function hasFailuresByGroup(summary, severityCount, groupName, fieldName) {
935
- var _a, _b;
936
- const group = summary.groups[groupName];
937
- if (!group) {
938
- return false;
939
- }
940
- if (fieldName) {
941
- return vestUtils.isPositive((_a = group[fieldName]) === null || _a === void 0 ? void 0 : _a[severityCount]);
942
- }
943
- for (const field in group) {
944
- if (vestUtils.isPositive((_b = group[field]) === null || _b === void 0 ? void 0 : _b[severityCount])) {
945
- return true;
946
- }
947
- }
948
- return false;
949
- }
950
- // Checks if there are any failures of a given severity
951
- // If a fieldName is provided, it will only check for failures within that field
952
- function hasFailures(summary, countKey, fieldName) {
953
- var _a;
954
- const failureCount = fieldName
955
- ? (_a = summary.tests[fieldName]) === null || _a === void 0 ? void 0 : _a[countKey]
956
- : summary[countKey] || 0;
957
- return vestUtils.isPositive(failureCount);
958
- }
959
- function getFailure(severity, summary, fieldName) {
960
- var _a;
961
- const summaryKey = summary[severity];
962
- if (!fieldName) {
963
- return summaryKey[0];
964
- }
965
- return (_a = summaryKey.find((summaryFailure) => matchingFieldName(summaryFailure, fieldName))) === null || _a === void 0 ? void 0 : _a.message;
966
- }
967
-
968
- var _a, _b;
969
- class SummaryBase {
970
- constructor() {
971
- this.errorCount = 0;
972
- this.warnCount = 0;
973
- this.testCount = 0;
974
- this.pendingCount = 0;
975
- }
976
- }
977
- class SuiteSummary extends SummaryBase {
978
- constructor() {
979
- super(...arguments);
980
- this[_a] = [];
981
- this[_b] = [];
982
- this.groups = {};
983
- this.tests = {};
984
- this.valid = false;
985
- }
986
- }
987
- _a = Severity.ERRORS, _b = Severity.WARNINGS;
988
-
989
- class SummaryFailure {
990
- constructor(fieldName, message, groupName) {
991
- this.fieldName = fieldName;
992
- this.message = message;
993
- this.groupName = groupName;
994
- }
995
- static fromTestObject(testObject) {
996
- const { fieldName, message, groupName } = VestTest.getData(testObject);
997
- return new SummaryFailure(fieldName, message, groupName);
998
- }
999
- }
1000
-
1001
- function useShouldAddValidProperty(fieldName) {
1002
- // Is the field optional, and the optional condition is applied
1003
- if (useIsOptionalFieldApplied(fieldName)) {
1004
- return true;
1005
- }
1006
- // Are there no tests?
1007
- if (TestWalker.hasNoTests()) {
1008
- return false;
1009
- }
1010
- // // Does the field have any tests with errors?
1011
- if (hasErrorsByTestObjects(fieldName)) {
1012
- return false;
1013
- }
1014
- // Does the given field have any pending tests that are not optional?
1015
- if (useHasNonOptionalIncomplete(fieldName)) {
1016
- return false;
1017
- }
1018
- // Does the field have no missing tests?
1019
- return useNoMissingTests(fieldName);
1020
- }
1021
- function useShouldAddValidPropertyInGroup(groupName, fieldName) {
1022
- if (useIsOptionalFieldApplied(fieldName)) {
1023
- return true;
1024
- }
1025
- if (hasGroupFailuresByTestObjects(Severity.ERRORS, groupName, fieldName)) {
1026
- return false;
1027
- }
1028
- // Do the given group/field have any pending tests that are not optional?
1029
- if (useHasNonOptionalIncompleteByGroup(groupName, fieldName)) {
1030
- return false;
1031
- }
1032
- return useNoMissingTestsByGroup(groupName, fieldName);
1033
- }
1034
- // Does the given field have any pending tests that are not optional?
1035
- function useHasNonOptionalIncomplete(fieldName) {
1036
- return SuiteWalker.hasPending(vestUtils.Predicates.all(VestTest.is, (testObject) => !nonMatchingFieldName(VestTest.getData(testObject), fieldName), () => !useIsOptionalFieldApplied(fieldName)));
1037
- }
1038
- // Do the given group/field have any pending tests that are not optional?
1039
- function useHasNonOptionalIncompleteByGroup(groupName, fieldName) {
1040
- return SuiteWalker.hasPending(vestUtils.Predicates.all(VestTest.is, (testObject) => !nonMatchingGroupName(testObject, groupName), (testObject) => !nonMatchingFieldName(VestTest.getData(testObject), fieldName), () => !useIsOptionalFieldApplied(fieldName)));
870
+ // Do the given group/field have any pending tests that are not optional?
871
+ function useHasNonOptionalIncompleteByGroup(groupName, fieldName) {
872
+ return SuiteWalker.hasPending(vestUtils.Predicates.all(VestTest.is, (testObject) => !nonMatchingGroupName(testObject, groupName), (testObject) => !nonMatchingFieldName(VestTest.getData(testObject), fieldName), () => !useIsOptionalFieldApplied(fieldName)));
1041
873
  }
1042
874
  // Did all of the tests for the provided field run/omit?
1043
875
  // This makes sure that the fields are not skipped or pending.
@@ -1200,30 +1032,81 @@ function useCreateSuiteResult() {
1200
1032
  }
1201
1033
 
1202
1034
  /**
1203
- * Conditionally omits tests from the suite.
1204
- *
1205
- * @example
1206
- *
1207
- * omitWhen(res => res.hasErrors('username'), () => {
1208
- * test('username', 'User already taken', async () => await doesUserExist(username)
1209
- * });
1035
+ * Checks if context has included tests
1210
1036
  */
1211
- // @vx-allow use-use
1212
- function omitWhen(conditional, callback) {
1213
- vestjsRuntime.Isolate.create(VestIsolateType.OmitWhen, () => {
1214
- SuiteContext.run({
1215
- omitted: useWithinActiveOmitWhen() ||
1216
- vestUtils.optionalFunctionValue(conditional, vestUtils.optionalFunctionValue(useCreateSuiteResult)),
1217
- }, callback);
1218
- });
1219
- }
1220
- // Checks that we're currently in an active omitWhen block
1221
- function useWithinActiveOmitWhen() {
1222
- return useOmitted();
1037
+ function useHasOnliedTests(testObject, fieldName) {
1038
+ return vestUtils.isNotNullish(vestjsRuntime.Walker.findClosest(testObject, (child) => {
1039
+ if (!FocusSelectors.isIsolateFocused(child))
1040
+ return false;
1041
+ return FocusSelectors.isOnlyFocused(child, fieldName);
1042
+ }));
1223
1043
  }
1224
1044
 
1225
1045
  /**
1226
- * Conditionally skips running tests within the callback.
1046
+ * Conditionally includes a field for testing, based on specified criteria.
1047
+ *
1048
+ * @param {string} fieldName - The name of the field to include for testing.
1049
+ *
1050
+ * @example
1051
+ * include('confirm').when('password');
1052
+ * // Includes the "confirm" field for testing when the "password" field is included
1053
+ *
1054
+ * include('confirm').when(someValue);
1055
+ * // Includes the "confirm" field for testing when the value of `someValue` is true
1056
+ *
1057
+ * include('confirm').when(() => someValue);
1058
+ * // Includes the "confirm" field for testing when the callback function returns true
1059
+ *
1060
+ * include('username').when(result => result.hasErrors('username'));
1061
+ * // Includes the "username" field for testing when there are errors associated with it in the current suite result
1062
+ */
1063
+ // @vx-allow use-use
1064
+ function include(fieldName) {
1065
+ vestUtils.invariant(vestUtils.isStringValue(fieldName));
1066
+ const inclusion = useInclusion();
1067
+ inclusion[fieldName] = true;
1068
+ return { when };
1069
+ /**
1070
+ * Specifies the inclusion criteria for the field in `include` function.
1071
+ */
1072
+ function when(condition) {
1073
+ vestUtils.invariant(condition !== fieldName, ErrorStrings.INCLUDE_SELF);
1074
+ const inclusion = useInclusion();
1075
+ // This callback will run as part of the "isExcluded" series of checks
1076
+ inclusion[fieldName] = function isIncluded(currentNode) {
1077
+ if (vestUtils.isStringValue(condition)) {
1078
+ return useHasOnliedTests(currentNode, condition);
1079
+ }
1080
+ return vestUtils.optionalFunctionValue(condition, vestUtils.optionalFunctionValue(useCreateSuiteResult));
1081
+ };
1082
+ }
1083
+ }
1084
+
1085
+ /**
1086
+ * Conditionally omits tests from the suite.
1087
+ *
1088
+ * @example
1089
+ *
1090
+ * omitWhen(res => res.hasErrors('username'), () => {
1091
+ * test('username', 'User already taken', async () => await doesUserExist(username)
1092
+ * });
1093
+ */
1094
+ // @vx-allow use-use
1095
+ function omitWhen(conditional, callback) {
1096
+ vestjsRuntime.Isolate.create(VestIsolateType.OmitWhen, () => {
1097
+ SuiteContext.run({
1098
+ omitted: useWithinActiveOmitWhen() ||
1099
+ vestUtils.optionalFunctionValue(conditional, vestUtils.optionalFunctionValue(useCreateSuiteResult)),
1100
+ }, callback);
1101
+ });
1102
+ }
1103
+ // Checks that we're currently in an active omitWhen block
1104
+ function useWithinActiveOmitWhen() {
1105
+ return useOmitted();
1106
+ }
1107
+
1108
+ /**
1109
+ * Conditionally skips running tests within the callback.
1227
1110
  *
1228
1111
  * @example
1229
1112
  *
@@ -1248,71 +1131,85 @@ function useIsExcludedIndividually() {
1248
1131
  return useSkipped();
1249
1132
  }
1250
1133
 
1251
- var FocusModes;
1252
- (function (FocusModes) {
1253
- FocusModes[FocusModes["ONLY"] = 0] = "ONLY";
1254
- FocusModes[FocusModes["SKIP"] = 1] = "SKIP";
1255
- })(FocusModes || (FocusModes = {}));
1134
+ var Events;
1135
+ (function (Events) {
1136
+ Events["TEST_RUN_STARTED"] = "test_run_started";
1137
+ Events["TEST_COMPLETED"] = "test_completed";
1138
+ Events["ALL_RUNNING_TESTS_FINISHED"] = "all_running_tests_finished";
1139
+ Events["REMOVE_FIELD"] = "remove_field";
1140
+ Events["RESET_FIELD"] = "reset_field";
1141
+ Events["RESET_SUITE"] = "reset_suite";
1142
+ Events["SUITE_RUN_STARTED"] = "suite_run_started";
1143
+ Events["SUITE_CALLBACK_RUN_FINISHED"] = "SUITE_CALLBACK_RUN_FINISHED";
1144
+ Events["DONE_TEST_OMISSION_PASS"] = "DONE_TEST_OMISSION_PASS";
1145
+ })(Events || (Events = {}));
1256
1146
 
1257
- function IsolateFocused(focusMode, match) {
1258
- return vestjsRuntime.Isolate.create(VestIsolateType.Focused, vestUtils.noop, {
1259
- focusMode,
1260
- match: vestUtils.asArray(match).filter(vestUtils.isStringValue),
1261
- matchAll: match === true,
1262
- });
1263
- }
1264
- class FocusSelectors {
1265
- static isSkipFocused(focus, fieldName) {
1266
- return ((focus === null || focus === void 0 ? void 0 : focus.data.focusMode) === FocusModes.SKIP &&
1267
- (hasFocus(focus, fieldName) || focus.data.matchAll === true));
1268
- }
1269
- static isOnlyFocused(focus, fieldName) {
1270
- return ((focus === null || focus === void 0 ? void 0 : focus.data.focusMode) === FocusModes.ONLY && hasFocus(focus, fieldName));
1147
+ function IsolateTest(callback, input, key) {
1148
+ const payload = Object.assign(Object.assign({}, IsolateTestBase()), { fieldName: input.fieldName, testFn: input.testFn });
1149
+ if (input.groupName) {
1150
+ payload.groupName = input.groupName;
1271
1151
  }
1272
- static isIsolateFocused(isolate) {
1273
- return vestjsRuntime.IsolateSelectors.isIsolateType(isolate, VestIsolateType.Focused);
1152
+ if (input.message) {
1153
+ payload.message = input.message;
1274
1154
  }
1155
+ const isolate = vestjsRuntime.Isolate.create(VestIsolateType.Test, callback, payload, key !== null && key !== void 0 ? key : null);
1156
+ return isolate;
1275
1157
  }
1276
- /**
1277
- * Adds a field or a list of fields into the inclusion list
1278
- *
1279
- * @example
1280
- *
1281
- * only('username');
1282
- */
1283
- // @vx-allow use-use
1284
- function only(match) {
1285
- return IsolateFocused(FocusModes.ONLY, defaultMatch(match));
1158
+ function IsolateTestBase() {
1159
+ return {
1160
+ severity: TestSeverity.Error,
1161
+ status: IsolateTestStateMachine.initial(),
1162
+ };
1286
1163
  }
1164
+
1165
+ function shouldUseErrorAsMessage(message, error) {
1166
+ // kind of cheating with this safe guard, but it does the job
1167
+ return vestUtils.isUndefined(message) && vestUtils.isStringValue(error);
1168
+ }
1169
+
1287
1170
  /**
1288
- * Adds a field or a list of fields into the exclusion list
1171
+ * Sets the current execution mode for the current suite.
1172
+ *
1173
+ * Supported modes:
1174
+ * - `EAGER` - (default) Runs all tests, but stops on first failure for each given field.
1175
+ * - `ALL` - Runs all tests, regardless of failures.
1176
+ * - `ONE` - Stops suite execution on first failure of any field.
1289
1177
  *
1290
1178
  * @example
1179
+ * ```js
1180
+ * import {Modes, create} from 'vest';
1291
1181
  *
1292
- * skip('username');
1182
+ * const suite = create('suite_name', () => {
1183
+ * vest.mode(Modes.ALL);
1184
+ *
1185
+ * // ...
1186
+ * });
1187
+ * ```
1188
+ * @param 'ALL' | 'EAGER' | 'ONE' mode - The mode to set.
1293
1189
  */
1294
1190
  // @vx-allow use-use
1295
- function skip(match) {
1296
- return IsolateFocused(FocusModes.SKIP, defaultMatch(match));
1191
+ function mode(mode) {
1192
+ const [, setMode] = useMode();
1193
+ setMode(mode);
1297
1194
  }
1298
- function defaultMatch(match) {
1299
- return match === false ? [] : match;
1195
+ function useIsMode(mode) {
1196
+ const [currentMode] = useMode();
1197
+ return currentMode === mode;
1300
1198
  }
1301
- function hasFocus(focus, fieldName) {
1302
- var _a, _b;
1303
- return (vestUtils.isNotEmpty(focus === null || focus === void 0 ? void 0 : focus.data.match) &&
1304
- (fieldName ? (_b = (_a = focus === null || focus === void 0 ? void 0 : focus.data.match) === null || _a === void 0 ? void 0 : _a.includes(fieldName)) !== null && _b !== void 0 ? _b : true : true));
1199
+ function useIsEager() {
1200
+ return useIsMode(exports.Modes.EAGER);
1305
1201
  }
1306
-
1307
- /**
1308
- * Checks if context has included tests
1309
- */
1310
- function useHasOnliedTests(testObject, fieldName) {
1311
- return vestUtils.isNotNullish(vestjsRuntime.Walker.findClosest(testObject, (child) => {
1312
- if (!FocusSelectors.isIsolateFocused(child))
1313
- return false;
1314
- return FocusSelectors.isOnlyFocused(child, fieldName);
1315
- }));
1202
+ function useIsOne() {
1203
+ return useIsMode(exports.Modes.ONE);
1204
+ }
1205
+ function useShouldSkipBasedOnMode(testData) {
1206
+ if (useIsOne()) {
1207
+ return hasErrorsByTestObjects();
1208
+ }
1209
+ if (useIsEager()) {
1210
+ return hasErrorsByTestObjects(testData.fieldName);
1211
+ }
1212
+ return false;
1316
1213
  }
1317
1214
 
1318
1215
  //Checks whether a certain test profile excluded by any of the exclusion groups.
@@ -1381,304 +1278,409 @@ function useForceSkipIfInSkipWhen(testNode) {
1381
1278
  return testNode;
1382
1279
  }
1383
1280
 
1384
- class IsolateTestReconciler extends IsolateReconciler {
1385
- static match(currentNode, historyNode) {
1386
- return VestTest.is(currentNode) && VestTest.is(historyNode);
1281
+ // eslint-disable-next-line max-statements
1282
+ function useAttemptRunTest(testObject) {
1283
+ useVerifyTestRun(testObject);
1284
+ if (VestTest.isUntested(testObject)) {
1285
+ return useRunTest(testObject);
1387
1286
  }
1388
- static reconcile(currentNode, historyNode) {
1389
- const reconcilerOutput = usePickNode(historyNode, currentNode);
1390
- cancelOverriddenPendingTestOnTestReRun(reconcilerOutput, currentNode, historyNode);
1391
- return reconcilerOutput;
1287
+ if (!VestTest.isNonActionable(testObject)) {
1288
+ // Probably unreachable. If we get here, it means that
1289
+ // something was really wrong and should be reported.
1290
+ /* istanbul ignore next */
1291
+ vestUtils.deferThrow(vestUtils.text(ErrorStrings.UNEXPECTED_TEST_REGISTRATION_ERROR, {
1292
+ testObject: JSON.stringify(testObject),
1293
+ }));
1392
1294
  }
1393
1295
  }
1394
- function usePickNode(historyNode, currentNode) {
1395
- const collisionResult = handleCollision(currentNode, historyNode);
1396
- return useVerifyTestRun(currentNode, collisionResult);
1296
+ function runSyncTest(testObject) {
1297
+ return SuiteContext.run({ currentTest: testObject }, () => {
1298
+ let result;
1299
+ const { message, testFn } = VestTest.getData(testObject);
1300
+ try {
1301
+ result = testFn({ signal: testObject.abortController.signal });
1302
+ }
1303
+ catch (error) {
1304
+ if (shouldUseErrorAsMessage(message, error)) {
1305
+ VestTest.getData(testObject).message = error;
1306
+ }
1307
+ result = false;
1308
+ }
1309
+ if (result === false) {
1310
+ VestTest.fail(testObject);
1311
+ }
1312
+ return result;
1313
+ });
1397
1314
  }
1398
- function handleCollision(newNode, prevNode) {
1399
- if (vestjsRuntime.IsolateInspector.usesKey(newNode)) {
1400
- return VestTest.cast(vestjsRuntime.Reconciler.handleIsolateNodeWithKey(newNode));
1401
- }
1402
- if (vestjsRuntime.Reconciler.dropNextNodesOnReorder(nodeReorderDetected, newNode, prevNode)) {
1403
- throwTestOrderError(newNode, prevNode);
1404
- return newNode;
1315
+ /**
1316
+ * runs test, if async - adds to pending array
1317
+ */
1318
+ function useRunTest(testObject) {
1319
+ // Run test callback.
1320
+ // If a promise is returned, set as async and
1321
+ // Move to pending list.
1322
+ const result = runSyncTest(testObject);
1323
+ try {
1324
+ // try catch for safe property access
1325
+ // in case object is an enforce chain
1326
+ if (vestUtils.isPromise(result)) {
1327
+ VestTest.getData(testObject).asyncTest = result;
1328
+ return useRunAsyncTest(testObject);
1329
+ }
1330
+ onTestCompleted(testObject);
1405
1331
  }
1406
- if (!VestTest.is(prevNode)) {
1407
- // I believe we cannot actually reach this point.
1408
- // Because it should already be handled by nodeReorderDetected.
1332
+ catch (e) {
1333
+ // Probably unreachable. If we get here, it means that
1334
+ // something was really wrong and should be reported.
1409
1335
  /* istanbul ignore next */
1410
- return newNode;
1336
+ throw new Error(vestUtils.text(ErrorStrings.UNEXPECTED_TEST_REGISTRATION_ERROR, {
1337
+ testObject: JSON.stringify(testObject),
1338
+ error: e,
1339
+ }));
1411
1340
  }
1412
- // FIXME: May-13-2023
1413
- // This may not be the most ideal solution.
1414
- // In short: if the node was omitted in the previous run,
1415
- // we want to re-evaluate it. The reason is that we may incorrectly
1416
- // identify it is "optional" because it was omitted in the previous run.
1417
- // There may be a better way to handle this. Need to revisit this.
1418
- if (VestTest.isOmitted(prevNode)) {
1419
- return newNode;
1341
+ }
1342
+ /**
1343
+ * Runs async test.
1344
+ */
1345
+ function useRunAsyncTest(testObject) {
1346
+ const { asyncTest, message } = VestTest.getData(testObject);
1347
+ if (!vestUtils.isPromise(asyncTest))
1348
+ return;
1349
+ // VestTest.setPending(testObject);
1350
+ const done = vestjsRuntime.VestRuntime.persist(() => {
1351
+ onTestCompleted(testObject);
1352
+ });
1353
+ const fail = vestjsRuntime.VestRuntime.persist((rejectionMessage) => {
1354
+ if (VestTest.isCanceled(testObject)) {
1355
+ return;
1356
+ }
1357
+ VestTest.getData(testObject).message = vestUtils.isStringValue(rejectionMessage)
1358
+ ? rejectionMessage
1359
+ : message;
1360
+ VestTest.fail(testObject);
1361
+ done();
1362
+ });
1363
+ return asyncTest.then(done, fail);
1364
+ }
1365
+ function onTestCompleted(testObject) {
1366
+ // Attempts passing if the test is not already failed.
1367
+ // or is not canceled/omitted.
1368
+ VestTest.pass(testObject);
1369
+ }
1370
+
1371
+ // @vx-allow use-use
1372
+ function wrapTestMemo(test) {
1373
+ function memo(fieldName, ...args) {
1374
+ const [deps, testFn, msg] = args.reverse();
1375
+ // Implicit dependency for better specificity
1376
+ const dependencies = [
1377
+ useSuiteId(),
1378
+ fieldName,
1379
+ vestjsRuntime.VestRuntime.useCurrentCursor(),
1380
+ ].concat(deps);
1381
+ return useGetTestFromCache(dependencies, cacheAction);
1382
+ function cacheAction() {
1383
+ return test(fieldName, msg, testFn);
1384
+ }
1420
1385
  }
1421
- return prevNode;
1386
+ return memo;
1422
1387
  }
1423
- function cancelOverriddenPendingTestOnTestReRun(nextNode, currentNode, prevTestObject) {
1424
- if (nextNode === currentNode && VestTest.is(currentNode)) {
1425
- cancelOverriddenPendingTest(prevTestObject, currentNode);
1388
+ function useGetTestFromCache(dependencies, cacheAction) {
1389
+ const cache = useTestMemoCache();
1390
+ const cached = cache.get(dependencies);
1391
+ if (vestUtils.isNull(cached)) {
1392
+ // cache miss
1393
+ return cache(dependencies, cacheAction);
1394
+ }
1395
+ const [, cachedValue] = cached;
1396
+ if (VestTest.isCanceled(cachedValue)) {
1397
+ // cache hit, but test is canceled
1398
+ cache.invalidate(dependencies);
1399
+ return cache(dependencies, cacheAction);
1426
1400
  }
1401
+ vestjsRuntime.VestRuntime.addNodeToHistory(cachedValue);
1402
+ return cachedValue;
1427
1403
  }
1428
- function nodeReorderDetected(newNode, prevNode) {
1429
- return VestTest.is(prevNode) && !isSameProfileTest(prevNode, newNode);
1404
+
1405
+ // @vx-allow use-use
1406
+ function vestTest(fieldName, ...args) {
1407
+ const [message, testFn, key] = (vestUtils.isFunction(args[1]) ? args : [undefined, ...args]);
1408
+ validateTestParams(fieldName, testFn);
1409
+ const groupName = useGroupName();
1410
+ const testObjectInput = { fieldName, groupName, message, testFn };
1411
+ // This invalidates the suite cache.
1412
+ vestjsRuntime.Bus.useEmit(Events.TEST_RUN_STARTED);
1413
+ return IsolateTest(useAttemptRunTest, testObjectInput, key);
1430
1414
  }
1431
- function throwTestOrderError(newNode, prevNode) {
1432
- if (vestjsRuntime.IsolateInspector.canReorder(newNode)) {
1433
- return;
1434
- }
1435
- vestUtils.deferThrow(vestUtils.text(ErrorStrings.TESTS_CALLED_IN_DIFFERENT_ORDER, {
1436
- fieldName: VestTest.getData(newNode).fieldName,
1437
- prevName: VestTest.is(prevNode)
1438
- ? VestTest.getData(prevNode).fieldName
1439
- : undefined,
1415
+ const test = vestUtils.assign(vestTest, {
1416
+ memo: wrapTestMemo(vestTest),
1417
+ });
1418
+ function validateTestParams(fieldName, testFn) {
1419
+ const fnName = 'test';
1420
+ vestUtils.invariant(vestUtils.isStringValue(fieldName), vestUtils.text(ErrorStrings.INVALID_PARAM_PASSED_TO_FUNCTION, {
1421
+ fn_name: fnName,
1422
+ param: 'fieldName',
1423
+ expected: 'string',
1424
+ }));
1425
+ vestUtils.invariant(vestUtils.isFunction(testFn), vestUtils.text(ErrorStrings.INVALID_PARAM_PASSED_TO_FUNCTION, {
1426
+ fn_name: fnName,
1427
+ param: 'callback',
1428
+ expected: 'function',
1440
1429
  }));
1441
1430
  }
1442
1431
 
1443
- function VestReconciler(currentNode, historyNode) {
1444
- var _a, _b;
1445
- return ((_b = (_a = [IsolateTestReconciler]
1446
- .find(reconciler => reconciler.match(currentNode, historyNode))) === null || _a === void 0 ? void 0 : _a.reconcile(currentNode, historyNode)) !== null && _b !== void 0 ? _b : null);
1432
+ // import { optional, skipWhen, omitWhen, IsolateTest, group } from 'vest';
1433
+ function getTypedMethods() {
1434
+ return {
1435
+ group,
1436
+ include,
1437
+ omitWhen,
1438
+ only,
1439
+ optional,
1440
+ skip,
1441
+ skipWhen,
1442
+ test,
1443
+ };
1447
1444
  }
1448
1445
 
1449
- function group(...args) {
1450
- const [callback, groupName] = args.reverse();
1451
- return vestjsRuntime.Isolate.create(VestIsolateType.Group, () => {
1452
- return SuiteContext.run(Object.assign({}, (groupName && { groupName })), callback);
1446
+ /**
1447
+ * This module gets triggered once the suite is done running its sync tests.
1448
+ *
1449
+ * It goes over all the tests in the state, and checks if they need to be omitted.
1450
+ */
1451
+ function useOmitOptionalFields() {
1452
+ const root = vestjsRuntime.VestRuntime.useAvailableRoot();
1453
+ const optionalFields = SuiteOptionalFields.getOptionalFields(root);
1454
+ // If there are no optional fields, we don't need to do anything
1455
+ if (vestUtils.isEmpty(optionalFields)) {
1456
+ return;
1457
+ }
1458
+ // Create an object to store the fields that need to be omitted
1459
+ const shouldOmit = new Set();
1460
+ // iterate over each of the tests in the state
1461
+ TestWalker.walkTests(testObject => {
1462
+ if (VestTest.isPending(testObject)) {
1463
+ return;
1464
+ }
1465
+ const { fieldName } = VestTest.getData(testObject);
1466
+ // If we already added the current field (not this test specifically)
1467
+ // no need for further checks, go and omit the test
1468
+ if (shouldOmit.has(fieldName)) {
1469
+ verifyAndOmit(testObject);
1470
+ }
1471
+ else {
1472
+ // check if the field has an optional function
1473
+ // if so, run it and verify/omit the test
1474
+ runOptionalConfig(testObject);
1475
+ }
1453
1476
  });
1477
+ vestjsRuntime.Bus.useEmit(Events.DONE_TEST_OMISSION_PASS);
1478
+ function verifyAndOmit(testObject) {
1479
+ const { fieldName } = VestTest.getData(testObject);
1480
+ if (shouldOmit.has(fieldName)) {
1481
+ VestTest.omit(testObject);
1482
+ SuiteOptionalFields.setOptionalField(root, fieldName, current => (Object.assign(Object.assign({}, current), { applied: true })));
1483
+ }
1484
+ }
1485
+ function runOptionalConfig(testObject) {
1486
+ const { fieldName } = VestTest.getData(testObject);
1487
+ // Ge the optional configuration for the given field
1488
+ const optionalConfig = SuiteOptionalFields.getOptionalField(root, fieldName);
1489
+ // If the optional was set to a function or a boolean, run it and verify/omit the test
1490
+ if (vestUtils.optionalFunctionValue(optionalConfig.rule) === true) {
1491
+ shouldOmit.add(fieldName);
1492
+ }
1493
+ verifyAndOmit(testObject);
1494
+ }
1454
1495
  }
1455
1496
 
1456
1497
  /**
1457
- * Conditionally includes a field for testing, based on specified criteria.
1458
- *
1459
- * @param {string} fieldName - The name of the field to include for testing.
1460
- *
1461
- * @example
1462
- * include('confirm').when('password');
1463
- * // Includes the "confirm" field for testing when the "password" field is included
1464
- *
1465
- * include('confirm').when(someValue);
1466
- * // Includes the "confirm" field for testing when the value of `someValue` is true
1467
- *
1468
- * include('confirm').when(() => someValue);
1469
- * // Includes the "confirm" field for testing when the callback function returns true
1470
- *
1471
- * include('username').when(result => result.hasErrors('username'));
1472
- * // Includes the "username" field for testing when there are errors associated with it in the current suite result
1498
+ * Runs done callback per field when async tests are finished running.
1473
1499
  */
1474
- // @vx-allow use-use
1475
- function include(fieldName) {
1476
- vestUtils.invariant(vestUtils.isStringValue(fieldName));
1477
- const inclusion = useInclusion();
1478
- inclusion[fieldName] = true;
1479
- return { when };
1480
- /**
1481
- * Specifies the inclusion criteria for the field in `include` function.
1482
- */
1483
- function when(condition) {
1484
- vestUtils.invariant(condition !== fieldName, ErrorStrings.INCLUDE_SELF);
1485
- const inclusion = useInclusion();
1486
- // This callback will run as part of the "isExcluded" series of checks
1487
- inclusion[fieldName] = function isIncluded(currentNode) {
1488
- if (vestUtils.isStringValue(condition)) {
1489
- return useHasOnliedTests(currentNode, condition);
1490
- }
1491
- return vestUtils.optionalFunctionValue(condition, vestUtils.optionalFunctionValue(useCreateSuiteResult));
1492
- };
1500
+ function useRunFieldCallbacks(fieldName) {
1501
+ const [fieldCallbacks] = useFieldCallbacks();
1502
+ if (fieldName &&
1503
+ !SuiteWalker.hasRemainingWithTestNameMatching(fieldName) &&
1504
+ vestUtils.isArray(fieldCallbacks[fieldName])) {
1505
+ vestUtils.callEach(fieldCallbacks[fieldName]);
1506
+ }
1507
+ }
1508
+ /**
1509
+ * Runs unlabelled done callback when async tests are finished running.
1510
+ */
1511
+ function useRunDoneCallbacks() {
1512
+ const [doneCallbacks] = useDoneCallbacks();
1513
+ vestUtils.callEach(doneCallbacks);
1514
+ }
1515
+
1516
+ // eslint-disable-next-line max-statements, max-lines-per-function
1517
+ function useInitVestBus() {
1518
+ const VestBus = vestjsRuntime.Bus.useBus();
1519
+ // Report a the completion of a test. There may be other tests with the same
1520
+ // name that are still running, or not yet started.
1521
+ on(Events.TEST_COMPLETED, (testObject) => {
1522
+ if (VestTest.isCanceled(testObject)) {
1523
+ return;
1524
+ }
1525
+ const { fieldName } = VestTest.getData(testObject);
1526
+ useRunFieldCallbacks(fieldName);
1527
+ });
1528
+ on(Events.TEST_RUN_STARTED, () => {
1529
+ /* Let's just invalidate the suite cache for now */
1530
+ });
1531
+ on(vestjsRuntime.RuntimeEvents.ISOLATE_PENDING, (isolate) => {
1532
+ if (VestTest.is(isolate)) {
1533
+ VestTest.setPending(isolate);
1534
+ }
1535
+ setPending(isolate);
1536
+ });
1537
+ on(vestjsRuntime.RuntimeEvents.ISOLATE_DONE, (isolate) => {
1538
+ if (VestTest.is(isolate)) {
1539
+ VestBus.emit(Events.TEST_COMPLETED, isolate);
1540
+ }
1541
+ setDone(isolate);
1542
+ if (!SuiteWalker.hasPending()) {
1543
+ // When no more tests are running, emit the done event
1544
+ VestBus.emit(Events.ALL_RUNNING_TESTS_FINISHED);
1545
+ }
1546
+ });
1547
+ on(Events.DONE_TEST_OMISSION_PASS, () => {
1548
+ /* We NEED to refresh the cache here. Don't ask */
1549
+ });
1550
+ // Called when all the tests, including async, are done running
1551
+ on(Events.ALL_RUNNING_TESTS_FINISHED, () => {
1552
+ // Small optimization. We don't need to run this if there are no async tests
1553
+ // The reason is that we run this function immediately after the suite callback
1554
+ // is run, so if the suite is only comprised of sync tests, we don't need to
1555
+ // run this function twice since we know for a fact the state is up to date
1556
+ if (TestWalker.someTests(VestTest.isAsyncTest)) {
1557
+ useOmitOptionalFields();
1558
+ }
1559
+ useRunDoneCallbacks();
1560
+ });
1561
+ on(Events.RESET_FIELD, (fieldName) => {
1562
+ TestWalker.resetField(fieldName);
1563
+ });
1564
+ on(Events.SUITE_RUN_STARTED, () => {
1565
+ useResetCallbacks();
1566
+ });
1567
+ on(Events.SUITE_CALLBACK_RUN_FINISHED, () => {
1568
+ useOmitOptionalFields();
1569
+ });
1570
+ on(Events.REMOVE_FIELD, (fieldName) => {
1571
+ TestWalker.removeTestByFieldName(fieldName);
1572
+ });
1573
+ on(Events.RESET_SUITE, () => {
1574
+ useResetSuite();
1575
+ });
1576
+ return {
1577
+ subscribe,
1578
+ };
1579
+ function subscribe(cb) {
1580
+ return VestBus.on('*', () => {
1581
+ cb();
1582
+ }).off;
1583
+ }
1584
+ function on(event, cb) {
1585
+ VestBus.on(event, (...args) => {
1586
+ // This is more concise, but it might be an overkill
1587
+ // if we're adding events that don't need to invalidate the cache
1588
+ useExpireSuiteResultCache();
1589
+ cb(...args);
1590
+ });
1493
1591
  }
1494
1592
  }
1495
1593
 
1496
- function IsolateTest(callback, input, key) {
1497
- const payload = Object.assign(Object.assign({}, IsolateTestBase()), { fieldName: input.fieldName, testFn: input.testFn });
1498
- if (input.groupName) {
1499
- payload.groupName = input.groupName;
1594
+ class IsolateReconciler {
1595
+ static match(_currentNode, _historyNode) {
1596
+ return false;
1500
1597
  }
1501
- if (input.message) {
1502
- payload.message = input.message;
1598
+ static reconcile(currentNode, historyNode) {
1599
+ return (currentNode !== null && currentNode !== void 0 ? currentNode : historyNode);
1503
1600
  }
1504
- const isolate = vestjsRuntime.Isolate.create(VestIsolateType.Test, callback, payload, key !== null && key !== void 0 ? key : null);
1505
- return isolate;
1506
1601
  }
1507
- function IsolateTestBase() {
1508
- return {
1509
- severity: TestSeverity.Error,
1510
- status: IsolateTestStateMachine.initial(),
1511
- };
1602
+
1603
+ function isSameProfileTest(testObject1, testObject2) {
1604
+ const { groupName: gn1 } = VestTest.getData(testObject1);
1605
+ const { groupName: gn2, fieldName: fn2 } = VestTest.getData(testObject2);
1606
+ return (matchingFieldName(VestTest.getData(testObject1), fn2) &&
1607
+ gn1 === gn2 &&
1608
+ // Specifically using == here. The reason is that when serializing
1609
+ // suite result, empty key gets removed, but it can also be null.
1610
+ testObject1.key == testObject2.key);
1512
1611
  }
1513
1612
 
1514
- function shouldUseErrorAsMessage(message, error) {
1515
- // kind of cheating with this safe guard, but it does the job
1516
- return vestUtils.isUndefined(message) && vestUtils.isStringValue(error);
1613
+ function cancelOverriddenPendingTest(prevRunTestObject, currentRunTestObject) {
1614
+ if (currentRunTestObject !== prevRunTestObject &&
1615
+ isSameProfileTest(prevRunTestObject, currentRunTestObject) &&
1616
+ VestTest.isPending(prevRunTestObject)) {
1617
+ VestTest.cancel(prevRunTestObject);
1618
+ }
1517
1619
  }
1518
1620
 
1519
- // eslint-disable-next-line max-statements
1520
- function useAttemptRunTest(testObject) {
1521
- useVerifyTestRun(testObject);
1522
- if (VestTest.isUntested(testObject)) {
1523
- return useRunTest(testObject);
1621
+ class IsolateTestReconciler extends IsolateReconciler {
1622
+ static match(currentNode, historyNode) {
1623
+ return VestTest.is(currentNode) && VestTest.is(historyNode);
1524
1624
  }
1525
- if (!VestTest.isNonActionable(testObject)) {
1526
- // Probably unreachable. If we get here, it means that
1527
- // something was really wrong and should be reported.
1528
- /* istanbul ignore next */
1529
- vestUtils.deferThrow(vestUtils.text(ErrorStrings.UNEXPECTED_TEST_REGISTRATION_ERROR, {
1530
- testObject: JSON.stringify(testObject),
1531
- }));
1625
+ static reconcile(currentNode, historyNode) {
1626
+ const reconcilerOutput = usePickNode(historyNode, currentNode);
1627
+ cancelOverriddenPendingTestOnTestReRun(reconcilerOutput, currentNode, historyNode);
1628
+ return reconcilerOutput;
1532
1629
  }
1533
1630
  }
1534
- function runSyncTest(testObject) {
1535
- return SuiteContext.run({ currentTest: testObject }, () => {
1536
- let result;
1537
- const { message, testFn } = VestTest.getData(testObject);
1538
- try {
1539
- result = testFn({ signal: testObject.abortController.signal });
1540
- }
1541
- catch (error) {
1542
- if (shouldUseErrorAsMessage(message, error)) {
1543
- VestTest.getData(testObject).message = error;
1544
- }
1545
- result = false;
1546
- }
1547
- if (result === false) {
1548
- VestTest.fail(testObject);
1549
- }
1550
- return result;
1551
- });
1631
+ function usePickNode(historyNode, currentNode) {
1632
+ const collisionResult = handleCollision(currentNode, historyNode);
1633
+ return useVerifyTestRun(currentNode, collisionResult);
1552
1634
  }
1553
- /**
1554
- * runs test, if async - adds to pending array
1555
- */
1556
- function useRunTest(testObject) {
1557
- // Run test callback.
1558
- // If a promise is returned, set as async and
1559
- // Move to pending list.
1560
- const result = runSyncTest(testObject);
1561
- try {
1562
- // try catch for safe property access
1563
- // in case object is an enforce chain
1564
- if (vestUtils.isPromise(result)) {
1565
- VestTest.getData(testObject).asyncTest = result;
1566
- return useRunAsyncTest(testObject);
1567
- }
1568
- onTestCompleted(testObject);
1635
+ function handleCollision(newNode, prevNode) {
1636
+ if (vestjsRuntime.IsolateInspector.usesKey(newNode)) {
1637
+ return VestTest.cast(vestjsRuntime.Reconciler.handleIsolateNodeWithKey(newNode, VestTest.isNonActionable));
1569
1638
  }
1570
- catch (e) {
1571
- // Probably unreachable. If we get here, it means that
1572
- // something was really wrong and should be reported.
1639
+ if (vestjsRuntime.Reconciler.dropNextNodesOnReorder(nodeReorderDetected, newNode, prevNode)) {
1640
+ throwTestOrderError(newNode, prevNode);
1641
+ return newNode;
1642
+ }
1643
+ if (!VestTest.is(prevNode)) {
1644
+ // I believe we cannot actually reach this point.
1645
+ // Because it should already be handled by nodeReorderDetected.
1573
1646
  /* istanbul ignore next */
1574
- throw new Error(vestUtils.text(ErrorStrings.UNEXPECTED_TEST_REGISTRATION_ERROR, {
1575
- testObject: JSON.stringify(testObject),
1576
- error: e,
1577
- }));
1647
+ return newNode;
1578
1648
  }
1579
- }
1580
- /**
1581
- * Runs async test.
1582
- */
1583
- function useRunAsyncTest(testObject) {
1584
- const { asyncTest, message } = VestTest.getData(testObject);
1585
- if (!vestUtils.isPromise(asyncTest))
1586
- return;
1587
- // VestTest.setPending(testObject);
1588
- const done = vestjsRuntime.VestRuntime.persist(() => {
1589
- onTestCompleted(testObject);
1590
- });
1591
- const fail = vestjsRuntime.VestRuntime.persist((rejectionMessage) => {
1592
- if (VestTest.isCanceled(testObject)) {
1593
- return;
1594
- }
1595
- VestTest.getData(testObject).message = vestUtils.isStringValue(rejectionMessage)
1596
- ? rejectionMessage
1597
- : message;
1598
- VestTest.fail(testObject);
1599
- done();
1600
- });
1601
- return asyncTest.then(done, fail);
1602
- }
1603
- function onTestCompleted(testObject) {
1604
- // Attempts passing if the test is not already failed.
1605
- // or is not canceled/omitted.
1606
- VestTest.pass(testObject);
1607
- }
1608
-
1609
- // @vx-allow use-use
1610
- function wrapTestMemo(test) {
1611
- function memo(fieldName, ...args) {
1612
- const [deps, testFn, msg] = args.reverse();
1613
- // Implicit dependency for better specificity
1614
- const dependencies = [
1615
- useSuiteId(),
1616
- fieldName,
1617
- vestjsRuntime.VestRuntime.useCurrentCursor(),
1618
- ].concat(deps);
1619
- return useGetTestFromCache(dependencies, cacheAction);
1620
- function cacheAction() {
1621
- return test(fieldName, msg, testFn);
1622
- }
1649
+ // FIXME: May-13-2023
1650
+ // This may not be the most ideal solution.
1651
+ // In short: if the node was omitted in the previous run,
1652
+ // we want to re-evaluate it. The reason is that we may incorrectly
1653
+ // identify it is "optional" because it was omitted in the previous run.
1654
+ // There may be a better way to handle this. Need to revisit this.
1655
+ if (VestTest.isOmitted(prevNode)) {
1656
+ return newNode;
1623
1657
  }
1624
- return memo;
1658
+ return prevNode;
1625
1659
  }
1626
- function useGetTestFromCache(dependencies, cacheAction) {
1627
- const cache = useTestMemoCache();
1628
- const cached = cache.get(dependencies);
1629
- if (vestUtils.isNull(cached)) {
1630
- // cache miss
1631
- return cache(dependencies, cacheAction);
1632
- }
1633
- const [, cachedValue] = cached;
1634
- if (VestTest.isCanceled(cachedValue)) {
1635
- // cache hit, but test is canceled
1636
- cache.invalidate(dependencies);
1637
- return cache(dependencies, cacheAction);
1660
+ function cancelOverriddenPendingTestOnTestReRun(nextNode, currentNode, prevTestObject) {
1661
+ if (nextNode === currentNode && VestTest.is(currentNode)) {
1662
+ cancelOverriddenPendingTest(prevTestObject, currentNode);
1638
1663
  }
1639
- vestjsRuntime.VestRuntime.addNodeToHistory(cachedValue);
1640
- return cachedValue;
1641
1664
  }
1642
-
1643
- // @vx-allow use-use
1644
- function vestTest(fieldName, ...args) {
1645
- const [message, testFn, key] = (vestUtils.isFunction(args[1]) ? args : [undefined, ...args]);
1646
- validateTestParams(fieldName, testFn);
1647
- const groupName = useGroupName();
1648
- const testObjectInput = { fieldName, groupName, message, testFn };
1649
- // This invalidates the suite cache.
1650
- vestjsRuntime.Bus.useEmit(Events.TEST_RUN_STARTED);
1651
- return IsolateTest(useAttemptRunTest, testObjectInput, key);
1665
+ function nodeReorderDetected(newNode, prevNode) {
1666
+ return VestTest.is(prevNode) && !isSameProfileTest(prevNode, newNode);
1652
1667
  }
1653
- const test = vestUtils.assign(vestTest, {
1654
- memo: wrapTestMemo(vestTest),
1655
- });
1656
- function validateTestParams(fieldName, testFn) {
1657
- const fnName = 'test';
1658
- vestUtils.invariant(vestUtils.isStringValue(fieldName), vestUtils.text(ErrorStrings.INVALID_PARAM_PASSED_TO_FUNCTION, {
1659
- fn_name: fnName,
1660
- param: 'fieldName',
1661
- expected: 'string',
1662
- }));
1663
- vestUtils.invariant(vestUtils.isFunction(testFn), vestUtils.text(ErrorStrings.INVALID_PARAM_PASSED_TO_FUNCTION, {
1664
- fn_name: fnName,
1665
- param: 'callback',
1666
- expected: 'function',
1668
+ function throwTestOrderError(newNode, prevNode) {
1669
+ if (vestjsRuntime.IsolateInspector.canReorder(newNode)) {
1670
+ return;
1671
+ }
1672
+ vestUtils.deferThrow(vestUtils.text(ErrorStrings.TESTS_CALLED_IN_DIFFERENT_ORDER, {
1673
+ fieldName: VestTest.getData(newNode).fieldName,
1674
+ prevName: VestTest.is(prevNode)
1675
+ ? VestTest.getData(prevNode).fieldName
1676
+ : undefined,
1667
1677
  }));
1668
1678
  }
1669
1679
 
1670
- // import { optional, skipWhen, omitWhen, IsolateTest, group } from 'vest';
1671
- function getTypedMethods() {
1672
- return {
1673
- group,
1674
- include,
1675
- omitWhen,
1676
- only,
1677
- optional,
1678
- skip,
1679
- skipWhen,
1680
- test,
1681
- };
1680
+ function VestReconciler(currentNode, historyNode) {
1681
+ var _a, _b;
1682
+ return ((_b = (_a = [IsolateTestReconciler]
1683
+ .find(reconciler => reconciler.match(currentNode, historyNode))) === null || _a === void 0 ? void 0 : _a.reconcile(currentNode, historyNode)) !== null && _b !== void 0 ? _b : null);
1682
1684
  }
1683
1685
 
1684
1686
  function useDeferDoneCallback(doneCallback, fieldName) {
@@ -1733,6 +1735,7 @@ function validateSuiteCallback(suiteCallback) {
1733
1735
  }
1734
1736
 
1735
1737
  // @vx-allow use-use
1738
+ // eslint-disable-next-line max-lines-per-function
1736
1739
  function createSuite(...args) {
1737
1740
  const [suiteCallback, suiteName] = args.reverse();
1738
1741
  validateSuiteCallback(suiteCallback);
@@ -1747,6 +1750,7 @@ function createSuite(...args) {
1747
1750
  return IsolateSuite(useRunSuiteCallback(suiteCallback, ...args));
1748
1751
  }).output;
1749
1752
  }
1753
+ const mountedStatic = staticSuite(...args);
1750
1754
  // Assign methods to the suite
1751
1755
  // We do this within the VestRuntime so that the suite methods
1752
1756
  // will be bound to the suite's stateRef and be able to access it.
@@ -1756,7 +1760,7 @@ function createSuite(...args) {
1756
1760
  return vestUtils.assign(
1757
1761
  // We're also binding the suite to the stateRef, so that the suite
1758
1762
  // can access the stateRef when it's called.
1759
- vestjsRuntime.VestRuntime.persist(suite), Object.assign(Object.assign({ dump: vestjsRuntime.VestRuntime.persist(() => vestjsRuntime.VestRuntime.useAvailableRoot()), get: vestjsRuntime.VestRuntime.persist(useCreateSuiteResult), remove: vestjsRuntime.Bus.usePrepareEmitter(Events.REMOVE_FIELD), reset: vestjsRuntime.Bus.usePrepareEmitter(Events.RESET_SUITE), resetField: vestjsRuntime.Bus.usePrepareEmitter(Events.RESET_FIELD), resume: vestjsRuntime.VestRuntime.persist(useLoadSuite), subscribe: VestBus.subscribe }, bindSuiteSelectors(vestjsRuntime.VestRuntime.persist(useCreateSuiteResult))), getTypedMethods()));
1763
+ vestjsRuntime.VestRuntime.persist(suite), Object.assign(Object.assign({ dump: vestjsRuntime.VestRuntime.persist(() => vestjsRuntime.VestRuntime.useAvailableRoot()), get: vestjsRuntime.VestRuntime.persist(useCreateSuiteResult), remove: vestjsRuntime.Bus.usePrepareEmitter(Events.REMOVE_FIELD), reset: vestjsRuntime.Bus.usePrepareEmitter(Events.RESET_SUITE), resetField: vestjsRuntime.Bus.usePrepareEmitter(Events.RESET_FIELD), resume: vestjsRuntime.VestRuntime.persist(useLoadSuite), runStatic: (...args) => mountedStatic(...args), subscribe: VestBus.subscribe }, bindSuiteSelectors(vestjsRuntime.VestRuntime.persist(useCreateSuiteResult))), getTypedMethods()));
1760
1764
  });
1761
1765
  }
1762
1766
  function useRunSuiteCallback(suiteCallback, ...args) {
@@ -1767,6 +1771,17 @@ function useRunSuiteCallback(suiteCallback, ...args) {
1767
1771
  return useSuiteRunResult();
1768
1772
  };
1769
1773
  }
1774
+ // @vx-allow use-use
1775
+ // eslint-disable-next-line max-lines-per-function
1776
+ function staticSuite(...createArgs) {
1777
+ return vestUtils.assign((...args) => {
1778
+ const suite = createSuite(...createArgs);
1779
+ const result = suite(...args);
1780
+ return Object.freeze(vestUtils.assign({
1781
+ dump: suite.dump,
1782
+ }, result));
1783
+ }, Object.assign({}, getTypedMethods()));
1784
+ }
1770
1785
 
1771
1786
  function IsolateEach(callback) {
1772
1787
  return vestjsRuntime.Isolate.create(VestIsolateType.Each, callback, {
@@ -1796,33 +1811,6 @@ function each(list, callback) {
1796
1811
  });
1797
1812
  }
1798
1813
 
1799
- /**
1800
- * Creates a static suite for server-side validation.
1801
- *
1802
- * @param {Function} validationFn - The validation function that defines the suite's tests.
1803
- * @returns {Function} - A function that runs the validations defined in the suite.
1804
- *
1805
- * @example
1806
- * import { staticSuite, test, enforce } from 'vest';
1807
- *
1808
- * const suite = staticSuite(data => {
1809
- * test('username', 'username is required', () => {
1810
- * enforce(data.username).isNotEmpty();
1811
- * });
1812
- * });
1813
- *
1814
- * suite(data);
1815
- */
1816
- function staticSuite(suiteCallback) {
1817
- return vestUtils.assign((...args) => {
1818
- const suite = createSuite(suiteCallback);
1819
- const result = suite(...args);
1820
- return Object.freeze(vestUtils.assign({
1821
- dump: suite.dump,
1822
- }, result));
1823
- }, Object.assign({}, getTypedMethods()));
1824
- }
1825
-
1826
1814
  const ERROR_OUTSIDE_OF_TEST = ErrorStrings.WARN_MUST_BE_CALLED_FROM_TEST;
1827
1815
  /**
1828
1816
  * Sets the severity level of a test to `warn`, allowing it to fail without marking the suite as invalid.