-
-
Notifications
You must be signed in to change notification settings - Fork 85
/
produceSuiteRunResult.ts
102 lines (84 loc) · 2.52 KB
/
produceSuiteRunResult.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import assign from 'assign';
import createCache from 'cache';
import { isEmpty } from 'isEmpty';
import isFunction from 'isFunction';
import ctx from 'ctx';
import hasRemainingTests from 'hasRemainingTests';
import { produceSuiteResult, SuiteResult } from 'produceSuiteResult';
import { useStateRef, useTestCallbacks, useTestsFlat } from 'stateHooks';
const cache = createCache(20);
export function produceFullResult(): SuiteRunResult {
const testObjects = useTestsFlat();
const ctxRef = { stateRef: useStateRef() };
return cache(
[testObjects],
ctx.bind(ctxRef, () =>
assign({}, produceSuiteResult(), {
done: ctx.bind(ctxRef, done),
})
)
);
}
/**
* DONE is here and not in its own module to prevent circular dependency issues.
*/
function shouldSkipDoneRegistration(
callback: (res: SuiteResult) => void,
fieldName: string | undefined,
output: SuiteRunResult
): boolean {
// If we do not have any test runs for the current field
return !!(
!isFunction(callback) ||
(fieldName &&
(!output.tests[fieldName] || isEmpty(output.tests[fieldName].testCount)))
);
}
function shouldRunDoneCallback(fieldName?: string): boolean {
// is suite finished || field name exists, and test is finished;
return !!(
!hasRemainingTests() ||
(fieldName && !hasRemainingTests(fieldName))
);
}
/**
* Registers done callbacks.
* @register {Object} Vest output object.
*/
const done: Done = function done(...args): SuiteRunResult {
const [callback, fieldName] = args.reverse() as [
(res: SuiteResult) => void,
string
];
const output = produceFullResult();
if (shouldSkipDoneRegistration(callback, fieldName, output)) {
return output;
}
const doneCallback = () => callback(produceSuiteResult());
if (shouldRunDoneCallback(fieldName)) {
doneCallback();
return output;
}
deferDoneCallback(doneCallback, fieldName);
return output;
};
function deferDoneCallback(doneCallback: () => void, fieldName?: string): void {
const [, setTestCallbacks] = useTestCallbacks();
setTestCallbacks(current => {
if (fieldName) {
current.fieldCallbacks[fieldName] = (
current.fieldCallbacks[fieldName] || []
).concat(doneCallback);
} else {
current.doneCallbacks.push(doneCallback);
}
return current;
});
}
export type SuiteRunResult = SuiteResult & { done: Done };
interface Done {
(...args: [cb: (res: SuiteResult) => void]): SuiteRunResult;
(
...args: [fieldName: string, cb: (res: SuiteResult) => void]
): SuiteRunResult;
}