risei 3.3.1 → 3.3.2
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/README.md +11 -4
- package/package.json +6 -2
- package/system/PropertySpoofer.js +1 -1
- package/system/SpoofDef.js +6 -18
- package/system/TestDef.js +341 -387
- package/system/TestFinder.js +1 -1
- package/system/TestFrame.js +20 -9
- package/system/TestRunner.js +12 -36
- package/system/TestStages.js +69 -172
- package/system/TestSummary.js +6 -18
- package/system/TestTargets.js +114 -0
- package/system/TotalComparer.js +0 -2
- package/system/TypeAnalyzer.js +0 -1
package/system/TestDef.js
CHANGED
|
@@ -13,481 +13,436 @@ import TotalDisplayer from "./TotalDisplayer.js";
|
|
|
13
13
|
export default class TestDef {
|
|
14
14
|
// region Definitions
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
static staticName = "static";
|
|
17
|
+
static instanceName = "instance";
|
|
18
|
+
static throwName = "throw";
|
|
19
|
+
static polyName = "poly";
|
|
20
|
+
static constructorName = "constructor";
|
|
21
|
+
static nonceLocalCallableName = "nonce";
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
// endregion Definitions
|
|
24
24
|
|
|
25
25
|
// region Static fields
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
27
|
+
static longsByShort = new Map([
|
|
28
|
+
[ "for", "nature" ],
|
|
29
|
+
[ "on", "type" ],
|
|
30
|
+
[ "with", "initors" ],
|
|
31
|
+
[ "of", "method" ],
|
|
32
|
+
[ "plus", "spoofed" ],
|
|
33
|
+
[ "in", "inputs" ],
|
|
34
|
+
[ "out", "output" ],
|
|
35
|
+
[ "from", "source" ],
|
|
36
|
+
[ "and", "factors" ],
|
|
37
|
+
[ "do", "enact" ],
|
|
38
|
+
[ "undo", "counteract" ]
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
// endregion Static fields
|
|
42
42
|
|
|
43
43
|
// region Fields
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
45
|
+
/* These longer names match the constructor-arg names.
|
|
46
|
+
The short-name properties use the same fields. */
|
|
47
|
+
|
|
48
|
+
nature;
|
|
49
|
+
type;
|
|
50
|
+
initors;
|
|
51
|
+
method;
|
|
52
|
+
spoofed;
|
|
53
|
+
inputs;
|
|
54
|
+
output;
|
|
55
|
+
source;
|
|
56
|
+
factors;
|
|
57
|
+
enact;
|
|
58
|
+
counteract;
|
|
59
|
+
|
|
60
|
+
target;
|
|
61
|
+
|
|
62
|
+
actual;
|
|
63
|
+
thrown; // Throw in inner scope (tested code).
|
|
64
|
+
trouble; // Throw in outer scope (test system or .do / .undo / .from).
|
|
65
|
+
|
|
66
|
+
// endregion Fields
|
|
67
67
|
|
|
68
68
|
// region Definition properties
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
/* These short names make JSON-like definitions easier. */
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
return this.nature;
|
|
74
|
-
}
|
|
72
|
+
get for() { return this.nature; }
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
this.nature = value;
|
|
78
|
-
}
|
|
74
|
+
set for(value) { this.nature = value; }
|
|
79
75
|
|
|
80
|
-
|
|
81
|
-
return this.type;
|
|
82
|
-
}
|
|
76
|
+
get on() { return this.type; }
|
|
83
77
|
|
|
84
|
-
|
|
85
|
-
this.type = value;
|
|
86
|
-
}
|
|
78
|
+
set on(value) { this.type = value; }
|
|
87
79
|
|
|
88
|
-
|
|
89
|
-
return this.initors;
|
|
90
|
-
}
|
|
80
|
+
get with() { return this.initors; }
|
|
91
81
|
|
|
92
|
-
|
|
93
|
-
this.initors = value;
|
|
94
|
-
}
|
|
82
|
+
set with(value) { this.initors = value; }
|
|
95
83
|
|
|
96
|
-
|
|
97
|
-
return this.method;
|
|
98
|
-
}
|
|
84
|
+
get of() { return this.method; }
|
|
99
85
|
|
|
100
|
-
|
|
101
|
-
this.method = value;
|
|
102
|
-
}
|
|
86
|
+
set of(value) { this.method = value; }
|
|
103
87
|
|
|
104
|
-
|
|
105
|
-
return this.spoofed;
|
|
106
|
-
}
|
|
88
|
+
get plus() { return this.spoofed; }
|
|
107
89
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
get in() {
|
|
113
|
-
return this.inputs;
|
|
114
|
-
}
|
|
90
|
+
set plus(value) { this.spoofed = value; }
|
|
91
|
+
|
|
92
|
+
get in() { return this.inputs; }
|
|
115
93
|
|
|
116
|
-
|
|
117
|
-
this.inputs = value;
|
|
118
|
-
}
|
|
94
|
+
set in(value) { this.inputs = value; }
|
|
119
95
|
|
|
120
|
-
|
|
121
|
-
return this.output;
|
|
122
|
-
}
|
|
96
|
+
get out() { return this.output; }
|
|
123
97
|
|
|
124
|
-
|
|
125
|
-
this.output = value;
|
|
126
|
-
}
|
|
98
|
+
set out(value) { this.output = value; }
|
|
127
99
|
|
|
128
|
-
|
|
129
|
-
return this.source;
|
|
130
|
-
}
|
|
100
|
+
get from() { return this.source; }
|
|
131
101
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return this.factors;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
set and(value) {
|
|
141
|
-
this.factors = value;
|
|
142
|
-
}
|
|
102
|
+
set from(value) { this.source = value; }
|
|
103
|
+
|
|
104
|
+
get and() { return this.factors; }
|
|
105
|
+
|
|
106
|
+
set and(value) { this.factors = value; }
|
|
143
107
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
get undo() {
|
|
153
|
-
return this.counteract;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
set undo(value) {
|
|
157
|
-
this.counteract = value;
|
|
158
|
-
}
|
|
108
|
+
get do() { return this.enact; }
|
|
109
|
+
|
|
110
|
+
set do(value) { this.enact = value; }
|
|
111
|
+
|
|
112
|
+
get undo() { return this.counteract; }
|
|
113
|
+
|
|
114
|
+
set undo(value) { this.counteract = value; }
|
|
159
115
|
|
|
160
|
-
|
|
116
|
+
// endregion Definition properties
|
|
161
117
|
|
|
162
118
|
// region State properties
|
|
163
119
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
120
|
+
get isRunnable() /* passed */ {
|
|
121
|
+
let isRunnable
|
|
122
|
+
= this.nature !== undefined
|
|
123
|
+
&& this.type !== undefined
|
|
124
|
+
&& this.initors !== undefined
|
|
125
|
+
&& this.method !== undefined
|
|
126
|
+
&& this.inputs !== undefined
|
|
127
|
+
&& this.output !== undefined;
|
|
172
128
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
get isInstanceTest() /* passed */ {
|
|
177
|
-
return this.#isNamedTypeTest(
|
|
178
|
-
TestDef.instanceName,
|
|
179
|
-
TestDef.staticName,
|
|
180
|
-
TypeAnalyzer.isInstanceMember
|
|
181
|
-
);
|
|
182
|
-
}
|
|
129
|
+
return isRunnable;
|
|
130
|
+
}
|
|
183
131
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
132
|
+
get isInstanceTest() /* passed */ {
|
|
133
|
+
return this.#isNamedTypeTest(
|
|
134
|
+
TestDef.instanceName,
|
|
135
|
+
TestDef.staticName,
|
|
136
|
+
TypeAnalyzer.isInstanceMember
|
|
137
|
+
);
|
|
138
|
+
}
|
|
191
139
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
140
|
+
get isStaticTest() /* passed */ {
|
|
141
|
+
return this.#isNamedTypeTest(
|
|
142
|
+
TestDef.staticName,
|
|
143
|
+
TestDef.instanceName,
|
|
144
|
+
TypeAnalyzer.isStaticMember
|
|
145
|
+
);
|
|
146
|
+
}
|
|
196
147
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
148
|
+
get isThrowTest() /* passed */ {
|
|
149
|
+
let is = this.andStringContains(TestDef.throwName);
|
|
150
|
+
return is;
|
|
151
|
+
}
|
|
200
152
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
153
|
+
get isMonoCallTest() /* passed */ {
|
|
154
|
+
return !this.isPolyCallTest;
|
|
155
|
+
}
|
|
205
156
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
157
|
+
get isPolyCallTest() /* passed */ {
|
|
158
|
+
let is = this.andStringContains(TestDef.polyName);
|
|
159
|
+
return is;
|
|
160
|
+
}
|
|
210
161
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
162
|
+
get isConstructorTest() /* passed */ {
|
|
163
|
+
let plainTarget = NameAnalyzer.plainNameOf(this.of);
|
|
164
|
+
return plainTarget === TestDef.constructorName;
|
|
165
|
+
}
|
|
214
166
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
let isPropertyTest
|
|
219
|
-
= NameAnalyzer.hasPropertySigil(this.of)
|
|
220
|
-
|| TypeAnalyzer.isPropertyMember(this.on, plainName);
|
|
221
|
-
|
|
222
|
-
return isPropertyTest;
|
|
223
|
-
}
|
|
167
|
+
get isMethodTest() /* passed */ {
|
|
168
|
+
return !this.isPropertyTest && !this.isConstructorTest;
|
|
169
|
+
}
|
|
224
170
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
else if (this.isConstructorTest) {
|
|
235
|
-
type = this.isMonoCallTest ? CallTypes.conMono : CallTypes.conPoly;
|
|
171
|
+
get isPropertyTest() /* passed */ {
|
|
172
|
+
let plainName = NameAnalyzer.plainNameOf(this.of);
|
|
173
|
+
|
|
174
|
+
let isPropertyTest
|
|
175
|
+
= NameAnalyzer.hasPropertySigil(this.of)
|
|
176
|
+
|| TypeAnalyzer.isPropertyMember(this.on, plainName);
|
|
177
|
+
|
|
178
|
+
return isPropertyTest;
|
|
236
179
|
}
|
|
237
180
|
|
|
238
|
-
|
|
239
|
-
|
|
181
|
+
get callType() /* passed */ {
|
|
182
|
+
let type;
|
|
183
|
+
|
|
184
|
+
if (this.isMethodTest) {
|
|
185
|
+
type = this.isMonoCallTest ? CallTypes.methodMono : CallTypes.methodPoly;
|
|
186
|
+
}
|
|
187
|
+
else if (this.isPropertyTest) {
|
|
188
|
+
type = this.isMonoCallTest ? CallTypes.propMono : CallTypes.propPoly;
|
|
189
|
+
}
|
|
190
|
+
else if (this.isConstructorTest) {
|
|
191
|
+
type = this.isMonoCallTest ? CallTypes.conMono : CallTypes.conPoly;
|
|
192
|
+
}
|
|
240
193
|
|
|
241
|
-
|
|
242
|
-
// Falsy code elements never are a retrieval.
|
|
243
|
-
if (!this.from) {
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// If a (non-falsy) string, must be a retrieval.
|
|
248
|
-
if (typeof this.from === "string") {
|
|
249
|
-
return true;
|
|
194
|
+
return type;
|
|
250
195
|
}
|
|
251
|
-
|
|
252
|
-
// If a function, is a retrieval.
|
|
253
|
-
if (this.from instanceof Function) {
|
|
254
|
-
return true;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Anything else is not a retrieval.
|
|
258
|
-
return false;
|
|
259
|
-
}
|
|
260
196
|
|
|
261
|
-
|
|
262
|
-
|
|
197
|
+
get isRetrievalTest() /* passed */ {
|
|
198
|
+
// Falsy code elements never are a retrieval.
|
|
199
|
+
if (!this.from) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// If a (non-falsy) string, must be a retrieval.
|
|
204
|
+
if (typeof this.from === "string") {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// If a function, is a retrieval.
|
|
209
|
+
if (this.from instanceof Function) {
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Anything else is not a retrieval.
|
|
263
214
|
return false;
|
|
264
215
|
}
|
|
265
216
|
|
|
266
|
-
|
|
267
|
-
|
|
217
|
+
get doesHaveDoEarly() /* passed */ {
|
|
218
|
+
if (this.do === undefined) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return TypeIdentifier.identify(this.do.early) === Types.isFunction;
|
|
223
|
+
}
|
|
268
224
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
225
|
+
get doesHaveDoLate() /* passed */ {
|
|
226
|
+
if (this.do === undefined) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return TypeIdentifier.identify(this.do.late) === Types.isFunction;
|
|
272
231
|
}
|
|
273
232
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
get doesHaveUndo() /* passed */ {
|
|
278
|
-
return TypeIdentifier.identify(this.undo) === Types.isFunction;
|
|
279
|
-
}
|
|
233
|
+
get doesHaveUndo() /* passed */ {
|
|
234
|
+
return TypeIdentifier.identify(this.undo) === Types.isFunction;
|
|
235
|
+
}
|
|
280
236
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
237
|
+
/* Used for grouping in output by method or
|
|
238
|
+
prop name, with type sigil only once. */
|
|
239
|
+
get runName() /* passed */ {
|
|
240
|
+
let plain = NameAnalyzer.plainNameOf(this.of);
|
|
285
241
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
242
|
+
if (!this.isPropertyTest) {
|
|
243
|
+
return `${ plain }()`;
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
return `.${ plain }`;
|
|
247
|
+
}
|
|
291
248
|
}
|
|
292
|
-
}
|
|
293
249
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
250
|
+
get anyUnsoughtThrow() /* passed */ {
|
|
251
|
+
// Prop is true when throw is sought.
|
|
252
|
+
if (this.isThrowTest) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
299
255
|
|
|
300
|
-
|
|
301
|
-
|
|
256
|
+
return this.thrown;
|
|
257
|
+
}
|
|
302
258
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
259
|
+
get doesHaveUnsoughtThrow() /* passed */ {
|
|
260
|
+
return this.anyUnsoughtThrow !== undefined;
|
|
261
|
+
}
|
|
306
262
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
263
|
+
get doesHaveTrouble() /* passed */ {
|
|
264
|
+
return this.trouble !== undefined;
|
|
265
|
+
}
|
|
310
266
|
|
|
311
|
-
|
|
267
|
+
// endregion State properties
|
|
312
268
|
|
|
313
269
|
// region State methods
|
|
314
270
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
// Analysis of what the type probably is.
|
|
323
|
-
let plainName = NameAnalyzer.plainNameOf(this.of);
|
|
324
|
-
let is = analyzer(this.on, plainName);
|
|
271
|
+
/* Dependency of .isInstanceTest and .isStaticTest. */
|
|
272
|
+
#isNamedTypeTest(type, antiType, analyzer) /* verified */ {
|
|
273
|
+
// If stated to be the opposite type, not this type.
|
|
274
|
+
if (this.andStringContains(antiType)) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
325
277
|
|
|
326
|
-
|
|
327
|
-
|
|
278
|
+
// Analysis of what the type probably is.
|
|
279
|
+
let plainName = NameAnalyzer.plainNameOf(this.of);
|
|
280
|
+
let is = analyzer(this.on, plainName);
|
|
328
281
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}
|
|
282
|
+
// If states to be this type, then this type.
|
|
283
|
+
let stated = this.andStringContains(type);
|
|
332
284
|
|
|
285
|
+
// Whichever may apply.
|
|
286
|
+
return is || stated;
|
|
287
|
+
}
|
|
333
288
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
289
|
+
/* Needed externally, and dependency
|
|
290
|
+
of all .and-based properties. */
|
|
291
|
+
andStringContains(keyword) /* passed */ {
|
|
292
|
+
let doesContain
|
|
293
|
+
= typeof this.and === "string"
|
|
294
|
+
&& this.and.includes(keyword);
|
|
340
295
|
|
|
341
|
-
|
|
342
|
-
|
|
296
|
+
return doesContain;
|
|
297
|
+
}
|
|
343
298
|
|
|
344
|
-
|
|
299
|
+
// endregion State methods
|
|
345
300
|
|
|
346
301
|
// region Initing, including constructor()
|
|
347
302
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
static fromNonceTuples(nonces) /* passed */ {
|
|
364
|
-
// Throughput and output.
|
|
365
|
-
let full = new TestDef();
|
|
366
|
-
let defs = [];
|
|
367
|
-
|
|
368
|
-
// Looping over all.
|
|
369
|
-
for (let nonce of nonces) {
|
|
370
|
-
// No possible test definition to output.
|
|
371
|
-
if (!TestDef.isANonce(nonce)) {
|
|
372
|
-
continue;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// Get latest test definition.
|
|
376
|
-
let latest = TestDef.fromNonceTuple(nonce);
|
|
377
|
-
|
|
378
|
-
// Restarting test definitions when desired.
|
|
379
|
-
full = TestDef.maybeRestartFull(full, latest);
|
|
380
|
-
|
|
381
|
-
// Merge any previous
|
|
382
|
-
// values into latest.
|
|
383
|
-
TestDef.combine(latest, full);
|
|
384
|
-
|
|
385
|
-
// Make latest the tuple for
|
|
386
|
-
// combining with next time.
|
|
387
|
-
full = latest;
|
|
303
|
+
/* Long names used, since some short names, like `for`, are parsed as keywords. */
|
|
304
|
+
constructor(nature, type, spoofed, initors, method, inputs, output, source, factors, enact, counteract) /* ok */ {
|
|
305
|
+
this.nature = nature; // .for
|
|
306
|
+
this.type = type; // .on
|
|
307
|
+
this.spoofed = spoofed; // .plus
|
|
308
|
+
this.initors = initors; // .with
|
|
309
|
+
this.method = method; // .of
|
|
310
|
+
this.inputs = inputs; // .in
|
|
311
|
+
this.output = output; // .out
|
|
312
|
+
this.source = source; // .from
|
|
313
|
+
this.factors = factors; // .and
|
|
314
|
+
this.enact = enact; // .do
|
|
315
|
+
this.counteract = counteract; // .undo
|
|
316
|
+
}
|
|
388
317
|
|
|
389
|
-
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
|
|
318
|
+
static fromNonceTuples(nonces) /* passed */ {
|
|
319
|
+
// Throughput and output.
|
|
320
|
+
let full = new TestDef();
|
|
321
|
+
let defs = [];
|
|
322
|
+
|
|
323
|
+
// Looping over all.
|
|
324
|
+
for (let nonce of nonces) {
|
|
325
|
+
// No possible test definition to output.
|
|
326
|
+
if (!TestDef.isANonce(nonce)) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Get latest test definition.
|
|
331
|
+
let latest = TestDef.fromNonceTuple(nonce);
|
|
332
|
+
|
|
333
|
+
// Restarting test definitions when desired.
|
|
334
|
+
full = TestDef.maybeRestartFull(full, latest);
|
|
335
|
+
|
|
336
|
+
// Merge any previous
|
|
337
|
+
// values into latest.
|
|
338
|
+
TestDef.combine(latest, full);
|
|
339
|
+
|
|
340
|
+
// Make latest the tuple for
|
|
341
|
+
// combining with next time.
|
|
342
|
+
full = latest;
|
|
343
|
+
|
|
344
|
+
// Changes to the current def, rather than
|
|
345
|
+
// a new one, should not result in a new def.
|
|
346
|
+
if (TestDef.isChangeOnlyNonce(nonce)) {
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Add latest, if it's ready to run as a test.
|
|
351
|
+
if (latest.isRunnable) {
|
|
352
|
+
defs.push(latest);
|
|
353
|
+
}
|
|
393
354
|
}
|
|
394
355
|
|
|
395
|
-
//
|
|
396
|
-
|
|
397
|
-
defs.push(latest);
|
|
398
|
-
}
|
|
356
|
+
// Back to caller.
|
|
357
|
+
return defs;
|
|
399
358
|
}
|
|
400
359
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
360
|
+
/* Transfers properties in 'nonce' to a new TestDef
|
|
361
|
+
if they match by either (first) short or long name.
|
|
362
|
+
Unmatched props remain undefined on the TestDef. */
|
|
363
|
+
static fromNonceTuple(nonce) /* passed */ {
|
|
364
|
+
// Empty, since properties can be set
|
|
365
|
+
// by either of two nonce naming styles.
|
|
366
|
+
let def = new TestDef();
|
|
367
|
+
|
|
368
|
+
let shortNames = TestDef.longsByShort.keys();
|
|
369
|
+
|
|
370
|
+
// Traversing matching pairs of names and applying
|
|
371
|
+
// whichever one is present as the tuple property;
|
|
372
|
+
// if neither is present, the property is undefined.
|
|
373
|
+
for (let shortName of shortNames) {
|
|
374
|
+
let longName = TestDef.longsByShort.get(shortName);
|
|
375
|
+
def[shortName] = shortName in nonce ? nonce[shortName] : nonce[longName];
|
|
376
|
+
}
|
|
404
377
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
Unmatched props remain undefined on the TestDef. */
|
|
408
|
-
static fromNonceTuple(nonce) /* passed */ {
|
|
409
|
-
// Empty, since properties can be set
|
|
410
|
-
// by either of two nonce naming styles.
|
|
411
|
-
let def = new TestDef();
|
|
412
|
-
|
|
413
|
-
let shortNames = TestDef.longsByShort.keys();
|
|
414
|
-
|
|
415
|
-
// Traversing matching pairs of names and applying
|
|
416
|
-
// whichever one is present as the tuple property;
|
|
417
|
-
// if neither is present, the property is undefined.
|
|
418
|
-
for (let shortName of shortNames) {
|
|
419
|
-
let longName = TestDef.longsByShort.get(shortName);
|
|
420
|
-
def[shortName] = shortName in nonce ? nonce[shortName] : nonce[longName];
|
|
378
|
+
// Back to caller.
|
|
379
|
+
return def;
|
|
421
380
|
}
|
|
422
381
|
|
|
423
|
-
//
|
|
424
|
-
return def;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// region Dependencies of nonce-tuple initing methods
|
|
428
|
-
|
|
429
|
-
static isANonce(topic) /* passed */ {
|
|
430
|
-
let type = TypeIdentifier.identify(topic);
|
|
431
|
-
return type === Types.isObject;
|
|
432
|
-
}
|
|
382
|
+
// region Dependencies of nonce-tuple initing methods
|
|
433
383
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
// When a (new) model class is named,
|
|
439
|
-
// wipe out all reused test values.
|
|
440
|
-
if (latest.type !== undefined) {
|
|
441
|
-
full = new TestDef();
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// When a (new) model method is named, wipe out reused
|
|
445
|
-
// test values except the general ones for its class
|
|
446
|
-
// and .nature, needed for collapsing forward.
|
|
447
|
-
if (latest.method !== undefined) {
|
|
448
|
-
full = TestDef.classOnlyDefFrom(full);
|
|
449
|
-
}
|
|
384
|
+
static isANonce(topic) /* passed */ {
|
|
385
|
+
let type = TypeIdentifier.identify(topic);
|
|
386
|
+
return type === Types.isObject;
|
|
387
|
+
}
|
|
450
388
|
|
|
451
|
-
|
|
452
|
-
|
|
389
|
+
/* Replaces some or all of the 'full' that gathers test
|
|
390
|
+
props for reuse when targeting changes significantly
|
|
391
|
+
in the middle of the collapsing-forward process. */
|
|
392
|
+
static maybeRestartFull(full, latest) /* passed */ {
|
|
393
|
+
// When a (new) model class is named,
|
|
394
|
+
// wipe out all reused test values.
|
|
395
|
+
if (latest.type !== undefined) {
|
|
396
|
+
full = new TestDef();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// When a (new) model method is named, wipe out reused
|
|
400
|
+
// test values except the general ones for its class
|
|
401
|
+
// and .nature, needed for collapsing forward.
|
|
402
|
+
if (latest.method !== undefined) {
|
|
403
|
+
full = TestDef.classOnlyDefFrom(full);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return full;
|
|
407
|
+
}
|
|
453
408
|
|
|
454
|
-
|
|
455
|
-
|
|
409
|
+
static classOnlyDefFrom(original) /* passed */ {
|
|
410
|
+
let output = new TestDef();
|
|
456
411
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
412
|
+
output.type = original.type;
|
|
413
|
+
output.initors = original.initors;
|
|
414
|
+
output.spoofed = original.spoofed;
|
|
460
415
|
|
|
461
|
-
|
|
462
|
-
|
|
416
|
+
return output;
|
|
417
|
+
}
|
|
463
418
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
419
|
+
/* Replaces properties of the 'self'
|
|
420
|
+
TestDef with any from 'other'. */
|
|
421
|
+
static combine(self, other) /* passed */ {
|
|
422
|
+
let shortNames = TestDef.longsByShort.keys();
|
|
468
423
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
424
|
+
// Collapse properties forward.
|
|
425
|
+
for (let shortName of shortNames) {
|
|
426
|
+
TestDef.combineValues(self, other, shortName);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
474
429
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
430
|
+
static isChangeOnlyNonce(nonce) /* passed */ {
|
|
431
|
+
return nonce.just !== undefined || nonce.only !== undefined;
|
|
432
|
+
}
|
|
478
433
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
434
|
+
/* Replaces the named property of 'self', if
|
|
435
|
+
missing, with any new property of 'other'. */
|
|
436
|
+
static combineValues(self, other, name) /* passed */ {
|
|
437
|
+
// Property may still end up undefined.
|
|
438
|
+
if (self[name] === undefined) {
|
|
439
|
+
self[name] = other[name];
|
|
440
|
+
}
|
|
441
|
+
}
|
|
487
442
|
|
|
488
|
-
|
|
443
|
+
// endregion Dependencies of nonce-tuple initing methods
|
|
489
444
|
|
|
490
|
-
|
|
445
|
+
// endregion Initing, including constructor()
|
|
491
446
|
|
|
492
447
|
toString() /* verified */ {
|
|
493
448
|
let displayer = new TotalDisplayer();
|
|
@@ -506,5 +461,4 @@ export default class TestDef {
|
|
|
506
461
|
|
|
507
462
|
return text;
|
|
508
463
|
}
|
|
509
|
-
|
|
510
464
|
}
|