risei 3.0.0 → 3.1.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 +38 -23
- package/index.js +18 -66
- package/package.json +7 -6
- package/system/CallTypes.js +10 -0
- package/system/Choices.js +92 -0
- package/system/LocalCaller.js +45 -5
- package/system/ObjectAnalyzer.js +36 -0
- package/system/SpoofDef.js +73 -58
- package/system/TerminalReporter.js +109 -25
- package/system/TestDef.js +72 -5
- package/system/TestFinder.js +31 -29
- package/system/TestFrame.js +14 -3
- package/system/TestResult.js +63 -13
- package/system/TestRunner.js +75 -40
- package/system/TestStages.js +40 -37
- package/system/TestSummary.js +22 -15
- package/system/TotalComparer.js +54 -17
- package/system/TotalDisplayer.js +29 -6
- package/system/TypeAnalyzer.js +52 -14
- 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/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.1**, 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
|
|
|
@@ -91,6 +91,9 @@ And add Risei's metadata to `package.json`:
|
|
|
91
91
|
}
|
|
92
92
|
```
|
|
93
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).
|
|
94
97
|
|
|
95
98
|
|
|
96
99
|
## Running Tests
|
|
@@ -205,21 +208,30 @@ To test TypeScript code with Risei, you make sure the code is transpiled before
|
|
|
205
208
|
|
|
206
209
|
## Troubleshooting
|
|
207
210
|
|
|
208
|
-
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:
|
|
209
212
|
|
|
210
213
|

|
|
211
214
|
|
|
215
|
+
- If files don't load, tests in those files disappear from the output and the totals.
|
|
212
216
|
- Those and other problems can be solved with the help of this [troubleshooting guide](https://deusware.com/risei/index.html#troubleshooting).
|
|
213
217
|
|
|
214
218
|
|
|
215
219
|
|
|
216
220
|
## Version history
|
|
217
221
|
|
|
218
|
-
- Release **3.
|
|
219
|
-
-
|
|
220
|
-
-
|
|
221
|
-
|
|
222
|
-
|
|
222
|
+
- Release **3.1.1** (January, 2025) contains these changes:
|
|
223
|
+
- Extra commas and non-objects in arrays of test objects are disregarded, and no longer cause a throw.
|
|
224
|
+
- Throws in wider scopes are now listed at the end, like others already found there.
|
|
225
|
+
|
|
226
|
+
- Release **3.1.0** (January, 2025) contains these changes:
|
|
227
|
+
- Accessor properties (formally _accessor descriptors_) are now compared for test results and displayed in test outputs.
|
|
228
|
+
- Any accessor properties that throw errors during display are displayed as `(threw)`.
|
|
229
|
+
- Throws in tested code and in test framing code are now listed at the end, and also displayed amid the tests.
|
|
230
|
+
- `File` objects now have a succinct custom display in outputs.
|
|
231
|
+
- **(Breaking change)** In `constructor` tests, constructed instances are available in `.from` functions only as `actual` / `test.actual`.
|
|
232
|
+
- **(Breaking change)** In `constructor` tests, `test.target` is now the `prototype` of the tested class.
|
|
233
|
+
- Widespread internal reengineering of other kinds.
|
|
234
|
+
|
|
223
235
|
|
|
224
236
|
|
|
225
237
|
<details>
|
|
@@ -227,7 +239,13 @@ If problems cause test files not to load, a gold bar appears and tests in those
|
|
|
227
239
|
Older releases
|
|
228
240
|
</summary>
|
|
229
241
|
|
|
230
|
-
- Release **
|
|
242
|
+
- Release **3.0.0** (August, 2024) contained all of these changes:
|
|
243
|
+
- Asynchronous code with `async` syntax is now supported, with no special test syntax.
|
|
244
|
+
- **(Breaking change)** `.from` functions now take `test` and `actual` as parameters, rather than `target` and `test`.
|
|
245
|
+
- 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`.
|
|
246
|
+
- You can now call target code more than once in one test using an `.and` of `"poly"` (AKA _poly-calling_).
|
|
247
|
+
|
|
248
|
+
- Release **2.0.0** / **2.0.1** (August, 2024) contained all of these changes:
|
|
231
249
|
- Risei now can determine automatically if tested methods are static.
|
|
232
250
|
- You can now directly test properties just like methods.
|
|
233
251
|
- Risei can also determine automatically if these are static.
|
|
@@ -242,17 +260,7 @@ Older releases
|
|
|
242
260
|
- **(Breaking change)** `ATestSource` is now a default export, changing its imports from `import { ATestSource } from` to `import ATestSource from`.
|
|
243
261
|
- Major internal re-engineering.
|
|
244
262
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
- Release **1.3.4** (March, 2024) fixed a bug that caused class display problems in some cases.
|
|
248
|
-
- Release **1.3.3** (March, 2024) fixed a major bug that prevented tests from running in Windows.
|
|
249
|
-
- Release **1.3.2** (February, 2024) only improved this read-me's contents.
|
|
250
|
-
- Release **1.3.1** (February, 2024) reversed some changes in 1.3.0 that did not work as hoped.
|
|
251
|
-
- Release **1.3.0** (February, 2024) added the loading-error gold bar and fixed a test-sorting bug.
|
|
252
|
-
- Release **1.2.0** (January, 2024) changed test sorting to move last-edited tests to the end.
|
|
253
|
-
- Release **1.1.2** of Risei (January, 2024) fixed class displays and inaccurate `Date` comparisons.
|
|
254
|
-
|
|
255
|
-
> The oldest releases are no longer listed here, and old releases are dropped progressively over time. Using the latest release is recommended.
|
|
263
|
+
> Older releases are dropped from this list progressively over time. Using the latest release is recommended.
|
|
256
264
|
|
|
257
265
|
</details>
|
|
258
266
|
|
|
@@ -260,9 +268,14 @@ Older releases
|
|
|
260
268
|
|
|
261
269
|
## Known issues and workarounds
|
|
262
270
|
|
|
263
|
-
|
|
271
|
+
There are two minor issues at present:
|
|
264
272
|
|
|
265
|
-
-
|
|
273
|
+
- If args for a test are mutated by tested code, the mutated args are used when collapsing forward.
|
|
274
|
+
- The workaround is just to restate those args for each test.
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
- Spoofing accessor properties only works when they have both a getter and a setter.
|
|
278
|
+
- The workaround is to find another way to produce the property values you need.
|
|
266
279
|
|
|
267
280
|
|
|
268
281
|
|
|
@@ -271,7 +284,9 @@ The only issue at present is reuse of method args mutated by tested code when co
|
|
|
271
284
|
At present, there are a few things Risei doesn't support. Some of these may be supported in the future.
|
|
272
285
|
|
|
273
286
|
- You can see the whole list [here](https://deusware.com/risei/index.html#exclusions-from-risei).
|
|
274
|
-
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
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.
|
|
275
290
|
|
|
276
291
|
|
|
277
292
|
|
|
@@ -291,7 +306,7 @@ Risei is published for use under the terms of the MIT license:
|
|
|
291
306
|
|
|
292
307
|
<div style="border: solid darkgray 1px; padding: 0.5rem;">
|
|
293
308
|
|
|
294
|
-
<b>Risei Copyright © 2023–
|
|
309
|
+
<b>Risei Copyright © 2023–2025 Ed Fallin</b>
|
|
295
310
|
|
|
296
311
|
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:
|
|
297
312
|
|
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.
|
|
3
|
+
"version": "3.1.1",
|
|
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.1.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": "^3.0.0"
|
|
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/LocalCaller.js
CHANGED
|
@@ -1,14 +1,54 @@
|
|
|
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
54
|
this.runner.useTests(tests);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**/
|
|
2
|
+
|
|
3
|
+
import TypeAnalyzer from "./TypeAnalyzer.js";
|
|
4
|
+
|
|
5
|
+
export default class ObjectAnalyzer {
|
|
6
|
+
/* Retrieves names of all properties, both values
|
|
7
|
+
and accessors, including all in superclasses. */
|
|
8
|
+
static allProperties(topic) /* passed */ {
|
|
9
|
+
let proto = Object.getPrototypeOf(topic);
|
|
10
|
+
|
|
11
|
+
let getters = [];
|
|
12
|
+
|
|
13
|
+
// Accessors, including in superclasses.
|
|
14
|
+
// Nonce object has no prototype / type.
|
|
15
|
+
if (proto !== null) {
|
|
16
|
+
let type = proto.constructor;
|
|
17
|
+
getters = TypeAnalyzer.allGetters(type);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let names = [];
|
|
21
|
+
|
|
22
|
+
// All value names, including inherited ones.
|
|
23
|
+
for (let name in topic) {
|
|
24
|
+
names.push(name);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Concat good enough since sorting needed after anyway.
|
|
28
|
+
let output = names.concat(getters);
|
|
29
|
+
|
|
30
|
+
// Instead of mixed two sets in order coded,
|
|
31
|
+
// accessors backwards up prototype chain.
|
|
32
|
+
output.sort();
|
|
33
|
+
|
|
34
|
+
return output;
|
|
35
|
+
}
|
|
36
|
+
}
|