risei 2.0.1 → 3.1.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 +50 -28
- package/index.js +18 -66
- package/package.json +7 -6
- package/system/CallTypes.js +10 -0
- package/system/Choices.js +92 -0
- package/system/ClassTestGroup.js +8 -8
- package/system/LocalCaller.js +47 -7
- 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/ObjectAnalyzer.js +36 -0
- package/system/PropertySpoofer.js +1 -1
- package/system/SpoofDef.js +73 -63
- package/system/TerminalReporter.js +102 -25
- package/system/TestDef.js +75 -17
- package/system/TestFinder.js +31 -29
- package/system/TestFrame.js +21 -12
- package/system/TestGroup.js +25 -25
- package/system/TestResult.js +63 -13
- package/system/TestRunner.js +44 -16
- package/system/TestStages.js +85 -26
- package/system/TestSummary.js +38 -37
- package/system/TotalComparer.js +54 -17
- package/system/TotalDisplayer.js +29 -6
- package/system/TypeAnalyzer.js +117 -26
- package/system/TypeIdentifier.js +10 -6
- package/system/Types.js +1 -0
- package/system/ATestCaller.js +0 -61
- package/system/ATestFinder.js +0 -38
- package/system/ATestReporter.js +0 -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
|
|
49
|
+
Risei's major features are now complete, but new enhancements or fixes may appear from time to time. The latest release, **3.1.0**, includes significant improvements and bug fixes, on top of the major improvements in releases **3.0.0** and **2.0.0**.
|
|
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
|
|
|
@@ -89,6 +91,9 @@ And add Risei's metadata to `package.json`:
|
|
|
89
91
|
}
|
|
90
92
|
```
|
|
91
93
|
|
|
94
|
+
## Testing Risei
|
|
95
|
+
|
|
96
|
+
To test Risei, you clone it from a parallel [repository](https://gitlab.com/riseimaker/risei-public.git), install its dependencies, and run its self-tests. See the full explanation [here](https://deusware.com/risei/index.html#self-testing).
|
|
92
97
|
|
|
93
98
|
|
|
94
99
|
## Running Tests
|
|
@@ -140,11 +145,11 @@ tests = [ ...
|
|
|
140
145
|
... ];
|
|
141
146
|
```
|
|
142
147
|
|
|
148
|
+
- Asynchronous code with `async` and `await` keywords can tested with no changes at all to this syntax.
|
|
143
149
|
- Use empty arrays for `.in` or `.with` when there are no args to pass.
|
|
144
150
|
- You can use [long names](https://deusware.com/risei/index.html#long-names) for properties if you want.
|
|
145
151
|
|
|
146
152
|
|
|
147
|
-
|
|
148
153
|
## Basic collapsing forward example
|
|
149
154
|
|
|
150
155
|
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 +192,7 @@ The most basic spoofing looks like this:
|
|
|
187
192
|
}
|
|
188
193
|
```
|
|
189
194
|
|
|
195
|
+
- It's just like _fakes_, _mocks_, or _test doubles_ in other test systems, but easier to write and read.
|
|
190
196
|
- Numerous additional capabilities, as well as compressed syntax, can be mixed freely in many ways.
|
|
191
197
|
- Learn more [here](https://deusware.com/risei/index.html#spoofing).
|
|
192
198
|
|
|
@@ -202,16 +208,40 @@ To test TypeScript code with Risei, you make sure the code is transpiled before
|
|
|
202
208
|
|
|
203
209
|
## Troubleshooting
|
|
204
210
|
|
|
205
|
-
If problems cause test files not to load, a gold bar
|
|
211
|
+
If errors are thrown while testing, gold bars listing them appear at the bottom, and full stack traces appear amid the test output. If problems cause test files not to load, a gold bar with the error message also appears:
|
|
206
212
|
|
|
207
213
|

|
|
208
214
|
|
|
215
|
+
- If files don't load, tests in those files disappear from the output and the totals.
|
|
209
216
|
- Those and other problems can be solved with the help of this [troubleshooting guide](https://deusware.com/risei/index.html#troubleshooting).
|
|
210
217
|
|
|
211
218
|
|
|
219
|
+
|
|
212
220
|
## Version history
|
|
213
221
|
|
|
214
|
-
- Release **
|
|
222
|
+
- Release **3.1.0** (January, 2025) contains these changes:
|
|
223
|
+
- Accessor properties (formally _accessor descriptors_) are now compared for test results and displayed in test outputs.
|
|
224
|
+
- Any accessor properties that throw errors during display are displayed as `(threw)`.
|
|
225
|
+
- Throws in tested code and in test framing code are now listed at the end and displayed amid the tests.
|
|
226
|
+
- `File` objects now have a succinct custom display in outputs.
|
|
227
|
+
- **(Breaking change)** In `constructor` tests, constructed instances are available in `.from` functions only as `actual` / `test.actual`.
|
|
228
|
+
- **(Breaking change)** In `constructor` tests, `test.target` is now the `prototype` of the tested class.
|
|
229
|
+
- Widespread internal reengineering of other kinds.
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
<details>
|
|
234
|
+
<summary>
|
|
235
|
+
Older releases
|
|
236
|
+
</summary>
|
|
237
|
+
|
|
238
|
+
- Release **3.0.0** (August, 2024) contained all of these changes:
|
|
239
|
+
- Asynchronous code with `async` syntax is now supported, with no special test syntax.
|
|
240
|
+
- **(Breaking change)** `.from` functions now take `test` and `actual` as parameters, rather than `target` and `test`.
|
|
241
|
+
- 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`.
|
|
242
|
+
- You can now call target code more than once in one test using an `.and` of `"poly"` (AKA _poly-calling_).
|
|
243
|
+
|
|
244
|
+
- Release **2.0.0** / **2.0.1** (August, 2024) contained all of these changes:
|
|
215
245
|
- Risei now can determine automatically if tested methods are static.
|
|
216
246
|
- You can now directly test properties just like methods.
|
|
217
247
|
- Risei can also determine automatically if these are static.
|
|
@@ -221,46 +251,38 @@ If problems cause test files not to load, a gold bar appears and tests in those
|
|
|
221
251
|
- You can now change test properties without accidentally creating a new test using `.just`.
|
|
222
252
|
- You can now directly test for `undefined` in `.out` using `this.undef` / `ATestSource.undefSymbol`.
|
|
223
253
|
- `Error` objects are now compared accurately.
|
|
224
|
-
- You can now identify member types with `.`, `:`, and `()` in `.of`, `.plus`, and `.from`, though
|
|
254
|
+
- You can now identify member types with `.`, `:`, and `()` in any of `.of`, `.plus`, and `.from`, though it isn't necessary.
|
|
225
255
|
- **(Breaking change)** The actual for throw tests is now the entire thrown object (usually an `Error`), rather than the `Error`'s message text.
|
|
226
256
|
- **(Breaking change)** `ATestSource` is now a default export, changing its imports from `import { ATestSource } from` to `import ATestSource from`.
|
|
257
|
+
- Major internal re-engineering.
|
|
227
258
|
|
|
228
|
-
>
|
|
229
|
-
|
|
259
|
+
> Older releases are dropped from this list progressively over time. Using the latest release is recommended.
|
|
230
260
|
|
|
261
|
+
</details>
|
|
231
262
|
|
|
232
|
-
<details>
|
|
233
|
-
<summary>
|
|
234
|
-
Older releases
|
|
235
|
-
</summary>
|
|
236
263
|
|
|
237
|
-
- Release **2.0.0** (August, 2024) is identical to 2.0.1 except for some unneeded extra files.
|
|
238
|
-
- Release **1.3.4** (March, 2024) fixed a bug that caused class display problems in some cases.
|
|
239
|
-
- Release **1.3.3** (March, 2024) fixed a major bug that prevented tests from running in Windows.
|
|
240
|
-
- Release **1.3.2** (February, 2024) only improved this read-me's contents.
|
|
241
|
-
- Release **1.3.1** (February, 2024) reversed some changes in 1.3.0 that did not work as hoped.
|
|
242
|
-
- Release **1.3.0** (February, 2024) added the loading-error gold bar and fixed a test-sorting bug.
|
|
243
|
-
- Release **1.2.0** (January, 2024) changed test sorting to move last-edited tests to the end.
|
|
244
|
-
- Release **1.1.2** of Risei (January, 2024) fixed class displays and inaccurate `Date` comparisons.
|
|
245
264
|
|
|
246
|
-
|
|
265
|
+
## Known issues and workarounds
|
|
247
266
|
|
|
248
|
-
|
|
267
|
+
There are two minor issues at present:
|
|
249
268
|
|
|
269
|
+
- If args for a test are mutated by tested code, the mutated args are used when collapsing forward.
|
|
270
|
+
- The workaround is just to restate those args for each test.
|
|
250
271
|
|
|
251
|
-
## Known issues and workarounds
|
|
252
272
|
|
|
253
|
-
|
|
273
|
+
- Spoofing accessor properties only works when they have both a getter and a setter.
|
|
274
|
+
- The workaround is to find another way to produce the property values you need.
|
|
254
275
|
|
|
255
|
-
- The workaround is just to restate those args for each test.
|
|
256
276
|
|
|
257
277
|
|
|
258
278
|
## Exclusions from Risei
|
|
259
279
|
|
|
260
|
-
At present, there are a few things Risei doesn't support
|
|
280
|
+
At present, there are a few things Risei doesn't support. Some of these may be supported in the future.
|
|
261
281
|
|
|
262
282
|
- You can see the whole list [here](https://deusware.com/risei/index.html#exclusions-from-risei).
|
|
263
|
-
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
Risei can be run alongside other test frameworks, so if you can't test all of your code with Risei, you can still save a lot of time by using Risei to test the bulk of it.
|
|
264
286
|
|
|
265
287
|
|
|
266
288
|
|
|
@@ -280,7 +302,7 @@ Risei is published for use under the terms of the MIT license:
|
|
|
280
302
|
|
|
281
303
|
<div style="border: solid darkgray 1px; padding: 0.5rem;">
|
|
282
304
|
|
|
283
|
-
<b>Risei Copyright © 2023–
|
|
305
|
+
<b>Risei Copyright © 2023–2025 Ed Fallin</b>
|
|
284
306
|
|
|
285
307
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
286
308
|
|
package/index.js
CHANGED
|
@@ -8,60 +8,21 @@
|
|
|
8
8
|
|
|
9
9
|
// region Imports
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
import TerminalReporter from "./system/TerminalReporter.js";
|
|
13
12
|
import TestRunner from "./system/TestRunner.js";
|
|
14
13
|
import LocalCaller from "./system/LocalCaller.js";
|
|
15
|
-
import TerminalReporter from "./system/TerminalReporter.js";
|
|
16
14
|
import TestFinder from "./system/TestFinder.js";
|
|
17
15
|
|
|
18
|
-
// endregion Test-running dependencies
|
|
19
|
-
|
|
20
|
-
// region Display dependencies
|
|
21
|
-
|
|
22
|
-
import chalk from "chalk";
|
|
23
|
-
import Moment from "./system/Moment.js";
|
|
24
|
-
|
|
25
|
-
// endregion Display dependencies
|
|
26
|
-
|
|
27
16
|
// endregion Imports
|
|
28
17
|
|
|
29
18
|
// region Exports
|
|
30
19
|
|
|
31
|
-
|
|
20
|
+
/* Class that users subclass for test classes. */
|
|
32
21
|
|
|
33
22
|
export * from "./system/ATestSource.js";
|
|
34
23
|
|
|
35
|
-
// endregion Classes that users typically subclass
|
|
36
|
-
|
|
37
|
-
// region Classes that users might subclass for uncommon cases
|
|
38
|
-
|
|
39
|
-
export * from "./system/ATestFinder.js";
|
|
40
|
-
export * from "./system/ATestReporter.js";
|
|
41
|
-
|
|
42
|
-
// endregion Classes that users might subclass for uncommon cases
|
|
43
|
-
|
|
44
24
|
// endregion Exports
|
|
45
25
|
|
|
46
|
-
// region Named styles
|
|
47
|
-
|
|
48
|
-
/* Display styles for the start title and other general needs. */
|
|
49
|
-
const title = chalk.hex("FFFFFF").bgHex("191970").bold;
|
|
50
|
-
const fails = chalk.hex("000000").bgHex("FFD700").bold;
|
|
51
|
-
|
|
52
|
-
// endregion Named styles
|
|
53
|
-
|
|
54
|
-
// region Styling for color stripes
|
|
55
|
-
|
|
56
|
-
let wide = (text) => {
|
|
57
|
-
let width = process.stdout.columns;
|
|
58
|
-
text = text || "";
|
|
59
|
-
|
|
60
|
-
return text.padEnd(width, "\u00A0");
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// endregion Styling for color stripes
|
|
64
|
-
|
|
65
26
|
// region Key callable, its scripted call, and its export
|
|
66
27
|
|
|
67
28
|
async function runRiseiTests(testFinderPath) {
|
|
@@ -76,30 +37,21 @@ async function runRiseiTests(testFinderPath) {
|
|
|
76
37
|
|
|
77
38
|
// endregion Converting test-finder from path to class
|
|
78
39
|
|
|
40
|
+
let reporter = new TerminalReporter();
|
|
41
|
+
|
|
79
42
|
// region Intro / title
|
|
80
43
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
let now = new Date();
|
|
86
|
-
now = new Moment(now);
|
|
87
|
-
|
|
88
|
-
console.log(title(wide(` Risei tests run on ${ now.asReadable() } local time.`)));
|
|
89
|
-
console.log(title(wide()));
|
|
90
|
-
|
|
91
|
-
console.log();
|
|
92
|
-
|
|
93
|
-
// endregion Intro / title
|
|
44
|
+
reporter.reportTitle();
|
|
45
|
+
|
|
46
|
+
// // endregion Intro / title
|
|
94
47
|
|
|
95
48
|
// region Running tests
|
|
96
49
|
|
|
97
50
|
// Test-system objects and their relationships.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const caller = new LocalCaller(finder, runner, reporter);
|
|
51
|
+
let finder = new finderClass.prototype.constructor();
|
|
52
|
+
let runner = new TestRunner();
|
|
53
|
+
|
|
54
|
+
let caller = new LocalCaller(finder, runner, reporter);
|
|
103
55
|
|
|
104
56
|
// Actually running the tests using this system.
|
|
105
57
|
await caller.runAllTests();
|
|
@@ -109,20 +61,20 @@ async function runRiseiTests(testFinderPath) {
|
|
|
109
61
|
// region Trailing display of test-loading issues
|
|
110
62
|
|
|
111
63
|
if (finder.thrown.length !== 0) {
|
|
64
|
+
reporter.blankLine();
|
|
65
|
+
|
|
112
66
|
let loadFails = finder.thrown;
|
|
113
67
|
|
|
114
68
|
for (let fail of loadFails) {
|
|
115
|
-
|
|
69
|
+
reporter.reportLoadFail(fail);
|
|
116
70
|
}
|
|
117
71
|
}
|
|
118
72
|
|
|
119
|
-
// endregion Trailing display of test-loading issues
|
|
120
|
-
|
|
121
73
|
// region Trailing formatting
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
74
|
+
|
|
75
|
+
reporter.blankLine();
|
|
76
|
+
reporter.blankLine();
|
|
77
|
+
|
|
126
78
|
// endregion Trailing formatting
|
|
127
79
|
}
|
|
128
80
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "risei",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.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",
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"private": false,
|
|
25
25
|
"scripts": {
|
|
26
26
|
"start": "node ./bin/www",
|
|
27
|
-
"rself": "clear && node
|
|
27
|
+
"rself": "clear && node ./TrialTests.js",
|
|
28
28
|
"rtest": "clear && node ./node_modules/risei/index.js",
|
|
29
29
|
"xtest": "clear && mocha **/*.tests.js",
|
|
30
30
|
"mixedtest": "clear && mocha **/*.tests.js; node ./node_modules/risei/index.js",
|
|
31
|
-
"alltest": "clear && mocha **/*.tests.js; node ./node_modules/risei/index.js; node
|
|
31
|
+
"alltest": "clear && mocha **/*.tests.js; node ./node_modules/risei/index.js; node ./TrialTests.js",
|
|
32
32
|
"test": "clear && node ./node_modules/risei/index.js"
|
|
33
33
|
},
|
|
34
34
|
"risei": {
|
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"chalk": "^5.0.0",
|
|
43
43
|
"fs": "^0.0.1-security",
|
|
44
|
-
"minimatch": "^9.0.1"
|
|
44
|
+
"minimatch": "^9.0.1",
|
|
45
|
+
"npm": "^11.0.0",
|
|
46
|
+
"risei": "^3.0.0"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
47
49
|
"chai": "^4.3.6",
|
|
@@ -49,7 +51,6 @@
|
|
|
49
51
|
"debug": "~2.6.9",
|
|
50
52
|
"fs": "^0.0.1-security",
|
|
51
53
|
"mocha": "^10.0.0",
|
|
52
|
-
"morgan": "~1.9.1"
|
|
53
|
-
"risei": "^1.3.4"
|
|
54
|
+
"morgan": "~1.9.1"
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**/
|
|
2
|
+
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
|
|
6
|
+
export default class Choices {
|
|
7
|
+
// region Definitions
|
|
8
|
+
|
|
9
|
+
static METADATA_FILE = "package.json";
|
|
10
|
+
static TESTS_PROP = "tests";
|
|
11
|
+
|
|
12
|
+
// endregion Definitions
|
|
13
|
+
|
|
14
|
+
// region Static fields
|
|
15
|
+
|
|
16
|
+
// Local copy of package.json's .risei node.
|
|
17
|
+
static #node;
|
|
18
|
+
|
|
19
|
+
// endregion Static fields
|
|
20
|
+
|
|
21
|
+
// region Static choice properties
|
|
22
|
+
|
|
23
|
+
static get testTargeting() /* verified */ {
|
|
24
|
+
let tests = Choices.#supplyOrThrow(Choices.TESTS_PROP);
|
|
25
|
+
return tests;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// endregion Static choice properties
|
|
29
|
+
|
|
30
|
+
// region Dependencies of static properties
|
|
31
|
+
|
|
32
|
+
/* Used for properties that are always needed. */
|
|
33
|
+
static #supplyOrThrow(prop) /* verified */ {
|
|
34
|
+
Choices.#maybeSetNode();
|
|
35
|
+
Choices.#throwWhenMissing(prop);
|
|
36
|
+
return Choices.#node[prop];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Used for properties that aren't always needed. */
|
|
40
|
+
static #supplyOrUndef(prop) /* verified */ {
|
|
41
|
+
Choices.#maybeSetNode();
|
|
42
|
+
|
|
43
|
+
if (!Choices.#nodeContains(prop)) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return Choices.#node[prop];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static #maybeSetNode() /* verified */ {
|
|
51
|
+
if (Choices.#node === undefined) {
|
|
52
|
+
Choices.#setNode();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// To init hidden Singleton instance.
|
|
57
|
+
static #setNode() /* verified */ {
|
|
58
|
+
// App's package.json always found at process.cwd().
|
|
59
|
+
let packageSite = process.cwd();
|
|
60
|
+
let pathAndName = path.join(packageSite, Choices.METADATA_FILE);
|
|
61
|
+
|
|
62
|
+
// Contents of package.json are just a single JSON object.
|
|
63
|
+
let packageJson = fs.readFileSync(pathAndName, { encoding: "utf8" });
|
|
64
|
+
packageJson = JSON.parse(packageJson);
|
|
65
|
+
|
|
66
|
+
// Can't run or reasonably recover if this is not defined.
|
|
67
|
+
if (packageJson.risei === undefined) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`For Risei tests to run, this app's package.json must contain `
|
|
70
|
+
+ `a node like this: "risei": { tests: "path-or-glob-here" }. `
|
|
71
|
+
+ `One glob or path may be used, or an array of them.`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Only Risei's own metadata is needed.
|
|
75
|
+
Choices.#node = packageJson.risei;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static #throwWhenMissing(prop) /* verified */ {
|
|
79
|
+
if (!Choices.#nodeContains(prop)) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
`The property .${ prop } is not defined `
|
|
82
|
+
+ `for .risei in package.json.`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static #nodeContains(prop) /* verified */ {
|
|
88
|
+
return prop in Choices.#node;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// endregion Dependencies of static properties
|
|
92
|
+
}
|
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
|
@@ -1,21 +1,61 @@
|
|
|
1
1
|
/**/
|
|
2
2
|
|
|
3
|
-
/* LocalCaller
|
|
4
|
-
|
|
3
|
+
/* LocalCaller has TestRunner run each test in turn on the server,
|
|
4
|
+
without HTTP calls from a browser or other external source. */
|
|
5
5
|
|
|
6
|
-
import ATestFinder from "./ATestFinder.js";
|
|
7
|
-
import ATestCaller from "./ATestCaller.js";
|
|
8
6
|
import TerminalReporter from "./TerminalReporter.js";
|
|
9
7
|
import TestRunner from "./TestRunner.js";
|
|
10
8
|
|
|
11
|
-
export default class LocalCaller
|
|
9
|
+
export default class LocalCaller {
|
|
10
|
+
// region Fields
|
|
11
|
+
|
|
12
|
+
#finder;
|
|
13
|
+
#runner;
|
|
14
|
+
#reporter;
|
|
15
|
+
|
|
16
|
+
// endregion Fields
|
|
17
|
+
|
|
18
|
+
// region Properties
|
|
19
|
+
|
|
20
|
+
get finder() {
|
|
21
|
+
return this.#finder;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
set finder(value) {
|
|
25
|
+
this.#finder = value;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get runner() {
|
|
29
|
+
return this.#runner;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
set runner(value) {
|
|
33
|
+
this.#runner = value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get reporter() {
|
|
37
|
+
return this.#reporter;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
set reporter(value) {
|
|
41
|
+
this.#reporter = value;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// endregion Properties
|
|
45
|
+
|
|
46
|
+
constructor(finder, runner, reporter) {
|
|
47
|
+
this.#finder = finder;
|
|
48
|
+
this.#runner = runner;
|
|
49
|
+
this.#reporter = reporter;
|
|
50
|
+
}
|
|
51
|
+
|
|
12
52
|
async runAllTests() {
|
|
13
53
|
let tests = await this.finder.findAllTests();
|
|
14
|
-
this.runner.useTests(tests);
|
|
54
|
+
this.runner.useTests(tests);
|
|
15
55
|
|
|
16
56
|
// Getting each run test / summary result
|
|
17
57
|
// and having it reported in the terminal.
|
|
18
|
-
for (let result of this.runner) {
|
|
58
|
+
for await (let result of this.runner.runTests()) {
|
|
19
59
|
this.reporter.reportNext(result);
|
|
20
60
|
}
|
|
21
61
|
}
|
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
|
+
}
|