vest 5.0.0-dev-9c596e → 5.0.0-dev-ec989a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/classnames.development.js +1 -2
- package/dist/cjs/classnames.production.js +1 -1
- package/dist/cjs/enforce/compose.development.js +1 -5
- package/dist/cjs/enforce/compose.production.js +1 -1
- package/dist/cjs/enforce/compounds.development.js +3 -6
- package/dist/cjs/enforce/compounds.production.js +1 -1
- package/dist/cjs/enforce/schema.development.js +3 -6
- package/dist/cjs/enforce/schema.production.js +1 -1
- package/dist/cjs/parser.development.js +1 -4
- package/dist/cjs/parser.production.js +1 -1
- package/dist/cjs/promisify.development.js +1 -2
- package/dist/cjs/promisify.production.js +1 -1
- package/dist/cjs/vest.development.js +596 -764
- package/dist/cjs/vest.production.js +1 -1
- package/dist/es/classnames.development.js +1 -2
- package/dist/es/classnames.production.js +1 -1
- package/dist/es/parser.development.js +1 -2
- package/dist/es/parser.production.js +1 -1
- package/dist/es/promisify.development.js +1 -2
- package/dist/es/promisify.production.js +1 -1
- package/dist/es/vest.development.js +591 -757
- package/dist/es/vest.production.js +1 -1
- package/dist/umd/classnames.development.js +1 -2
- package/dist/umd/classnames.production.js +1 -1
- package/dist/umd/enforce/compose.development.js +1 -7
- package/dist/umd/enforce/compose.production.js +1 -1
- package/dist/umd/enforce/compounds.development.js +3 -6
- package/dist/umd/enforce/compounds.production.js +1 -1
- package/dist/umd/enforce/schema.development.js +3 -6
- package/dist/umd/enforce/schema.production.js +1 -1
- package/dist/umd/parser.development.js +1 -4
- package/dist/umd/parser.production.js +1 -1
- package/dist/umd/promisify.development.js +1 -2
- package/dist/umd/promisify.production.js +1 -1
- package/dist/umd/vest.development.js +599 -768
- package/dist/umd/vest.production.js +1 -1
- package/package.json +137 -136
- package/testUtils/TVestMock.ts +1 -1
- package/testUtils/asVestTest.ts +9 -0
- package/types/classnames.d.ts +82 -4
- package/types/classnames.d.ts.map +1 -1
- package/types/parser.d.ts +82 -4
- package/types/parser.d.ts.map +1 -1
- package/types/promisify.d.ts +82 -4
- package/types/promisify.d.ts.map +1 -1
- package/types/vest.d.ts +150 -138
- package/types/vest.d.ts.map +1 -1
|
@@ -1,33 +1,55 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var n4s = require('n4s');
|
|
4
|
+
var vestRuntime = require('vest-runtime');
|
|
6
5
|
var vestUtils = require('vest-utils');
|
|
7
6
|
var context = require('context');
|
|
8
7
|
|
|
9
8
|
var OptionalFieldTypes;
|
|
10
9
|
(function (OptionalFieldTypes) {
|
|
11
|
-
OptionalFieldTypes[OptionalFieldTypes["
|
|
12
|
-
OptionalFieldTypes[OptionalFieldTypes["
|
|
10
|
+
OptionalFieldTypes[OptionalFieldTypes["CUSTOM_LOGIC"] = 0] = "CUSTOM_LOGIC";
|
|
11
|
+
OptionalFieldTypes[OptionalFieldTypes["AUTO"] = 1] = "AUTO";
|
|
13
12
|
})(OptionalFieldTypes || (OptionalFieldTypes = {}));
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
// @vx-allow use-use
|
|
15
|
+
function optional(optionals) {
|
|
16
|
+
const suiteRoot = vestRuntime.VestRuntime.useAvailableRoot();
|
|
17
|
+
// There are two types of optional field declarations:
|
|
18
|
+
// 1 AUTO: Vest will automatically determine whether the field should be omitted
|
|
19
|
+
// Based on the current run. Vest will ommit "auto" added fields without any
|
|
20
|
+
// configuration if their tests did not run at all in the suite.
|
|
21
|
+
//
|
|
22
|
+
// 2 Custom logic: Vest will determine whether they should fail based on the custom
|
|
23
|
+
// logic supplied by the user.
|
|
24
|
+
// AUTO case (field name)
|
|
25
|
+
if (vestUtils.isArray(optionals) || vestUtils.isStringValue(optionals)) {
|
|
26
|
+
vestUtils.asArray(optionals).forEach(optionalField => {
|
|
27
|
+
suiteRoot.setOptionalField(optionalField, () => ({
|
|
28
|
+
type: OptionalFieldTypes.AUTO,
|
|
29
|
+
applied: false,
|
|
30
|
+
rule: null,
|
|
31
|
+
}));
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// CUSTOM_LOGIC case (function or boolean)
|
|
36
|
+
for (const field in optionals) {
|
|
37
|
+
const value = optionals[field];
|
|
38
|
+
suiteRoot.setOptionalField(field, () => ({
|
|
39
|
+
type: OptionalFieldTypes.CUSTOM_LOGIC,
|
|
40
|
+
rule: value,
|
|
41
|
+
applied: value === true,
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function useIsOptionalFiedApplied(fieldName) {
|
|
47
|
+
var _a, _b, _c;
|
|
48
|
+
if (!fieldName) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return ((_c = (_b = (_a = vestRuntime.VestRuntime.useAvailableRoot()) === null || _a === void 0 ? void 0 : _a.getOptionalField(fieldName)) === null || _b === void 0 ? void 0 : _b.applied) !== null && _c !== void 0 ? _c : false);
|
|
52
|
+
}
|
|
31
53
|
|
|
32
54
|
var Events;
|
|
33
55
|
(function (Events) {
|
|
@@ -38,250 +60,74 @@ var Events;
|
|
|
38
60
|
Events["RESET_FIELD"] = "reset_field";
|
|
39
61
|
Events["RESET_SUITE"] = "reset_suite";
|
|
40
62
|
Events["SUITE_RUN_STARTED"] = "suite_run_started";
|
|
63
|
+
Events["SUITE_CALLBACK_RUN_FINISHED"] = "SUITE_CALLBACK_RUN_FINISHED";
|
|
64
|
+
Events["DONE_TEST_OMISSION_PASS"] = "DONE_TEST_OMISSION_PASS";
|
|
41
65
|
})(Events || (Events = {}));
|
|
42
66
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
let broke = false;
|
|
49
|
-
for (const isolate of startNode.children) {
|
|
50
|
-
if (broke) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
if (vestUtils.isNullish(visitOnly) || vestUtils.optionalFunctionValue(visitOnly, isolate)) {
|
|
54
|
-
callback(isolate, breakout);
|
|
55
|
-
}
|
|
56
|
-
if (broke) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
walk(isolate, (child, innerBreakout) => {
|
|
60
|
-
callback(child, () => {
|
|
61
|
-
innerBreakout();
|
|
62
|
-
breakout();
|
|
63
|
-
});
|
|
64
|
-
}, visitOnly);
|
|
65
|
-
}
|
|
66
|
-
function breakout() {
|
|
67
|
-
broke = true;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
function some(startNode, predicate, visitOnly) {
|
|
71
|
-
let hasMatch = false;
|
|
72
|
-
walk(startNode, (node, breakout) => {
|
|
73
|
-
if (predicate(node)) {
|
|
74
|
-
breakout();
|
|
75
|
-
hasMatch = true;
|
|
76
|
-
}
|
|
77
|
-
}, visitOnly);
|
|
78
|
-
return hasMatch;
|
|
79
|
-
}
|
|
80
|
-
function has(startNode, match) {
|
|
81
|
-
return some(startNode, () => true, match);
|
|
82
|
-
}
|
|
83
|
-
function every(startNode, predicate, visitOnly) {
|
|
84
|
-
let hasMatch = true;
|
|
85
|
-
walk(startNode, (node, breakout) => {
|
|
86
|
-
if (!predicate(node)) {
|
|
87
|
-
breakout();
|
|
88
|
-
hasMatch = false;
|
|
89
|
-
}
|
|
90
|
-
}, visitOnly);
|
|
91
|
-
return hasMatch;
|
|
92
|
-
}
|
|
93
|
-
function pluck(startNode, predicate, visitOnly) {
|
|
94
|
-
walk(startNode, node => {
|
|
95
|
-
if (predicate(node) && node.parent) {
|
|
96
|
-
node.parent.removeChild(node);
|
|
97
|
-
}
|
|
98
|
-
}, visitOnly);
|
|
99
|
-
}
|
|
100
|
-
function closest(startNode, predicate) {
|
|
101
|
-
let current = startNode;
|
|
102
|
-
while (current.parent) {
|
|
103
|
-
if (predicate(current)) {
|
|
104
|
-
return current;
|
|
105
|
-
}
|
|
106
|
-
current = current.parent;
|
|
67
|
+
class IsolateSuite extends vestRuntime.Isolate {
|
|
68
|
+
constructor() {
|
|
69
|
+
super(...arguments);
|
|
70
|
+
this.optional = {};
|
|
107
71
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
class Reconciler {
|
|
115
|
-
static reconciler(currentNode, historicNode) {
|
|
116
|
-
if (vestUtils.isNullish(historicNode)) {
|
|
117
|
-
return currentNode;
|
|
118
|
-
}
|
|
119
|
-
return currentNode;
|
|
72
|
+
setOptionalField(fieldName, setter) {
|
|
73
|
+
const current = this.optional;
|
|
74
|
+
const currentField = current[fieldName];
|
|
75
|
+
Object.assign(current, {
|
|
76
|
+
[fieldName]: Object.assign({}, currentField, setter(currentField)),
|
|
77
|
+
});
|
|
120
78
|
}
|
|
121
|
-
|
|
79
|
+
getOptionalField(fieldName) {
|
|
122
80
|
var _a;
|
|
123
|
-
|
|
124
|
-
const historyNode = useHistoryNode();
|
|
125
|
-
let localHistoryNode = historyNode;
|
|
126
|
-
if (parent) {
|
|
127
|
-
// If we have a parent, we need to get the history node from the parent's children
|
|
128
|
-
// We take the history node from the cursor of the active node's children
|
|
129
|
-
localHistoryNode = (_a = historyNode === null || historyNode === void 0 ? void 0 : historyNode.at(useCurrentCursor())) !== null && _a !== void 0 ? _a : null;
|
|
130
|
-
}
|
|
131
|
-
const nextNode = this.reconciler(node, localHistoryNode);
|
|
132
|
-
vestUtils.invariant(nextNode);
|
|
133
|
-
if (Object.is(nextNode, node)) {
|
|
134
|
-
return [node, useRunAsNew(localHistoryNode, node, callback)];
|
|
135
|
-
}
|
|
136
|
-
return [nextNode, nextNode.output];
|
|
81
|
+
return (_a = this.optional[fieldName]) !== null && _a !== void 0 ? _a : {};
|
|
137
82
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const historyNode = useHistoryNode();
|
|
141
|
-
if (!historyNode || !testIsolate) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
historyNode.slice(useCurrentCursor());
|
|
83
|
+
getOptionalFields() {
|
|
84
|
+
return this.optional;
|
|
145
85
|
}
|
|
146
|
-
static handleCollision(newNode, prevNode) {
|
|
147
|
-
// we should base our calculation on the key property
|
|
148
|
-
if (newNode.usesKey()) {
|
|
149
|
-
return this.handleIsolateNodeWithKey(newNode);
|
|
150
|
-
}
|
|
151
|
-
if (this.nodeReorderDetected(newNode, prevNode)) {
|
|
152
|
-
this.onNodeReorder(newNode, prevNode);
|
|
153
|
-
}
|
|
154
|
-
return prevNode ? prevNode : newNode;
|
|
155
|
-
}
|
|
156
|
-
static nodeReorderDetected(newNode, prevNode) {
|
|
157
|
-
// This is a dummy return just to satisfy the linter. Overrides will supply the real implementation.
|
|
158
|
-
return !(newNode !== null && newNode !== void 0 ? newNode : prevNode);
|
|
159
|
-
}
|
|
160
|
-
static onNodeReorder(newNode, prevNode) {
|
|
161
|
-
this.removeAllNextNodesInIsolate();
|
|
162
|
-
// This is a dummy return just to satisfy the linter. Overrides will supply the real implementation.
|
|
163
|
-
return newNode !== null && newNode !== void 0 ? newNode : prevNode;
|
|
164
|
-
}
|
|
165
|
-
static handleIsolateNodeWithKey(node) {
|
|
166
|
-
vestUtils.invariant(node.usesKey());
|
|
167
|
-
const prevNodeByKey = useHistoryKey(node.key);
|
|
168
|
-
let nextNode = node;
|
|
169
|
-
if (!vestUtils.isNullish(prevNodeByKey)) {
|
|
170
|
-
nextNode = prevNodeByKey;
|
|
171
|
-
}
|
|
172
|
-
useSetIsolateKey(node.key, node);
|
|
173
|
-
return nextNode;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
function useRunAsNew(localHistoryNode, current, callback) {
|
|
177
|
-
const runtimeRoot = useRuntimeRoot();
|
|
178
|
-
// We're creating a new child isolate context where the local history node
|
|
179
|
-
// is the current history node, thus advancing the history cursor.
|
|
180
|
-
const output = PersistedContext.run(Object.assign({ historyNode: localHistoryNode, runtimeNode: current }, (!runtimeRoot && { runtimeRoot: current })), () => callback(current));
|
|
181
|
-
current.output = output;
|
|
182
|
-
return output;
|
|
183
86
|
}
|
|
184
87
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
this.parent = parent;
|
|
196
|
-
return this;
|
|
197
|
-
}
|
|
198
|
-
saveOutput(output) {
|
|
199
|
-
this.output = output;
|
|
200
|
-
return this;
|
|
201
|
-
}
|
|
202
|
-
setKey(key) {
|
|
203
|
-
this.key = key;
|
|
204
|
-
return this;
|
|
205
|
-
}
|
|
206
|
-
usesKey() {
|
|
207
|
-
return vestUtils.isNotNullish(this.key);
|
|
208
|
-
}
|
|
209
|
-
addChild(child) {
|
|
210
|
-
vestUtils.invariant(this.children);
|
|
211
|
-
this.children.push(child);
|
|
212
|
-
}
|
|
213
|
-
removeChild(node) {
|
|
214
|
-
var _a, _b;
|
|
215
|
-
this.children = (_b = (_a = this.children) === null || _a === void 0 ? void 0 : _a.filter(child => child !== node)) !== null && _b !== void 0 ? _b : null;
|
|
216
|
-
}
|
|
217
|
-
slice(at) {
|
|
218
|
-
if (vestUtils.isNullish(this.children)) {
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
this.children.length = at;
|
|
222
|
-
}
|
|
223
|
-
at(at) {
|
|
224
|
-
var _a, _b;
|
|
225
|
-
return (_b = (_a = this.children) === null || _a === void 0 ? void 0 : _a[at]) !== null && _b !== void 0 ? _b : null;
|
|
226
|
-
}
|
|
227
|
-
cursor() {
|
|
228
|
-
var _a, _b;
|
|
229
|
-
return (_b = (_a = this.children) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
|
230
|
-
}
|
|
231
|
-
shouldAllowReorder() {
|
|
232
|
-
var _a;
|
|
233
|
-
return (_a = closestExists(this, node => node.allowReorder)) !== null && _a !== void 0 ? _a : false;
|
|
234
|
-
}
|
|
235
|
-
get rootNode() {
|
|
236
|
-
var _a;
|
|
237
|
-
return (_a = closest(this, node => vestUtils.isNullish(node.parent))) !== null && _a !== void 0 ? _a : this;
|
|
238
|
-
}
|
|
239
|
-
static create(callback, data) {
|
|
240
|
-
return this.createImplementation(callback, data);
|
|
241
|
-
}
|
|
242
|
-
static createImplementation(callback, data) {
|
|
243
|
-
const parent = useIsolate();
|
|
244
|
-
const newCreatedNode = new this(data).setParent(parent);
|
|
245
|
-
const [nextIsolateChild, output] = this.reconciler.reconcile(newCreatedNode, callback);
|
|
246
|
-
nextIsolateChild.saveOutput(output);
|
|
247
|
-
this.setNode(nextIsolateChild);
|
|
248
|
-
return nextIsolateChild;
|
|
249
|
-
}
|
|
250
|
-
static setNode(node) {
|
|
251
|
-
const parent = useIsolate();
|
|
252
|
-
if (parent) {
|
|
253
|
-
useSetNextIsolateChild(node);
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
useSetHistory(node);
|
|
257
|
-
}
|
|
258
|
-
node.setParent(parent);
|
|
259
|
-
}
|
|
260
|
-
static is(node) {
|
|
261
|
-
return node instanceof Isolate;
|
|
262
|
-
}
|
|
88
|
+
const suiteResultCache = vestUtils.cache();
|
|
89
|
+
function useCreateVestState({ suiteName, } = {}) {
|
|
90
|
+
const stateRef = {
|
|
91
|
+
doneCallbacks: vestUtils.tinyState.createTinyState(() => []),
|
|
92
|
+
fieldCallbacks: vestUtils.tinyState.createTinyState(() => ({})),
|
|
93
|
+
suiteId: vestUtils.seq(),
|
|
94
|
+
suiteName,
|
|
95
|
+
suiteResultCache,
|
|
96
|
+
};
|
|
97
|
+
return vestRuntime.VestRuntime.createRef(stateRef);
|
|
263
98
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
function nonMatchingFieldName(WithFieldName, fieldName) {
|
|
267
|
-
return !!fieldName && !matchingFieldName(WithFieldName, fieldName);
|
|
99
|
+
function useX() {
|
|
100
|
+
return vestRuntime.VestRuntime.useXAppData();
|
|
268
101
|
}
|
|
269
|
-
function
|
|
270
|
-
return
|
|
102
|
+
function useDoneCallbacks() {
|
|
103
|
+
return useX().doneCallbacks();
|
|
271
104
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
return (matchingFieldName(testObject1, testObject2.fieldName) &&
|
|
275
|
-
testObject1.groupName === testObject2.groupName &&
|
|
276
|
-
testObject1.key === testObject2.key);
|
|
105
|
+
function useFieldCallbacks() {
|
|
106
|
+
return useX().fieldCallbacks();
|
|
277
107
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
108
|
+
function useSuiteName() {
|
|
109
|
+
return useX().suiteName;
|
|
110
|
+
}
|
|
111
|
+
function useSuiteId() {
|
|
112
|
+
return useX().suiteId;
|
|
113
|
+
}
|
|
114
|
+
function useSuiteResultCache(action) {
|
|
115
|
+
const suiteResultCache = useX().suiteResultCache;
|
|
116
|
+
return suiteResultCache([useSuiteId()], action);
|
|
117
|
+
}
|
|
118
|
+
function useExpireSuiteResultCache() {
|
|
119
|
+
const suiteResultCache = useX().suiteResultCache;
|
|
120
|
+
suiteResultCache.invalidate([useSuiteId()]);
|
|
121
|
+
}
|
|
122
|
+
function useResetCallbacks() {
|
|
123
|
+
const [, , resetDoneCallbacks] = useDoneCallbacks();
|
|
124
|
+
const [, , resetFieldCallbacks] = useFieldCallbacks();
|
|
125
|
+
resetDoneCallbacks();
|
|
126
|
+
resetFieldCallbacks();
|
|
127
|
+
}
|
|
128
|
+
function useResetSuite() {
|
|
129
|
+
useResetCallbacks();
|
|
130
|
+
vestRuntime.VestRuntime.reset();
|
|
285
131
|
}
|
|
286
132
|
|
|
287
133
|
var Severity;
|
|
@@ -299,135 +145,47 @@ function countKeyBySeverity(severity) {
|
|
|
299
145
|
? SeverityCount.ERROR_COUNT
|
|
300
146
|
: SeverityCount.WARN_COUNT;
|
|
301
147
|
}
|
|
148
|
+
var TestSeverity;
|
|
149
|
+
(function (TestSeverity) {
|
|
150
|
+
TestSeverity["Error"] = "error";
|
|
151
|
+
TestSeverity["Warning"] = "warning";
|
|
152
|
+
})(TestSeverity || (TestSeverity = {}));
|
|
302
153
|
|
|
303
|
-
|
|
304
|
-
function
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
154
|
+
var ErrorStrings;
|
|
155
|
+
(function (ErrorStrings) {
|
|
156
|
+
ErrorStrings["HOOK_CALLED_OUTSIDE"] = "hook called outside of a running suite.";
|
|
157
|
+
ErrorStrings["EXPECTED_VEST_TEST"] = "Expected value to be an instance of IsolateTest";
|
|
158
|
+
ErrorStrings["FIELD_NAME_REQUIRED"] = "Field name must be passed";
|
|
159
|
+
ErrorStrings["SUITE_MUST_BE_INITIALIZED_WITH_FUNCTION"] = "Suite must be initialized with a function";
|
|
160
|
+
ErrorStrings["PROMISIFY_REQUIRE_FUNCTION"] = "Vest.Promisify must be called with a function";
|
|
161
|
+
ErrorStrings["PARSER_EXPECT_RESULT_OBJECT"] = "Vest parser: expected argument at position 0 to be Vest's result object.";
|
|
162
|
+
ErrorStrings["WARN_MUST_BE_CALLED_FROM_TEST"] = "Warn must be called from within the body of a test function";
|
|
163
|
+
ErrorStrings["EACH_CALLBACK_MUST_BE_A_FUNCTION"] = "Each must be called with a function";
|
|
164
|
+
ErrorStrings["INVALID_PARAM_PASSED_TO_FUNCTION"] = "Incompatible params passed to {fn_name} function. \"{param}\" must be of type {expected}";
|
|
165
|
+
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.";
|
|
166
|
+
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}.";
|
|
167
|
+
ErrorStrings["UNEXPECTED_TEST_RUN_ERROR"] = "Unexpected error encountered during test run. Please report this issue to Vest's Github repository.\n Test Object: {testObject}.";
|
|
168
|
+
})(ErrorStrings || (ErrorStrings = {}));
|
|
314
169
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
* summary object, while this one uses the actual validation state
|
|
318
|
-
*/
|
|
319
|
-
function hasErrorsByTestObjects(fieldName) {
|
|
320
|
-
return hasFailuresByTestObjects(Severity.ERRORS, fieldName);
|
|
321
|
-
}
|
|
322
|
-
function hasFailuresByTestObjects(severityKey, fieldName) {
|
|
323
|
-
return TestWalker.someTests(testObject => {
|
|
324
|
-
return hasFailuresByTestObject(testObject, severityKey, fieldName);
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
function hasGroupFailuresByTestObjects(severityKey, groupName, fieldName) {
|
|
328
|
-
return TestWalker.someTests(testObject => {
|
|
329
|
-
if (nonMatchingGroupName(testObject, groupName)) {
|
|
330
|
-
return false;
|
|
331
|
-
}
|
|
332
|
-
return hasFailuresByTestObject(testObject, severityKey, fieldName);
|
|
333
|
-
});
|
|
170
|
+
function nonMatchingFieldName(WithFieldName, fieldName) {
|
|
171
|
+
return !!fieldName && !matchingFieldName(WithFieldName, fieldName);
|
|
334
172
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
*/
|
|
338
|
-
function hasFailuresByTestObject(testObject, severityKey, fieldName) {
|
|
339
|
-
if (!testObject.hasFailures()) {
|
|
340
|
-
return false;
|
|
341
|
-
}
|
|
342
|
-
if (nonMatchingFieldName(testObject, fieldName)) {
|
|
343
|
-
return false;
|
|
344
|
-
}
|
|
345
|
-
if (nonMatchingSeverityProfile(severityKey, testObject)) {
|
|
346
|
-
return false;
|
|
347
|
-
}
|
|
348
|
-
return true;
|
|
173
|
+
function matchingFieldName(WithFieldName, fieldName) {
|
|
174
|
+
return !!(fieldName && WithFieldName.fieldName === fieldName);
|
|
349
175
|
}
|
|
350
176
|
|
|
351
|
-
|
|
352
|
-
(
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
})(exports.Modes || (exports.Modes = {}));
|
|
356
|
-
/**
|
|
357
|
-
* Sets the suite to "eager" (fail fast) mode.
|
|
358
|
-
* Eager mode will skip running subsequent tests of a failing fields.
|
|
359
|
-
*
|
|
360
|
-
* @example
|
|
361
|
-
* // in the following example, the second test of username will not run
|
|
362
|
-
* // if the first test of username failed.
|
|
363
|
-
* const suite = create((data) => {
|
|
364
|
-
* eager();
|
|
365
|
-
*
|
|
366
|
-
* test('username', 'username is required', () => {
|
|
367
|
-
* enforce(data.username).isNotBlank();
|
|
368
|
-
* });
|
|
369
|
-
*
|
|
370
|
-
* test('username', 'username is too short', () => {
|
|
371
|
-
* enforce(data.username).longerThan(2);
|
|
372
|
-
* });
|
|
373
|
-
* });
|
|
374
|
-
*/
|
|
375
|
-
// @vx-allow use-use
|
|
376
|
-
function mode(mode) {
|
|
377
|
-
const [, setMode] = useMode();
|
|
378
|
-
setMode(mode);
|
|
379
|
-
}
|
|
380
|
-
function useIsMode(mode) {
|
|
381
|
-
const [currentMode] = useMode();
|
|
382
|
-
return currentMode === mode;
|
|
383
|
-
}
|
|
384
|
-
function useIsEager() {
|
|
385
|
-
return useIsMode(exports.Modes.EAGER);
|
|
386
|
-
}
|
|
387
|
-
function useShouldSkipBasedOnMode(testObject) {
|
|
388
|
-
return useIsEager() && hasErrorsByTestObjects(testObject.fieldName);
|
|
177
|
+
function isSameProfileTest(testObject1, testObject2) {
|
|
178
|
+
return (matchingFieldName(testObject1, testObject2.fieldName) &&
|
|
179
|
+
testObject1.groupName === testObject2.groupName &&
|
|
180
|
+
testObject1.key === testObject2.key);
|
|
389
181
|
}
|
|
390
182
|
|
|
391
|
-
|
|
392
|
-
if (
|
|
393
|
-
|
|
183
|
+
function cancelOverriddenPendingTest(prevRunTestObject, currentRunTestObject) {
|
|
184
|
+
if (currentRunTestObject !== prevRunTestObject &&
|
|
185
|
+
isSameProfileTest(prevRunTestObject, currentRunTestObject) &&
|
|
186
|
+
prevRunTestObject.isPending()) {
|
|
187
|
+
prevRunTestObject.cancel();
|
|
394
188
|
}
|
|
395
|
-
return vestUtils.assign({
|
|
396
|
-
exclusion: {
|
|
397
|
-
tests: {},
|
|
398
|
-
groups: {},
|
|
399
|
-
},
|
|
400
|
-
inclusion: {},
|
|
401
|
-
mode: vestUtils.tinyState.createTinyState(exports.Modes.EAGER),
|
|
402
|
-
testMemoCache,
|
|
403
|
-
}, ctxRef);
|
|
404
|
-
});
|
|
405
|
-
function useCurrentTest(msg) {
|
|
406
|
-
return SuiteContext.useX(msg).currentTest;
|
|
407
|
-
}
|
|
408
|
-
function useGroupName() {
|
|
409
|
-
return SuiteContext.useX().groupName;
|
|
410
|
-
}
|
|
411
|
-
function useExclusion(hookError) {
|
|
412
|
-
return SuiteContext.useX(hookError).exclusion;
|
|
413
|
-
}
|
|
414
|
-
function useInclusion() {
|
|
415
|
-
return SuiteContext.useX().inclusion;
|
|
416
|
-
}
|
|
417
|
-
function useMode() {
|
|
418
|
-
return SuiteContext.useX().mode();
|
|
419
|
-
}
|
|
420
|
-
function useSkipped() {
|
|
421
|
-
var _a;
|
|
422
|
-
return (_a = SuiteContext.useX().skipped) !== null && _a !== void 0 ? _a : false;
|
|
423
|
-
}
|
|
424
|
-
function useOmitted() {
|
|
425
|
-
var _a;
|
|
426
|
-
return (_a = SuiteContext.useX().omitted) !== null && _a !== void 0 ? _a : false;
|
|
427
|
-
}
|
|
428
|
-
const testMemoCache = vestUtils.cache(10);
|
|
429
|
-
function useTestMemoCache() {
|
|
430
|
-
return SuiteContext.useX().testMemoCache;
|
|
431
189
|
}
|
|
432
190
|
|
|
433
191
|
var _a, _b;
|
|
@@ -450,6 +208,25 @@ class SuiteSummary extends SummaryBase {
|
|
|
450
208
|
}
|
|
451
209
|
_a = Severity.ERRORS, _b = Severity.WARNINGS;
|
|
452
210
|
|
|
211
|
+
class SummaryFailure {
|
|
212
|
+
constructor(fieldName, message, groupName) {
|
|
213
|
+
this.fieldName = fieldName;
|
|
214
|
+
this.message = message;
|
|
215
|
+
this.groupName = groupName;
|
|
216
|
+
}
|
|
217
|
+
static fromTestObject(testObject) {
|
|
218
|
+
return new SummaryFailure(testObject.fieldName, testObject.message, testObject.groupName);
|
|
219
|
+
}
|
|
220
|
+
toString() {
|
|
221
|
+
return this.message || '';
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const nonMatchingGroupName = vestUtils.bindNot(matchingGroupName);
|
|
226
|
+
function matchingGroupName(testObject, groupName) {
|
|
227
|
+
return testObject.groupName === groupName;
|
|
228
|
+
}
|
|
229
|
+
|
|
453
230
|
function useShouldAddValidProperty(fieldName) {
|
|
454
231
|
// Is the field optional, and the optional condition is applied
|
|
455
232
|
if (useIsOptionalFiedApplied(fieldName)) {
|
|
@@ -486,7 +263,10 @@ function useShouldAddValidPropertyInGroup(groupName, fieldName) {
|
|
|
486
263
|
// Does the given field have any pending tests that are not optional?
|
|
487
264
|
function useHasNonOptionalIncomplete(fieldName) {
|
|
488
265
|
return TestWalker.someIncompleteTests(testObject => {
|
|
489
|
-
|
|
266
|
+
if (nonMatchingFieldName(testObject, fieldName)) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
return !useIsOptionalFiedApplied(fieldName);
|
|
490
270
|
});
|
|
491
271
|
}
|
|
492
272
|
// Do the given group/field have any pending tests that are not optional?
|
|
@@ -495,15 +275,12 @@ function useHasNonOptionalIncompleteByGroup(groupName, fieldName) {
|
|
|
495
275
|
if (nonMatchingGroupName(testObject, groupName)) {
|
|
496
276
|
return false;
|
|
497
277
|
}
|
|
498
|
-
|
|
278
|
+
if (nonMatchingFieldName(testObject, fieldName)) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
return !useIsOptionalFiedApplied(fieldName);
|
|
499
282
|
});
|
|
500
283
|
}
|
|
501
|
-
function useIsTestObjectOptional(testObject, fieldName) {
|
|
502
|
-
if (nonMatchingFieldName(testObject, fieldName)) {
|
|
503
|
-
return false;
|
|
504
|
-
}
|
|
505
|
-
return useIsOptionalFiedApplied(fieldName);
|
|
506
|
-
}
|
|
507
284
|
// Did all of the tests for the provided field run/omit?
|
|
508
285
|
// This makes sure that the fields are not skipped or pending.
|
|
509
286
|
function useNoMissingTests(fieldName) {
|
|
@@ -533,16 +310,15 @@ function useNoMissingTestsLogic(testObject, fieldName) {
|
|
|
533
310
|
* or if it is marked as optional, even if the optional check did not apply yet -
|
|
534
311
|
* but the test did not reach its final state.
|
|
535
312
|
*/
|
|
536
|
-
return (
|
|
313
|
+
return (testObject.isOmitted() ||
|
|
537
314
|
testObject.isTested() ||
|
|
538
|
-
testObject
|
|
315
|
+
useOptionalTestAwaitsResolution(testObject));
|
|
539
316
|
}
|
|
540
317
|
function useOptionalTestAwaitsResolution(testObject) {
|
|
541
318
|
// Does the test belong to an optional field,
|
|
542
319
|
// and the test itself is still in an indeterminate state?
|
|
543
320
|
var _a;
|
|
544
|
-
return (((_a =
|
|
545
|
-
OptionalFieldTypes.Delayed && testObject.awaitsResolution());
|
|
321
|
+
return (((_a = vestRuntime.VestRuntime.useAvailableRoot()) === null || _a === void 0 ? void 0 : _a.getOptionalField(testObject.fieldName).type) === OptionalFieldTypes.AUTO && testObject.awaitsResolution());
|
|
546
322
|
}
|
|
547
323
|
|
|
548
324
|
function useProduceSuiteSummary() {
|
|
@@ -557,13 +333,12 @@ function useProduceSuiteSummary() {
|
|
|
557
333
|
return countFailures(summary);
|
|
558
334
|
}
|
|
559
335
|
function appendFailures(key, failures, testObject) {
|
|
336
|
+
if (testObject.isOmitted()) {
|
|
337
|
+
return failures;
|
|
338
|
+
}
|
|
560
339
|
const shouldAppend = key === Severity.WARNINGS ? testObject.isWarning() : testObject.isFailing();
|
|
561
340
|
if (shouldAppend) {
|
|
562
|
-
return failures.concat(
|
|
563
|
-
fieldName: testObject.fieldName,
|
|
564
|
-
groupName: testObject.groupName,
|
|
565
|
-
message: testObject.message,
|
|
566
|
-
});
|
|
341
|
+
return failures.concat(SummaryFailure.fromTestObject(testObject));
|
|
567
342
|
}
|
|
568
343
|
return failures;
|
|
569
344
|
}
|
|
@@ -663,6 +438,22 @@ function collectAll(testGroup, severityKey) {
|
|
|
663
438
|
return output;
|
|
664
439
|
}
|
|
665
440
|
|
|
441
|
+
function bindSuiteSelectors(get) {
|
|
442
|
+
return {
|
|
443
|
+
getError: (...args) => get().getError(...args),
|
|
444
|
+
getErrors: (...args) => get().getErrors(...args),
|
|
445
|
+
getErrorsByGroup: (...args) => get().getErrorsByGroup(...args),
|
|
446
|
+
getWarning: (...args) => get().getWarning(...args),
|
|
447
|
+
getWarnings: (...args) => get().getWarnings(...args),
|
|
448
|
+
getWarningsByGroup: (...args) => get().getWarningsByGroup(...args),
|
|
449
|
+
hasErrors: (...args) => get().hasErrors(...args),
|
|
450
|
+
hasErrorsByGroup: (...args) => get().hasErrorsByGroup(...args),
|
|
451
|
+
hasWarnings: (...args) => get().hasWarnings(...args),
|
|
452
|
+
hasWarningsByGroup: (...args) => get().hasWarningsByGroup(...args),
|
|
453
|
+
isValid: (...args) => get().isValid(...args),
|
|
454
|
+
isValidByGroup: (...args) => get().isValidByGroup(...args),
|
|
455
|
+
};
|
|
456
|
+
}
|
|
666
457
|
// eslint-disable-next-line max-lines-per-function, max-statements
|
|
667
458
|
function suiteSelectors(summary) {
|
|
668
459
|
const selectors = {
|
|
@@ -781,11 +572,15 @@ function getFailure(severity, summary, fieldName) {
|
|
|
781
572
|
}
|
|
782
573
|
|
|
783
574
|
function useCreateSuiteResult() {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
575
|
+
return useSuiteResultCache(() => {
|
|
576
|
+
// eslint-disable-next-line vest-internal/use-use
|
|
577
|
+
const summary = useProduceSuiteSummary();
|
|
578
|
+
// eslint-disable-next-line vest-internal/use-use
|
|
579
|
+
const suiteName = useSuiteName();
|
|
580
|
+
return Object.freeze(vestUtils.assign(summary, suiteSelectors(summary), {
|
|
581
|
+
suiteName,
|
|
582
|
+
}));
|
|
583
|
+
});
|
|
789
584
|
}
|
|
790
585
|
|
|
791
586
|
/**
|
|
@@ -799,7 +594,7 @@ function useCreateSuiteResult() {
|
|
|
799
594
|
*/
|
|
800
595
|
// @vx-allow use-use
|
|
801
596
|
function skipWhen(condition, callback) {
|
|
802
|
-
Isolate.create(() => {
|
|
597
|
+
vestRuntime.Isolate.create(() => {
|
|
803
598
|
SuiteContext.run({
|
|
804
599
|
skipped:
|
|
805
600
|
// Checking for nested conditional. If we're in a nested skipWhen,
|
|
@@ -881,8 +676,6 @@ function useIsExcluded(testObject) {
|
|
|
881
676
|
// If there is _ANY_ `only`ed test (and we already know this one isn't) return true
|
|
882
677
|
if (hasIncludedTests(keyTests)) {
|
|
883
678
|
// Check if inclusion rules for this field (`include` hook)
|
|
884
|
-
// TODO: Check if this may need to be moved outside of the condition.
|
|
885
|
-
// What if there are no included tests? This shouldn't run then?
|
|
886
679
|
return !vestUtils.optionalFunctionValue(inclusion[fieldName]);
|
|
887
680
|
}
|
|
888
681
|
// We're done here. This field is not excluded
|
|
@@ -959,7 +752,7 @@ function useHasIncludedGroups() {
|
|
|
959
752
|
*/
|
|
960
753
|
// @vx-allow use-use
|
|
961
754
|
function omitWhen(conditional, callback) {
|
|
962
|
-
Isolate.create(() => {
|
|
755
|
+
vestRuntime.Isolate.create(() => {
|
|
963
756
|
SuiteContext.run({
|
|
964
757
|
omitted: useWithinActiveOmitWhen() ||
|
|
965
758
|
vestUtils.optionalFunctionValue(conditional, vestUtils.optionalFunctionValue(useCreateSuiteResult)),
|
|
@@ -1003,49 +796,64 @@ function useForceSkipIfInSkipWhen(testNode) {
|
|
|
1003
796
|
return testNode;
|
|
1004
797
|
}
|
|
1005
798
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
if (vestUtils.isNullish(historyNode)) {
|
|
1013
|
-
return this.handleNoHistoryNode(currentNode);
|
|
1014
|
-
}
|
|
1015
|
-
if (!IsolateTest.is(historyNode)) {
|
|
1016
|
-
return currentNode;
|
|
1017
|
-
}
|
|
1018
|
-
const reconcilerOutput = this.pickNode(historyNode, currentNode);
|
|
1019
|
-
cancelOverriddenPendingTestOnTestReRun(reconcilerOutput, currentNode, historyNode);
|
|
1020
|
-
return reconcilerOutput;
|
|
799
|
+
// @vx-allow use-use
|
|
800
|
+
function IsolateTestReconciler(currentNode, historyNode) {
|
|
801
|
+
// Start by verifying params
|
|
802
|
+
if (!IsolateTest.is(currentNode)) {
|
|
803
|
+
// This is unreachable, since this function should only be called with IsolateTest nodes
|
|
804
|
+
return currentNode;
|
|
1021
805
|
}
|
|
1022
|
-
|
|
1023
|
-
return
|
|
806
|
+
if (vestUtils.isNullish(historyNode)) {
|
|
807
|
+
return handleNoHistoryNode(currentNode);
|
|
1024
808
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
809
|
+
if (!IsolateTest.is(historyNode)) {
|
|
810
|
+
return currentNode;
|
|
811
|
+
}
|
|
812
|
+
const reconcilerOutput = usePickNode(historyNode, currentNode);
|
|
813
|
+
cancelOverriddenPendingTestOnTestReRun(reconcilerOutput, currentNode, historyNode);
|
|
814
|
+
return reconcilerOutput;
|
|
815
|
+
}
|
|
816
|
+
// eslint-disable-next-line max-statements
|
|
817
|
+
function nodeReorderDetected(newNode, prevNode) {
|
|
818
|
+
return !!IsolateTest.is(prevNode) && !isSameProfileTest(prevNode, newNode);
|
|
819
|
+
}
|
|
820
|
+
function handleCollision(newNode, prevNode) {
|
|
821
|
+
if (newNode.usesKey()) {
|
|
822
|
+
return IsolateTest.cast(vestRuntime.Reconciler.handleIsolateNodeWithKey(newNode));
|
|
823
|
+
}
|
|
824
|
+
if (nodeReorderDetected(newNode, prevNode)) {
|
|
825
|
+
return onNodeReorder(newNode, prevNode);
|
|
1033
826
|
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
827
|
+
if (!IsolateTest.is(prevNode)) {
|
|
828
|
+
// I believe we cannot actually reach this point.
|
|
829
|
+
// Because it should already be handled by nodeReorderDetected.
|
|
1037
830
|
return newNode;
|
|
1038
831
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
832
|
+
// FIXME: May-13-2023
|
|
833
|
+
// This may not be the most ideal solution.
|
|
834
|
+
// In short: if the node was omitted in the previous run,
|
|
835
|
+
// we want to re-evaluate it. The reason is that we may incorrectly
|
|
836
|
+
// identify it is "optional" because it was omitted in the previous run.
|
|
837
|
+
// There may be a better way to handle this. Need to revisit this.
|
|
838
|
+
if (prevNode.isOmitted()) {
|
|
839
|
+
return newNode;
|
|
1042
840
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
841
|
+
return prevNode;
|
|
842
|
+
}
|
|
843
|
+
function onNodeReorder(newNode, prevNode) {
|
|
844
|
+
throwTestOrderError(newNode, prevNode);
|
|
845
|
+
vestRuntime.Reconciler.removeAllNextNodesInIsolate();
|
|
846
|
+
return newNode;
|
|
847
|
+
}
|
|
848
|
+
function usePickNode(historyNode, currentNode) {
|
|
849
|
+
const collisionResult = handleCollision(currentNode, historyNode);
|
|
850
|
+
return useVerifyTestRun(currentNode, collisionResult);
|
|
851
|
+
}
|
|
852
|
+
function handleNoHistoryNode(testNode) {
|
|
853
|
+
if (testNode.usesKey()) {
|
|
854
|
+
return IsolateTest.cast(vestRuntime.Reconciler.handleIsolateNodeWithKey(testNode));
|
|
1048
855
|
}
|
|
856
|
+
return testNode;
|
|
1049
857
|
}
|
|
1050
858
|
function cancelOverriddenPendingTestOnTestReRun(nextNode, currentNode, prevTestObject) {
|
|
1051
859
|
if (nextNode === currentNode && IsolateTest.is(currentNode)) {
|
|
@@ -1062,30 +870,6 @@ function throwTestOrderError(newNode, prevNode) {
|
|
|
1062
870
|
}));
|
|
1063
871
|
}
|
|
1064
872
|
|
|
1065
|
-
function StateMachine(machine) {
|
|
1066
|
-
let state = machine.initial;
|
|
1067
|
-
const api = { getState, transition };
|
|
1068
|
-
return api;
|
|
1069
|
-
function getState() {
|
|
1070
|
-
return state;
|
|
1071
|
-
}
|
|
1072
|
-
function transition(action, payload) {
|
|
1073
|
-
const transitionTo = machine.states[state][action];
|
|
1074
|
-
let target = transitionTo;
|
|
1075
|
-
if (Array.isArray(target)) {
|
|
1076
|
-
const [, conditional] = target;
|
|
1077
|
-
if (!conditional(payload)) {
|
|
1078
|
-
return;
|
|
1079
|
-
}
|
|
1080
|
-
target = target[0];
|
|
1081
|
-
}
|
|
1082
|
-
if (!target || target === state) {
|
|
1083
|
-
return;
|
|
1084
|
-
}
|
|
1085
|
-
state = target;
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
873
|
var TestStatus;
|
|
1090
874
|
(function (TestStatus) {
|
|
1091
875
|
TestStatus["UNTESTED"] = "UNTESTED";
|
|
@@ -1102,38 +886,27 @@ var TestAction;
|
|
|
1102
886
|
TestAction["RESET"] = "RESET";
|
|
1103
887
|
})(TestAction || (TestAction = {}));
|
|
1104
888
|
function createTestStateMachine() {
|
|
1105
|
-
return StateMachine(machine);
|
|
889
|
+
return vestUtils.StateMachine(machine);
|
|
1106
890
|
}
|
|
1107
891
|
/* eslint-disable sort-keys */
|
|
1108
892
|
const machine = {
|
|
1109
893
|
initial: TestStatus.UNTESTED,
|
|
1110
894
|
states: {
|
|
895
|
+
'*': {
|
|
896
|
+
[TestStatus.OMITTED]: TestStatus.OMITTED,
|
|
897
|
+
[TestAction.RESET]: TestStatus.UNTESTED,
|
|
898
|
+
},
|
|
1111
899
|
[TestStatus.UNTESTED]: {
|
|
1112
900
|
[TestStatus.CANCELED]: TestStatus.CANCELED,
|
|
1113
901
|
[TestStatus.FAILED]: TestStatus.FAILED,
|
|
1114
|
-
[TestStatus.OMITTED]: TestStatus.OMITTED,
|
|
1115
902
|
[TestStatus.PASSING]: TestStatus.PASSING,
|
|
1116
903
|
[TestStatus.PENDING]: TestStatus.PENDING,
|
|
1117
904
|
[TestStatus.SKIPPED]: TestStatus.SKIPPED,
|
|
1118
905
|
[TestStatus.WARNING]: TestStatus.WARNING,
|
|
1119
906
|
},
|
|
1120
|
-
[TestStatus.SKIPPED]: {
|
|
1121
|
-
[TestAction.RESET]: TestStatus.UNTESTED,
|
|
1122
|
-
},
|
|
1123
|
-
[TestStatus.FAILED]: {
|
|
1124
|
-
[TestAction.RESET]: TestStatus.UNTESTED,
|
|
1125
|
-
},
|
|
1126
|
-
[TestStatus.WARNING]: {
|
|
1127
|
-
[TestAction.RESET]: TestStatus.UNTESTED,
|
|
1128
|
-
},
|
|
1129
|
-
[TestStatus.PASSING]: {
|
|
1130
|
-
[TestAction.RESET]: TestStatus.UNTESTED,
|
|
1131
|
-
},
|
|
1132
907
|
[TestStatus.PENDING]: {
|
|
1133
|
-
[TestAction.RESET]: TestStatus.UNTESTED,
|
|
1134
908
|
[TestStatus.CANCELED]: TestStatus.CANCELED,
|
|
1135
909
|
[TestStatus.FAILED]: TestStatus.FAILED,
|
|
1136
|
-
[TestStatus.OMITTED]: TestStatus.OMITTED,
|
|
1137
910
|
[TestStatus.PASSING]: TestStatus.PASSING,
|
|
1138
911
|
[TestStatus.SKIPPED]: [
|
|
1139
912
|
TestStatus.SKIPPED,
|
|
@@ -1141,12 +914,12 @@ const machine = {
|
|
|
1141
914
|
],
|
|
1142
915
|
[TestStatus.WARNING]: TestStatus.WARNING,
|
|
1143
916
|
},
|
|
1144
|
-
[TestStatus.
|
|
1145
|
-
|
|
1146
|
-
},
|
|
1147
|
-
[TestStatus.
|
|
1148
|
-
|
|
1149
|
-
},
|
|
917
|
+
[TestStatus.SKIPPED]: {},
|
|
918
|
+
[TestStatus.FAILED]: {},
|
|
919
|
+
[TestStatus.WARNING]: {},
|
|
920
|
+
[TestStatus.PASSING]: {},
|
|
921
|
+
[TestStatus.CANCELED]: {},
|
|
922
|
+
[TestStatus.OMITTED]: {},
|
|
1150
923
|
},
|
|
1151
924
|
};
|
|
1152
925
|
/* eslint-enable sort-keys */
|
|
@@ -1156,7 +929,7 @@ function shouldUseErrorAsMessage(message, error) {
|
|
|
1156
929
|
return vestUtils.isUndefined(message) && vestUtils.isStringValue(error);
|
|
1157
930
|
}
|
|
1158
931
|
|
|
1159
|
-
class IsolateTest extends Isolate {
|
|
932
|
+
class IsolateTest extends vestRuntime.Isolate {
|
|
1160
933
|
constructor({ fieldName, testFn, message, groupName, key = null, }) {
|
|
1161
934
|
super();
|
|
1162
935
|
this.children = null;
|
|
@@ -1296,79 +1069,262 @@ class IsolateTest extends Isolate {
|
|
|
1296
1069
|
}
|
|
1297
1070
|
}
|
|
1298
1071
|
IsolateTest.reconciler = IsolateTestReconciler;
|
|
1299
|
-
var TestSeverity;
|
|
1300
|
-
(function (TestSeverity) {
|
|
1301
|
-
TestSeverity["Error"] = "error";
|
|
1302
|
-
TestSeverity["Warning"] = "warning";
|
|
1303
|
-
})(TestSeverity || (TestSeverity = {}));
|
|
1304
1072
|
|
|
1305
1073
|
class TestWalker {
|
|
1306
1074
|
static defaultRoot() {
|
|
1307
|
-
return
|
|
1075
|
+
return vestRuntime.VestRuntime.useAvailableRoot();
|
|
1308
1076
|
}
|
|
1309
1077
|
static hasNoTests(root = TestWalker.defaultRoot()) {
|
|
1310
1078
|
if (!root)
|
|
1311
1079
|
return true;
|
|
1312
|
-
return !has(root, IsolateTest.is);
|
|
1080
|
+
return !vestRuntime.Walker.has(root, IsolateTest.is);
|
|
1081
|
+
}
|
|
1082
|
+
static someIncompleteTests(predicate, root = TestWalker.defaultRoot()) {
|
|
1083
|
+
if (!root)
|
|
1084
|
+
return false;
|
|
1085
|
+
return vestRuntime.Walker.some(root, isolate => {
|
|
1086
|
+
IsolateTest.isX(isolate);
|
|
1087
|
+
return isolate.isPending() && predicate(isolate);
|
|
1088
|
+
}, IsolateTest.is);
|
|
1089
|
+
}
|
|
1090
|
+
static someTests(predicate, root = TestWalker.defaultRoot()) {
|
|
1091
|
+
if (!root)
|
|
1092
|
+
return false;
|
|
1093
|
+
return vestRuntime.Walker.some(root, isolate => {
|
|
1094
|
+
IsolateTest.isX(isolate);
|
|
1095
|
+
return predicate(isolate);
|
|
1096
|
+
}, IsolateTest.is);
|
|
1097
|
+
}
|
|
1098
|
+
static everyTest(predicate, root = TestWalker.defaultRoot()) {
|
|
1099
|
+
if (!root)
|
|
1100
|
+
return false;
|
|
1101
|
+
return vestRuntime.Walker.every(root, isolate => {
|
|
1102
|
+
IsolateTest.isX(isolate);
|
|
1103
|
+
return predicate(isolate);
|
|
1104
|
+
}, IsolateTest.is);
|
|
1105
|
+
}
|
|
1106
|
+
static walkTests(callback, root = TestWalker.defaultRoot()) {
|
|
1107
|
+
if (!root)
|
|
1108
|
+
return;
|
|
1109
|
+
vestRuntime.Walker.walk(root, (isolate, breakout) => {
|
|
1110
|
+
callback(IsolateTest.cast(isolate), breakout);
|
|
1111
|
+
}, IsolateTest.is);
|
|
1112
|
+
}
|
|
1113
|
+
static hasRemainingTests(fieldName) {
|
|
1114
|
+
return TestWalker.someIncompleteTests(testObject => {
|
|
1115
|
+
if (fieldName) {
|
|
1116
|
+
return matchingFieldName(testObject, fieldName);
|
|
1117
|
+
}
|
|
1118
|
+
return true;
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
static pluckTests(predicate, root = TestWalker.defaultRoot()) {
|
|
1122
|
+
if (!root)
|
|
1123
|
+
return;
|
|
1124
|
+
vestRuntime.Walker.pluck(root, isolate => {
|
|
1125
|
+
IsolateTest.isX(isolate);
|
|
1126
|
+
return predicate(isolate);
|
|
1127
|
+
}, IsolateTest.is);
|
|
1128
|
+
}
|
|
1129
|
+
static resetField(fieldName) {
|
|
1130
|
+
TestWalker.walkTests(testObject => {
|
|
1131
|
+
if (matchingFieldName(testObject, fieldName)) {
|
|
1132
|
+
testObject.reset();
|
|
1133
|
+
}
|
|
1134
|
+
}, TestWalker.defaultRoot());
|
|
1135
|
+
}
|
|
1136
|
+
static removeTestByFieldName(fieldName, root = TestWalker.defaultRoot()) {
|
|
1137
|
+
TestWalker.pluckTests(testObject => {
|
|
1138
|
+
return matchingFieldName(testObject, fieldName);
|
|
1139
|
+
}, root);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* Checks that a given test object matches the currently specified severity level
|
|
1145
|
+
*/
|
|
1146
|
+
function nonMatchingSeverityProfile(severity, testObject) {
|
|
1147
|
+
return vestUtils.either(severity === Severity.WARNINGS, testObject.warns());
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* The difference between this file and hasFailures is that hasFailures uses the static
|
|
1152
|
+
* summary object, while this one uses the actual validation state
|
|
1153
|
+
*/
|
|
1154
|
+
function hasErrorsByTestObjects(fieldName) {
|
|
1155
|
+
return hasFailuresByTestObjects(Severity.ERRORS, fieldName);
|
|
1156
|
+
}
|
|
1157
|
+
function hasFailuresByTestObjects(severityKey, fieldName) {
|
|
1158
|
+
return TestWalker.someTests(testObject => {
|
|
1159
|
+
return hasFailuresByTestObject(testObject, severityKey, fieldName);
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
function hasGroupFailuresByTestObjects(severityKey, groupName, fieldName) {
|
|
1163
|
+
return TestWalker.someTests(testObject => {
|
|
1164
|
+
if (nonMatchingGroupName(testObject, groupName)) {
|
|
1165
|
+
return false;
|
|
1166
|
+
}
|
|
1167
|
+
return hasFailuresByTestObject(testObject, severityKey, fieldName);
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
/**
|
|
1171
|
+
* Determines whether a certain test profile has failures.
|
|
1172
|
+
*/
|
|
1173
|
+
function hasFailuresByTestObject(testObject, severityKey, fieldName) {
|
|
1174
|
+
if (!testObject.hasFailures()) {
|
|
1175
|
+
return false;
|
|
1176
|
+
}
|
|
1177
|
+
if (nonMatchingFieldName(testObject, fieldName)) {
|
|
1178
|
+
return false;
|
|
1179
|
+
}
|
|
1180
|
+
if (nonMatchingSeverityProfile(severityKey, testObject)) {
|
|
1181
|
+
return false;
|
|
1182
|
+
}
|
|
1183
|
+
return true;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
exports.Modes = void 0;
|
|
1187
|
+
(function (Modes) {
|
|
1188
|
+
Modes["EAGER"] = "EAGER";
|
|
1189
|
+
Modes["ALL"] = "ALL";
|
|
1190
|
+
Modes["ONE"] = "ONE";
|
|
1191
|
+
})(exports.Modes || (exports.Modes = {}));
|
|
1192
|
+
/**
|
|
1193
|
+
* Sets the current execution mode for the current suite.
|
|
1194
|
+
*
|
|
1195
|
+
* Supported modes:
|
|
1196
|
+
* - `EAGER` - (default) Runs all tests, but stops on first failure for each given field.
|
|
1197
|
+
* - `ALL` - Runs all tests, regardless of failures.
|
|
1198
|
+
* - `ONE` - Stops suite execution on first failure of any field.
|
|
1199
|
+
*
|
|
1200
|
+
* @example
|
|
1201
|
+
* ```js
|
|
1202
|
+
* import {Modes, create} from 'vest';
|
|
1203
|
+
*
|
|
1204
|
+
* const suite = create('suite_name', () => {
|
|
1205
|
+
* vest.mode(Modes.ALL);
|
|
1206
|
+
*
|
|
1207
|
+
* // ...
|
|
1208
|
+
* });
|
|
1209
|
+
* ```
|
|
1210
|
+
* @param 'ALL' | 'EAGER' | 'ONE' mode - The mode to set.
|
|
1211
|
+
*/
|
|
1212
|
+
// @vx-allow use-use
|
|
1213
|
+
function mode(mode) {
|
|
1214
|
+
const [, setMode] = useMode();
|
|
1215
|
+
setMode(mode);
|
|
1216
|
+
}
|
|
1217
|
+
function useIsMode(mode) {
|
|
1218
|
+
const [currentMode] = useMode();
|
|
1219
|
+
return currentMode === mode;
|
|
1220
|
+
}
|
|
1221
|
+
function useIsEager() {
|
|
1222
|
+
return useIsMode(exports.Modes.EAGER);
|
|
1223
|
+
}
|
|
1224
|
+
function useIsOne() {
|
|
1225
|
+
return useIsMode(exports.Modes.ONE);
|
|
1226
|
+
}
|
|
1227
|
+
function useShouldSkipBasedOnMode(testObject) {
|
|
1228
|
+
if (useIsOne()) {
|
|
1229
|
+
return hasErrorsByTestObjects();
|
|
1313
1230
|
}
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
return false;
|
|
1317
|
-
return some(root, isolate => {
|
|
1318
|
-
IsolateTest.isX(isolate);
|
|
1319
|
-
return isolate.isPending() && predicate(isolate);
|
|
1320
|
-
}, IsolateTest.is);
|
|
1231
|
+
if (useIsEager()) {
|
|
1232
|
+
return hasErrorsByTestObjects(testObject.fieldName);
|
|
1321
1233
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
}, IsolateTest.is);
|
|
1234
|
+
return false;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
const SuiteContext = context.createCascade((ctxRef, parentContext) => {
|
|
1238
|
+
if (parentContext) {
|
|
1239
|
+
return null;
|
|
1329
1240
|
}
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1241
|
+
return vestUtils.assign({
|
|
1242
|
+
exclusion: {
|
|
1243
|
+
tests: {},
|
|
1244
|
+
groups: {},
|
|
1245
|
+
},
|
|
1246
|
+
inclusion: {},
|
|
1247
|
+
mode: vestUtils.tinyState.createTinyState(exports.Modes.EAGER),
|
|
1248
|
+
testMemoCache,
|
|
1249
|
+
}, ctxRef);
|
|
1250
|
+
});
|
|
1251
|
+
function useCurrentTest(msg) {
|
|
1252
|
+
return SuiteContext.useX(msg).currentTest;
|
|
1253
|
+
}
|
|
1254
|
+
function useGroupName() {
|
|
1255
|
+
return SuiteContext.useX().groupName;
|
|
1256
|
+
}
|
|
1257
|
+
function useExclusion(hookError) {
|
|
1258
|
+
return SuiteContext.useX(hookError).exclusion;
|
|
1259
|
+
}
|
|
1260
|
+
function useInclusion() {
|
|
1261
|
+
return SuiteContext.useX().inclusion;
|
|
1262
|
+
}
|
|
1263
|
+
function useMode() {
|
|
1264
|
+
return SuiteContext.useX().mode();
|
|
1265
|
+
}
|
|
1266
|
+
function useSkipped() {
|
|
1267
|
+
var _a;
|
|
1268
|
+
return (_a = SuiteContext.useX().skipped) !== null && _a !== void 0 ? _a : false;
|
|
1269
|
+
}
|
|
1270
|
+
function useOmitted() {
|
|
1271
|
+
var _a;
|
|
1272
|
+
return (_a = SuiteContext.useX().omitted) !== null && _a !== void 0 ? _a : false;
|
|
1273
|
+
}
|
|
1274
|
+
const testMemoCache = vestUtils.cache(10);
|
|
1275
|
+
function useTestMemoCache() {
|
|
1276
|
+
return SuiteContext.useX().testMemoCache;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
/**
|
|
1280
|
+
* This module gets triggered once the suite is done running its sync tests.
|
|
1281
|
+
*
|
|
1282
|
+
* It goes over all the tests in the state, and checks if they need to be omitted.
|
|
1283
|
+
*/
|
|
1284
|
+
function useOmitOptionalFields() {
|
|
1285
|
+
const root = vestRuntime.VestRuntime.useAvailableRoot();
|
|
1286
|
+
const emit = vestRuntime.VestRuntime.useEmit();
|
|
1287
|
+
const optionalFields = root === null || root === void 0 ? void 0 : root.getOptionalFields();
|
|
1288
|
+
// If there are no optional fields, we don't need to do anything
|
|
1289
|
+
if (vestUtils.isEmpty(optionalFields)) {
|
|
1290
|
+
return;
|
|
1337
1291
|
}
|
|
1338
|
-
|
|
1339
|
-
|
|
1292
|
+
// Create an object to store the fields that need to be omitted
|
|
1293
|
+
const shouldOmit = new Set();
|
|
1294
|
+
// iterate over each of the tests in the state
|
|
1295
|
+
TestWalker.walkTests(testObject => {
|
|
1296
|
+
if (testObject.isPending()) {
|
|
1340
1297
|
return;
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
}
|
|
1298
|
+
}
|
|
1299
|
+
// If we already added the current field (not this test specifically)
|
|
1300
|
+
// no need for further checks, go and omit the test
|
|
1301
|
+
if (vestUtils.hasOwnProperty(shouldOmit, testObject.fieldName)) {
|
|
1302
|
+
verifyAndOmit(testObject);
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
// check if the field has an optional function
|
|
1306
|
+
// if so, run it and verify/omit the test
|
|
1307
|
+
runOptionalConfig(testObject);
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
emit(Events.DONE_TEST_OMISSION_PASS);
|
|
1311
|
+
function verifyAndOmit(testObject) {
|
|
1312
|
+
if (shouldOmit.has(testObject.fieldName)) {
|
|
1313
|
+
testObject.omit();
|
|
1314
|
+
root === null || root === void 0 ? void 0 : root.setOptionalField(testObject.fieldName, current => (Object.assign(Object.assign({}, current), { applied: true })));
|
|
1315
|
+
}
|
|
1352
1316
|
}
|
|
1353
|
-
|
|
1354
|
-
|
|
1317
|
+
function runOptionalConfig(testObject) {
|
|
1318
|
+
// Ge the optional configuration for the given field
|
|
1319
|
+
const optionalConfig = root === null || root === void 0 ? void 0 : root.getOptionalField(testObject.fieldName);
|
|
1320
|
+
if (vestUtils.isNullish(optionalConfig)) {
|
|
1355
1321
|
return;
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
TestWalker.walkTests(testObject => {
|
|
1363
|
-
if (matchingFieldName(testObject, fieldName)) {
|
|
1364
|
-
testObject.reset();
|
|
1365
|
-
}
|
|
1366
|
-
}, TestWalker.defaultRoot());
|
|
1367
|
-
}
|
|
1368
|
-
static removeTestByFieldName(fieldName, root = TestWalker.defaultRoot()) {
|
|
1369
|
-
TestWalker.pluckTests(testObject => {
|
|
1370
|
-
return matchingFieldName(testObject, fieldName);
|
|
1371
|
-
}, root);
|
|
1322
|
+
}
|
|
1323
|
+
// If the optional was set to a function or a boolean, run it and verify/omit the test
|
|
1324
|
+
if (vestUtils.optionalFunctionValue(optionalConfig.rule) === true) {
|
|
1325
|
+
shouldOmit.add(testObject.fieldName);
|
|
1326
|
+
}
|
|
1327
|
+
verifyAndOmit(testObject);
|
|
1372
1328
|
}
|
|
1373
1329
|
}
|
|
1374
1330
|
|
|
@@ -1391,8 +1347,9 @@ function useRunDoneCallbacks() {
|
|
|
1391
1347
|
vestUtils.callEach(doneCallbacks);
|
|
1392
1348
|
}
|
|
1393
1349
|
|
|
1350
|
+
// eslint-disable-next-line max-statements
|
|
1394
1351
|
function useInitVestBus() {
|
|
1395
|
-
const VestBus =
|
|
1352
|
+
const VestBus = vestRuntime.VestRuntime.useBus();
|
|
1396
1353
|
// Report a the completion of a test. There may be other tests with the same
|
|
1397
1354
|
// name that are still running, or not yet started.
|
|
1398
1355
|
on(Events.TEST_COMPLETED, (testObject) => {
|
|
@@ -1408,8 +1365,18 @@ function useInitVestBus() {
|
|
|
1408
1365
|
on(Events.TEST_RUN_STARTED, () => {
|
|
1409
1366
|
/* Let's just invalidate the suite cache for now */
|
|
1410
1367
|
});
|
|
1368
|
+
on(Events.DONE_TEST_OMISSION_PASS, () => {
|
|
1369
|
+
/* We NEED to refresh the cache here. Don't ask */
|
|
1370
|
+
});
|
|
1411
1371
|
// Called when all the tests, including async, are done running
|
|
1412
1372
|
on(Events.ALL_RUNNING_TESTS_FINISHED, () => {
|
|
1373
|
+
// Small optimization. We don't need to run this if there are no async tests
|
|
1374
|
+
// The reason is that we run this function immediately after the suite callback
|
|
1375
|
+
// is run, so if the suite is only comprised of sync tests, we don't need to
|
|
1376
|
+
// run this function twice since we know for a fact the state is up to date
|
|
1377
|
+
if (TestWalker.someTests(test => test.isAsyncTest())) {
|
|
1378
|
+
useOmitOptionalFields();
|
|
1379
|
+
}
|
|
1413
1380
|
useRunDoneCallbacks();
|
|
1414
1381
|
});
|
|
1415
1382
|
on(Events.RESET_FIELD, (fieldName) => {
|
|
@@ -1418,6 +1385,9 @@ function useInitVestBus() {
|
|
|
1418
1385
|
on(Events.SUITE_RUN_STARTED, () => {
|
|
1419
1386
|
useResetCallbacks();
|
|
1420
1387
|
});
|
|
1388
|
+
on(Events.SUITE_CALLBACK_RUN_FINISHED, () => {
|
|
1389
|
+
useOmitOptionalFields();
|
|
1390
|
+
});
|
|
1421
1391
|
on(Events.REMOVE_FIELD, (fieldName) => {
|
|
1422
1392
|
TestWalker.removeTestByFieldName(fieldName);
|
|
1423
1393
|
});
|
|
@@ -1435,202 +1405,24 @@ function useInitVestBus() {
|
|
|
1435
1405
|
}
|
|
1436
1406
|
}
|
|
1437
1407
|
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
doneCallbacks: vestUtils.tinyState.createTinyState(() => []),
|
|
1457
|
-
fieldCallbacks: vestUtils.tinyState.createTinyState(() => ({})),
|
|
1458
|
-
historyRoot: vestUtils.tinyState.createTinyState(null),
|
|
1459
|
-
suiteId: vestUtils.seq(),
|
|
1460
|
-
suiteName,
|
|
1461
|
-
suiteResultCache,
|
|
1462
|
-
};
|
|
1463
|
-
return stateRef;
|
|
1464
|
-
}
|
|
1465
|
-
function persist(cb) {
|
|
1466
|
-
const prev = PersistedContext.useX();
|
|
1467
|
-
return function persisted(...args) {
|
|
1468
|
-
var _a;
|
|
1469
|
-
const ctxToUse = (_a = PersistedContext.use()) !== null && _a !== void 0 ? _a : prev;
|
|
1470
|
-
return PersistedContext.run(ctxToUse, () => cb(...args));
|
|
1471
|
-
};
|
|
1472
|
-
}
|
|
1473
|
-
function useSuiteResultCache(action) {
|
|
1474
|
-
const suiteResultCache = useX().suiteResultCache;
|
|
1475
|
-
return suiteResultCache([useSuiteId()], action);
|
|
1476
|
-
}
|
|
1477
|
-
function useExpireSuiteResultCache() {
|
|
1478
|
-
const suiteResultCache = useX().suiteResultCache;
|
|
1479
|
-
suiteResultCache.invalidate([useSuiteId()]);
|
|
1480
|
-
}
|
|
1481
|
-
function useResetCallbacks() {
|
|
1482
|
-
const [, , resetDoneCallbacks] = useDoneCallbacks();
|
|
1483
|
-
const [, , resetFieldCallbacks] = useFieldCallbacks();
|
|
1484
|
-
resetDoneCallbacks();
|
|
1485
|
-
resetFieldCallbacks();
|
|
1486
|
-
}
|
|
1487
|
-
function useResetSuite() {
|
|
1488
|
-
useResetCallbacks();
|
|
1489
|
-
const [, , resetHistoryRoot] = useHistoryRoot();
|
|
1490
|
-
resetHistoryRoot();
|
|
1491
|
-
}
|
|
1492
|
-
function useX() {
|
|
1493
|
-
return PersistedContext.useX();
|
|
1494
|
-
}
|
|
1495
|
-
function useVestBus() {
|
|
1496
|
-
return useX().VestBus;
|
|
1497
|
-
}
|
|
1498
|
-
/*
|
|
1499
|
-
Returns an emitter, but it also has a shortcut for emitting an event immediately
|
|
1500
|
-
by passing an event name.
|
|
1501
|
-
*/
|
|
1502
|
-
function useEmit() {
|
|
1503
|
-
return persist(useVestBus().emit);
|
|
1504
|
-
}
|
|
1505
|
-
function usePrepareEmitter(event) {
|
|
1506
|
-
const emit = useEmit();
|
|
1507
|
-
return (arg) => emit(event, arg);
|
|
1508
|
-
}
|
|
1509
|
-
function useDoneCallbacks() {
|
|
1510
|
-
return useX().doneCallbacks();
|
|
1511
|
-
}
|
|
1512
|
-
function useFieldCallbacks() {
|
|
1513
|
-
return useX().fieldCallbacks();
|
|
1514
|
-
}
|
|
1515
|
-
function useHistoryRoot() {
|
|
1516
|
-
return useX().historyRoot();
|
|
1517
|
-
}
|
|
1518
|
-
function useHistoryNode() {
|
|
1519
|
-
return useX().historyNode;
|
|
1520
|
-
}
|
|
1521
|
-
function useSuiteName() {
|
|
1522
|
-
return useX().suiteName;
|
|
1523
|
-
}
|
|
1524
|
-
function useSuiteId() {
|
|
1525
|
-
return useX().suiteId;
|
|
1526
|
-
}
|
|
1527
|
-
function useSetHistory(history) {
|
|
1528
|
-
const context = PersistedContext.useX();
|
|
1529
|
-
const [, setHistoryRoot] = context.historyRoot();
|
|
1530
|
-
setHistoryRoot(history);
|
|
1531
|
-
}
|
|
1532
|
-
function useHistoryKey(key) {
|
|
1533
|
-
var _a;
|
|
1534
|
-
if (vestUtils.isNullish(key)) {
|
|
1535
|
-
return null;
|
|
1536
|
-
}
|
|
1537
|
-
const historyNode = useX().historyNode;
|
|
1538
|
-
return (_a = historyNode === null || historyNode === void 0 ? void 0 : historyNode.keys[key]) !== null && _a !== void 0 ? _a : null;
|
|
1539
|
-
}
|
|
1540
|
-
function useIsolate() {
|
|
1541
|
-
var _a;
|
|
1542
|
-
return (_a = useX().runtimeNode) !== null && _a !== void 0 ? _a : null;
|
|
1543
|
-
}
|
|
1544
|
-
function useCurrentCursor() {
|
|
1545
|
-
var _a, _b;
|
|
1546
|
-
return (_b = (_a = useIsolate()) === null || _a === void 0 ? void 0 : _a.cursor()) !== null && _b !== void 0 ? _b : 0;
|
|
1547
|
-
}
|
|
1548
|
-
function useRuntimeRoot() {
|
|
1549
|
-
return useX().runtimeRoot;
|
|
1550
|
-
}
|
|
1551
|
-
function useSetNextIsolateChild(child) {
|
|
1552
|
-
const currentIsolate = useIsolate();
|
|
1553
|
-
vestUtils.invariant(currentIsolate, ErrorStrings.NO_ACTIVE_ISOLATE);
|
|
1554
|
-
currentIsolate.addChild(child);
|
|
1555
|
-
}
|
|
1556
|
-
function useSetIsolateKey(key, value) {
|
|
1557
|
-
if (!key) {
|
|
1558
|
-
return;
|
|
1559
|
-
}
|
|
1560
|
-
const currentIsolate = useIsolate();
|
|
1561
|
-
vestUtils.invariant(currentIsolate, ErrorStrings.NO_ACTIVE_ISOLATE);
|
|
1562
|
-
if (vestUtils.isNullish(currentIsolate.keys[key])) {
|
|
1563
|
-
currentIsolate.keys[key] = value;
|
|
1564
|
-
return;
|
|
1565
|
-
}
|
|
1566
|
-
vestUtils.deferThrow(vestUtils.text(ErrorStrings.ENCOUNTERED_THE_SAME_KEY_TWICE, { key }));
|
|
1567
|
-
}
|
|
1568
|
-
function useAvailableSuiteRoot() {
|
|
1569
|
-
const root = useRuntimeRoot();
|
|
1570
|
-
if (root) {
|
|
1571
|
-
return root;
|
|
1572
|
-
}
|
|
1573
|
-
const [historyRoot] = useHistoryRoot();
|
|
1574
|
-
return historyRoot;
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
|
-
// @vx-allow use-use
|
|
1578
|
-
function optional(optionals) {
|
|
1579
|
-
const suiteRoot = useRuntimeRoot();
|
|
1580
|
-
// There are two types of optional field declarations:
|
|
1581
|
-
// 1. Delayed: A string, which is the name of the field to be optional.
|
|
1582
|
-
// We will only determine whether to omit the test after the suite is done running
|
|
1583
|
-
//
|
|
1584
|
-
// 2. Immediate: Either a boolean or a function, which is used to determine
|
|
1585
|
-
// if the field should be optional.
|
|
1586
|
-
// Delayed case (field name)
|
|
1587
|
-
if (vestUtils.isArray(optionals) || vestUtils.isStringValue(optionals)) {
|
|
1588
|
-
vestUtils.asArray(optionals).forEach(optionalField => {
|
|
1589
|
-
suiteRoot.setOptionalField(optionalField, () => ({
|
|
1590
|
-
type: OptionalFieldTypes.Delayed,
|
|
1591
|
-
applied: false,
|
|
1592
|
-
rule: null,
|
|
1593
|
-
}));
|
|
1594
|
-
});
|
|
1595
|
-
}
|
|
1596
|
-
else {
|
|
1597
|
-
// Immediately case (function or boolean)
|
|
1598
|
-
for (const field in optionals) {
|
|
1599
|
-
const value = optionals[field];
|
|
1600
|
-
suiteRoot.setOptionalField(field, () => ({
|
|
1601
|
-
type: OptionalFieldTypes.Immediate,
|
|
1602
|
-
rule: value,
|
|
1603
|
-
applied: vestUtils.optionalFunctionValue(value),
|
|
1604
|
-
}));
|
|
1605
|
-
}
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
function useIsOptionalFiedApplied(fieldName) {
|
|
1609
|
-
var _a, _b, _c;
|
|
1610
|
-
if (!fieldName) {
|
|
1611
|
-
return false;
|
|
1612
|
-
}
|
|
1613
|
-
return (_c = (_b = (_a = useAvailableSuiteRoot()) === null || _a === void 0 ? void 0 : _a.getOptionalField(fieldName)) === null || _b === void 0 ? void 0 : _b.applied) !== null && _c !== void 0 ? _c : false;
|
|
1614
|
-
}
|
|
1615
|
-
|
|
1616
|
-
class IsolateSuite extends Isolate {
|
|
1617
|
-
constructor() {
|
|
1618
|
-
super(...arguments);
|
|
1619
|
-
this.optional = {};
|
|
1620
|
-
}
|
|
1621
|
-
setOptionalField(fieldName, setter) {
|
|
1622
|
-
const current = this.optional;
|
|
1623
|
-
const currentField = current[fieldName];
|
|
1624
|
-
Object.assign(current, {
|
|
1625
|
-
[fieldName]: Object.assign({}, currentField, setter(currentField)),
|
|
1626
|
-
});
|
|
1627
|
-
}
|
|
1628
|
-
getOptionalField(fieldName) {
|
|
1629
|
-
var _a;
|
|
1630
|
-
return (_a = this.optional[fieldName]) !== null && _a !== void 0 ? _a : {};
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1408
|
+
/**
|
|
1409
|
+
* Conditionally includes a field for testing, based on specified criteria.
|
|
1410
|
+
*
|
|
1411
|
+
* @param {string} fieldName - The name of the field to include for testing.
|
|
1412
|
+
*
|
|
1413
|
+
* @example
|
|
1414
|
+
* include('confirm').when('password');
|
|
1415
|
+
* // Includes the "confirm" field for testing when the "password" field is included
|
|
1416
|
+
*
|
|
1417
|
+
* include('confirm').when(someValue);
|
|
1418
|
+
* // Includes the "confirm" field for testing when the value of `someValue` is true
|
|
1419
|
+
*
|
|
1420
|
+
* include('confirm').when(() => someValue);
|
|
1421
|
+
* // Includes the "confirm" field for testing when the callback function returns true
|
|
1422
|
+
*
|
|
1423
|
+
* include('username').when(result => result.hasErrors('username'));
|
|
1424
|
+
* // Includes the "username" field for testing when there are errors associated with it in the current suite result
|
|
1425
|
+
*/
|
|
1634
1426
|
// @vx-allow use-use
|
|
1635
1427
|
function include(fieldName) {
|
|
1636
1428
|
const inclusion = useInclusion();
|
|
@@ -1638,6 +1430,9 @@ function include(fieldName) {
|
|
|
1638
1430
|
vestUtils.invariant(vestUtils.isStringValue(fieldName));
|
|
1639
1431
|
inclusion[fieldName] = vestUtils.defaultTo(exclusion.tests[fieldName], true);
|
|
1640
1432
|
return { when };
|
|
1433
|
+
/**
|
|
1434
|
+
* Specifies the inclusion criteria for the field in `include` function.
|
|
1435
|
+
*/
|
|
1641
1436
|
function when(condition) {
|
|
1642
1437
|
const inclusion = useInclusion();
|
|
1643
1438
|
const exclusion = useExclusion();
|
|
@@ -1657,18 +1452,16 @@ function include(fieldName) {
|
|
|
1657
1452
|
}
|
|
1658
1453
|
}
|
|
1659
1454
|
|
|
1660
|
-
|
|
1455
|
+
// eslint-disable-next-line max-statements
|
|
1456
|
+
function useAttemptRunTest(testObject) {
|
|
1661
1457
|
useVerifyTestRun(testObject);
|
|
1662
|
-
if (testObject.isNonActionable()) {
|
|
1663
|
-
// TODO: Need to test that this works as expected
|
|
1664
|
-
return;
|
|
1665
|
-
}
|
|
1666
1458
|
if (testObject.isUntested()) {
|
|
1667
|
-
useRunTest(testObject);
|
|
1459
|
+
return useRunTest(testObject);
|
|
1668
1460
|
}
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1461
|
+
if (!testObject.isNonActionable()) {
|
|
1462
|
+
vestUtils.deferThrow(vestUtils.text(ErrorStrings.UNEXPECTED_TEST_REGISTRATION_ERROR, {
|
|
1463
|
+
testObject: JSON.stringify(testObject),
|
|
1464
|
+
}));
|
|
1672
1465
|
}
|
|
1673
1466
|
}
|
|
1674
1467
|
function runSyncTest(testObject) {
|
|
@@ -1678,7 +1471,7 @@ function runSyncTest(testObject) {
|
|
|
1678
1471
|
* runs test, if async - adds to pending array
|
|
1679
1472
|
*/
|
|
1680
1473
|
function useRunTest(testObject) {
|
|
1681
|
-
const VestBus =
|
|
1474
|
+
const VestBus = vestRuntime.VestRuntime.useBus();
|
|
1682
1475
|
// Run test callback.
|
|
1683
1476
|
// If a promise is returned, set as async and
|
|
1684
1477
|
// Move to pending list.
|
|
@@ -1688,7 +1481,6 @@ function useRunTest(testObject) {
|
|
|
1688
1481
|
// in case object is an enforce chain
|
|
1689
1482
|
if (vestUtils.isPromise(result)) {
|
|
1690
1483
|
testObject.asyncTest = result;
|
|
1691
|
-
testObject.setPending();
|
|
1692
1484
|
useRunAsyncTest(testObject);
|
|
1693
1485
|
}
|
|
1694
1486
|
else {
|
|
@@ -1709,11 +1501,12 @@ function useRunAsyncTest(testObject) {
|
|
|
1709
1501
|
const { asyncTest, message } = testObject;
|
|
1710
1502
|
if (!vestUtils.isPromise(asyncTest))
|
|
1711
1503
|
return;
|
|
1712
|
-
|
|
1713
|
-
const
|
|
1504
|
+
testObject.setPending();
|
|
1505
|
+
const VestBus = vestRuntime.VestRuntime.useBus();
|
|
1506
|
+
const done = vestRuntime.VestRuntime.persist(() => {
|
|
1714
1507
|
onTestCompleted(VestBus, testObject);
|
|
1715
1508
|
});
|
|
1716
|
-
const fail = persist((rejectionMessage) => {
|
|
1509
|
+
const fail = vestRuntime.VestRuntime.persist((rejectionMessage) => {
|
|
1717
1510
|
if (testObject.isCanceled()) {
|
|
1718
1511
|
return;
|
|
1719
1512
|
}
|
|
@@ -1737,7 +1530,11 @@ function wrapTestMemo(test) {
|
|
|
1737
1530
|
function memo(fieldName, ...args) {
|
|
1738
1531
|
const [deps, testFn, msg] = args.reverse();
|
|
1739
1532
|
// Implicit dependency for better specificity
|
|
1740
|
-
const dependencies = [
|
|
1533
|
+
const dependencies = [
|
|
1534
|
+
useSuiteId(),
|
|
1535
|
+
fieldName,
|
|
1536
|
+
vestRuntime.VestRuntime.useCurrentCursor(),
|
|
1537
|
+
].concat(deps);
|
|
1741
1538
|
return useGetTestFromCache(dependencies, cacheAction);
|
|
1742
1539
|
function cacheAction() {
|
|
1743
1540
|
return test(fieldName, msg, testFn);
|
|
@@ -1767,11 +1564,11 @@ function vestTest(fieldName, ...args) {
|
|
|
1767
1564
|
const [message, testFn, key] = (vestUtils.isFunction(args[1]) ? args : [undefined, ...args]);
|
|
1768
1565
|
validateTestParams(fieldName, testFn);
|
|
1769
1566
|
const groupName = useGroupName();
|
|
1770
|
-
const emit = useEmit();
|
|
1567
|
+
const emit = vestRuntime.VestRuntime.useEmit();
|
|
1771
1568
|
const testObjectInput = { fieldName, groupName, key, message, testFn };
|
|
1772
1569
|
// This invalidates the suite cache.
|
|
1773
1570
|
emit(Events.TEST_RUN_STARTED);
|
|
1774
|
-
return IsolateTest.create(
|
|
1571
|
+
return IsolateTest.create(useAttemptRunTest, testObjectInput);
|
|
1775
1572
|
}
|
|
1776
1573
|
const test = vestUtils.assign(vestTest, {
|
|
1777
1574
|
memo: wrapTestMemo(vestTest),
|
|
@@ -1826,9 +1623,9 @@ function shouldSkipDoneRegistration(callback, fieldName, output) {
|
|
|
1826
1623
|
}
|
|
1827
1624
|
|
|
1828
1625
|
function useSuiteRunResult() {
|
|
1829
|
-
return vestUtils.assign({
|
|
1830
|
-
done: persist(done),
|
|
1831
|
-
});
|
|
1626
|
+
return Object.freeze(vestUtils.assign({
|
|
1627
|
+
done: vestRuntime.VestRuntime.persist(done),
|
|
1628
|
+
}, useCreateSuiteResult()));
|
|
1832
1629
|
}
|
|
1833
1630
|
/**
|
|
1834
1631
|
* Registers done callbacks.
|
|
@@ -1864,29 +1661,32 @@ function createSuite(...args) {
|
|
|
1864
1661
|
function suite(...args) {
|
|
1865
1662
|
return SuiteContext.run({}, () => {
|
|
1866
1663
|
// eslint-disable-next-line vest-internal/use-use
|
|
1867
|
-
const emit = useEmit();
|
|
1664
|
+
const emit = vestRuntime.VestRuntime.useEmit();
|
|
1868
1665
|
emit(Events.SUITE_RUN_STARTED);
|
|
1869
1666
|
return IsolateSuite.create(useRunSuiteCallback(suiteCallback, ...args));
|
|
1870
1667
|
}).output;
|
|
1871
1668
|
}
|
|
1872
1669
|
// Assign methods to the suite
|
|
1873
|
-
// We do this within the
|
|
1670
|
+
// We do this within the VestRuntime so that the suite methods
|
|
1874
1671
|
// will be bound to the suite's stateRef and be able to access it.
|
|
1875
|
-
return
|
|
1672
|
+
return vestRuntime.VestRuntime.Run(stateRef, () => {
|
|
1673
|
+
useInitVestBus();
|
|
1876
1674
|
return vestUtils.assign(
|
|
1877
1675
|
// We're also binding the suite to the stateRef, so that the suite
|
|
1878
1676
|
// can access the stateRef when it's called.
|
|
1879
|
-
|
|
1677
|
+
vestRuntime.VestRuntime.persist(suite), Object.assign(Object.assign({ get: vestRuntime.VestRuntime.persist(useCreateSuiteResult), remove: vestRuntime.VestRuntime.usePrepareEmitter(Events.REMOVE_FIELD), reset: vestRuntime.VestRuntime.usePrepareEmitter(Events.RESET_SUITE), resetField: vestRuntime.VestRuntime.usePrepareEmitter(Events.RESET_FIELD) }, bindSuiteSelectors(vestRuntime.VestRuntime.persist(useCreateSuiteResult))), getTypedMethods()));
|
|
1880
1678
|
});
|
|
1881
1679
|
}
|
|
1882
1680
|
function useRunSuiteCallback(suiteCallback, ...args) {
|
|
1681
|
+
const emit = vestRuntime.VestRuntime.useEmit();
|
|
1883
1682
|
return () => {
|
|
1884
1683
|
suiteCallback(...args);
|
|
1684
|
+
emit(Events.SUITE_CALLBACK_RUN_FINISHED);
|
|
1885
1685
|
return useSuiteRunResult();
|
|
1886
1686
|
};
|
|
1887
1687
|
}
|
|
1888
1688
|
|
|
1889
|
-
class IsolateEach extends Isolate {
|
|
1689
|
+
class IsolateEach extends vestRuntime.Isolate {
|
|
1890
1690
|
constructor() {
|
|
1891
1691
|
super(...arguments);
|
|
1892
1692
|
this.allowReorder = true;
|
|
@@ -1916,18 +1716,50 @@ function each(list, callback) {
|
|
|
1916
1716
|
}
|
|
1917
1717
|
|
|
1918
1718
|
function group(groupName, callback) {
|
|
1919
|
-
return Isolate.create(() => {
|
|
1719
|
+
return vestRuntime.Isolate.create(() => {
|
|
1920
1720
|
SuiteContext.run({ groupName }, callback);
|
|
1921
1721
|
});
|
|
1922
1722
|
}
|
|
1923
1723
|
|
|
1724
|
+
/**
|
|
1725
|
+
* Creates a static suite for server-side validation.
|
|
1726
|
+
*
|
|
1727
|
+
* @param {Function} validationFn - The validation function that defines the suite's tests.
|
|
1728
|
+
* @returns {Function} - A function that runs the validations defined in the suite.
|
|
1729
|
+
*
|
|
1730
|
+
* @example
|
|
1731
|
+
* import { staticSuite, test, enforce } from 'vest';
|
|
1732
|
+
*
|
|
1733
|
+
* const suite = staticSuite(data => {
|
|
1734
|
+
* test('username', 'username is required', () => {
|
|
1735
|
+
* enforce(data.username).isNotEmpty();
|
|
1736
|
+
* });
|
|
1737
|
+
* });
|
|
1738
|
+
*
|
|
1739
|
+
* suite(data);
|
|
1740
|
+
*/
|
|
1924
1741
|
function staticSuite(suiteCallback) {
|
|
1925
1742
|
return vestUtils.assign((...args) => createSuite(suiteCallback)(...args), Object.assign({}, getTypedMethods()));
|
|
1926
1743
|
}
|
|
1927
1744
|
|
|
1928
1745
|
const ERROR_OUTSIDE_OF_TEST = ErrorStrings.WARN_MUST_BE_CALLED_FROM_TEST;
|
|
1929
1746
|
/**
|
|
1930
|
-
* Sets a
|
|
1747
|
+
* Sets the severity level of a test to `warn`, allowing it to fail without marking the suite as invalid.
|
|
1748
|
+
* Use this function within the body of a test to create warn-only tests.
|
|
1749
|
+
*
|
|
1750
|
+
* @returns {void}
|
|
1751
|
+
*
|
|
1752
|
+
* @example
|
|
1753
|
+
* test('password', 'Your password strength is: WEAK', () => {
|
|
1754
|
+
* warn();
|
|
1755
|
+
*
|
|
1756
|
+
* enforce(data.password).matches(/0-9/);
|
|
1757
|
+
* });
|
|
1758
|
+
*
|
|
1759
|
+
* @limitations
|
|
1760
|
+
* - The `warn` function should only be used within the body of a `test` function.
|
|
1761
|
+
* - When using `warn()` in an async test, it should be called in the synchronous portion of the test, not after an `await` call or in the Promise body.
|
|
1762
|
+
* - It is recommended to call `warn()` at the top of the test function.
|
|
1931
1763
|
*/
|
|
1932
1764
|
// @vx-allow use-use
|
|
1933
1765
|
function warn() {
|