risei 1.2.0 → 1.3.0
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 +113 -46
- package/index.js +18 -5
- package/package.json +3 -4
- package/system/ASpoofingFixture.js +3 -3
- package/system/ATestFinder.js +13 -0
- package/system/Risei.js +82 -52
- package/system/SpoofClassMethodsFixture.js +5 -5
- package/system/{SpoofTuple.js → SpoofDefinition.js} +20 -20
- package/system/SpoofObjectMethodsFixture.js +3 -3
- package/system/{TestTuple.js → TestDefinition.js} +43 -28
- package/system/TestFinder.js +11 -5
- package/system/TestFrame.js +16 -108
- package/system/TestRunner.js +4 -4
- package/system/TestStages.js +5 -13
- package/system/TotalCopier.js +28 -4
|
@@ -4,7 +4,7 @@ import { TypeAnalyzer } from "./TypeAnalyzer.js";
|
|
|
4
4
|
|
|
5
5
|
/* Defines what is found in a spoof-definition tuple (SDT). Actual SDTs don't need to be instances of this class. */
|
|
6
6
|
|
|
7
|
-
export class
|
|
7
|
+
export class SpoofDefinition {
|
|
8
8
|
// region Static fields
|
|
9
9
|
|
|
10
10
|
/* Properties can have short or long names. */
|
|
@@ -15,7 +15,7 @@ export class SpoofTuple {
|
|
|
15
15
|
]);
|
|
16
16
|
|
|
17
17
|
/* Objects with either of these property names aren't
|
|
18
|
-
converted to
|
|
18
|
+
converted to SpoofDefinitions by from-nonce methods. */
|
|
19
19
|
static skipNames = [ "not", "skip" ];
|
|
20
20
|
|
|
21
21
|
// endregion Static fields
|
|
@@ -107,23 +107,23 @@ export class SpoofTuple {
|
|
|
107
107
|
|
|
108
108
|
static fromNonceTuples(nonces) {
|
|
109
109
|
// Throughput and output.
|
|
110
|
-
let full = new
|
|
110
|
+
let full = new SpoofDefinition();
|
|
111
111
|
let output = [];
|
|
112
112
|
|
|
113
113
|
// Looping over all.
|
|
114
114
|
for (let nonce of nonces) {
|
|
115
115
|
// Don't convert non-tuples, but output
|
|
116
116
|
// them unchanged for the caller.
|
|
117
|
-
if (
|
|
117
|
+
if (SpoofDefinition.isNotASpoof(nonce)) {
|
|
118
118
|
output.push(nonce);
|
|
119
119
|
continue;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
// Get latest spoof definition.
|
|
123
|
-
let latest =
|
|
123
|
+
let latest = SpoofDefinition.fromNonceTuple(nonce);
|
|
124
124
|
|
|
125
125
|
// Restarting spoof definitions when desired.
|
|
126
|
-
full =
|
|
126
|
+
full = SpoofDefinition.maybeRestartFull(full, latest);
|
|
127
127
|
|
|
128
128
|
// Merge any previous
|
|
129
129
|
// values into latest.
|
|
@@ -147,21 +147,21 @@ export class SpoofTuple {
|
|
|
147
147
|
/* Returns true if arg should not be used for spoofing.
|
|
148
148
|
See isSpoofable() for a contrasting condition. */
|
|
149
149
|
static isNotASpoof(nonce) /* passed */ {
|
|
150
|
-
/* Any nonce that is null or undefined is not a
|
|
150
|
+
/* Any nonce that is null or undefined is not a SpoofDefinition. */
|
|
151
151
|
if (nonce === undefined || nonce === null) {
|
|
152
152
|
return true;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
/* Any nonce with .not or .skip isn't a
|
|
156
|
-
for (let non of
|
|
155
|
+
/* Any nonce with .not or .skip isn't a SpoofDefinition, even if it has SpoofDefinition properties. */
|
|
156
|
+
for (let non of SpoofDefinition.skipNames) {
|
|
157
157
|
if (nonce[non] !== undefined) {
|
|
158
158
|
return true;
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
/* Any other nonce with any
|
|
163
|
-
for (let key of
|
|
164
|
-
let value =
|
|
162
|
+
/* Any other nonce with any SpoofDefinition properties is a full or partial SpoofDefinition. */
|
|
163
|
+
for (let key of SpoofDefinition.#longsByShort.keys()) {
|
|
164
|
+
let value = SpoofDefinition.#longsByShort.get(key);
|
|
165
165
|
|
|
166
166
|
if (nonce[key] !== undefined) {
|
|
167
167
|
return false;
|
|
@@ -172,7 +172,7 @@ export class SpoofTuple {
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
/* Any nonce without
|
|
175
|
+
/* Any nonce without SpoofDefinition properties is not a spoof. */
|
|
176
176
|
return true;
|
|
177
177
|
}
|
|
178
178
|
|
|
@@ -183,15 +183,15 @@ export class SpoofTuple {
|
|
|
183
183
|
static fromNonceTuple(nonce) /* passed */ {
|
|
184
184
|
// Empty, since properties can be set
|
|
185
185
|
// by either of two nonce naming styles.
|
|
186
|
-
let tuple = new
|
|
186
|
+
let tuple = new SpoofDefinition();
|
|
187
187
|
|
|
188
|
-
let shortNames =
|
|
188
|
+
let shortNames = SpoofDefinition.#longsByShort.keys();
|
|
189
189
|
|
|
190
190
|
// Traversing matching pairs of names and applying
|
|
191
191
|
// whichever one is present as the tuple property;
|
|
192
192
|
// if neither is present, the property is undefined.
|
|
193
193
|
for (let shortName of shortNames) {
|
|
194
|
-
let longName =
|
|
194
|
+
let longName = SpoofDefinition.#longsByShort.get(shortName);
|
|
195
195
|
tuple[shortName] = shortName in nonce ? nonce[shortName] : nonce[longName];
|
|
196
196
|
}
|
|
197
197
|
|
|
@@ -203,7 +203,7 @@ export class SpoofTuple {
|
|
|
203
203
|
|
|
204
204
|
static maybeRestartFull(full, latest) /* passed */ {
|
|
205
205
|
// When a (new) spoof target is named, return the new
|
|
206
|
-
//
|
|
206
|
+
// SpoofDefinition to wipe out all reused spoof values.
|
|
207
207
|
if (latest.target !== undefined) {
|
|
208
208
|
full = latest;
|
|
209
209
|
}
|
|
@@ -212,10 +212,10 @@ export class SpoofTuple {
|
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
combineWith(other) {
|
|
215
|
-
let shortNames =
|
|
215
|
+
let shortNames = SpoofDefinition.#longsByShort.keys();
|
|
216
216
|
|
|
217
217
|
for (let shortName of shortNames) {
|
|
218
|
-
|
|
218
|
+
SpoofDefinition.combineValues(this, other, shortName);
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
|
|
@@ -233,7 +233,7 @@ export class SpoofTuple {
|
|
|
233
233
|
// region Overrides and dependencies
|
|
234
234
|
|
|
235
235
|
toString() /* passed */ {
|
|
236
|
-
let text = `
|
|
236
|
+
let text = `SpoofDefinition:{ target:${ this.#asRawOrString(this.target) }, `
|
|
237
237
|
+ `method:${ this.#asRawOrString(this.method) }, `
|
|
238
238
|
+ `output:${ this.#asRawOrString(this.output) } }`;
|
|
239
239
|
return text;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* */
|
|
2
2
|
|
|
3
3
|
import { ASpoofingFixture } from "./ASpoofingFixture.js";
|
|
4
|
-
import {
|
|
4
|
+
import { SpoofDefinition } from "./SpoofDefinition.js";
|
|
5
5
|
|
|
6
6
|
export class SpoofObjectMethodsFixture extends ASpoofingFixture {
|
|
7
7
|
/* Algorithm: Forward method spoof() looks at a test's .with and .in, and replaces entire objects
|
|
@@ -31,12 +31,12 @@ export class SpoofObjectMethodsFixture extends ASpoofingFixture {
|
|
|
31
31
|
|
|
32
32
|
spoofTarget(target) {
|
|
33
33
|
// Non-spoof targets are returned unchanged.
|
|
34
|
-
if (
|
|
34
|
+
if (SpoofDefinition.isNotASpoof(target)) {
|
|
35
35
|
return target;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// Spoof definition targets are converted.
|
|
39
|
-
let tuple =
|
|
39
|
+
let tuple = SpoofDefinition.fromNonceTuple(target);
|
|
40
40
|
let ofAsPairs = this.#supplySpoofPairs(tuple);
|
|
41
41
|
|
|
42
42
|
// Returning object with one or more spoofed members.
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**/
|
|
2
2
|
|
|
3
3
|
import { TypeAnalyzer } from "./TypeAnalyzer.js";
|
|
4
|
+
import { TypeIdentifier } from "./TypeIdentifier.js";
|
|
5
|
+
import { Types } from "./Types.js";
|
|
6
|
+
import { TotalCopier } from "./TotalCopier.js";
|
|
4
7
|
|
|
5
8
|
/* Defines what is found in a test-definition tuple (TDT). Actual TDTs don't need to be instances of this class. */
|
|
6
9
|
|
|
7
|
-
export class
|
|
10
|
+
export class TestDefinition {
|
|
8
11
|
// region Definitions
|
|
9
12
|
|
|
10
13
|
static staticName = "static";
|
|
@@ -33,6 +36,10 @@ export class TestTuple {
|
|
|
33
36
|
[ "and", "factors" ]
|
|
34
37
|
]);
|
|
35
38
|
|
|
39
|
+
static #copier = new TotalCopier();
|
|
40
|
+
|
|
41
|
+
static #identifier = new TypeIdentifier();
|
|
42
|
+
|
|
36
43
|
// endregion Static fields
|
|
37
44
|
|
|
38
45
|
// region Private fields
|
|
@@ -57,12 +64,6 @@ export class TestTuple {
|
|
|
57
64
|
source;
|
|
58
65
|
factors;
|
|
59
66
|
|
|
60
|
-
/* &cruft, possibly drop defaults when properties settable in tests */
|
|
61
|
-
// These fields are not part of collapse-forward system:
|
|
62
|
-
// Local copies of args; local test targets; outcome fields.
|
|
63
|
-
localInitors = [ ];
|
|
64
|
-
localInputs = [ ];
|
|
65
|
-
|
|
66
67
|
localTarget;
|
|
67
68
|
localMethod;
|
|
68
69
|
|
|
@@ -179,12 +180,12 @@ export class TestTuple {
|
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
get isStaticTest() /* passed */ {
|
|
182
|
-
let does = this.andStringContains(
|
|
183
|
+
let does = this.andStringContains(TestDefinition.staticName);
|
|
183
184
|
return does;
|
|
184
185
|
}
|
|
185
186
|
|
|
186
187
|
get isThrowTest() /* passed */ {
|
|
187
|
-
let is = this.andStringContains(
|
|
188
|
+
let is = this.andStringContains(TestDefinition.throwName);
|
|
188
189
|
return is;
|
|
189
190
|
}
|
|
190
191
|
|
|
@@ -199,8 +200,8 @@ export class TestTuple {
|
|
|
199
200
|
}
|
|
200
201
|
|
|
201
202
|
get isConstructorTest() /* passed */ {
|
|
202
|
-
let plainTarget =
|
|
203
|
-
return plainTarget ===
|
|
203
|
+
let plainTarget = TestDefinition.plainNameOf(this.of);
|
|
204
|
+
return plainTarget === TestDefinition.constructorName;
|
|
204
205
|
}
|
|
205
206
|
|
|
206
207
|
get isMethodTest() /* passed */ {
|
|
@@ -208,11 +209,11 @@ export class TestTuple {
|
|
|
208
209
|
}
|
|
209
210
|
|
|
210
211
|
get isPropertyTest() /* passed */ {
|
|
211
|
-
let plainName =
|
|
212
|
+
let plainName = TestDefinition.plainNameOf(this.of);
|
|
212
213
|
|
|
213
214
|
let isPropertyTest
|
|
214
|
-
= this.of.startsWith(
|
|
215
|
-
|| this.of.endsWith(
|
|
215
|
+
= this.of.startsWith(TestDefinition.dotOperator)
|
|
216
|
+
|| this.of.endsWith(TestDefinition.colonOperator)
|
|
216
217
|
|| this.#typeAnalyzer.memberIsProperty(plainName);
|
|
217
218
|
|
|
218
219
|
return isPropertyTest;
|
|
@@ -261,18 +262,31 @@ export class TestTuple {
|
|
|
261
262
|
this.#typeAnalyzer = new TypeAnalyzer(this.type);
|
|
262
263
|
}
|
|
263
264
|
|
|
265
|
+
copy() {
|
|
266
|
+
// Empty initial copy.
|
|
267
|
+
let copy = new TestDefinition();
|
|
268
|
+
|
|
269
|
+
let names = TestDefinition.longsByShort.values();
|
|
270
|
+
|
|
271
|
+
for (let name of names) {
|
|
272
|
+
copy[name] = TestDefinition.#copier.copy(this[name]);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return copy;
|
|
276
|
+
}
|
|
277
|
+
|
|
264
278
|
static fromNonceTuples(nonces) {
|
|
265
279
|
// Throughput and output.
|
|
266
|
-
let full = new
|
|
280
|
+
let full = new TestDefinition();
|
|
267
281
|
let tuples = [];
|
|
268
282
|
|
|
269
283
|
// Looping over all.
|
|
270
284
|
for (let nonce of nonces) {
|
|
271
285
|
// Get latest test definition.
|
|
272
|
-
let latest =
|
|
286
|
+
let latest = TestDefinition.fromNonceTuple(nonce);
|
|
273
287
|
|
|
274
288
|
// Restarting test definitions when desired.
|
|
275
|
-
full =
|
|
289
|
+
full = TestDefinition.maybeRestartFull(full, latest);
|
|
276
290
|
|
|
277
291
|
// Merge any previous
|
|
278
292
|
// values into latest.
|
|
@@ -282,10 +296,11 @@ export class TestTuple {
|
|
|
282
296
|
// combining with next time.
|
|
283
297
|
full = latest;
|
|
284
298
|
|
|
285
|
-
// Add latest
|
|
286
|
-
// ready to run as a test.
|
|
299
|
+
// Add (copy of) latest (for isolation),
|
|
300
|
+
// only if it's ready to run as a test.
|
|
287
301
|
if (latest.isRunnable) {
|
|
288
|
-
|
|
302
|
+
let copy = latest.copy();
|
|
303
|
+
tuples.push(copy);
|
|
289
304
|
}
|
|
290
305
|
}
|
|
291
306
|
|
|
@@ -296,15 +311,15 @@ export class TestTuple {
|
|
|
296
311
|
static fromNonceTuple(nonce) {
|
|
297
312
|
// Empty, since properties can be set
|
|
298
313
|
// by either of two nonce naming styles.
|
|
299
|
-
let tuple = new
|
|
314
|
+
let tuple = new TestDefinition();
|
|
300
315
|
|
|
301
|
-
let shortNames =
|
|
316
|
+
let shortNames = TestDefinition.longsByShort.keys();
|
|
302
317
|
|
|
303
318
|
// Traversing matching pairs of names and applying
|
|
304
319
|
// whichever one is present as the tuple property;
|
|
305
320
|
// if neither is present, the property is undefined.
|
|
306
321
|
for (let shortName of shortNames) {
|
|
307
|
-
let longName =
|
|
322
|
+
let longName = TestDefinition.longsByShort.get(shortName);
|
|
308
323
|
tuple[shortName] = shortName in nonce ? nonce[shortName] : nonce[longName];
|
|
309
324
|
}
|
|
310
325
|
|
|
@@ -318,13 +333,13 @@ export class TestTuple {
|
|
|
318
333
|
// When a (new) model class is named,
|
|
319
334
|
// wipe out all reused test values.
|
|
320
335
|
if (latest.type !== undefined) {
|
|
321
|
-
full = new
|
|
336
|
+
full = new TestDefinition();
|
|
322
337
|
}
|
|
323
338
|
|
|
324
339
|
// When a (new) model method is named, wipe out reused
|
|
325
340
|
// test values except the general ones for its class.
|
|
326
341
|
if (latest.method !== undefined) {
|
|
327
|
-
full = new
|
|
342
|
+
full = new TestDefinition(
|
|
328
343
|
full.nature, full.type,
|
|
329
344
|
full.spoofed, full.initors
|
|
330
345
|
);
|
|
@@ -334,10 +349,10 @@ export class TestTuple {
|
|
|
334
349
|
}
|
|
335
350
|
|
|
336
351
|
combineWith(other) {
|
|
337
|
-
let shortNames =
|
|
352
|
+
let shortNames = TestDefinition.longsByShort.keys();
|
|
338
353
|
|
|
339
354
|
for (let shortName of shortNames) {
|
|
340
|
-
|
|
355
|
+
TestDefinition.combineValues(this, other, shortName);
|
|
341
356
|
}
|
|
342
357
|
}
|
|
343
358
|
|
|
@@ -355,7 +370,7 @@ export class TestTuple {
|
|
|
355
370
|
// region Other statics
|
|
356
371
|
|
|
357
372
|
static plainNameOf(name) /* passed */ {
|
|
358
|
-
let plain = name.replaceAll(
|
|
373
|
+
let plain = name.replaceAll(TestDefinition.operatorsRegExp, "");
|
|
359
374
|
return plain;
|
|
360
375
|
}
|
|
361
376
|
|
package/system/TestFinder.js
CHANGED
|
@@ -43,7 +43,7 @@ export class TestFinder extends ATestFinder {
|
|
|
43
43
|
for (let testPath of testPaths) {
|
|
44
44
|
// Contents of test sources have to be loaded.
|
|
45
45
|
let sources = await this.convertPathToClassInstances(testPath.path);
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
// Any test classes in each source have to be loaded.
|
|
48
48
|
for (let source of sources) {
|
|
49
49
|
let local = source.tests;
|
|
@@ -77,8 +77,8 @@ export class TestFinder extends ATestFinder {
|
|
|
77
77
|
|
|
78
78
|
pathsFromTargetingSource() {
|
|
79
79
|
let paths = [];
|
|
80
|
-
let root = process.cwd();
|
|
81
|
-
|
|
80
|
+
let root = process.cwd();
|
|
81
|
+
|
|
82
82
|
// Recursively add all test
|
|
83
83
|
// files in tree to `paths`.
|
|
84
84
|
this.searchTree(root, paths);
|
|
@@ -88,7 +88,7 @@ export class TestFinder extends ATestFinder {
|
|
|
88
88
|
|
|
89
89
|
searchTree(root, paths) {
|
|
90
90
|
let entries = fs.readdirSync(root, { withFileTypes: true });
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
for (let entry of entries) {
|
|
93
93
|
// Working around a recent bug in fs of .path always undefined or wrong.
|
|
94
94
|
entry.path = path.join(root, entry.name);
|
|
@@ -115,6 +115,11 @@ export class TestFinder extends ATestFinder {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
sortTestPaths(testPaths) /* passed */ {
|
|
118
|
+
// An empty array can't be reduced, but can be returned as-is.
|
|
119
|
+
if (Array.isArray(testPaths) && testPaths.length === 0) {
|
|
120
|
+
return testPaths;
|
|
121
|
+
}
|
|
122
|
+
|
|
118
123
|
// Latest is found for placing at end.
|
|
119
124
|
let latest = testPaths.reduce((prior, now) => { return now.changed > prior.changed ? now : prior; });
|
|
120
125
|
|
|
@@ -148,8 +153,9 @@ export class TestFinder extends ATestFinder {
|
|
|
148
153
|
return testSources;
|
|
149
154
|
}
|
|
150
155
|
catch (e) {
|
|
156
|
+
// Throw messages are retained for listing after tests are run.
|
|
151
157
|
let fileName = path.basename(classPath);
|
|
152
|
-
|
|
158
|
+
this.thrown.push(`Test loading failed for ${ fileName }. ${ e }`);
|
|
153
159
|
return [];
|
|
154
160
|
}
|
|
155
161
|
}
|
package/system/TestFrame.js
CHANGED
|
@@ -17,67 +17,60 @@ export class TestFrame {
|
|
|
17
17
|
// Outer try for fails of groundwork requested.
|
|
18
18
|
try {
|
|
19
19
|
console.log(`cruft : b`);
|
|
20
|
-
/* &cruft, maybe simplify explanations here */
|
|
21
|
-
|
|
22
|
-
// Certain args must be isolated for collapsing forward, in case tested
|
|
23
|
-
// code mutates them. Sets test.localInitors and test.localInputs.
|
|
24
|
-
this.#stages.setLocalInitorsAndInputs(test);
|
|
25
|
-
|
|
26
|
-
console.log(`cruft : c`);
|
|
27
20
|
|
|
28
21
|
// Spoofing, setting static properties, and so on.
|
|
29
22
|
this.#stages.anyPreTargetingGroundwork(test);
|
|
30
23
|
|
|
31
|
-
console.log(`cruft :
|
|
24
|
+
console.log(`cruft : c`);
|
|
32
25
|
|
|
33
26
|
// Target may be instance, prototype for constructors, the class
|
|
34
27
|
// itself for statics, or nonce for properties. Sets test.target.
|
|
35
28
|
this.#stages.setLocalTarget(test);
|
|
36
29
|
|
|
37
|
-
console.log(`cruft :
|
|
30
|
+
console.log(`cruft : d`);
|
|
38
31
|
|
|
39
32
|
// Method under test may be on instance, class,
|
|
40
33
|
// or nonce for properties. Sets test.callable.
|
|
41
34
|
this.#stages.setLocalCallable(test);
|
|
42
35
|
|
|
43
|
-
console.log(`cruft :
|
|
36
|
+
console.log(`cruft : e`);
|
|
44
37
|
|
|
45
38
|
// Setting instance properties and so on.
|
|
46
39
|
this.#stages.anyPostTargetingGroundwork(test);
|
|
47
40
|
|
|
48
41
|
|
|
49
|
-
console.log(`cruft :
|
|
42
|
+
console.log(`cruft : f`);
|
|
50
43
|
|
|
51
44
|
// Inner try for fails of targeted code only.
|
|
52
45
|
try {
|
|
53
|
-
console.log(`cruft :
|
|
46
|
+
console.log(`cruft : g`);
|
|
54
47
|
|
|
55
48
|
console.log(`cruft : test.actual:`, test.actual);
|
|
56
49
|
console.log(`cruft : test.localTarget:`, test.localTarget);
|
|
57
50
|
console.log(`cruft : test.localCallable:`, test.localCallable);
|
|
58
|
-
console.log(`cruft : test.
|
|
51
|
+
console.log(`cruft : test.in:`, test.in);
|
|
59
52
|
|
|
60
53
|
// Tests usually look for this.
|
|
61
|
-
test.actual = test.localTarget[test.localCallable](...test.
|
|
54
|
+
test.actual = test.localTarget[test.localCallable](...test.in);
|
|
62
55
|
|
|
63
56
|
console.log(`cruft : test.actual:`, test.actual);
|
|
64
|
-
console.log(`cruft :
|
|
57
|
+
console.log(`cruft : h`);
|
|
65
58
|
}
|
|
66
59
|
catch (thrown) {
|
|
67
|
-
console.log(`cruft :
|
|
60
|
+
console.log(`cruft : i`);
|
|
68
61
|
|
|
69
62
|
// Sometimes tests look for this.
|
|
70
63
|
test.thrown = thrown;
|
|
71
64
|
|
|
72
|
-
console.log(`cruft :
|
|
65
|
+
console.log(`cruft : j`);
|
|
73
66
|
}
|
|
74
67
|
|
|
75
|
-
console.log(`cruft :
|
|
68
|
+
console.log(`cruft : k`);
|
|
76
69
|
|
|
77
70
|
// Sometimes tests look for results elsewhere.
|
|
78
71
|
this.#stages.anyModifyActual(test);
|
|
79
72
|
|
|
80
|
-
console.log(`cruft :
|
|
73
|
+
console.log(`cruft : l`);
|
|
81
74
|
|
|
82
75
|
/* &cruft, remove test-checking line when all tests pass */
|
|
83
76
|
// test.didPass = "fails";
|
|
@@ -85,103 +78,18 @@ export class TestFrame {
|
|
|
85
78
|
// Actually testing the result.
|
|
86
79
|
test.didPass = this.#stages.compareResults(test.output, test.actual);
|
|
87
80
|
|
|
88
|
-
console.log(`cruft :
|
|
81
|
+
console.log(`cruft : m`);
|
|
89
82
|
|
|
90
83
|
}
|
|
91
84
|
finally {
|
|
92
|
-
console.log(`cruft :
|
|
85
|
+
console.log(`cruft : n`);
|
|
93
86
|
|
|
94
87
|
// Undoing any groundwork changes made.
|
|
95
88
|
this.#stages.anyGroundworkReversion(test);
|
|
96
89
|
|
|
97
|
-
console.log(`cruft :
|
|
90
|
+
console.log(`cruft : o`);
|
|
98
91
|
}
|
|
99
92
|
|
|
100
|
-
console.log(`cruft :
|
|
93
|
+
console.log(`cruft : p`);
|
|
101
94
|
}
|
|
102
|
-
|
|
103
|
-
// // region Dependencies of test frames
|
|
104
|
-
//
|
|
105
|
-
// /* &cruft, remove if / once superseded by code in TestStages */
|
|
106
|
-
//
|
|
107
|
-
// #anyOriginalPropertyGetting(target, settables) {
|
|
108
|
-
// if (!Array.isArray(settables)) {
|
|
109
|
-
// return;
|
|
110
|
-
// }
|
|
111
|
-
//
|
|
112
|
-
// let unsettables = [ ];
|
|
113
|
-
//
|
|
114
|
-
// for (let settable of settables) {
|
|
115
|
-
// // Not a setter tuple.
|
|
116
|
-
// if (!settable.of) {
|
|
117
|
-
// continue;
|
|
118
|
-
// }
|
|
119
|
-
//
|
|
120
|
-
// // Retaining original.
|
|
121
|
-
// let original = target[settable.of];
|
|
122
|
-
// let unsettable = { of: settable.of, as: original };
|
|
123
|
-
// unsettables.push(unsettable);
|
|
124
|
-
// }
|
|
125
|
-
//
|
|
126
|
-
// return unsettables;
|
|
127
|
-
// }
|
|
128
|
-
//
|
|
129
|
-
// #anyPropertySetting(target, settables) {
|
|
130
|
-
// // No properties to set.
|
|
131
|
-
// if (!Array.isArray(settables)) {
|
|
132
|
-
// return;
|
|
133
|
-
// }
|
|
134
|
-
//
|
|
135
|
-
// for (let settable of settables) {
|
|
136
|
-
// // Not a setter tuple.
|
|
137
|
-
// if (!settable.of) {
|
|
138
|
-
// continue;
|
|
139
|
-
// }
|
|
140
|
-
//
|
|
141
|
-
// // Actually setting property.
|
|
142
|
-
// target[settable.of] = settable.as;
|
|
143
|
-
// }
|
|
144
|
-
// }
|
|
145
|
-
//
|
|
146
|
-
// #anyPropertyUnsetting(target, unsettables) {
|
|
147
|
-
// // Unsetting is the same as setting,
|
|
148
|
-
// // but with tuples of original values.
|
|
149
|
-
// return this.#anyPropertySetting(target, unsettables);
|
|
150
|
-
// }
|
|
151
|
-
//
|
|
152
|
-
// // #compare(expected, actual) {
|
|
153
|
-
// // return this.#comparer.compare(expected, actual);
|
|
154
|
-
// // }
|
|
155
|
-
//
|
|
156
|
-
// #supplyNonReturnActual(test, target) {
|
|
157
|
-
// // When there is a .from that's a string,
|
|
158
|
-
// // the actual is the named target member.
|
|
159
|
-
// if (typeof test.from === "string") {
|
|
160
|
-
// // Common member host;
|
|
161
|
-
// // undefined if static.
|
|
162
|
-
// let host = target;
|
|
163
|
-
//
|
|
164
|
-
// // When .and defines static.
|
|
165
|
-
// if (this.#doesAddressStatics(test)) {
|
|
166
|
-
// host = test.on;
|
|
167
|
-
// }
|
|
168
|
-
//
|
|
169
|
-
// return host[test.from];
|
|
170
|
-
// }
|
|
171
|
-
//
|
|
172
|
-
// // When there is a .from that's a function,
|
|
173
|
-
// // the actual is the result of calling it,
|
|
174
|
-
// // given everything that might be needed.
|
|
175
|
-
// if (test.from instanceof Function) {
|
|
176
|
-
// return test.from(target, test);
|
|
177
|
-
// }
|
|
178
|
-
//
|
|
179
|
-
// // When there is any other .from, the actual is the
|
|
180
|
-
// // value of the code element provided as .from.
|
|
181
|
-
// return test.from;
|
|
182
|
-
// }
|
|
183
|
-
//
|
|
184
|
-
// // endregion Dependencies of test frames
|
|
185
|
-
//
|
|
186
|
-
|
|
187
95
|
}
|
package/system/TestRunner.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/* Runs tests one by one as an ATestCaller requests them. */
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { TestDefinition } from "./TestDefinition.js";
|
|
6
6
|
import { TestGroup } from "./TestGroup.js";
|
|
7
7
|
import { ClassTestGroup } from "./ClassTestGroup.js";
|
|
8
8
|
import { MethodTestGroup } from "./MethodTestGroup.js";
|
|
@@ -14,7 +14,7 @@ import { TestFrames } from "./TestFrames.js";
|
|
|
14
14
|
|
|
15
15
|
import { SpoofClassMethodsFixture } from "./SpoofClassMethodsFixture.js";
|
|
16
16
|
import { SpoofObjectMethodsFixture } from "./SpoofObjectMethodsFixture.js";
|
|
17
|
-
import {
|
|
17
|
+
import { SpoofDefinition } from "./SpoofDefinition.js";
|
|
18
18
|
|
|
19
19
|
export class TestRunner {
|
|
20
20
|
// region Static definition fields
|
|
@@ -143,7 +143,7 @@ export class TestRunner {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
// Converting so that property names can be relied on.
|
|
146
|
-
this.#tests =
|
|
146
|
+
this.#tests = TestDefinition.fromNonceTuples(this.tests);
|
|
147
147
|
|
|
148
148
|
// Needed for displaying classes and methods as groups.
|
|
149
149
|
let classGroup = new ClassTestGroup();
|
|
@@ -222,7 +222,7 @@ export class TestRunner {
|
|
|
222
222
|
|
|
223
223
|
// region Dependencies of runOneTest()
|
|
224
224
|
|
|
225
|
-
// Spoofs objects as defined in
|
|
225
|
+
// Spoofs objects as defined in TestDefinition's
|
|
226
226
|
// .with and .in, which can contain spoofs.
|
|
227
227
|
#anyObjectSpoofing(test) {
|
|
228
228
|
// Spoofing objects may be skipped for self-testing.
|
package/system/TestStages.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**/
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { TestDefinition } from "./TestDefinition.js";
|
|
4
4
|
import { TotalComparer } from "./TotalComparer.js";
|
|
5
5
|
import { TotalCopier } from "./TotalCopier.js";
|
|
6
6
|
|
|
@@ -14,14 +14,6 @@ export class TestStages {
|
|
|
14
14
|
static #comparer = new TotalComparer();
|
|
15
15
|
static #copier = new TotalCopier();
|
|
16
16
|
|
|
17
|
-
setLocalInitorsAndInputs(test) /* passed */ {
|
|
18
|
-
/* Sets local__ of each to a copy of the original,
|
|
19
|
-
so any mutated args aren't collapsed forward. */
|
|
20
|
-
|
|
21
|
-
test.localInitors = TestStages.#copier.copy(test.with);
|
|
22
|
-
test.localInputs = TestStages.#copier.copy(test.in);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
17
|
anyPreTargetingGroundwork(test) {
|
|
26
18
|
// Spoofing of class members here.
|
|
27
19
|
// Setting any static properties here.
|
|
@@ -37,7 +29,7 @@ export class TestStages {
|
|
|
37
29
|
return;
|
|
38
30
|
}
|
|
39
31
|
|
|
40
|
-
let callable =
|
|
32
|
+
let callable = TestDefinition.plainNameOf(test.of);
|
|
41
33
|
|
|
42
34
|
let target = test.isInstanceTest
|
|
43
35
|
? this.#supplyInstanceLocalTarget(test, callable)
|
|
@@ -61,7 +53,7 @@ export class TestStages {
|
|
|
61
53
|
}
|
|
62
54
|
|
|
63
55
|
#supplyInstanceLocalTarget(test, callable) /* verified */ {
|
|
64
|
-
let instance = new test.on.prototype.constructor(...test.
|
|
56
|
+
let instance = new test.on.prototype.constructor(...test.with);
|
|
65
57
|
|
|
66
58
|
// Methods are called on instance directly.
|
|
67
59
|
// Properties are called on instance in nonce.
|
|
@@ -79,8 +71,8 @@ export class TestStages {
|
|
|
79
71
|
or a nonce method for a property test. */
|
|
80
72
|
|
|
81
73
|
test.localCallable = test.isMethodTest
|
|
82
|
-
?
|
|
83
|
-
:
|
|
74
|
+
? TestDefinition.plainNameOf(test.method)
|
|
75
|
+
: TestDefinition.nonceLocalCallableName;
|
|
84
76
|
}
|
|
85
77
|
|
|
86
78
|
anyPostTargetingGroundwork(test) {
|