risei 1.3.4 → 2.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.
Files changed (69) hide show
  1. package/README.md +142 -379
  2. package/Read-me reduced.md +294 -0
  3. package/Read-me redux.md +581 -0
  4. package/index.js +5 -5
  5. package/package.json +10 -11
  6. package/system/ASpoofingFixture.js +7 -8
  7. package/system/ATestCaller.js +3 -3
  8. package/system/ATestFinder.js +2 -2
  9. package/system/ATestReporter.js +2 -1
  10. package/system/ATestSource.js +5 -1
  11. package/system/ChosenTestFinder.js +4 -4
  12. package/system/ClassTestGroup.js +2 -2
  13. package/system/LocalCaller.js +5 -5
  14. package/system/{ClassMethodSpoofer.js → MethodSpoofer.js} +54 -48
  15. package/system/MethodTestGroup.js +2 -2
  16. package/system/Moment.js +1 -1
  17. package/system/NameAnalyzer.js +26 -0
  18. package/system/PropertySpoofer.js +156 -0
  19. package/system/Risei.js +5 -5
  20. package/system/SpoofDef.js +260 -0
  21. package/system/TerminalReporter.js +8 -8
  22. package/system/{TestDefinition.js → TestDef.js} +153 -107
  23. package/system/TestFinder.js +3 -3
  24. package/system/TestFrame.js +15 -52
  25. package/system/TestGroup.js +1 -1
  26. package/system/TestResult.js +2 -2
  27. package/system/TestRunner.js +23 -107
  28. package/system/TestStages.js +80 -76
  29. package/system/TestSummary.js +1 -1
  30. package/system/TotalComparer.js +60 -11
  31. package/system/TotalDisplayer.js +33 -12
  32. package/system/TypeAnalyzer.js +41 -79
  33. package/system/TypeIdentifier.js +18 -8
  34. package/system/Types.js +3 -1
  35. package/test-target-objects/ConditionalThrowTarget.js +11 -0
  36. package/test-target-objects/Counter.js +46 -0
  37. package/test-target-objects/DomTarget.js +37 -0
  38. package/test-target-objects/InterSpoofer.js +230 -0
  39. package/test-target-objects/MixedContents.js +33 -0
  40. package/test-target-objects/MutationTarget.js +37 -0
  41. package/test-target-objects/ObjectComposer.js +34 -0
  42. package/test-target-objects/PolySpoofableInner.js +29 -0
  43. package/test-target-objects/PolySpoofableOuter.js +52 -0
  44. package/test-target-objects/PropertiesTarget.js +98 -0
  45. package/test-target-objects/Returner.js +7 -0
  46. package/test-target-objects/Searcher.js +25 -0
  47. package/test-target-objects/Sorter.js +91 -0
  48. package/test-target-objects/Spoofable.js +36 -0
  49. package/test-target-objects/StateTarget.js +34 -0
  50. package/test-target-objects/StaticTarget.js +17 -0
  51. package/test-target-objects/TestableTarget.js +57 -0
  52. package/trial-tests/SelfTests.outward-rt.js +511 -0
  53. package/trial-tests/TopicTests.outward-rt.js +313 -0
  54. package/usage-examples/Gold-bar-example.png +0 -0
  55. package/usage-examples/Title-example.png +0 -0
  56. package/xternal-tests/ASpoofingFixture.tests.js +242 -0
  57. package/xternal-tests/MethodSpoofer.tests.js +130 -0
  58. package/xternal-tests/SpoofDef.tests.js +91 -0
  59. package/xternal-tests/TotalComparer.tests.js +1055 -0
  60. package/xternal-tests/package.json +7 -0
  61. package/system/AComparer.js +0 -9
  62. package/system/ATestFixture.js +0 -44
  63. package/system/ClassPropertySpoofer.js +0 -185
  64. package/system/ObjectMethodSpoofer.js +0 -58
  65. package/system/ObjectPropertySpoofer.js +0 -136
  66. package/system/SpoofDefinition.js +0 -243
  67. package/system/TestFrameChooser.js +0 -54
  68. package/system/TestFrames.js +0 -232
  69. package/system/TotalCopier.js +0 -106
package/README.md CHANGED
@@ -4,16 +4,16 @@
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 and TypeScript in no time.
8
- * Refactor or replace existing designs without worrying about the cost in past or future test time.
9
- * Create tests with immediate confidence, because you can't introduce mistakes in test code you write.
7
+ * Whip up full test coverage in no time for object-oriented (or object-hosted) JavaScript and TypeScript.
8
+ * Refactor or replace existing designs without worrying about about a heavy cost in past or future test construction.
9
+ * Create tests with immediate confidence, since you can't introduce mistakes when writing test code.
10
10
 
11
11
 
12
12
 
13
13
 
14
14
  ## The Risei approach
15
15
 
16
- Risei replaces coded tests with simple declarative syntax that's far easier to draft than any other unit-testing approach.
16
+ Risei replaces coded tests with simple declarative syntax.
17
17
 
18
18
  Here are two example tests.  `SortModel.countSort()` is being tested using the inputs from `.in` and the expected output from `.out`:
19
19
 
@@ -25,12 +25,16 @@ Here is the terminal output of these two example tests.  Tests are grouped
25
25
  ![https://deusware.com/Output-example.png](https://deusware.com/Output-example.png)
26
26
 
27
27
 
28
- - An individual test may appear on one line or multiple lines, depending on how wide the terminal window is.
29
28
  - Any failing tests appear in light red.
30
- - Your latest-edited tests always sort to the bottom, so you can see your current test results at a glance.
29
+ - Your latest tests always sort to the bottom so it's easy to find their results.
31
30
 
32
31
 
33
- Test runs also feature a title bar at the top, as well as a summary bar at the bottom:
32
+ Test runs also feature a title bar at the top:
33
+
34
+ ![https://deusware.com/Title-example.png](https://deusware.com/Title-example.png)
35
+
36
+
37
+ As well as a summary bar at the bottom:
34
38
 
35
39
  ![https://deusware.com/Summary-example.png](https://deusware.com/Summary-example.png)
36
40
 
@@ -39,9 +43,30 @@ Test runs also feature a title bar at the top, as well as a summary bar at the b
39
43
 
40
44
  ## Using Risei
41
45
 
42
- 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).
46
+ Risei is under active development.  The newest release, **2.0.0**, brings many major improvements:
47
+
48
+ - You can now test properties just like methods.
49
+ - You can now spoof properties on the targeted class instance.
50
+ - Risei now can determine automatically if tested or spoofed methods and properties are static.
51
+ - You can now perform arbitrary operations if needed.
52
+ - You can now change a test property without accidentally creating a new test.
53
+ - `Error` objects are now compared accurately.
54
+ - Outputs for `throw` tests are now the entire `Error` objects (breaking change).
55
+
56
+ Risei has been reengineered internally along with these improvements.
57
+
58
+ - In addition, `ATestSource` is now a default export (breaking change).
59
+ - This means a simple adjustment from `import { ATestSource }` to `import ATestSource`.
60
+
61
+ These changes and others are detailed at the new external Risei documentation website:
62
+
63
+ &cruft, new site
64
+ [https://deusware.com/risei-docs/index.html](https://deusware.com/risei-docs/index.html)
65
+
66
+ 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).
67
+
68
+ Risei works with Typescript, requiring only a few additional or different steps, described in [using Typescript with Risei](#using-typescript-with-risei).
43
69
 
44
- There are a few additional or different steps for [using Typescript with Risei](#using-typescript-with-risei).
45
70
 
46
71
 
47
72
 
@@ -53,7 +78,7 @@ Install Risei for development time only:
53
78
  npm install --save-dev risei
54
79
  ```
55
80
 
56
- Make sure your `package.json` specifies that ESM is in use:
81
+ Make sure your `package.json` specifies that ECMAScript modules are in use:
57
82
 
58
83
  ```json
59
84
  "type": "module"
@@ -67,99 +92,20 @@ And add Risei's metadata to `package.json`:
67
92
  }
68
93
  ```
69
94
 
70
- Just a [few extra steps](#using-typescript-with-risei) are required for Risei to work with TypeScript.
71
-
72
-
73
-
74
- ### Siting tests
75
-
76
- Add tests in files ending in `.rt.js` like this:
77
-
78
- ```javascript
79
- import { ATestSource } from "risei/ATestSource";
80
- import { ClassToBeTested } from "somewhere";
81
-
82
- export class SomeTests extends ATestSource {
83
- tests = [ ... ]; // This array is where test definitions are written.
84
- }
85
- ```
86
-
87
-
88
-
89
- ### Writing tests
90
-
91
- Write tests with Risei's easy syntax:
92
-
93
- ```javascript
94
- tests = [ ...
95
- { on: ContainerModelClass, with: [ "a", "b", "c" ], // Target class and constructor args.
96
- of: "doesContain", // Target method.
97
- for: "When the input arg is present, returns true.", // Description of test.
98
- in: [ "c" ], // Inputs.
99
- out: true }, // Expected output.
100
- ...];
101
- ```
102
-
103
-
104
-
105
- #### Write more tests with less syntax:
106
-
107
- You can save a lot of time by putting repeated test properties into an object once, just before the related tests:
108
-
109
- ```javascript
110
- /* All of the following tests are of ContainerModelClass. */
111
- { on: ContainerModelClass, with: [ "a", "b", "c", "a", "b" ] },
95
+ > Just a [few extra steps](#using-typescript-with-risei) are required for Risei to work with TypeScript.
112
96
 
113
- /* Two tests for ContainerModelClass .doesContain(). */
114
- { of: "doesContain" },
115
- { for: "When the input arg is present, returns true.",
116
- in: [ "c" ], out: true },
117
- { for: "When the input arg is not present, returns false.",
118
- in: [ "d" ], out: false },
119
-
120
- /* First test for ContainerModelClass .countOf(). */
121
- { of: "countOf", for: "Returns the number present.", in: [ "b" ], out: 2 }
122
- ```
97
+ &cruft, new site / section
98
+ - Further general options can be found [here](https://deusware.com/risei-docs/index.html#installation).
123
99
 
124
- - This _collapsing forward_ 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 `[]`.
100
+ &cruft, new site / section
101
+ - Further Typescript details can be found [here](https://deusware.com/risei-docs/index.html#using-typescript).
125
102
 
126
- - Tests are isolated in general, but if the code you're testing mutates its arguments, you have to state them in each test so the mutations aren't carried forward.
127
-
128
-
129
-
130
- #### Spoof away code dependencies:
131
-
132
- When your tests need certain results from code dependencies, just _spoof_ what you want using a `.plus` test property:
133
-
134
- ```javascript
135
- { on: CombinerClass, with: [],
136
- of: "combineResults",
137
- plus: [
138
- { on: ClassA, of: "someMethod", as: 10 }, // Spoof this ClassA method to return 10.
139
- { on: ClassB, of: "someMethod" }, // Spoof this ClassB method not to return (or do) anything.
140
- { of: "firstMethod", as: [ 7, 8, 9, 10 ] }, // Spoof a method on the tested class (CombinerClass).
141
- { of: "secondMethod" }, // Spoof a method on CombinerClass not to do anything.
142
- { on: ClassC, // Spoof this ClassC method to be this nonce code.
143
- of: "someMethod",
144
- as: (arg) => { return { color: arg }; } },
145
- { on: ClassD, as: [ // Spoof two methods on ClassD at the same time.
146
- { of: "firstMethod", as: 11 },
147
- { of: "secondMethod", as: 12 }
148
- ] },
149
- ],
150
- for: "When called, returns an array of values from sources.",
151
- in: [ "green" ], out: [ 7, 8, 9, 10, 10, 11, 12, { color: "green" } ] }
152
- ```
153
-
154
- - It's just like _fakes_, _mocks_, or _test doubles_ in other test systems, but much easier to write and read.
155
-
156
- - Spoofed code is fully isolated within tests, even though spoof definitions collapse forward across tests (and within `.plus`).
157
103
 
158
104
 
159
105
 
160
106
  ### Running tests
161
107
 
162
- Run your tests by invoking Risei's `index.js` file:
108
+ Once you've written your tests, run them by invoking Risei's `index.js` file:
163
109
 
164
110
  ```bash
165
111
  node ./node_modules/risei/index.js
@@ -179,292 +125,126 @@ And then run that script:
179
125
  npm test
180
126
  ```
181
127
 
182
- Risei can be used alongside other test frameworks, and even run with them from the same test script if you want.
183
-
128
+ - Risei can be used alongside other test frameworks, and even run with them from the same test script if you want.
184
129
 
130
+ &cruft, new site / section
131
+ - Find more information about this mixed testing and other config / run options [here](https://deusware.com/risei-docs/index.html#running-tests).
185
132
 
186
- ### Learning more about Risei
187
-
188
- Read through the rest of this doc to learn more about Risei's many capabilities, and about where Risei is headed.
189
-
190
- - For instance, learn about using `.and` to test static methods or throws.
191
- - Or learn about using `.from` to test property results or other state.
192
- - Don't miss out:  Once you've tried the basics, read the rest...!
193
-
194
-
195
-
196
-
197
- ## Risei in depth
198
-
199
- <details>
200
- <summary>
201
- There's plenty more to learn about Risei and how it makes testing easy...
202
- </summary>
203
-
204
- ### Installation
205
-
206
- - You can use any file extension you want in Risei's metadata in `package.json`, and Risei will scan those files for tests.
207
-
208
- - You can install Risei outside of development time the usual way, but as with any test system, this is definitely not recommended.
209
-
210
- - Risei uses ESM syntax, and may not work in older environments where that's not available or is patched in.
211
133
 
212
134
 
213
135
 
214
136
  ### Siting tests
215
137
 
216
- - Match your Risei test file's extensions to whatever you choose in the metadata in `package.json`.
217
-
218
- - Test classes must inherit from `ATestSource` in `"risei/ATestSource"`: this type name is looked for specifically, so duck-typing doesn't work.
219
-
220
-
221
-
222
- ### Writing tests
223
-
224
- - The order and placement of test properties doesn't matter, although the order seen in the examples is probably most readable.
225
-
226
-
227
-
228
- #### Basic test properties and options for each:
229
-
230
- | Name | Contents |
231
- |--------|-----------------------------------------------------------------------------------------------------------|
232
- | `on` | The class under test, as a symbol / name (already imported into the test file) |
233
- | `with` | An array of any arguments to pass to the constructor of the tested class, or an empty array `[]` if none |
234
- | `of` | The name of the method under test, as a string, no `()` needed |
235
- | `for` | A description of what the test proves, for test output |
236
- | `in` | An array of the input arguments to pass to the tested method, or an empty array `[]` if none |
237
- | `out` | The expected return value, not in an array |
238
-
239
- - There are additional properties for extended functionality, covered later.
240
- - The property names were chosen to be easy to remember and type, but longer alternatives are available, covered later.
241
-
242
-
243
-
244
- ### Test-property reuse _AKA_ Collapsing forward
245
-
246
- - 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 `[]`.
247
- - Property values are gathered across partial test objects until they add up to a runnable test, which is then run.
248
- - Changes to properties are combined with previous ones to produce intended new tests.
249
- - For a rare and avoidable side-effect of this system, see [known issues and workarounds](#known-issues-and-workarounds).
250
-
251
- - Test contents, reused or not, are automatically reset when it makes the most sense:
252
- - Changing the tested class in `.on` wipes out all prior test properties, so the new class has a fresh start.
253
- - Changing the tested method in `.of` wipes out only test properties related to methods, to preserve class values you usually want.
254
-
255
- - Individual tests remain isolated, except for when args are mutated by the code under test.
256
- - Restate args for each test when the code mutates them.
257
- - This limitation is the result of limits on what can be copied reliably in JavaScript.
258
-
259
-
260
- ### Choosing test-only dependency inputs _AKA_ Spoofing
261
-
262
- - Spoofing is Risei's way of providing test-only inputs from dependencies the tested code uses, written in simple declarative syntax.
263
- - It's therefore the equivalent of test doubles, mocks, fakes, and so on.
264
-
265
-
266
- - As the earlier examples and this table show, you can spoof in many ways, both on the dependencies, and on the class being tested.
267
- - All classes whose members are being spoofed have to be imported.
268
-
269
-
270
-
271
- #### Spoof-definition properties:
272
-
273
- | Name | Necessary or Optional | Contents |
274
- |------|-----------------------|----------------------------------------------------------------------------|
275
- | `on` | Optional | Symbol for a type (class); if omitted, the targeted model class is assumed |
276
- | `of` | Necessary | Name of the method to spoof, as a string, trailing `()` not needed |
277
- | `as` | Optional | Value to return or nonce implementation; if omitted, an empty method with no return value is used<br> &mdash; or &mdash;<br>A list of partial spoof definitions for the same class |
278
-
279
-
280
- - You can spoof multiple methods of a class individually, or list them together with partial definitions as seen in the example, with the same effect either way.
281
-
282
-
283
- #### Partial spoof-definition properties:
284
-
285
- | Name | Necessary or Optional | Contents |
286
- |------|-----------------------|---------------------------------------------------------------------------------------------------|
287
- | `of` | Necessary | Name of the method to spoof, as a string, trailing `()` not needed |
288
- | `as` | Optional | Value to return or nonce implementation; if omitted, an empty method with no return value is used |
289
-
290
-
291
- - Defining new spoofing wipes out all old definitions.
292
-
293
-
294
- - Spoofing is done at the start of each test and undone at the end of each test, keeping all tests isolated.
295
-
296
-
297
-
298
-
299
- ## Advanced Risei usage
300
-
301
- ### Testing special test conditions with `.and`
302
-
303
- You can use the special test property `.and`, always a string, to indicate special conditions that apply to your test.
304
- - At present, the values available are `"static"` and `"throw"` / `"throws"` (either one works).
305
- - You can list `static` and `throw` / `throws` together if needed, separated by a space.
306
-
307
- The `.and` property is an expansion point for supporting more special conditions in the future.&nbsp; Values will always be listable together (as long as any particular grouping makes sense).
308
-
309
-
310
-
311
- #### Testing static methods
312
-
313
- To test a static method, use an `.and` of `"static"`:
138
+ Add tests in files ending in `.rt.js` like this:
314
139
 
315
140
  ```javascript
316
- { on: StaticTextProfileModel, with: [] },
141
+ import ATestSource from "risei/ATestSource";
142
+ import { ClassToBeTested } from "somewhere";
317
143
 
318
- { of: "getTextProfile",
319
- for: "Returns accurate profile of arg text.",
320
- and: "static",
321
- in: [ "This is a short sentence." ],
322
- out: { isFullSentence: true, characters: 25, words: 5 }
144
+ export class SomeTests extends ATestSource {
145
+ tests = [ ... ]; // Test definitions are added here.
323
146
  }
324
147
  ```
325
148
 
326
149
 
327
150
 
328
- #### Testing throws
151
+ ### Writing tests
329
152
 
330
- To test a throw, use an `.and` of `"throw"` or `"throws"`:
153
+ Write tests with Risei's simple syntax:
331
154
 
332
155
  ```javascript
333
- { on: InstanceTextProfileModel, with: [] },
334
-
335
- { of: "getTextProfile",
336
- for: "Throws with a helpful message when there is no arg text.",
337
- and: "throws",
338
- in: [],
339
- out: "Could not build a profile. Did you forget to provide a text?"
340
- }
156
+ tests = [ ...
157
+ { on: ContainerModelClass, with: [ "a", "b", "c" ], // Target class and constructor args.
158
+ of: "doesContain", // Target method name.
159
+ for: "When the arg is present, returns true.", // Description of test.
160
+ in: [ "c" ], // Inputs to method.
161
+ out: true }, // Expected output.
162
+ ...];
341
163
  ```
342
164
 
165
+ - To test a throw path in a method, add an `.and` test property with the text value `"throws"`.
166
+
167
+ - To test a property of the target instance after running code, add a `.from` property with the property's name as a string.
343
168
 
169
+ - To test a value derived from the initial actual value, or otherwise from any available context, add a `from` property that's an arrow function taking (at present) `target` and `test` parameters: `(target, test) => { return test.actual.someProperty; }`.
344
170
 
345
- ### Testing object properties and other non-`return` results
171
+ - To perform operations like creating files temporarily, use the `.do` property (encompassing two stages, `.before` and `.after`) to set up isolated test state, and `.undo` to restore normal state.
172
+ - The `.do`-`.before` steps are taken before the target class instance is created, the `.do`-`.after steps are taken after that but before the target method / property is run.
173
+ - The `.undo` is an arrow function taking a `test` arg.&nbsp; It is run after all other steps of the test have been run.&nbsp; **(2.0.0)**
346
174
 
347
- To test a value that isn't the exercised code's return value, you use `.out` normally, and you add a `.from` property to your test, which can be one of two things:
175
+ - To maintain the benefits of using Risei's declarative style, avoid arbitrary options as much as possible.
348
176
 
349
- | Contents of `.from` | Usage |
350
- |--------------------------------|-------------------------------------------------------------------------|
351
- | Property name as string | Retrieves the actual from the named property on the test's target class |
352
- | Specialized function | Retrieves the actual from either its `target` or `test` parameter |
177
+ - If you prefer test property names that aren't JavaScript keywords, alternatives are available for all of them.
353
178
 
179
+ - Further details about syntax options can be found [here](https://deusware.com/risei-docs/index.html#test-syntax).
354
180
 
355
- - Getting properties, mutated args, and other non-return values is known as _retrieving_.
356
- - Retrieving definitions collapse forward across tests unless replaced with new definitions, or erased by setting `.from` to an empty array `[]`.
357
181
 
358
182
 
359
- <details>
360
- <summary>
361
- &nbsp; More information
362
- </summary>
363
- <br>
364
183
 
365
- - Use of `.from` with a property name looks like this:
184
+ #### Write more tests with less syntax:
185
+
186
+ To save a lot of time, state repeated test values just once, and let them _collapse forward_ into following tests:
366
187
 
367
188
  ```javascript
368
- { on: StatefulModel, with: [] },
189
+ /* All of the following tests are of ContainerModelClass. */
190
+ { on: ContainerModelClass, with: [ "a", "b", "c", "a", "b" ] },
369
191
 
370
- { of: "storePolyProduct",
371
- for: "The result of the calculation is stored as .result.",
372
- in: [ 10, 8, 9, 6 ], out: 4320, from: "result" },
192
+ /* Two tests for ContainerModelClass .doesContain(). */
193
+ { of: "doesContain" },
194
+ { for: "When the input arg is present, returns true.",
195
+ in: [ "c" ], out: true },
196
+ { for: "When the input arg is not present, returns false.",
197
+ in: [ "d" ], out: false },
198
+
199
+ /* First test for ContainerModelClass .countOf(). */
200
+ { of: "countOf", for: "Returns the number present.", in: [ "b" ], out: 2 }
373
201
  ```
374
202
 
375
- - Only instance properties can be retrieved by name.&nbsp; For static properties, use `.and` (covered earlier), plus a function as `.from` (covered next).
203
+ - When you change the class in `.on`, all test properties are wiped away, and when you change the method in `.of`, only test properties about the class (like `.with`) are retained.
376
204
 
377
- When the contents of `.from` are a function, these are the two parameters:
205
+ - Tests remain isolated, in effect, except when a test mutates input arguments.&nbsp; In that case, restate them in each test so the mutations aren't carried forward.
378
206
 
379
- | Name | Contents |
380
- |----------|---------------------------------------------------------------------------------------------------|
381
- | `target` | The instance of the class being tested |
382
- | `test` | The test definition itself, whose properties may have been mutated by the tested method |
207
+ - Change test contents without possibly adding an unintended new test by adding a `.just` property (with any value, such as `true`) alongside the changed properties.&nbsp; **(2.0.0)**
383
208
 
209
+ &cruft, new site / details
210
+ - Further options and details can be found [here](https://deusware.com/risei-docs/index.html#collapsing-forward).
384
211
 
385
- - The `test` parameter to a `.from` function contains all of the properties of your test definition, including those that collapsed forward.
386
- - These properties are available by both short or long names (covered later).
387
- - The `test.on` property always references the class under test, rather than an instance of it.
388
212
 
389
213
 
390
- - You can write a function for `.from` that uses `test.on` to get the values of static properties, in conjunction with `and: "static"` in the encompassing test.
391
214
 
215
+ #### Ensure desired inputs from dependencies
392
216
 
393
- - Another usage of a `.from` function is to look at an input to see if it was changed as expected:
217
+ To make code dependencies return what your tests need, just _spoof_ what you want using a `.plus` test property:
394
218
 
395
219
  ```javascript
396
- { on: SecurityModel, with: [] },
397
-
398
- { of: "addHash",
399
- for: "The content's hash is added to the input arg a new property.",
400
- in: [ { content: "SecretValue" }, iterations: 8 ],
401
- out: { content: "SecretValue", hash: "FasBdQ-fljk%asPcdf" },
402
- from: (target, test) => { return test.in[0]; }
403
- },
220
+ { on: CombinerClass, with: [],
221
+ of: "combineResults",
222
+ plus: [
223
+ { on: ClassA, of: "someMethod", as: 10 }, // Spoofing one method to return 10.
224
+ { on: ClassB, of: "someMethod" }, // Spoofing one method not to return anything.
225
+ { on: ClassC, as: [ // Spoofing two class methods together.
226
+ { of: "firstMethod", as: 11 },
227
+ { of: "secondMethod", as: 12 }
228
+ ] },
229
+ ],
230
+ for: "When called, returns an array of values from sources.",
231
+ in: [ "green" ], out: [ 7, 8, 9, 10, 10, 11, 12, { color: "green" } ] }
404
232
  ```
405
233
 
406
- </details>
407
-
408
-
409
-
410
- ### Property long names
411
-
412
- Property names are short so they're easy to use.&nbsp; Some of them overlap with JavaScript keywords, but this causes no harm.
413
-
414
- All test properties have long names that you can use instead of the short ones if you prefer, mixed together as much as you want.&nbsp; None of the long names are JavaScript keywords.
415
-
416
-
417
- <details>
418
- <summary>
419
- &nbsp; Test properties' short and long names
420
- </summary>
234
+ - It's just like _fakes_, _mocks_, or _test doubles_ in other test systems, but easier to write and read.
421
235
 
422
- | Short Name | Long Name |
423
- |------------|-----------|
424
- | `on` | `type` |
425
- | `with` | `initors` |
426
- | `of` | `method` |
427
- | `for` | `nature` |
428
- | `in` | `inputs` |
429
- | `out` | `output` |
430
- | `plus` | `spoofed` |
431
- | `from` | `source` |
432
- | `and` | `factors` |
236
+ &cruft, site / section
237
+ - There are many further spoofing options that save effort, including using nonce methods as spoofs and spoofing target-instance properties.&nbsp; **(2.0.0)**&nbsp; Check out all your options [here](https://deusware.com/risei-docs/index.html#collapsing-forward).
433
238
 
434
- </details>
435
239
 
436
- <br>
437
-
438
- <details>
439
- <summary>
440
- &nbsp; Spoof properties' short and long names
441
- </summary>
442
-
443
- | Short Name | Long Name |
444
- |------------|-----------|
445
- | `on` | `target` |
446
- | `of` | `method` |
447
- | `as` | `output` |
448
-
449
- </details>
450
-
451
-
452
-
453
- ### Further capabilities of Risei
454
-
455
- Constructors can be tested with no special test properties or keywords.
456
- - The method name in `.of` is simply `"constructor"`.
457
- - Any `.with` args are completely ignored for a constructor test.&nbsp; Only those in the test's `.in` property are used.
458
- - However, a `.with` must still be provided.&nbsp; It can simply be an empty array `[]`.
459
-
460
- </details>
240
+ - Spoofed code is fully isolated within tests, even though spoof definitions collapse forward across tests (and within `.plus`).
461
241
 
462
242
 
463
243
 
464
244
 
465
245
  ## Using TypeScript with Risei
466
246
 
467
- 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.
247
+ Testing TypeScript code with Risei basically just means transpiling before running the tests, and pointing Risei to the transpiled JS files.
468
248
 
469
249
  - Anything beyond those basics is intended to keep JS files separate from TS files and the output of web frameworks' own, complex build processes.
470
250
 
@@ -509,7 +289,6 @@ You set up the transpiler to output files to a directory with these settings:
509
289
 
510
290
 
511
291
 
512
-
513
292
  ### In test files:
514
293
 
515
294
  All `import` statements have to point to the Javascript (`.js`) files in the `outDir` path or subfolders there, using relative-path syntax:
@@ -523,90 +302,72 @@ import { TestedClass } from "../../dist/out-tsc/SubPath/TestedClass.js";
523
302
 
524
303
 
525
304
 
526
- ## Limitations in Risei
527
-
528
- The following are not supported at present:
529
- - Use of `async` syntax
530
- - Code written in ESM `export` modules, but not within classes
531
- - Standalone functions and other functionality not built into classes, AKA _loose code_
532
- - CJS syntax using `require()`
533
- - Spoofing mixes of properties and methods, such as `something.method.property.method`
534
- - Debugging model code during tests
535
- - Comparing rare JS object types like `Proxy` or `ArrayBuffer` in test assertions
536
-
537
- Some of these are on the tentative future-development list.&nbsp; In the meantime, Risei can be used to save development time for most of your JavaScript code, while these can be tested using another framework invoked alongside Risei.
305
+ ## What's new in Risei
538
306
 
307
+ - Release **2.0.0** (month, 2024) introduces many [improvements](#using-risei), including new capabilities, bug fixes, and two breaking changes with only minor impacts on consuming code.
539
308
 
309
+ - Release **1.3.4** (March, 2024) fixed a bug that caused class display problems in some cases.
540
310
 
311
+ - Release **1.3.3** (March, 2024) fixed a major bug that prevented tests from running in Windows.
541
312
 
542
- ## Troubleshooting
313
+ - Release **1.3.2** (February, 2024) only improved this read-me's contents.
543
314
 
544
- Most problems with using Risei are minor mistakes in syntax, or omissions in test definitions:
315
+ - Release **1.3.1** (February, 2024) reversed some changes in 1.3.0 that did not work as hoped.
545
316
 
546
- | Error condition or text | Probable cause |
547
- |---------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
548
- | 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 |
549
- | `"Test loading failed for... SyntaxError: Unexpected token ':'"` | Missing comma in your tests in the named file |
550
- | `"Test loading failed for... SyntaxError: Unexpected token '.'"` | Using `this.tests = []` instead of `tests = []` in the file named |
551
- | Other `... Unexpected token ...` errors | Some other syntax error in the file named, most likely a missing or extra delimiter |
552
- | Unexpected extra, failing test/s | Partial test properties in a mid-list object have produced extra tests |
553
- | Unexpected actual values, or unexpected passes / fails in test runs | Test properties from previous tests not replaced or reset with `[]` <br>&mdash; or &mdash;<br> Args mutated by tested code were not restated in following tests to isolate them |
317
+ - Release **1.3.0** (February, 2024) added the loading-error gold bar and fixed a test-sorting bug.
554
318
 
319
+ - Release **1.2.0** (January, 2024) changed test sorting to move last-edited tests to the end.
555
320
 
321
+ - Release **1.1.2** of Risei (January, 2024) fixed class displays and inaccurate `Date` comparisons.
556
322
 
323
+ - The oldest releases are not listed here, and old releases are dropped progressively over time.&nbsp; Using the latest release is recommended.
557
324
 
558
- ## Known issues and workarounds
559
325
 
560
- Two issues are known to exist:
561
326
 
562
- - When code mutates its args in test definitions, the mutated forms are used in subsequent tests unless those args are restated.
563
- - To avoid this problem, just restate the args in each test of this code.
564
- - The workaround for this &mdash; copying and initing objects to bypass mutation &mdash; requires too many assumptions to be reliable.
565
327
 
328
+ ## Troubleshooting
566
329
 
567
- - When a few properties are changed in separate objects, they are treated as whole new tests, which usually fail because of their unintended mix of old and new properties.
568
- - To avoid this problem, just change properties as part of whole new tests, or else restate `.of` along with the changed properties.
569
- - Risei is actually working as intended when this happens, but ways to optionally prevent it are being considered.
330
+ Problems loading tests are almost always a missing or extra comma, brace, or similar.&nbsp; When a test file can't be loaded, loading continues with the next file.&nbsp; The number of tests drops (or doesn't increase as expected), and a gold bar appears naming the file and problem:
570
331
 
332
+ ![https://deusware.com/Gold-bar-example.png](https://deusware.com/Gold-bar-example.png)
571
333
 
334
+ - Unfortunately, there is no way to list the problem line number.
335
+ - A sudden fail of many test files is usually due to a problem in the tested code, not the tests themselves.
572
336
 
573
- ## What's new in Risei
337
+ Problems with test results themselves are usually due to omissions or other mistakes in test definitions.
574
338
 
575
- - Release **1.3.4** (March, 2024) fixes a bug that caused class definitions still to appear instead of class names when classes were used as object properties.
576
- - As a side effect of this change, objects' own `toString()` is never used in onscreen test output any longer, but all of Risei's output display is now handled the same.
339
+ For far more information about troubleshooting, including some specific error messages, check out the documentation [here](https://deusware.com/risei-docs/index.html#troubleshooting).
577
340
 
578
341
 
579
- - Release **1.3.3** (March, 2024) fixes a major bug related to file paths that prevented any tests from loading or running in Windows environments.
580
- - Risei is now fully usable in Windows environments again.
581
342
 
582
343
 
583
- - Release **1.3.2** (February, 2024) does not change the code at all, but improves this read-me.
584
- - It now explains the easiest way to deal with mutable args (which is just restating the args).
585
- - A few mistakes in the text were also fixed.
344
+ ## Known issues and workarounds
586
345
 
346
+ At present, there are two known issues, both with simple workarounds:
587
347
 
588
- - 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.
589
- - Supporting built-in total test isolation is not feasible with collapsing forward, nor is it usually necessary given easy usage alternatives.
590
- - In contrast, collapsing forward is both highly beneficial and frequently used.
348
+ - When tested code mutates its args, the mutated forms are used in subsequent tests if collapsed forward.
349
+ - To avoid this, simply restate the args for each test that mutates them.
591
350
 
592
351
 
593
- - Release **1.3.0** (February, 2024) makes two changes:
594
- - If there are any test-loading errors, their messages now appear in a new gold bar that appears below the summary of the test run.
595
- - A test-sorting error has also been fixed that occurred when no test files existed yet.
352
+ - When a few properties are changed in separate objects, they are treated as whole new tests, which usually fail because of their unintended mix of old and new properties.
353
+ - To avoid this problem, just add a `.just` or `.only` property, of any value, in the same objects as those tests.change properties as part of whole new tests, or else restate `.of` along with the changed properties.
354
+ - You can also clear existing properties with `.on` or `.of` and then do this, since then there aren't enough test properties present yet to comprise a full test.
596
355
 
597
356
 
598
- - Release **1.2.0** (January, 2024) changes sorting of test files to make tests you're working on now appear at the bottom.
599
- - Previously tests were displayed in the order found, which is always alphabetical (though is not guaranteed to be so).
600
- - The order for all files except one remains the same.
601
- - The last-edited file is moved to the bottom, making it easy to see the latest test results.
602
357
 
358
+ ## Limitations in Risei
603
359
 
604
- - Release **1.1.2** of Risei (January, 2024) fixes two problems:
605
- - Classes were sometimes displayed in output as their entire definition.&nbsp; Now just the class name is displayed.
606
- - All `Date` instances were considered equal, regardless of their actual value.&nbsp; Now they only are considered equal when they actually are.
360
+ The following are not supported at present:
361
+ - Use of `async` syntax
362
+ - Code written in ESM `export` modules, but not within classes
363
+ - Standalone functions and other functionality not built into classes, AKA _loose code_
364
+ - CJS syntax using `require()`
365
+ - Debugging model code during tests
366
+ - Comparing rare JS object types like `Proxy` or `ArrayBuffer` in test assertions
607
367
 
368
+ Some of these are on the tentative future-development list.
369
+ - In the meantime, Risei can be used to save development time for most of your JavaScript code, while these cases can be tested using another framework invoked alongside Risei.
608
370
 
609
- - Don't use release **1.1.1**, which contains an internal path error.
610
371
 
611
372
 
612
373
 
@@ -638,3 +399,5 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
638
399
 
639
400
 
640
401
  &nbsp;
402
+
403
+