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