risei 1.3.4 → 2.0.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.
Files changed (44) hide show
  1. package/README.md +134 -479
  2. package/index.js +5 -5
  3. package/package.json +10 -11
  4. package/system/ASpoofingFixture.js +7 -8
  5. package/system/ATestCaller.js +3 -3
  6. package/system/ATestFinder.js +2 -2
  7. package/system/ATestReporter.js +2 -1
  8. package/system/ATestSource.js +5 -1
  9. package/system/ChosenTestFinder.js +4 -4
  10. package/system/ClassTestGroup.js +2 -2
  11. package/system/LocalCaller.js +5 -5
  12. package/system/{ClassMethodSpoofer.js → MethodSpoofer.js} +54 -48
  13. package/system/MethodTestGroup.js +2 -2
  14. package/system/Moment.js +1 -1
  15. package/system/NameAnalyzer.js +26 -0
  16. package/system/PropertySpoofer.js +156 -0
  17. package/system/Risei.js +5 -5
  18. package/system/SpoofDef.js +260 -0
  19. package/system/TerminalReporter.js +8 -8
  20. package/system/{TestDefinition.js → TestDef.js} +153 -107
  21. package/system/TestFinder.js +3 -3
  22. package/system/TestFrame.js +15 -52
  23. package/system/TestGroup.js +1 -1
  24. package/system/TestResult.js +2 -2
  25. package/system/TestRunner.js +23 -107
  26. package/system/TestStages.js +80 -76
  27. package/system/TestSummary.js +1 -1
  28. package/system/TotalComparer.js +60 -11
  29. package/system/TotalDisplayer.js +33 -12
  30. package/system/TypeAnalyzer.js +41 -79
  31. package/system/TypeIdentifier.js +18 -8
  32. package/system/Types.js +3 -1
  33. package/system/AComparer.js +0 -9
  34. package/system/ATestFixture.js +0 -44
  35. package/system/ClassPropertySpoofer.js +0 -185
  36. package/system/ObjectMethodSpoofer.js +0 -58
  37. package/system/ObjectPropertySpoofer.js +0 -136
  38. package/system/SpoofDefinition.js +0 -243
  39. package/system/TestFrameChooser.js +0 -54
  40. package/system/TestFrames.js +0 -232
  41. package/system/TotalCopier.js +0 -106
  42. package/usage-examples/Output-example.png +0 -0
  43. package/usage-examples/Summary-example.png +0 -0
  44. package/usage-examples/Syntax-example.png +0 -0
@@ -0,0 +1,260 @@
1
+ /**/
2
+
3
+ import TypeAnalyzer from "./TypeAnalyzer.js";
4
+ import NameAnalyzer from "./NameAnalyzer.js";
5
+
6
+ /* Defines what is found in a spoof definition, typically as
7
+ a nonce object rather than an instance of this class. */
8
+
9
+ export default class SpoofDef {
10
+ // region Static fields
11
+
12
+ /* Properties can have short or long names. */
13
+ static #onNames = [ "on", "target" ];
14
+ static #ofNames = [ "of", "method" ];
15
+ static #asNames = [ "as", "output" ];
16
+
17
+ static #longsByShort = new Map([
18
+ SpoofDef.#onNames,
19
+ SpoofDef.#ofNames,
20
+ SpoofDef.#asNames
21
+ ]);
22
+
23
+ /* &cruft, remove these after spoofing in .with and .in is removed */
24
+ /* Objects with either of these property names aren't
25
+ converted to spoofDefs by from-nonce methods. */
26
+ static skipNames = [ "not", "skip" ];
27
+
28
+ // endregion Static fields
29
+
30
+ // region Public fields (long names)
31
+
32
+ /* These long names are clearer and match the constructor's parameter names. */
33
+
34
+ /* The test-definition field names use the longer, possibly clearer forms.
35
+ Equivalent short-name and long-name properties use the same fields. */
36
+
37
+ target;
38
+ method;
39
+ output;
40
+
41
+ // endregion Public fields (long names)
42
+
43
+ // region Properties
44
+
45
+ // region Spoof definition, short names
46
+
47
+ /* These short names make JSON-like definitions easier. */
48
+
49
+ get on() {
50
+ return this.target;
51
+ }
52
+
53
+ set on(value) {
54
+ this.target = value;
55
+ }
56
+
57
+ get of() {
58
+ return this.method;
59
+ }
60
+
61
+ set of(value) {
62
+ this.method = value;
63
+ }
64
+
65
+ get as() {
66
+ return this.output;
67
+ }
68
+
69
+ set as(value) {
70
+ this.output = value;
71
+ }
72
+
73
+ // endregion Spoof definition, short names
74
+
75
+ // region Def state
76
+
77
+ /* Returns true if arg doesn't provide enough to spoof with. */
78
+ static isNotASpoof(nonce) /* passed */ {
79
+ return !SpoofDef.isASpoof(nonce);
80
+ }
81
+
82
+ /* Returns true if arg provides enough to spoof with. */
83
+ static isASpoof(nonce) /* passed */ {
84
+ /* Any nonce that is null or undefined is not a SpoofDef. */
85
+ if (nonce === undefined || nonce === null) {
86
+ return false;
87
+ }
88
+
89
+ let hasAnOf = SpoofDef.#hasEitherName(nonce, SpoofDef.#ofNames);
90
+ let hasAnAs = SpoofDef.#hasEitherName(nonce, SpoofDef.#asNames);
91
+
92
+ /* Any nonce with at least an .of or an .as is a SpoofDef. */
93
+ return hasAnOf || hasAnAs;
94
+ }
95
+
96
+ get isMethodSpoof() /* passed */ {
97
+ if (this.target === undefined) {
98
+ throw new Error("No .on / .target present. It must be set for .isMethodSpoof to work.");
99
+ }
100
+
101
+ let plainName = NameAnalyzer.plainNameOf(this.method);
102
+
103
+ if (NameAnalyzer.hasPropertySigil(this.method)) {
104
+ return false;
105
+ }
106
+
107
+ let isMethod
108
+ = NameAnalyzer.hasMethodSigil(this.method)
109
+ || TypeAnalyzer.isMethodMember(this.target, plainName);
110
+
111
+ return isMethod;
112
+ }
113
+
114
+ get isPropertySpoof() /* passed */ {
115
+ if (this.target === undefined) {
116
+ throw new Error("No .on / .target present. It must be set for .isPropertySpoof to work.");
117
+ }
118
+
119
+ let plainName = NameAnalyzer.plainNameOf(this.method);
120
+
121
+ if (NameAnalyzer.hasMethodSigil(this.method)) {
122
+ return false;
123
+ }
124
+
125
+ let isProperty
126
+ = NameAnalyzer.hasPropertySigil(this.method)
127
+ || TypeAnalyzer.isPropertyMember(this.target, plainName);
128
+
129
+ return isProperty;
130
+ }
131
+
132
+ // endregion Def state
133
+
134
+ // endregion Properties
135
+
136
+ // region Initing, including constructor() and statics
137
+
138
+ /* Constructor can't use param names like `of`, because when not .-prefixed, they are keywords. */
139
+
140
+ constructor(target, method, output) /* passed */ {
141
+ this.target = target;
142
+ this.method = method;
143
+ this.output = output;
144
+ }
145
+
146
+ static fromNonceTuples(nonces, type) /* passed */ {
147
+ // Throughput and output.
148
+ let full = new SpoofDef();
149
+ let output = [ ];
150
+
151
+ // Looping over all.
152
+ for (let nonce of nonces) {
153
+ // Get latest spoof definition/s and retain for output.
154
+ let latests = SpoofDef.fromNonceTuple(nonce, type);
155
+ output.push(...latests);
156
+ }
157
+
158
+ // Back to caller.
159
+ return output;
160
+ }
161
+
162
+ static fromNonceTuple(nonce, type) /* passed */ {
163
+ /* No spoof-def to output. */
164
+ if (SpoofDef.isNotASpoof(nonce)) {
165
+ return [ ];
166
+ }
167
+
168
+ // Empty, since properties can be set
169
+ // by either of two nonce naming styles.
170
+ let def = new SpoofDef();
171
+
172
+ let shortNames = SpoofDef.#longsByShort.keys();
173
+
174
+ /* &cruft, maybe refactor to put property-setting loop in its own method, and possibly
175
+ recurse internally using it without inner arrays, for a cleaner algorithm */
176
+
177
+ // Traversing matching pairs of names and applying
178
+ // whichever one is present as the tuple property;
179
+ // if neither is present, the property is undefined.
180
+ for (let shortName of shortNames) {
181
+ let longName = SpoofDef.#longsByShort.get(shortName);
182
+ def[shortName] = shortName in nonce ? nonce[shortName] : nonce[longName];
183
+ }
184
+
185
+ // No nested partial spoof-defs
186
+ // (mono-spoof) is most likely.
187
+ let defs = [ def ];
188
+
189
+ // Recursion to handle nested partial spoof-defs (poly-spoofs).
190
+ if (def.method === undefined && Array.isArray(def.output)) {
191
+ let locals = [ ];
192
+
193
+ for (let ofAsPair of def.output) {
194
+ let localOf = ofAsPair.of !== undefined ? ofAsPair.of : ofAsPair.method;
195
+ let localAs = ofAsPair.as !== undefined ? ofAsPair.as : ofAsPair.output;
196
+
197
+ let passer = SpoofDef.fromNonceTuple({ on: def.target, of: localOf, as: localAs });
198
+ locals.push(passer[0]);
199
+ }
200
+
201
+ // Replace default spoof
202
+ // with real poly-spoofs.
203
+ defs = locals;
204
+ }
205
+
206
+ // All defs need a type / target class.
207
+ SpoofDef.#setAnyMissingTypes(defs, type);
208
+
209
+ // Back to caller.
210
+ return defs;
211
+ }
212
+
213
+ // region Dependencies of nonce-tuple initing methods
214
+
215
+ static #hasEitherName(nonce, names) /* verified */ {
216
+ let hasEither = false;
217
+
218
+ for (let name of names) {
219
+ hasEither ||= SpoofDef.#hasName(nonce, name);
220
+ }
221
+
222
+ return hasEither;
223
+ }
224
+
225
+ static #hasName(nonce, name) /* verified */ {
226
+ return nonce[name] !== undefined;
227
+ }
228
+
229
+ static #setAnyMissingTypes(defs, type) /* verified */ {
230
+ // Adding test target's type, if no type provided.
231
+ for (let def of defs) {
232
+ if (def.target === undefined) {
233
+ def.target = type;
234
+ }
235
+ }
236
+ }
237
+
238
+ // endregion Dependencies of nonce-tuple initing methods
239
+
240
+ // endregion Initing, including constructor() and statics
241
+
242
+ // region Overrides and dependencies
243
+
244
+ toString() /* passed */ {
245
+ let text = `SpoofDefinition:{ target:${ this.#asRawOrString(this.target) }, `
246
+ + `method:${ this.#asRawOrString(this.method) }, `
247
+ + `output:${ this.#asRawOrString(this.output) } }`;
248
+ return text;
249
+ }
250
+
251
+ #asRawOrString(value) /* verified */ {
252
+ if (typeof value === "string") {
253
+ return `"${ value }"`;
254
+ }
255
+
256
+ return value;
257
+ }
258
+
259
+ // endregion Overrides and dependencies
260
+ }
@@ -2,16 +2,16 @@
2
2
 
3
3
  /* TerminalReporter is an ATestReporter that sends each result to the terminal / console for display. */
4
4
 
5
- import { ATestReporter } from "./ATestReporter.js";
6
- import { TestGroup } from "./TestGroup.js";
7
- import { ClassTestGroup } from "./ClassTestGroup.js";
8
- import { MethodTestGroup } from "./MethodTestGroup.js";
9
- import { TestResult } from "./TestResult.js";
10
- import { TestSummary } from "./TestSummary.js";
5
+ import ATestReporter from "./ATestReporter.js";
6
+ import TestGroup from "./TestGroup.js";
7
+ import ClassTestGroup from "./ClassTestGroup.js";
8
+ import MethodTestGroup from "./MethodTestGroup.js";
9
+ import TestResult from "./TestResult.js";
10
+ import TestSummary from "./TestSummary.js";
11
11
 
12
12
  import chalk from "chalk";
13
13
 
14
- export class TerminalReporter extends ATestReporter {
14
+ export default class TerminalReporter extends ATestReporter {
15
15
  // region Private fields
16
16
 
17
17
  /* Foreground-colors using dependency calls and hex. */
@@ -69,7 +69,7 @@ export class TerminalReporter extends ATestReporter {
69
69
  }
70
70
 
71
71
  if (result instanceof MethodTestGroup) {
72
- console.log(" " + this.#methodGroup(` ${ result.group }(): `));
72
+ console.log(" " + this.#methodGroup(` ${ result.group }: `));
73
73
  }
74
74
  }
75
75