risei 1.2.0 → 1.3.1
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 +118 -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} +41 -27
- package/system/TestFinder.js +11 -5
- package/system/TestFrame.js +17 -108
- package/system/TestRunner.js +4 -4
- package/system/TestStages.js +5 -13
- package/system/TotalCopier.js +106 -79
- package/system/TypeAnalyzer.js +103 -103
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
## What Risei is
|
|
5
5
|
|
|
6
6
|
**Risei is a new way to write unit tests that allows you to:**
|
|
7
|
-
* Whip up full test coverage of object-oriented or object-hosted JavaScript in no time.
|
|
7
|
+
* Whip up full test coverage of object-oriented or object-hosted JavaScript and TypeScript in no time.
|
|
8
8
|
* Refactor or replace existing designs without worrying about the cost in past or future test time.
|
|
9
9
|
* Create tests with immediate confidence, because you can't introduce mistakes in test code you write.
|
|
10
10
|
|
|
@@ -41,7 +41,11 @@ Test runs also feature a title bar at the top, as well as a summary bar at the b
|
|
|
41
41
|
|
|
42
42
|
## Using Risei
|
|
43
43
|
|
|
44
|
-
Risei is under active development. If you've been here before, check out [what's new in Risei](#whats-new-in-risei) for the latest. Also see [known
|
|
44
|
+
Risei is under active development. If you've been here before, check out [what's new in Risei](#whats-new-in-risei) for the latest. Also see [known issues and workarounds](#known-issues-and-workarounds) and [limitations in Risei](#limitations-in-risei).
|
|
45
|
+
|
|
46
|
+
There are a few additional or different steps for [using Typescript with Risei](#using-typescript-with-risei).
|
|
47
|
+
|
|
48
|
+
|
|
45
49
|
|
|
46
50
|
### Installation
|
|
47
51
|
|
|
@@ -65,6 +69,8 @@ And add Risei's metadata to `package.json`:
|
|
|
65
69
|
}
|
|
66
70
|
```
|
|
67
71
|
|
|
72
|
+
Just a [few extra steps](#using-typescript-with-risei) are required for Risei to work with TypeScript.
|
|
73
|
+
|
|
68
74
|
|
|
69
75
|
|
|
70
76
|
### Siting tests
|
|
@@ -117,13 +123,15 @@ You can save a lot of time by putting repeated test properties into an object on
|
|
|
117
123
|
{ of: "countOf", for: "Returns the number present.", in: [ "b" ], out: 2 }
|
|
118
124
|
```
|
|
119
125
|
|
|
120
|
-
This _collapsing forward_ works for just about every test property, but is reset when you change the class in `.on`, when you give the property a new value, or you erase it with an empty array `[ ]`.
|
|
126
|
+
- This _collapsing forward_ works for just about every test property, but is reset when you change the class in `.on`, when you give the property a new value, or you erase it with an empty array `[ ]`.
|
|
127
|
+
|
|
128
|
+
- When the tested code mutates the contents of `.with` or `.in`, provide these args as the output of a function or method, because at present, the mutated values are collapsed forward.
|
|
121
129
|
|
|
122
130
|
|
|
123
131
|
|
|
124
132
|
#### Spoof away code dependencies:
|
|
125
133
|
|
|
126
|
-
When your
|
|
134
|
+
When your tests need certain results from code dependencies, just _spoof_ what you want using a `.plus` test property:
|
|
127
135
|
|
|
128
136
|
```javascript
|
|
129
137
|
{ on: CombinerClass, with: [ ],
|
|
@@ -145,7 +153,9 @@ When your code has dependencies on other code, just _spoof_ the results of that
|
|
|
145
153
|
in: [ "green" ], out: [ 7, 8, 9, 10, 10, 11, 12, { color: "green" } ] }
|
|
146
154
|
```
|
|
147
155
|
|
|
148
|
-
|
|
156
|
+
- Spoofing collapses forward across tests, but not across the elements within `.plus`.
|
|
157
|
+
|
|
158
|
+
- Spoofing is also fully isolated within tests.
|
|
149
159
|
|
|
150
160
|
|
|
151
161
|
|
|
@@ -171,15 +181,15 @@ And then run that script:
|
|
|
171
181
|
npm test
|
|
172
182
|
```
|
|
173
183
|
|
|
174
|
-
Risei can be used alongside other test frameworks
|
|
184
|
+
Risei can be used alongside other test frameworks, and even run with them from the same test script if you want.
|
|
175
185
|
|
|
176
186
|
|
|
177
187
|
|
|
178
188
|
### Learning more about Risei
|
|
179
189
|
|
|
180
|
-
|
|
190
|
+
Read through the rest of this doc to learn more about Risei's many capabilities, and about where Risei is headed.
|
|
181
191
|
|
|
182
|
-
- For instance, learn about using `.and` to test static
|
|
192
|
+
- For instance, learn about using `.and` to test static methods or throws.
|
|
183
193
|
- Or learn about using `.from` to test property results or other state.
|
|
184
194
|
- Don't miss out: Once you've tried the basics, read the rest...!
|
|
185
195
|
|
|
@@ -188,6 +198,11 @@ Be sure to read through the rest of this doc to learn more about Risei's many ca
|
|
|
188
198
|
|
|
189
199
|
## Risei in depth
|
|
190
200
|
|
|
201
|
+
<details>
|
|
202
|
+
<summary>
|
|
203
|
+
There's plenty more to learn about Risei and how it makes testing easy...
|
|
204
|
+
</summary>
|
|
205
|
+
|
|
191
206
|
### Installation
|
|
192
207
|
|
|
193
208
|
- You can use any file extension you want in Risei's metadata in `package.json`, and Risei will scan those files for tests.
|
|
@@ -211,6 +226,7 @@ Be sure to read through the rest of this doc to learn more about Risei's many ca
|
|
|
211
226
|
- The order and placement of test properties doesn't matter, although the order seen in the examples is probably most readable.
|
|
212
227
|
|
|
213
228
|
|
|
229
|
+
|
|
214
230
|
#### Basic test properties and options for each:
|
|
215
231
|
|
|
216
232
|
| Name | Contents |
|
|
@@ -226,25 +242,21 @@ Be sure to read through the rest of this doc to learn more about Risei's many ca
|
|
|
226
242
|
- The property names were chosen to be easy to remember and type, but longer alternatives are available, covered later.
|
|
227
243
|
|
|
228
244
|
|
|
229
|
-
</details>
|
|
230
|
-
|
|
231
245
|
|
|
232
246
|
### Test-property reuse _AKA_ Collapsing forward
|
|
233
247
|
|
|
234
248
|
- To save time and effort, any property you write is collapsed forward to subsequent tests unless you replace it or erase it with an empty array `[ ]`.
|
|
235
249
|
- Property values are gathered across partial test objects until they add up to a runnable test, which is then run.
|
|
236
250
|
- Changes to properties are combined with previous ones to produce intended new tests.
|
|
237
|
-
- For a rare and avoidable side-effect of this system, see [
|
|
251
|
+
- For a rare and avoidable side-effect of this system, see [known issues and workarounds](#known-issues-and-workarounds).
|
|
238
252
|
|
|
239
253
|
- Test contents, reused or not, are automatically reset when it makes the most sense:
|
|
240
254
|
- Changing the tested class in `.on` wipes out all prior test properties, so the new class has a fresh start.
|
|
241
255
|
- Changing the tested method in `.of` wipes out only test properties related to methods, to preserve class values you usually want.
|
|
242
256
|
|
|
257
|
+
- Individual tests remain isolated, except for when args are mutable.
|
|
258
|
+
- To use the original, un-mutated args for successive tests, just return them from a function or method to set `.with` or `.in`.
|
|
243
259
|
|
|
244
|
-
- Individual tests remain isolated because class instances, spoofed methods (covered later) and so on are all created anew for each test.
|
|
245
|
-
- However, input (`.in`) and instantiation (`.with`) arguments that are mutated by tested code are not yet isolated.
|
|
246
|
-
- They will be fully isolated in a future release.
|
|
247
|
-
- In the meantime, calling a function to supply them to `.in` or `.with` does isolate them completely.
|
|
248
260
|
|
|
249
261
|
|
|
250
262
|
### Choosing test-only dependency inputs _AKA_ Spoofing
|
|
@@ -257,6 +269,7 @@ Be sure to read through the rest of this doc to learn more about Risei's many ca
|
|
|
257
269
|
- All classes whose members are being spoofed have to be imported.
|
|
258
270
|
|
|
259
271
|
|
|
272
|
+
|
|
260
273
|
#### Spoof-definition properties:
|
|
261
274
|
|
|
262
275
|
| Name | Necessary or Optional | Contents |
|
|
@@ -342,7 +355,7 @@ To test a value that isn't the exercised code's return value, you use `.out` nor
|
|
|
342
355
|
|
|
343
356
|
|
|
344
357
|
- Getting properties, mutated args, and other non-return values is known as _retrieving_.
|
|
345
|
-
- Retrieving definitions collapse forward across tests unless
|
|
358
|
+
- Retrieving definitions collapse forward across tests unless replaced with new definitions, or erased by setting `.from` to an empty array `[ ]`.
|
|
346
359
|
|
|
347
360
|
|
|
348
361
|
<details>
|
|
@@ -446,9 +459,72 @@ Constructors can be tested with no special test properties or keywords.
|
|
|
446
459
|
- Any `.with` args are completely ignored for a constructor test. Only those in the test's `.in` property are used.
|
|
447
460
|
- However, a `.with` must still be provided. It can simply be an empty array `[ ]`.
|
|
448
461
|
|
|
462
|
+
</details>
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
## Using TypeScript with Risei
|
|
468
|
+
|
|
469
|
+
Testing TypeScript code with Risei basically just means transpiling before running the tests, and being sure to point to its output JS files, not the TS ones.
|
|
470
|
+
|
|
471
|
+
- Anything beyond those basics is intended to keep JS files separate from TS files and the output of web frameworks' own, complex build processes.
|
|
472
|
+
|
|
473
|
+
If you follow the general Risei set-up, you can just make the following few modifications for TypeScript applications.
|
|
474
|
+
- These steps have worked with both Angular and React.
|
|
475
|
+
- Variant approaches are also sure to work, depending on the other technical choices in play.
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
### In `package.json`:
|
|
480
|
+
|
|
481
|
+
Add transpilation and deletion operations to the `test` script, with each operation conditional on completion of the preceding one:
|
|
482
|
+
|
|
483
|
+
```json
|
|
484
|
+
"scripts": {
|
|
485
|
+
"test": "tsc && node ./node_modules/risei/index.js && rm -r ./dist/out-tsc"
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
- Generally, you should use `tsc` or another plain transpiler, not web frameworks' complex processes with single output files.
|
|
490
|
+
- Deleting the files at the end prevents interference with web frameworks' bundling.
|
|
491
|
+
- The deletion path must match the `outDir` in `tsconfig.json`.
|
|
492
|
+
|
|
493
|
+
> You can run Risei manually with the same sequence of operations.
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
### In `tsconfig.json`:
|
|
498
|
+
|
|
499
|
+
You set up the transpiler to output files to a directory with these settings:
|
|
500
|
+
|
|
501
|
+
```json
|
|
502
|
+
{
|
|
503
|
+
"outDir": "dist/out-tsc",
|
|
504
|
+
"noEmit": false
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
- The `outDir` can be any location. It's best not to just use `dist`, where adding or deleting files may interfere with web frameworks' build steps.
|
|
509
|
+
- These settings are normally not near each other in the file (as seen here).
|
|
510
|
+
- You can also set the `target` to `es6` or higher, although Risei works fine with ES5.
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
449
514
|
|
|
515
|
+
### In test files:
|
|
450
516
|
|
|
451
|
-
|
|
517
|
+
All `import` statements have to point to the `outDir` path or subfolders there, using relative-path syntax:
|
|
518
|
+
|
|
519
|
+
```javascript
|
|
520
|
+
import { TestedClass } from "../../dist/out-tsc/SubPath/TestedClass.js";
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
- Output files may be in a folder tree parallel to the originals (Angular), or may all be in the `outDir` folder itself (React).
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
## Limitations in Risei
|
|
452
528
|
|
|
453
529
|
The following are not supported at present:
|
|
454
530
|
- Use of `async` syntax
|
|
@@ -468,52 +544,48 @@ Some of these are on the tentative future-development list. In the meanti
|
|
|
468
544
|
|
|
469
545
|
Most problems with using Risei are minor mistakes in syntax, or omissions in test definitions:
|
|
470
546
|
|
|
471
|
-
| Error condition or text
|
|
472
|
-
|
|
473
|
-
|
|
|
474
|
-
| `"Test loading failed for... SyntaxError: Unexpected token ':'"` | Missing comma in your tests in the named file
|
|
475
|
-
| `"Test loading failed for... SyntaxError: Unexpected token '.'"` | Using `this.tests = []` instead of `tests = []` in the file named
|
|
476
|
-
| Other `... Unexpected token ...` errors | Some other syntax error in the file named, most likely a missing or extra delimiter
|
|
477
|
-
| Unexpected actual values, or unexpected passes / fails in test runs | Spoofs, retrievals, or special conditions from previous tests not replaced or reset with `[ ]
|
|
478
|
-
|
|
547
|
+
| Error condition or text | Probable cause / fix |
|
|
548
|
+
|---------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
549
|
+
| Gold bar appears below the summary, and the number of tests run drops | A syntax error caused a test file not to load; error output in the gold bar explains why |
|
|
550
|
+
| `"Test loading failed for... SyntaxError: Unexpected token ':'"` | Missing comma in your tests in the named file |
|
|
551
|
+
| `"Test loading failed for... SyntaxError: Unexpected token '.'"` | Using `this.tests = []` instead of `tests = []` in the file named |
|
|
552
|
+
| Other `... Unexpected token ...` errors | Some other syntax error in the file named, most likely a missing or extra delimiter |
|
|
553
|
+
| Unexpected actual values, or unexpected passes / fails in test runs | Spoofs, retrievals, or special conditions from previous tests not replaced or reset with `[ ]` |
|
|
554
|
+
| Unexpected actual values, or unexpected passes / fails in test runs | Pre-listed test properties have produced extra tests; changing properties as part of new tests prevents this |
|
|
555
|
+
| Unexpected actual values, or unexpected passes / fails in test runs | `.with` or `.in` values were mutated by a test and passed to subsequent tests; providing contents of these properties with a function prevents this |
|
|
479
556
|
|
|
480
557
|
|
|
481
558
|
|
|
482
|
-
## Known
|
|
559
|
+
## Known issues and workarounds
|
|
483
560
|
|
|
484
|
-
|
|
485
|
-
- When the args stated in `.with` or `.in` are mutated by the method under test (or by anything done within a test), the mutated values are carried forward to other tests.
|
|
486
|
-
- A workaround exists for now: just provide those args using a fixture function when they may be mutated. The function is called each time, isolating them completely.
|
|
561
|
+
Two issues are known to exist:
|
|
487
562
|
|
|
563
|
+
- If the contents of `.with` or `.in` are mutated by the code being tested, the mutated values are carried from test to test.
|
|
564
|
+
- To use the original, un-mutated args for successive tests, just return them from a function or method, and call it to set `.with` or `.in`.
|
|
565
|
+
- Ways to prevent this are being looked at.
|
|
488
566
|
|
|
489
|
-
- This problem with test isolation is being fixed in an upcoming release.
|
|
490
567
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
-
|
|
494
|
-
-
|
|
495
|
-
|
|
496
|
-
- This means you see an extra unexpected test that most likely fails, due to the mix of old and new properties.
|
|
497
|
-
|
|
498
|
-
- A workaround exists: if you pre-state new properties, also restate the class under test in `.on`, which erases all prior test properties.
|
|
499
|
-
- Restating `.on` doesn't cause the class name to be displayed again in output.
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
- This output is rarely an issue, and may be what is wanted in some cases, but options for preventing it are being considered.
|
|
568
|
+
- Changing one or more properties in objects by themselves in the middle of tests (perhaps to emphasize them) can create extra tests.
|
|
569
|
+
- The extra tests usually fail, because they have an unintended mix of old and new properties.
|
|
570
|
+
- In this case, Rs is actually working properly, running prior tests with the new properties swapped in.
|
|
571
|
+
- To avoid this problem, include changed properties in full tests to run, or restate `.of` along with the changed properties.
|
|
572
|
+
- This situation is rarely an issue, but ways to optionally prevent it are being considered.
|
|
503
573
|
|
|
504
574
|
|
|
505
575
|
|
|
506
576
|
## What's new in Risei
|
|
507
577
|
|
|
508
|
-
- Release **1.
|
|
578
|
+
- Release **1.3.1** (February, 2024) reverses some changes in 1.3.0 that were intended to fully isolate tests against mutable args, but which caused incomplete or inaccurate object contents in some cases. Later work may restore full isolation in a different way at some point.
|
|
579
|
+
|
|
580
|
+
- Release **1.3.0** (February, 2024) moves the display of test-loading error messages to a new gold bar that appears at the bottom of the summary when there are any loading errors. A sorting error that occurs when no test files exist yet has also been fixed.
|
|
509
581
|
|
|
582
|
+
- Release **1.2.0** (January, 2024) changes sorting of test files. Previously they were displayed in the order found. Now the order remains the same, except that the last-edited file is moved to the bottom, making it easy to see the latest test results.
|
|
510
583
|
|
|
511
584
|
- Release **1.1.2** of Risei (January, 2024) fixes two problems:
|
|
512
585
|
- Classes were sometimes displayed in output as their entire definition. Now just the class name is displayed.
|
|
513
586
|
- All `Date` instances were considered equal, regardless of their actual value. Now they only are considered equal when they actually are.
|
|
514
587
|
|
|
515
|
-
|
|
516
|
-
> Don't use release **1.1.1**, which contains an internal path error.
|
|
588
|
+
- Don't use release **1.1.1**, which contains an internal path error.
|
|
517
589
|
|
|
518
590
|
|
|
519
591
|
|
|
@@ -534,7 +606,7 @@ Risei is published for use under the terms of the MIT license:
|
|
|
534
606
|
|
|
535
607
|
<div style="border: solid darkgray 1px; padding: 0.5rem;">
|
|
536
608
|
|
|
537
|
-
<b>Risei Copyright © 2023 Ed Fallin</b>
|
|
609
|
+
<b>Risei Copyright © 2023–2024 Ed Fallin</b>
|
|
538
610
|
|
|
539
611
|
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:
|
|
540
612
|
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**/
|
|
2
2
|
|
|
3
|
-
/* Copyright (c) 2023 Ed Fallin. Published under the terms of the MIT license. */
|
|
3
|
+
/* Copyright (c) 2023-2024 Ed Fallin. Published under the terms of the MIT license. */
|
|
4
4
|
|
|
5
5
|
/* This index.js is the entry point for running Risei tests from
|
|
6
6
|
other code. It imports other modules to perform its work.
|
|
@@ -47,6 +47,7 @@ export * from "./system/ATestReporter.js";
|
|
|
47
47
|
|
|
48
48
|
/* Display styles for the start title and other general needs. */
|
|
49
49
|
const title = chalk.hex("FFFFFF").bgHex("191970").bold;
|
|
50
|
+
const fails = chalk.hex("000000").bgHex("FFD700").bold;
|
|
50
51
|
|
|
51
52
|
// endregion Named styles
|
|
52
53
|
|
|
@@ -61,7 +62,7 @@ let wide = (text) => {
|
|
|
61
62
|
|
|
62
63
|
// endregion Styling for color stripes
|
|
63
64
|
|
|
64
|
-
// region Key callable, its
|
|
65
|
+
// region Key callable, its scripted call, and its export
|
|
65
66
|
|
|
66
67
|
async function runRiseiTests(testFinderPath) {
|
|
67
68
|
// region Converting test-finder from path to class
|
|
@@ -90,7 +91,7 @@ async function runRiseiTests(testFinderPath) {
|
|
|
90
91
|
console.log();
|
|
91
92
|
|
|
92
93
|
// endregion Intro / title
|
|
93
|
-
|
|
94
|
+
|
|
94
95
|
// region Running tests
|
|
95
96
|
|
|
96
97
|
// Test-system objects and their relationships.
|
|
@@ -104,7 +105,19 @@ async function runRiseiTests(testFinderPath) {
|
|
|
104
105
|
await caller.runAllTests();
|
|
105
106
|
|
|
106
107
|
// endregion Running tests
|
|
107
|
-
|
|
108
|
+
|
|
109
|
+
// region Trailing display of test-loading issues
|
|
110
|
+
|
|
111
|
+
if (finder.thrown.length !== 0) {
|
|
112
|
+
let loadFails = finder.thrown;
|
|
113
|
+
|
|
114
|
+
for (let fail of loadFails) {
|
|
115
|
+
console.log(fails(wide(` ${ fail }`)));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// endregion Trailing display of test-loading issues
|
|
120
|
+
|
|
108
121
|
// region Trailing formatting
|
|
109
122
|
|
|
110
123
|
console.log();
|
|
@@ -118,5 +131,5 @@ await runRiseiTests();
|
|
|
118
131
|
|
|
119
132
|
export default runRiseiTests;
|
|
120
133
|
|
|
121
|
-
// endregion Key callable, its
|
|
134
|
+
// endregion Key callable, its scripted call, and its export
|
|
122
135
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "risei",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Risei is the framework that allows you to write unit tests as collections of values in JavaScript objects, so it's easy and fast, and tests don't serve as a drag on redesigns.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"unit test",
|
|
@@ -28,8 +28,7 @@
|
|
|
28
28
|
"test": "clear; node ./node_modules/risei/index.js"
|
|
29
29
|
},
|
|
30
30
|
"risei": {
|
|
31
|
-
"tests": "**.rt.js"
|
|
32
|
-
"sort": "normal"
|
|
31
|
+
"tests": "**.rt.js"
|
|
33
32
|
},
|
|
34
33
|
"exports": {
|
|
35
34
|
".": "./index.js",
|
|
@@ -49,6 +48,6 @@
|
|
|
49
48
|
"fs": "^0.0.1-security",
|
|
50
49
|
"mocha": "^10.0.0",
|
|
51
50
|
"morgan": "~1.9.1",
|
|
52
|
-
"risei": "1.1
|
|
51
|
+
"risei": "1.3.1"
|
|
53
52
|
}
|
|
54
53
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**/
|
|
2
2
|
|
|
3
3
|
import { ATestFixture } from "./ATestFixture.js";
|
|
4
|
-
import {
|
|
4
|
+
import { SpoofDefinition } from "./SpoofDefinition.js";
|
|
5
5
|
|
|
6
6
|
export class ASpoofingFixture extends ATestFixture {
|
|
7
7
|
constructor(name, kind) {
|
|
@@ -25,8 +25,8 @@ export class ASpoofingFixture extends ATestFixture {
|
|
|
25
25
|
// Recursive case: Spoof defines a whole object
|
|
26
26
|
// tree to be returned as method output.
|
|
27
27
|
if (Array.isArray(spoofOutput)) {
|
|
28
|
-
if (spoofOutput.every(x =>
|
|
29
|
-
spoofOutput =
|
|
28
|
+
if (spoofOutput.every(x => SpoofDefinition.isASpoof(x))) {
|
|
29
|
+
spoofOutput = SpoofDefinition.fromNonceTuples(spoofOutput);
|
|
30
30
|
spoofOutput = this.spoofObjectTree(spoofOutput);
|
|
31
31
|
}
|
|
32
32
|
}
|
package/system/ATestFinder.js
CHANGED
|
@@ -5,7 +5,14 @@
|
|
|
5
5
|
import { ATestSource } from "./ATestSource.js";
|
|
6
6
|
|
|
7
7
|
export class ATestFinder {
|
|
8
|
+
// region Fields
|
|
9
|
+
|
|
8
10
|
#testSources;
|
|
11
|
+
#thrown = [];
|
|
12
|
+
|
|
13
|
+
// endregion Fields
|
|
14
|
+
|
|
15
|
+
// region Properties
|
|
9
16
|
|
|
10
17
|
get testSources() {
|
|
11
18
|
return this.#testSources;
|
|
@@ -15,6 +22,12 @@ export class ATestFinder {
|
|
|
15
22
|
this.#testSources = value;
|
|
16
23
|
}
|
|
17
24
|
|
|
25
|
+
get thrown() {
|
|
26
|
+
return this.#thrown;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// endregion Properties
|
|
30
|
+
|
|
18
31
|
constructor() {
|
|
19
32
|
this.#testSources = [];
|
|
20
33
|
}
|
package/system/Risei.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/**/
|
|
2
2
|
|
|
3
|
-
/*
|
|
4
|
-
|
|
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
|
|
5
10
|
|
|
6
11
|
// region Test-running dependencies
|
|
7
12
|
|
|
8
13
|
import { TestRunner } from "./TestRunner.js";
|
|
9
|
-
import { ChosenTestFinder } from "./ChosenTestFinder.js";
|
|
10
14
|
import { LocalCaller } from "./LocalCaller.js";
|
|
11
15
|
import { TerminalReporter } from "./TerminalReporter.js";
|
|
16
|
+
import { TestFinder } from "./TestFinder.js";
|
|
12
17
|
|
|
13
18
|
// endregion Test-running dependencies
|
|
14
19
|
|
|
@@ -19,19 +24,13 @@ import { Moment } from "./Moment.js";
|
|
|
19
24
|
|
|
20
25
|
// endregion Display dependencies
|
|
21
26
|
|
|
27
|
+
// endregion Imports
|
|
28
|
+
|
|
22
29
|
// region Named styles
|
|
23
30
|
|
|
24
31
|
/* Display styles for the start title and other general needs. */
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const onGreen = chalk.bgGreenBright;
|
|
28
|
-
|
|
29
|
-
const future = chalk.hex("FFFFFF").bgHex("191970").bold;
|
|
30
|
-
|
|
31
|
-
/* Display styles for tests. */
|
|
32
|
-
const group = chalk.hex("FFFFFF").bgHex("0000CD");
|
|
33
|
-
const passed = chalk.hex("000000").bgHex("90EE90");
|
|
34
|
-
const failed = chalk.hex("000000").bgHex("F08080");
|
|
32
|
+
const title = chalk.hex("FFFFFF").bgHex("191970").bold;
|
|
33
|
+
const fails = chalk.hex("000000").bgHex("FFD700").bold;
|
|
35
34
|
|
|
36
35
|
// endregion Named styles
|
|
37
36
|
|
|
@@ -46,43 +45,74 @@ let wide = (text) => {
|
|
|
46
45
|
|
|
47
46
|
// endregion Styling for color stripes
|
|
48
47
|
|
|
49
|
-
// region
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
let
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
|
88
118
|
|
|
@@ -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 SpoofClassMethodsFixture extends ASpoofingFixture {
|
|
7
7
|
/* Algorithm: Forward method spoof() looks at spoof definitions in .plus and applies them
|
|
@@ -53,10 +53,10 @@ export class SpoofClassMethodsFixture extends ASpoofingFixture {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
// Converting to scope object type.
|
|
56
|
-
let
|
|
56
|
+
let spoofDefinitions = SpoofDefinition.fromNonceTuples(spoofNonces);
|
|
57
57
|
|
|
58
58
|
// Storing spoofing definitions.
|
|
59
|
-
this.#retainSpoofsByClass(type,
|
|
59
|
+
this.#retainSpoofsByClass(type, spoofDefinitions);
|
|
60
60
|
|
|
61
61
|
// Storing originals for restoring later.
|
|
62
62
|
this.#reserveOriginalsByClass();
|
|
@@ -67,9 +67,9 @@ export class SpoofClassMethodsFixture extends ASpoofingFixture {
|
|
|
67
67
|
|
|
68
68
|
// region Dependencies of spoof()
|
|
69
69
|
|
|
70
|
-
#retainSpoofsByClass(type,
|
|
70
|
+
#retainSpoofsByClass(type, spoofDefinitions) {
|
|
71
71
|
// Map of Maps: by type, then by method.
|
|
72
|
-
for (let tuple of
|
|
72
|
+
for (let tuple of spoofDefinitions) {
|
|
73
73
|
// If no .target, use `type`.
|
|
74
74
|
if (!tuple.target) {
|
|
75
75
|
tuple.target = type;
|