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