risei 2.0.1 → 3.0.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 +26 -15
- package/package.json +2 -2
- package/system/ATestReporter.js +26 -26
- package/system/ClassTestGroup.js +8 -8
- package/system/LocalCaller.js +2 -2
- package/system/MethodSpoofer.js +2 -2
- package/system/MethodTestGroup.js +8 -8
- package/system/Moment.js +29 -29
- package/system/NameAnalyzer.js +26 -26
- package/system/PropertySpoofer.js +1 -1
- package/system/SpoofDef.js +0 -5
- package/system/TestDef.js +14 -13
- package/system/TestFrame.js +8 -10
- package/system/TestGroup.js +25 -25
- package/system/TestRunner.js +8 -6
- package/system/TestStages.js +66 -10
- package/system/TestSummary.js +37 -37
- package/system/TypeAnalyzer.js +79 -26
- package/system/ChosenTestFinder.js +0 -31
- package/system/Risei.js +0 -118
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ And they have a summary bar at the bottom:
|
|
|
46
46
|
|
|
47
47
|
## Status
|
|
48
48
|
|
|
49
|
-
Risei is under active development and new enhancements appear often. The latest release, **
|
|
49
|
+
Risei is under active development and new enhancements appear often. The latest release, **3.0.0**, brings major improvements, starting with the ability to test `async` code, and builds on many major improvements in **2.0.0**, including broader capabilities and simpler syntax, and a few minor breaking changes.
|
|
50
50
|
|
|
51
51
|
Check out the [full list of changes](#version-history).
|
|
52
52
|
|
|
@@ -58,11 +58,13 @@ Check out the [full list of changes](#version-history).
|
|
|
58
58
|
- #### Easy-to-read test definitions and test outputs. ► [Test and output examples](https://deusware.com/risei/index.html#examples) (also above)
|
|
59
59
|
- #### Even less to write by stating reused test properties only once. ► [Collapsing forward](https://deusware.com/risei/index.html#collapsing-forward) (basics below)
|
|
60
60
|
- #### Built-in declarative syntax to fake test-time values from dependencies. ► [Spoofing using `.plus`](https://deusware.com/risei/index.html#spoofing) (basics below)
|
|
61
|
-
- ####
|
|
61
|
+
- #### Full support for `async` code with no special syntax needed. ► [Writing tests](https://deusware.com/risei/index.html#writing-tests) (basics below)
|
|
62
|
+
- #### Testing properties and methods, static and instance members all the same way. ► [Properties and statics](https://deusware.com/risei/index.html#testing-properties-and-static-methods)
|
|
62
63
|
- #### Testing `throw` paths effortlessly. ► [Using `.and: "throws"`](https://deusware.com/risei/index.html#using-and-throws)
|
|
63
64
|
- #### Deriving actual values to test from raw outputs or property retrieval. ► [Using `.from`](https://deusware.com/risei/index.html#using-from)
|
|
64
65
|
- #### Setting up and tearing down arbitrary test state. ► [Using `.do` and `.undo`](https://deusware.com/risei/index.html#using-do-and-undo)
|
|
65
66
|
- #### Testing for `undefined` as output. ► [Using `this.undef`](https://deusware.com/risei/index.html#using-undef)
|
|
67
|
+
- #### Running a method repeatedly in one test. ► [Using `.and: "poly"`](https://deusware.com/risei/index.html#using-and-poly)
|
|
66
68
|
|
|
67
69
|
- And more! Check out the full [Risei home page](https://deusware.com/risei).
|
|
68
70
|
|
|
@@ -140,11 +142,11 @@ tests = [ ...
|
|
|
140
142
|
... ];
|
|
141
143
|
```
|
|
142
144
|
|
|
145
|
+
- Asynchronous code with `async` and `await` keywords can tested with no changes at all to this syntax.
|
|
143
146
|
- Use empty arrays for `.in` or `.with` when there are no args to pass.
|
|
144
147
|
- You can use [long names](https://deusware.com/risei/index.html#long-names) for properties if you want.
|
|
145
148
|
|
|
146
149
|
|
|
147
|
-
|
|
148
150
|
## Basic collapsing forward example
|
|
149
151
|
|
|
150
152
|
You can state test properties once and let them _collapse forward_ across subsequent tests to save time and make tests easier to read.
|
|
@@ -187,6 +189,7 @@ The most basic spoofing looks like this:
|
|
|
187
189
|
}
|
|
188
190
|
```
|
|
189
191
|
|
|
192
|
+
- It's just like _fakes_, _mocks_, or _test doubles_ in other test systems, but easier to write and read.
|
|
190
193
|
- Numerous additional capabilities, as well as compressed syntax, can be mixed freely in many ways.
|
|
191
194
|
- Learn more [here](https://deusware.com/risei/index.html#spoofing).
|
|
192
195
|
|
|
@@ -209,9 +212,22 @@ If problems cause test files not to load, a gold bar appears and tests in those
|
|
|
209
212
|
- Those and other problems can be solved with the help of this [troubleshooting guide](https://deusware.com/risei/index.html#troubleshooting).
|
|
210
213
|
|
|
211
214
|
|
|
215
|
+
|
|
212
216
|
## Version history
|
|
213
217
|
|
|
214
|
-
- Release **
|
|
218
|
+
- Release **3.0.0** (August, 2024) contains all of these changes:
|
|
219
|
+
- Asynchronous code with `async` syntax is now fully supported, with no special test syntax required.
|
|
220
|
+
- **(Breaking change)** `.from` functions now take `test` and `actual` as parameters, rather than `target` and `test`.
|
|
221
|
+
- If you need to work with the target of the test (usually an instance of the class being tested), it's available as `test.target`.
|
|
222
|
+
- You can now call target code more than once in one test using an `.and` of `"poly"` (AKA _poly-calling_).
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
<details>
|
|
226
|
+
<summary>
|
|
227
|
+
Older releases
|
|
228
|
+
</summary>
|
|
229
|
+
|
|
230
|
+
- Release **2.0.1** (August, 2024) contained all of these changes:
|
|
215
231
|
- Risei now can determine automatically if tested methods are static.
|
|
216
232
|
- You can now directly test properties just like methods.
|
|
217
233
|
- Risei can also determine automatically if these are static.
|
|
@@ -221,20 +237,13 @@ If problems cause test files not to load, a gold bar appears and tests in those
|
|
|
221
237
|
- You can now change test properties without accidentally creating a new test using `.just`.
|
|
222
238
|
- You can now directly test for `undefined` in `.out` using `this.undef` / `ATestSource.undefSymbol`.
|
|
223
239
|
- `Error` objects are now compared accurately.
|
|
224
|
-
- You can now identify member types with `.`, `:`, and `()` in `.of`, `.plus`, and `.from`, though
|
|
240
|
+
- You can now identify member types with `.`, `:`, and `()` in any of `.of`, `.plus`, and `.from`, though it isn't necessary.
|
|
225
241
|
- **(Breaking change)** The actual for throw tests is now the entire thrown object (usually an `Error`), rather than the `Error`'s message text.
|
|
226
242
|
- **(Breaking change)** `ATestSource` is now a default export, changing its imports from `import { ATestSource } from` to `import ATestSource from`.
|
|
243
|
+
- Major internal re-engineering.
|
|
227
244
|
|
|
228
|
-
|
|
245
|
+
- Release **2.0.0** (August, 2024) was identical to 2.0.1 except for some unneeded extra files.
|
|
229
246
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
<details>
|
|
233
|
-
<summary>
|
|
234
|
-
Older releases
|
|
235
|
-
</summary>
|
|
236
|
-
|
|
237
|
-
- Release **2.0.0** (August, 2024) is identical to 2.0.1 except for some unneeded extra files.
|
|
238
247
|
- Release **1.3.4** (March, 2024) fixed a bug that caused class display problems in some cases.
|
|
239
248
|
- Release **1.3.3** (March, 2024) fixed a major bug that prevented tests from running in Windows.
|
|
240
249
|
- Release **1.3.2** (February, 2024) only improved this read-me's contents.
|
|
@@ -248,6 +257,7 @@ Older releases
|
|
|
248
257
|
</details>
|
|
249
258
|
|
|
250
259
|
|
|
260
|
+
|
|
251
261
|
## Known issues and workarounds
|
|
252
262
|
|
|
253
263
|
The only issue at present is reuse of method args mutated by tested code when collapsing forward.
|
|
@@ -255,9 +265,10 @@ The only issue at present is reuse of method args mutated by tested code when co
|
|
|
255
265
|
- The workaround is just to restate those args for each test.
|
|
256
266
|
|
|
257
267
|
|
|
268
|
+
|
|
258
269
|
## Exclusions from Risei
|
|
259
270
|
|
|
260
|
-
At present, there are a few things Risei doesn't support
|
|
271
|
+
At present, there are a few things Risei doesn't support. Some of these may be supported in the future.
|
|
261
272
|
|
|
262
273
|
- You can see the whole list [here](https://deusware.com/risei/index.html#exclusions-from-risei).
|
|
263
274
|
- You can save a lot of time by using Risei for most of your code, and another framework for whatever it doesn't support.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "risei",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Risei allows you to write unit tests as simple JavaScript objects, so it's easy and fast, with no drag on redesign.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"unit test",
|
|
@@ -50,6 +50,6 @@
|
|
|
50
50
|
"fs": "^0.0.1-security",
|
|
51
51
|
"mocha": "^10.0.0",
|
|
52
52
|
"morgan": "~1.9.1",
|
|
53
|
-
"risei": "^
|
|
53
|
+
"risei": "^3.0.0"
|
|
54
54
|
}
|
|
55
55
|
}
|
package/system/ATestReporter.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
/* Defines operations that a test reporter must implement. A = abstract. */
|
|
4
|
-
|
|
5
|
-
/* &cruft, ? replace with my own code eventually */
|
|
6
|
-
import chalk from "chalk";
|
|
7
|
-
|
|
8
|
-
export default class ATestReporter {
|
|
9
|
-
// Reports whatever was just provided by the TestRunner.
|
|
10
|
-
// Can delegate to the other report-x methods.
|
|
11
|
-
reportNext(result) {
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
reportGroup() {
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
reportPassed(result) {
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
reportFailed(result) {
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
reportSummary(summary) {
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
}
|
|
1
|
+
/**/
|
|
2
|
+
|
|
3
|
+
/* Defines operations that a test reporter must implement. A = abstract. */
|
|
4
|
+
|
|
5
|
+
/* &cruft, ? replace with my own code eventually */
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
|
|
8
|
+
export default class ATestReporter {
|
|
9
|
+
// Reports whatever was just provided by the TestRunner.
|
|
10
|
+
// Can delegate to the other report-x methods.
|
|
11
|
+
reportNext(result) {
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
reportGroup() {
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
reportPassed(result) {
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
reportFailed(result) {
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
reportSummary(summary) {
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
}
|
package/system/ClassTestGroup.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
import TestGroup from "./TestGroup.js";
|
|
4
|
-
|
|
5
|
-
/* Identifies a grouping of tests by class. No specialized workings. */
|
|
6
|
-
|
|
7
|
-
export default class ClassTestGroup extends TestGroup {
|
|
8
|
-
}
|
|
1
|
+
/**/
|
|
2
|
+
|
|
3
|
+
import TestGroup from "./TestGroup.js";
|
|
4
|
+
|
|
5
|
+
/* Identifies a grouping of tests by class. No specialized workings. */
|
|
6
|
+
|
|
7
|
+
export default class ClassTestGroup extends TestGroup {
|
|
8
|
+
}
|
package/system/LocalCaller.js
CHANGED
|
@@ -11,11 +11,11 @@ import TestRunner from "./TestRunner.js";
|
|
|
11
11
|
export default class LocalCaller extends ATestCaller {
|
|
12
12
|
async runAllTests() {
|
|
13
13
|
let tests = await this.finder.findAllTests();
|
|
14
|
-
this.runner.useTests(tests);
|
|
14
|
+
this.runner.useTests(tests);
|
|
15
15
|
|
|
16
16
|
// Getting each run test / summary result
|
|
17
17
|
// and having it reported in the terminal.
|
|
18
|
-
for (let result of this.runner) {
|
|
18
|
+
for await (let result of this.runner.runTests()) {
|
|
19
19
|
this.reporter.reportNext(result);
|
|
20
20
|
}
|
|
21
21
|
}
|
package/system/MethodSpoofer.js
CHANGED
|
@@ -39,7 +39,7 @@ export default class MethodSpoofer extends ASpoofingFixture {
|
|
|
39
39
|
// endregion Properties
|
|
40
40
|
|
|
41
41
|
constructor() {
|
|
42
|
-
super(
|
|
42
|
+
super();
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// Spoofs methods of classes as defined in nonce
|
|
@@ -53,7 +53,7 @@ export default class MethodSpoofer extends ASpoofingFixture {
|
|
|
53
53
|
if (!Array.isArray(spoofNonces)) {
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
// Converting to scope object type.
|
|
58
58
|
let spoofDefs = SpoofDef.fromNonceTuples(spoofNonces, type);
|
|
59
59
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
import TestGroup from "./TestGroup.js";
|
|
4
|
-
|
|
5
|
-
/* Identifies a grouping of tests by method. No specialized workings. */
|
|
6
|
-
|
|
7
|
-
export default class MethodTestGroup extends TestGroup {
|
|
8
|
-
}
|
|
1
|
+
/**/
|
|
2
|
+
|
|
3
|
+
import TestGroup from "./TestGroup.js";
|
|
4
|
+
|
|
5
|
+
/* Identifies a grouping of tests by method. No specialized workings. */
|
|
6
|
+
|
|
7
|
+
export default class MethodTestGroup extends TestGroup {
|
|
8
|
+
}
|
package/system/Moment.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class Moment {
|
|
4
|
-
#now;
|
|
5
|
-
|
|
6
|
-
constructor(now) {
|
|
7
|
-
this.#now = now;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
asReadable() /* passed */ {
|
|
11
|
-
let now = this.#now;
|
|
12
|
-
let asTwo = this.#asTwo;
|
|
13
|
-
|
|
14
|
-
let day = `${ now.getMonth() + 1 }/${ asTwo(now.getDate()) }/${ now.getFullYear() }`;
|
|
15
|
-
|
|
16
|
-
let time = `${ now.getHours() % 12 || 12 }:${ asTwo(now.getMinutes()) }:${ asTwo(now.getSeconds()) } `
|
|
17
|
-
+ `${ now.getHours() < 12 ? "AM" : "PM" }`;
|
|
18
|
-
|
|
19
|
-
return `${ day } at ${ time }`;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
#asTwo(number) /* verified */ {
|
|
23
|
-
let text = `${ number }`;
|
|
24
|
-
text = text.padStart(2, "0");
|
|
25
|
-
|
|
26
|
-
return text;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
}
|
|
1
|
+
/**/
|
|
2
|
+
|
|
3
|
+
export default class Moment {
|
|
4
|
+
#now;
|
|
5
|
+
|
|
6
|
+
constructor(now) {
|
|
7
|
+
this.#now = now;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
asReadable() /* passed */ {
|
|
11
|
+
let now = this.#now;
|
|
12
|
+
let asTwo = this.#asTwo;
|
|
13
|
+
|
|
14
|
+
let day = `${ now.getMonth() + 1 }/${ asTwo(now.getDate()) }/${ now.getFullYear() }`;
|
|
15
|
+
|
|
16
|
+
let time = `${ now.getHours() % 12 || 12 }:${ asTwo(now.getMinutes()) }:${ asTwo(now.getSeconds()) } `
|
|
17
|
+
+ `${ now.getHours() < 12 ? "AM" : "PM" }`;
|
|
18
|
+
|
|
19
|
+
return `${ day } at ${ time }`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#asTwo(number) /* verified */ {
|
|
23
|
+
let text = `${ number }`;
|
|
24
|
+
text = text.padStart(2, "0");
|
|
25
|
+
|
|
26
|
+
return text;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
package/system/NameAnalyzer.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class NameAnalyzer {
|
|
4
|
-
// region Definitions
|
|
5
|
-
|
|
6
|
-
static dotOperator = ".";
|
|
7
|
-
static colonOperator = ":";
|
|
8
|
-
static parensOperator = "()";
|
|
9
|
-
static operatorsRegExp = /\.|:|\(\)/g;
|
|
10
|
-
|
|
11
|
-
// endregion Definitions
|
|
12
|
-
|
|
13
|
-
static hasPropertySigil(name) /* passed */ {
|
|
14
|
-
return name.startsWith(NameAnalyzer.dotOperator) || name.endsWith(NameAnalyzer.colonOperator);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static hasMethodSigil(name) /* passed */ {
|
|
18
|
-
return name.endsWith(NameAnalyzer.parensOperator);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
static plainNameOf(name) /* passed */ {
|
|
22
|
-
let plain = name.replaceAll(NameAnalyzer.operatorsRegExp, "");
|
|
23
|
-
return plain;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
1
|
+
/**/
|
|
2
|
+
|
|
3
|
+
export default class NameAnalyzer {
|
|
4
|
+
// region Definitions
|
|
5
|
+
|
|
6
|
+
static dotOperator = ".";
|
|
7
|
+
static colonOperator = ":";
|
|
8
|
+
static parensOperator = "()";
|
|
9
|
+
static operatorsRegExp = /\.|:|\(\)/g;
|
|
10
|
+
|
|
11
|
+
// endregion Definitions
|
|
12
|
+
|
|
13
|
+
static hasPropertySigil(name) /* passed */ {
|
|
14
|
+
return name.startsWith(NameAnalyzer.dotOperator) || name.endsWith(NameAnalyzer.colonOperator);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static hasMethodSigil(name) /* passed */ {
|
|
18
|
+
return name.endsWith(NameAnalyzer.parensOperator);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static plainNameOf(name) /* passed */ {
|
|
22
|
+
let plain = name.replaceAll(NameAnalyzer.operatorsRegExp, "");
|
|
23
|
+
return plain;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
package/system/SpoofDef.js
CHANGED
|
@@ -20,11 +20,6 @@ export default class SpoofDef {
|
|
|
20
20
|
SpoofDef.#asNames
|
|
21
21
|
]);
|
|
22
22
|
|
|
23
|
-
/* &cruft, remove these after spoofing in .with and .in is removed */
|
|
24
|
-
/* Objects with either of these property names aren't
|
|
25
|
-
converted to spoofDefs by from-nonce methods. */
|
|
26
|
-
static skipNames = [ "not", "skip" ];
|
|
27
|
-
|
|
28
23
|
// endregion Static fields
|
|
29
24
|
|
|
30
25
|
// region Public fields (long names)
|
package/system/TestDef.js
CHANGED
|
@@ -13,6 +13,7 @@ export default class TestDef {
|
|
|
13
13
|
|
|
14
14
|
static staticName = "static";
|
|
15
15
|
static throwName = "throw";
|
|
16
|
+
static polyName = "poly";
|
|
16
17
|
static constructorName = "constructor";
|
|
17
18
|
static nonceLocalCallableName = "nonce";
|
|
18
19
|
|
|
@@ -60,9 +61,7 @@ export default class TestDef {
|
|
|
60
61
|
|
|
61
62
|
// endregion Fields
|
|
62
63
|
|
|
63
|
-
// region
|
|
64
|
-
|
|
65
|
-
// region Test definition, short names
|
|
64
|
+
// region Definition properties
|
|
66
65
|
|
|
67
66
|
/* These short names make JSON-like definitions easier. */
|
|
68
67
|
|
|
@@ -154,9 +153,9 @@ export default class TestDef {
|
|
|
154
153
|
this.counteract = value;
|
|
155
154
|
}
|
|
156
155
|
|
|
157
|
-
// endregion
|
|
156
|
+
// endregion Definition properties
|
|
158
157
|
|
|
159
|
-
// region
|
|
158
|
+
// region State properties
|
|
160
159
|
|
|
161
160
|
get isRunnable() /* passed */ {
|
|
162
161
|
let isRunnable
|
|
@@ -182,12 +181,17 @@ export default class TestDef {
|
|
|
182
181
|
|
|
183
182
|
return is || stated;
|
|
184
183
|
}
|
|
185
|
-
|
|
184
|
+
|
|
186
185
|
get isThrowTest() /* passed */ {
|
|
187
186
|
let is = this.andStringContains(TestDef.throwName);
|
|
188
187
|
return is;
|
|
189
188
|
}
|
|
190
189
|
|
|
190
|
+
get isPolyCallTest() /* passed */ {
|
|
191
|
+
let is = this.andStringContains(TestDef.polyName);
|
|
192
|
+
return is;
|
|
193
|
+
}
|
|
194
|
+
|
|
191
195
|
get isConstructorTest() /* passed */ {
|
|
192
196
|
let plainTarget = NameAnalyzer.plainNameOf(this.of);
|
|
193
197
|
return plainTarget === TestDef.constructorName;
|
|
@@ -255,17 +259,14 @@ export default class TestDef {
|
|
|
255
259
|
if (this.isMethodTest) {
|
|
256
260
|
return `${ plain }()`;
|
|
257
261
|
}
|
|
258
|
-
|
|
259
|
-
if (this.isPropertyTest) {
|
|
262
|
+
else {
|
|
260
263
|
return `.${ plain }`;
|
|
261
264
|
}
|
|
262
265
|
}
|
|
263
266
|
|
|
264
|
-
// endregion
|
|
265
|
-
|
|
266
|
-
// endregion Properties
|
|
267
|
+
// endregion State properties
|
|
267
268
|
|
|
268
|
-
// region
|
|
269
|
+
// region State methods
|
|
269
270
|
|
|
270
271
|
/* Needed externally, and dependency
|
|
271
272
|
of all .and-based properties. */
|
|
@@ -277,7 +278,7 @@ export default class TestDef {
|
|
|
277
278
|
return doesContain;
|
|
278
279
|
}
|
|
279
280
|
|
|
280
|
-
// endregion
|
|
281
|
+
// endregion State methods
|
|
281
282
|
|
|
282
283
|
// region Initing, including constructor()
|
|
283
284
|
|
package/system/TestFrame.js
CHANGED
|
@@ -9,12 +9,12 @@ export default class TestFrame {
|
|
|
9
9
|
// A TestStages is inited for each test.
|
|
10
10
|
this.#stages = new TestStages();
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
run(test) /* passed */ {
|
|
12
|
+
|
|
13
|
+
async run(test) /* passed */ {
|
|
14
14
|
// Outer try for fails of groundwork requested.
|
|
15
15
|
try {
|
|
16
16
|
// Spoofing and so on.
|
|
17
|
-
this.#stages.anyPreTargetingGroundwork(test);
|
|
17
|
+
await this.#stages.anyPreTargetingGroundwork(test);
|
|
18
18
|
|
|
19
19
|
// Target may be instance, prototype for constructors, the class
|
|
20
20
|
// itself for statics, or nonce for properties. Sets test.target.
|
|
@@ -25,14 +25,14 @@ export default class TestFrame {
|
|
|
25
25
|
// Method under test may be on instance, class,
|
|
26
26
|
// or nonce for properties. Sets test.callable.
|
|
27
27
|
let callable = this.#stages.supplyCallableName(test);
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
// Setting (spoofing) properties and so on.
|
|
30
|
-
this.#stages.anyPostTargetingGroundwork(test);
|
|
31
|
-
|
|
30
|
+
await this.#stages.anyPostTargetingGroundwork(test);
|
|
31
|
+
|
|
32
32
|
// Inner try for fails of targeted code only.
|
|
33
33
|
try {
|
|
34
34
|
// Tests usually look for this.
|
|
35
|
-
test.actual = target[callable](...test.in);
|
|
35
|
+
test.actual = await target[callable](...test.in);
|
|
36
36
|
}
|
|
37
37
|
catch (thrown) {
|
|
38
38
|
// Sometimes tests look for this.
|
|
@@ -50,9 +50,7 @@ export default class TestFrame {
|
|
|
50
50
|
}
|
|
51
51
|
finally {
|
|
52
52
|
// Undoing any groundwork changes made.
|
|
53
|
-
this.#stages.anyGroundworkReversal(test);
|
|
53
|
+
await this.#stages.anyGroundworkReversal(test);
|
|
54
54
|
}
|
|
55
|
-
|
|
56
|
-
// console.log(`cruft : q, outer try-catch : after`);
|
|
57
55
|
}
|
|
58
56
|
}
|
package/system/TestGroup.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class TestGroup {
|
|
4
|
-
// region Private fields
|
|
5
|
-
|
|
6
|
-
#group;
|
|
7
|
-
|
|
8
|
-
// endregion Private fields
|
|
9
|
-
|
|
10
|
-
// region Properties
|
|
11
|
-
|
|
12
|
-
get group() {
|
|
13
|
-
return this.#group;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
set group(value) {
|
|
17
|
-
this.#group = value;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// endregion Properties
|
|
21
|
-
|
|
22
|
-
constructor(group) {
|
|
23
|
-
this.#group = group;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
1
|
+
/**/
|
|
2
|
+
|
|
3
|
+
export default class TestGroup {
|
|
4
|
+
// region Private fields
|
|
5
|
+
|
|
6
|
+
#group;
|
|
7
|
+
|
|
8
|
+
// endregion Private fields
|
|
9
|
+
|
|
10
|
+
// region Properties
|
|
11
|
+
|
|
12
|
+
get group() {
|
|
13
|
+
return this.#group;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
set group(value) {
|
|
17
|
+
this.#group = value;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// endregion Properties
|
|
21
|
+
|
|
22
|
+
constructor(group) {
|
|
23
|
+
this.#group = group;
|
|
24
|
+
}
|
|
25
|
+
}
|
package/system/TestRunner.js
CHANGED
|
@@ -101,7 +101,7 @@ export default class TestRunner {
|
|
|
101
101
|
|
|
102
102
|
// Generator for all test results,
|
|
103
103
|
// including groups and summary.
|
|
104
|
-
*
|
|
104
|
+
async * runTests() {
|
|
105
105
|
if (!this.#tests) {
|
|
106
106
|
throw new Error("No tests available to run. TestRunner's .tests must be set before an attempt to run is made.");
|
|
107
107
|
}
|
|
@@ -126,13 +126,15 @@ export default class TestRunner {
|
|
|
126
126
|
|
|
127
127
|
// Each new method / prop name should be a group,
|
|
128
128
|
// and so should the first method for a class.
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
let runName = test.runName;
|
|
130
|
+
|
|
131
|
+
if (runName !== methodGroup.group || atFirstClassMethod) {
|
|
132
|
+
methodGroup.group = runName;
|
|
131
133
|
atFirstClassMethod = false;
|
|
132
134
|
yield methodGroup;
|
|
133
135
|
}
|
|
134
136
|
|
|
135
|
-
let result = this.runOneTest(test);
|
|
137
|
+
let result = await this.runOneTest(test);
|
|
136
138
|
yield result;
|
|
137
139
|
}
|
|
138
140
|
|
|
@@ -140,7 +142,7 @@ export default class TestRunner {
|
|
|
140
142
|
yield this.summarize();
|
|
141
143
|
}
|
|
142
144
|
|
|
143
|
-
runOneTest(test) {
|
|
145
|
+
async runOneTest(test) {
|
|
144
146
|
// Default outputs. Never left undefined.
|
|
145
147
|
test.didPass = false;
|
|
146
148
|
test.anyThrow = null;
|
|
@@ -151,7 +153,7 @@ export default class TestRunner {
|
|
|
151
153
|
result.setNature();
|
|
152
154
|
|
|
153
155
|
// Actually running the test.
|
|
154
|
-
this.#frame.run(test);
|
|
156
|
+
await this.#frame.run(test);
|
|
155
157
|
|
|
156
158
|
// Gathering facts based on the test run.
|
|
157
159
|
result.setResults();
|
package/system/TestStages.js
CHANGED
|
@@ -14,18 +14,22 @@ export default class TestStages {
|
|
|
14
14
|
or before / after all test frames, in the test runner.
|
|
15
15
|
Not necessarily all test steps are found here. */
|
|
16
16
|
|
|
17
|
+
// region Components
|
|
18
|
+
|
|
17
19
|
static #methodSpoofer = new MethodSpoofer();
|
|
18
20
|
static #propertySpoofer = new PropertySpoofer();
|
|
19
21
|
static #comparer = new TotalComparer();
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
// endregion Components
|
|
24
|
+
|
|
25
|
+
async anyPreTargetingGroundwork(test) /* passed */ {
|
|
22
26
|
// Spoofing methods; properties spoofed later.
|
|
23
27
|
TestStages.#methodSpoofer.spoof(test);
|
|
24
28
|
|
|
25
29
|
// Arbitrary user-defined actions.
|
|
26
30
|
// Only spoofed methods available.
|
|
27
31
|
if (test.doesHaveDoEarly) {
|
|
28
|
-
test.do.early(test);
|
|
32
|
+
await test.do.early(test);
|
|
29
33
|
}
|
|
30
34
|
}
|
|
31
35
|
|
|
@@ -48,36 +52,58 @@ export default class TestStages {
|
|
|
48
52
|
|
|
49
53
|
supplyLocalTarget(test) /* passed */ {
|
|
50
54
|
/* Methods are called on instance / type / prototype directly.
|
|
51
|
-
Properties are called on instance / type in a nonce.
|
|
55
|
+
Properties are called on instance / type in a nonce.
|
|
56
|
+
Methods or properties are poly-called in a nonce. */
|
|
52
57
|
|
|
53
58
|
let callable = NameAnalyzer.plainNameOf(test.method);
|
|
54
59
|
|
|
60
|
+
// Two most common cases: mono-call
|
|
61
|
+
// tests of methods and properties.
|
|
55
62
|
let localTarget = test.isMethodTest
|
|
56
63
|
? test.target
|
|
57
64
|
: { nonce: () => { return test.target[callable]; } };
|
|
58
65
|
|
|
66
|
+
// Rare cases: poly-call tests
|
|
67
|
+
// of methods and properties.
|
|
68
|
+
if (test.isPolyCallTest) {
|
|
69
|
+
let nonce = test.isMethodTest
|
|
70
|
+
? this.supplyPolyMethodNonce(test, callable)
|
|
71
|
+
: this.supplyPolyPropNonce(test, callable);
|
|
72
|
+
|
|
73
|
+
localTarget = { nonce };
|
|
74
|
+
}
|
|
75
|
+
|
|
59
76
|
return localTarget;
|
|
60
77
|
}
|
|
61
78
|
|
|
62
79
|
supplyCallableName(test) /* passed */ {
|
|
63
|
-
/*
|
|
64
|
-
or a nonce method for a property
|
|
80
|
+
/* Name is of the method named in test,
|
|
81
|
+
or a nonce method for a property or
|
|
82
|
+
any poly-call test (method or prop). */
|
|
65
83
|
|
|
84
|
+
// Two most common cases: mono-call
|
|
85
|
+
// test of a method or property.
|
|
66
86
|
let name = test.isMethodTest
|
|
67
87
|
? NameAnalyzer.plainNameOf(test.method)
|
|
68
88
|
: TestDef.nonceLocalCallableName;
|
|
69
89
|
|
|
90
|
+
// Rare cases: poly-call tests
|
|
91
|
+
// of a method or property.
|
|
92
|
+
if (test.isPolyCallTest) {
|
|
93
|
+
name = TestDef.nonceLocalCallableName;
|
|
94
|
+
}
|
|
95
|
+
|
|
70
96
|
return name;
|
|
71
97
|
}
|
|
72
98
|
|
|
73
|
-
anyPostTargetingGroundwork(test) /* passed */ {
|
|
99
|
+
async anyPostTargetingGroundwork(test) /* passed */ {
|
|
74
100
|
// Spoofing properties; methods spoofed earlier.
|
|
75
101
|
TestStages.#propertySpoofer.spoof(test);
|
|
76
102
|
|
|
77
103
|
// Arbitrary user-defined actions.
|
|
78
104
|
// All spoofs normally available.
|
|
79
105
|
if (test.doesHaveDoLate) {
|
|
80
|
-
test.do.late(test);
|
|
106
|
+
await test.do.late(test);
|
|
81
107
|
}
|
|
82
108
|
}
|
|
83
109
|
|
|
@@ -99,7 +125,7 @@ export default class TestStages {
|
|
|
99
125
|
return TestStages.#comparer.compare(expected, actual);
|
|
100
126
|
}
|
|
101
127
|
|
|
102
|
-
anyGroundworkReversal(test) /* passed */ {
|
|
128
|
+
async anyGroundworkReversal(test) /* passed */ {
|
|
103
129
|
// Unspoofing methods and properties.
|
|
104
130
|
TestStages.#methodSpoofer.unspoof(test);
|
|
105
131
|
TestStages.#propertySpoofer.unspoof(test);
|
|
@@ -107,12 +133,42 @@ export default class TestStages {
|
|
|
107
133
|
// Arbitrary user-defined operations.
|
|
108
134
|
// No spoofs are available here.
|
|
109
135
|
if (test.doesHaveUndo) {
|
|
110
|
-
test.undo(test);
|
|
136
|
+
await test.undo(test);
|
|
111
137
|
}
|
|
112
138
|
}
|
|
113
139
|
|
|
114
140
|
// region Dependencies of test stages
|
|
115
141
|
|
|
142
|
+
supplyPolyMethodNonce(test, callable) /* verified */ {
|
|
143
|
+
let nonce = (...inputs) => {
|
|
144
|
+
let actuals = [];
|
|
145
|
+
|
|
146
|
+
for (let args of inputs) {
|
|
147
|
+
let local = test.target[callable](...args);
|
|
148
|
+
actuals.push(local);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return actuals;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
return nonce;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
supplyPolyPropNonce(test, callable) /* verified */ {
|
|
158
|
+
let nonce = (...inputs) => {
|
|
159
|
+
let actuals = [];
|
|
160
|
+
|
|
161
|
+
for (let args of inputs) {
|
|
162
|
+
let local = test.target[callable];
|
|
163
|
+
actuals.push(local);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return actuals;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
return nonce;
|
|
170
|
+
}
|
|
171
|
+
|
|
116
172
|
supplyNonReturnActual(test) /* passed */ {
|
|
117
173
|
// When .from is a string, the actual
|
|
118
174
|
// is the named target or type member.
|
|
@@ -136,7 +192,7 @@ export default class TestStages {
|
|
|
136
192
|
// given everything that might be needed.
|
|
137
193
|
if (test.from instanceof Function) {
|
|
138
194
|
// Actually supplying value.
|
|
139
|
-
return test.from(test
|
|
195
|
+
return test.from(test, test.actual);
|
|
140
196
|
}
|
|
141
197
|
|
|
142
198
|
// Only property names and functions make sense to support.
|
package/system/TestSummary.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class TestSummary {
|
|
4
|
-
#summary;
|
|
5
|
-
#allDidPass;
|
|
6
|
-
#anyWereRun;
|
|
7
|
-
|
|
8
|
-
get summary() {
|
|
9
|
-
return this.#summary;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
set summary(value) {
|
|
13
|
-
this.#summary = value;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
get allDidPass() {
|
|
17
|
-
return this.#allDidPass;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
set allDidPass(value) {
|
|
21
|
-
this.#allDidPass = value;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get anyWereRun() {
|
|
25
|
-
return this.#anyWereRun;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
set anyWereRun(value) {
|
|
29
|
-
this.#anyWereRun = value;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
constructor(summary, allDidPass, anyWereRun) {
|
|
33
|
-
this.summary = summary;
|
|
34
|
-
this.allDidPass = allDidPass;
|
|
35
|
-
this.anyWereRun = anyWereRun;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
1
|
+
/**/
|
|
2
|
+
|
|
3
|
+
export default class TestSummary {
|
|
4
|
+
#summary;
|
|
5
|
+
#allDidPass;
|
|
6
|
+
#anyWereRun;
|
|
7
|
+
|
|
8
|
+
get summary() {
|
|
9
|
+
return this.#summary;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
set summary(value) {
|
|
13
|
+
this.#summary = value;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get allDidPass() {
|
|
17
|
+
return this.#allDidPass;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
set allDidPass(value) {
|
|
21
|
+
this.#allDidPass = value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get anyWereRun() {
|
|
25
|
+
return this.#anyWereRun;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
set anyWereRun(value) {
|
|
29
|
+
this.#anyWereRun = value;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
constructor(summary, allDidPass, anyWereRun) {
|
|
33
|
+
this.summary = summary;
|
|
34
|
+
this.allDidPass = allDidPass;
|
|
35
|
+
this.anyWereRun = anyWereRun;
|
|
36
|
+
}
|
|
37
|
+
}
|
package/system/TypeAnalyzer.js
CHANGED
|
@@ -45,40 +45,93 @@ export default class TypeAnalyzer {
|
|
|
45
45
|
/* Returns true if instance or static member is a method.
|
|
46
46
|
Returns false if member is any kind of property. */
|
|
47
47
|
static isMethodMember(type, name) /* passed */ {
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
return !TypeAnalyzer.isPropertyMember(type, name);
|
|
49
|
+
}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
/* Returns true if instance or static member is a property
|
|
52
|
+
(value or accessor). Returns false if member is a method. */
|
|
53
|
+
static isPropertyMember(type, name) /* passed */ {
|
|
54
|
+
/* Type and supertypes are tested directly for static props,
|
|
55
|
+
and their definition texts are read for instance props. */
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
let isInstanceMethod = anyInstanceType === Types.isFunction;
|
|
57
|
-
let isStaticMethod = anyStaticType === Types.isFunction;
|
|
57
|
+
let isProperty = this.#typeChainIncludesAsProperty(type, name);
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
return isProperty;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static #typeChainIncludesAsProperty(type, name) /* verified */ {
|
|
63
|
+
let prototype = type.prototype;
|
|
64
|
+
|
|
65
|
+
while (prototype !== null) {
|
|
66
|
+
// Type is needed, rather than prototype.
|
|
67
|
+
type = prototype.constructor;
|
|
68
|
+
|
|
69
|
+
// First line finds any static props; second, any instance props.
|
|
70
|
+
let isProperty
|
|
71
|
+
= TypeAnalyzer.#typeDefinitionIncludesAsProperty(type, name)
|
|
72
|
+
|| TypeAnalyzer.#typeTextContainsNameAsProperty(type, name);
|
|
73
|
+
|
|
74
|
+
// Found as static or instance.
|
|
75
|
+
if (isProperty) {
|
|
76
|
+
return true;
|
|
69
77
|
}
|
|
70
78
|
|
|
71
|
-
|
|
72
|
-
|
|
79
|
+
// Parent class.
|
|
80
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
81
|
+
|
|
82
|
+
if (prototype === null) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
73
85
|
}
|
|
74
86
|
|
|
75
|
-
|
|
76
|
-
|
|
87
|
+
// Never found.
|
|
88
|
+
return false;
|
|
77
89
|
}
|
|
78
90
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
static #typeDefinitionIncludesAsProperty(type, name) /* verified */ {
|
|
92
|
+
let named = Object.getOwnPropertyDescriptor(type, name);
|
|
93
|
+
|
|
94
|
+
// If not found, try parent.
|
|
95
|
+
if (named === undefined) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Members with getters are properties.
|
|
100
|
+
if (named.get !== undefined) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Members with function values are methods.
|
|
105
|
+
if (named.value instanceof Function) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Members with any other values are properties.
|
|
110
|
+
if (named.value !== undefined) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static #typeTextContainsNameAsProperty(type, name) /* verified */ {
|
|
116
|
+
let text = type.toString();
|
|
117
|
+
|
|
118
|
+
// Instance properties are always defined as 'name =',
|
|
119
|
+
// 'name;', or 'get name()' at the start of a line.
|
|
120
|
+
let valueRegex = new RegExp(`^\\s*${ name }\\s*[=;]`, "m");
|
|
121
|
+
let accessorRegex = new RegExp(`^\\s*get ${ name }\\(\\)`, "m");
|
|
122
|
+
|
|
123
|
+
let anyIndexOf = text.search(valueRegex);
|
|
124
|
+
|
|
125
|
+
if (anyIndexOf >= 0) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
anyIndexOf = text.search(accessorRegex);
|
|
130
|
+
|
|
131
|
+
if (anyIndexOf >= 0) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return false;
|
|
83
136
|
}
|
|
84
137
|
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
/* ChosenTestFinder is an ATestFinder that finds tests in the places coded in its constructor. */
|
|
4
|
-
|
|
5
|
-
import ATestFinder from "./ATestFinder.js";
|
|
6
|
-
import TopicTests from "../trial-tests/TopicTests.outward-rt.js";
|
|
7
|
-
import SelfTests from "../trial-tests/SelfTests.outward-rt.js";
|
|
8
|
-
|
|
9
|
-
export default class ChosenTestFinder extends ATestFinder {
|
|
10
|
-
constructor() {
|
|
11
|
-
super();
|
|
12
|
-
|
|
13
|
-
let testSource = new TopicTests();
|
|
14
|
-
let selfTestSource = new SelfTests();
|
|
15
|
-
|
|
16
|
-
this.testSources = [ testSource, selfTestSource ];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async findAllTests() {
|
|
20
|
-
let tests = [];
|
|
21
|
-
|
|
22
|
-
for (let source of this.testSources) {
|
|
23
|
-
let local = source.tests;
|
|
24
|
-
tests.push(...local);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Returning an awaitable value
|
|
28
|
-
// to match async signature.
|
|
29
|
-
return Promise.resolve(tests);
|
|
30
|
-
}
|
|
31
|
-
}
|
package/system/Risei.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
/* Copyright (c) 2023-2024 Ed Fallin. Published under the terms of the MIT license. */
|
|
4
|
-
|
|
5
|
-
/* This index.js is the entry point for running Risei tests from
|
|
6
|
-
other code. It imports other modules to perform its work.
|
|
7
|
-
It also exports modules that should / can be subclassed. */
|
|
8
|
-
|
|
9
|
-
// region Imports
|
|
10
|
-
|
|
11
|
-
// region Test-running dependencies
|
|
12
|
-
|
|
13
|
-
import TestRunner from "./TestRunner.js";
|
|
14
|
-
import LocalCaller from "./LocalCaller.js";
|
|
15
|
-
import TerminalReporter from "./TerminalReporter.js";
|
|
16
|
-
import TestFinder from "./TestFinder.js";
|
|
17
|
-
|
|
18
|
-
// endregion Test-running dependencies
|
|
19
|
-
|
|
20
|
-
// region Display dependencies
|
|
21
|
-
|
|
22
|
-
import chalk from "chalk";
|
|
23
|
-
import Moment from "./Moment.js";
|
|
24
|
-
|
|
25
|
-
// endregion Display dependencies
|
|
26
|
-
|
|
27
|
-
// endregion Imports
|
|
28
|
-
|
|
29
|
-
// region Named styles
|
|
30
|
-
|
|
31
|
-
/* Display styles for the start title and other general needs. */
|
|
32
|
-
const title = chalk.hex("FFFFFF").bgHex("191970").bold;
|
|
33
|
-
const fails = chalk.hex("000000").bgHex("FFD700").bold;
|
|
34
|
-
|
|
35
|
-
// endregion Named styles
|
|
36
|
-
|
|
37
|
-
// region Styling for color stripes
|
|
38
|
-
|
|
39
|
-
let wide = (text) => {
|
|
40
|
-
let width = process.stdout.columns;
|
|
41
|
-
text = text || "";
|
|
42
|
-
|
|
43
|
-
return text.padEnd(width, "\u00A0");
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// endregion Styling for color stripes
|
|
47
|
-
|
|
48
|
-
// region Key callable and its scripted call
|
|
49
|
-
|
|
50
|
-
async function runRiseiMetaTests(testFinderPath) {
|
|
51
|
-
// region Converting test-finder from path to class
|
|
52
|
-
|
|
53
|
-
testFinderPath = testFinderPath || "./TestFinder.js";
|
|
54
|
-
let finderModule = await import(testFinderPath);
|
|
55
|
-
|
|
56
|
-
let moduleKeys = Object.keys(finderModule);
|
|
57
|
-
let classKey = moduleKeys[0];
|
|
58
|
-
let finderClass = finderModule[classKey];
|
|
59
|
-
|
|
60
|
-
// endregion Converting test-finder from path to class
|
|
61
|
-
|
|
62
|
-
// region Intro / title
|
|
63
|
-
|
|
64
|
-
console.clear();
|
|
65
|
-
console.log();
|
|
66
|
-
console.log(title(wide()));
|
|
67
|
-
|
|
68
|
-
let now = new Date();
|
|
69
|
-
now = new Moment(now);
|
|
70
|
-
|
|
71
|
-
console.log(title(wide(` Risei tests run on ${ now.asReadable() } local time.`)));
|
|
72
|
-
console.log(title(wide()));
|
|
73
|
-
|
|
74
|
-
console.log();
|
|
75
|
-
|
|
76
|
-
// endregion Intro / title
|
|
77
|
-
|
|
78
|
-
// region Running tests
|
|
79
|
-
|
|
80
|
-
// Test-system objects and their relationships.
|
|
81
|
-
const finder = new finderClass.prototype.constructor();
|
|
82
|
-
finder.sourceBySearch = () => { return { tests: "**.outward-rt.js" }; };
|
|
83
|
-
|
|
84
|
-
const runner = new TestRunner();
|
|
85
|
-
const reporter = new TerminalReporter();
|
|
86
|
-
|
|
87
|
-
const caller = new LocalCaller(finder, runner, reporter);
|
|
88
|
-
|
|
89
|
-
// Actually running the tests using this system.
|
|
90
|
-
await caller.runAllTests();
|
|
91
|
-
|
|
92
|
-
// endregion Running tests
|
|
93
|
-
|
|
94
|
-
// region Trailing display of test-loading issues
|
|
95
|
-
|
|
96
|
-
if (finder.thrown.length !== 0) {
|
|
97
|
-
let loadFails = finder.thrown;
|
|
98
|
-
|
|
99
|
-
for (let fail of loadFails) {
|
|
100
|
-
console.log(fails(wide(` ${ fail }`)));
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// endregion Trailing display of test-loading issues
|
|
105
|
-
|
|
106
|
-
// region Trailing formatting
|
|
107
|
-
|
|
108
|
-
console.log();
|
|
109
|
-
console.log();
|
|
110
|
-
|
|
111
|
-
// endregion Trailing formatting
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/* Runs tests now. */
|
|
115
|
-
await runRiseiMetaTests();
|
|
116
|
-
|
|
117
|
-
// endregion Key callable and its scripted call
|
|
118
|
-
|