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
@@ -6,10 +6,10 @@
6
6
  and the ATestReporter for out / formatting if needed.
7
7
  A = abstract. */
8
8
 
9
- import { TestRunner } from "./TestRunner.js";
10
- import { ATestReporter } from "./ATestReporter.js";
9
+ import TestRunner from "./TestRunner.js";
10
+ import ATestReporter from "./ATestReporter.js";
11
11
 
12
- export class ATestCaller {
12
+ export default class ATestCaller {
13
13
  // region Private fields
14
14
 
15
15
  #finder;
@@ -2,9 +2,9 @@
2
2
 
3
3
  /* Defines operations that test-finding classes should implement. A = abstract. */
4
4
 
5
- import { ATestSource } from "./ATestSource.js";
5
+ import ATestSource from "./ATestSource.js";
6
6
 
7
- export class ATestFinder {
7
+ export default class ATestFinder {
8
8
  // region Fields
9
9
 
10
10
  #testSources;
@@ -2,9 +2,10 @@
2
2
 
3
3
  /* Defines operations that a test reporter must implement. A = abstract. */
4
4
 
5
+ /* &cruft, ? replace with my own code eventually */
5
6
  import chalk from "chalk";
6
7
 
7
- export class ATestReporter {
8
+ export default class ATestReporter {
8
9
  // Reports whatever was just provided by the TestRunner.
9
10
  // Can delegate to the other report-x methods.
10
11
  reportNext(result) {
@@ -2,7 +2,11 @@
2
2
 
3
3
  /* Defines operations that a source of tests must (trivially) implement, basically listing tests and fixtures. */
4
4
 
5
- export class ATestSource {
5
+ export default class ATestSource {
6
+ /* These support testing for undefined values. */
7
+ static undefSymbol = Symbol.for("undefined");
8
+ undef = ATestSource.undefSymbol;
9
+
6
10
  /* Must be implemented by subclasses. */
7
11
  tests = [];
8
12
  }
@@ -2,11 +2,11 @@
2
2
 
3
3
  /* ChosenTestFinder is an ATestFinder that finds tests in the places coded in its constructor. */
4
4
 
5
- import { ATestFinder } from "./ATestFinder.js";
6
- import { TopicTests } from "../tests/topic-tests/TopicTests.outward-rt.js";
7
- import { SelfTests } from "../tests/self-tests/SelfTests.outward-rt.js";
5
+ import ATestFinder from "./ATestFinder.js";
6
+ import TopicTests from "../trial-tests/TopicTests.outward-rt.js";
7
+ import SelfTests from "../trial-tests/SelfTests.outward-rt.js";
8
8
 
9
- export class ChosenTestFinder extends ATestFinder {
9
+ export default class ChosenTestFinder extends ATestFinder {
10
10
  constructor() {
11
11
  super();
12
12
 
@@ -1,8 +1,8 @@
1
1
  /**/
2
2
 
3
- import { TestGroup } from "./TestGroup.js";
3
+ import TestGroup from "./TestGroup.js";
4
4
 
5
5
  /* Identifies a grouping of tests by class. No specialized workings. */
6
6
 
7
- export class ClassTestGroup extends TestGroup {
7
+ export default class ClassTestGroup extends TestGroup {
8
8
  }
@@ -3,12 +3,12 @@
3
3
  /* LocalCaller is an ATestCaller that invokes each available test in turn locally
4
4
  on the server, 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
- import { TerminalReporter } from "./TerminalReporter.js";
9
- import { TestRunner } from "./TestRunner.js";
6
+ import ATestFinder from "./ATestFinder.js";
7
+ import ATestCaller from "./ATestCaller.js";
8
+ import TerminalReporter from "./TerminalReporter.js";
9
+ import TestRunner from "./TestRunner.js";
10
10
 
11
- export class LocalCaller extends ATestCaller {
11
+ export default class LocalCaller extends ATestCaller {
12
12
  async runAllTests() {
13
13
  let tests = await this.finder.findAllTests();
14
14
  this.runner.useTests(tests);
@@ -1,14 +1,15 @@
1
1
  /**/
2
2
 
3
- import { ASpoofingFixture } from "./ASpoofingFixture.js";
4
- import { SpoofDefinition } from "./SpoofDefinition.js";
5
- import { TypeAnalyzer } from "./TypeAnalyzer.js";
3
+ import ASpoofingFixture from "./ASpoofingFixture.js";
4
+ import SpoofDef from "./SpoofDef.js";
5
+ import TypeAnalyzer from "./TypeAnalyzer.js";
6
+ import NameAnalyzer from "./NameAnalyzer.js";
6
7
 
7
- export class ClassMethodSpoofer extends ASpoofingFixture {
8
+ export default class MethodSpoofer extends ASpoofingFixture {
8
9
  /* Algorithm: Forward method spoof() looks at spoof definitions in .plus and applies them
9
10
  to each class' prototypes after first saving the original member definitions.
10
11
  Reverse method unspoof() restores each original member definition.
11
- Fundamentally different from what ObjectMethodSpoofer does. */
12
+ More complex and purely class based than what PropertySpoofer does. */
12
13
 
13
14
  // region Private fields
14
15
 
@@ -38,12 +39,12 @@ export class ClassMethodSpoofer extends ASpoofingFixture {
38
39
  // endregion Properties
39
40
 
40
41
  constructor() {
41
- super("ClassMethodSpoofer", "Construction");
42
+ super("MethodSpoofer", "Construction");
42
43
  }
43
44
 
44
- /* Spoofs methods of classes as defined in nonce
45
- spoof-tuple definitions in any test.plus. */
46
- spoof(test) {
45
+ // Spoofs methods of classes as defined in nonce
46
+ // spoof-tuple definitions in any test.plus.
47
+ spoof(test) /* passed */ {
47
48
  // Localizing.
48
49
  let type = test.on;
49
50
  let spoofNonces = test.plus;
@@ -52,12 +53,19 @@ export class ClassMethodSpoofer extends ASpoofingFixture {
52
53
  if (!Array.isArray(spoofNonces)) {
53
54
  return;
54
55
  }
55
-
56
+
56
57
  // Converting to scope object type.
57
- let spoofDefinitions = SpoofDefinition.fromNonceTuples(spoofNonces);
58
-
58
+ let spoofDefs = SpoofDef.fromNonceTuples(spoofNonces, type);
59
+
60
+ // Working only with method spoofs.
61
+ let methodSpoofs = Array.from(spoofDefs)
62
+ .filter(x => x.isMethodSpoof);
63
+
64
+ // Stripping spoofs of any sigils.
65
+ methodSpoofs.forEach(x => x.method = NameAnalyzer.plainNameOf(x.method));
66
+
59
67
  // Storing spoofing definitions.
60
- this.#retainSpoofsByClass(type, spoofDefinitions);
68
+ this.#retainSpoofsByClass(type, methodSpoofs);
61
69
 
62
70
  // Storing originals for restoring later.
63
71
  this.#reserveOriginalsByClass();
@@ -68,36 +76,20 @@ export class ClassMethodSpoofer extends ASpoofingFixture {
68
76
 
69
77
  // region Dependencies of spoof()
70
78
 
71
- #retainSpoofsByClass(type, spoofDefinitions) {
79
+ #retainSpoofsByClass(type, spoofDefs) /* verified */ {
72
80
  // Map of Maps: by type, then by method.
73
- for (let tuple of spoofDefinitions) {
74
- // If no .target, use `type`.
75
- if (!tuple.target) {
76
- tuple.target = type;
77
- }
78
-
79
- let spoofsByTarget = this.#supplyMemberMap(this.#spoofsByClass, tuple.target);
81
+ for (let def of spoofDefs) {
82
+ let spoofsByTarget = this.#supplyMemberMap(this.#spoofsByClass, def.target);
80
83
 
81
84
  // A single-method spoof is set for later use.
82
- if (tuple.method) {
83
- spoofsByTarget.set(tuple.method, tuple.output);
84
- continue;
85
- }
86
-
87
- // Two or more method spoofs are set for later use.
88
- if (tuple.output) {
89
- let ofAsPairs = tuple.output;
90
-
91
- for (let pair of ofAsPairs) {
92
- spoofsByTarget.set(pair.of, pair.as);
93
- }
94
-
85
+ if (def.method) {
86
+ spoofsByTarget.set(def.method, def.output);
95
87
  continue;
96
88
  }
97
89
  }
98
90
  }
99
91
 
100
- #reserveOriginalsByClass() {
92
+ #reserveOriginalsByClass() /* verified */ {
101
93
  /* Any spoofing of multiple methods on each class has already been
102
94
  split up into Map elements, so this code can use those naively. */
103
95
 
@@ -112,7 +104,10 @@ export class ClassMethodSpoofer extends ASpoofingFixture {
112
104
 
113
105
  // Saving originals in the Map for later.
114
106
  for (let name of names) {
115
- let original = type.prototype[name];
107
+ let original = TypeAnalyzer.isInstanceMember(type, name)
108
+ ? type.prototype[name]
109
+ : type[name];
110
+
116
111
  originalsByTarget.set(name, original);
117
112
  }
118
113
  }
@@ -120,7 +115,7 @@ export class ClassMethodSpoofer extends ASpoofingFixture {
120
115
 
121
116
  /* Dependency of #retainSpoofsByClass()
122
117
  and #reserveOriginalsByClass(). */
123
- #supplyMemberMap(source, target) {
118
+ #supplyMemberMap(source, target) /* verified */ {
124
119
  let mapForType = source.get(target);
125
120
 
126
121
  if (!mapForType) {
@@ -131,31 +126,36 @@ export class ClassMethodSpoofer extends ASpoofingFixture {
131
126
  return mapForType;
132
127
  }
133
128
 
134
- #spoofMembersByClass() {
129
+ #spoofMembersByClass() /* verified */ {
135
130
  /* Any spoofing of multiple methods on each class has already been
136
131
  split up into Map elements, so this code can use those naively. */
137
132
 
138
133
  let types = this.#spoofsByClass.keys();
139
134
 
140
135
  // For each class.
141
- for (let type of types) {
142
- let spoofsByTarget = this.#spoofsByClass.get(type);
136
+ for (let target of types) {
137
+ let spoofsByTarget = this.#spoofsByClass.get(target);
143
138
  let names = spoofsByTarget.keys();
144
139
 
145
140
  // Actually spoofing, one by one.
146
141
  for (let name of names) {
147
142
  let spoofSource = spoofsByTarget.get(name);
148
143
  let spoof = super.spoofMethod(spoofSource);
149
- type.prototype[name] = spoof;
144
+
145
+ // Instance members are on prototype,
146
+ // static members on the type itself.
147
+ TypeAnalyzer.isInstanceMember(target, name)
148
+ ? target.prototype[name] = spoof
149
+ : target[name] = spoof;
150
150
  }
151
151
  }
152
152
  }
153
153
 
154
154
  // endregion Dependencies of spoof()
155
155
 
156
- // Spoofed methods on any targeted classes
157
- // are restored to their original forms.
158
- unspoof() {
156
+ // Spoofed methods on any targeted classes are restored to
157
+ // their original forms, and spoof definitions are erased.
158
+ unspoof() /* passed */ {
159
159
  let types = this.#originalsByClass.keys();
160
160
 
161
161
  // For each class.
@@ -168,14 +168,20 @@ export class ClassMethodSpoofer extends ASpoofingFixture {
168
168
  // Actually restoring, one by one.
169
169
  for (let name of names) {
170
170
  let original = originalsByTarget.get(name);
171
- target.prototype[name] = original;
171
+
172
+ TypeAnalyzer.isInstanceMember(target, name)
173
+ ? target.prototype[name] = original
174
+ : target[name] = original;
172
175
  }
173
176
  }
177
+
178
+ // Letting next call of spoof() start from scratch.
179
+ this.removeDefinitions();
174
180
  }
175
181
 
176
- // Removes definitions, useful if this instance is reused,
177
- // or else they might be applied when they shouldn't be.
178
- removeDefinitions() {
182
+ // Removes definitions, useful since this instance is reused,
183
+ // so they won't be used in tests when they shouldn't be.
184
+ removeDefinitions() /* verified */ {
179
185
  this.#spoofsByClass.clear();
180
186
  this.#originalsByClass.clear();
181
187
  }
@@ -1,8 +1,8 @@
1
1
  /**/
2
2
 
3
- import { TestGroup } from "./TestGroup.js";
3
+ import TestGroup from "./TestGroup.js";
4
4
 
5
5
  /* Identifies a grouping of tests by method. No specialized workings. */
6
6
 
7
- export class MethodTestGroup extends TestGroup {
7
+ export default class MethodTestGroup extends TestGroup {
8
8
  }
package/system/Moment.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**/
2
2
 
3
- export class Moment {
3
+ export default class Moment {
4
4
  #now;
5
5
 
6
6
  constructor(now) {
@@ -0,0 +1,26 @@
1
+ /**/
2
+
3
+ export default class NameAnalyzer {
4
+ // region Definitions
5
+
6
+ static dotOperator = ".";
7
+ static colonOperator = ":";
8
+ static parensOperator = "()";
9
+ static operatorsRegExp = /\.|:|\(\)/g;
10
+
11
+ // endregion Definitions
12
+
13
+ static hasPropertySigil(name) /* passed */ {
14
+ return name.startsWith(NameAnalyzer.dotOperator) || name.endsWith(NameAnalyzer.colonOperator);
15
+ }
16
+
17
+ static hasMethodSigil(name) /* passed */ {
18
+ return name.endsWith(NameAnalyzer.parensOperator);
19
+ }
20
+
21
+ static plainNameOf(name) /* passed */ {
22
+ let plain = name.replaceAll(NameAnalyzer.operatorsRegExp, "");
23
+ return plain;
24
+ }
25
+ }
26
+
@@ -0,0 +1,156 @@
1
+ /**/
2
+
3
+ import ASpoofingFixture from "./ASpoofingFixture.js";
4
+ import SpoofDef from "./SpoofDef.js";
5
+ import TypeAnalyzer from "./TypeAnalyzer.js";
6
+ import NameAnalyzer from "./NameAnalyzer.js";
7
+
8
+ export default class PropertySpoofer extends ASpoofingFixture {
9
+ /* Algorithm: Forward method spoof() looks at property spoof definitions in .plus
10
+ and first saves the original values on the target object
11
+ (or its type, if a property is static), then applies the spoofed ones.
12
+ Reverse method unspoof() restores each original property value.
13
+ Works on test target and its class only, unlike MethodSpoofer. */
14
+
15
+ // region Private fields
16
+
17
+ #target;
18
+ #type;
19
+
20
+ // Spoofed and original property values.
21
+ #settables = [ ];
22
+ #unsettables = [ ];
23
+
24
+ // endregion Private fields
25
+
26
+ // region Properties
27
+
28
+ get target() {
29
+ return this.#target;
30
+ }
31
+
32
+ set target(value) {
33
+ this.#target = value;
34
+ }
35
+
36
+ get settables() {
37
+ return this.#settables;
38
+ }
39
+
40
+ set settables(value) {
41
+ this.#settables = value;
42
+ }
43
+
44
+ get unsettables() {
45
+ return this.#unsettables;
46
+ }
47
+
48
+ set unsettables(value) {
49
+ this.#unsettables = value;
50
+ }
51
+
52
+ // endregion Properties
53
+
54
+ constructor() {
55
+ super("PropertySpoofer", "Construction");
56
+ }
57
+
58
+ /* Spoofs properties of test.target as defined in any test.plus. */
59
+ spoof(test) /* passed */ {
60
+ // Localizing.
61
+ this.#target = test.target;
62
+ this.#type = test.type;
63
+
64
+ let spoofNonces = test.plus;
65
+
66
+ // Spoofing definitions are always in an array.
67
+ if (!Array.isArray(spoofNonces)) {
68
+ return;
69
+ }
70
+
71
+ // Converting to scope object type.
72
+ let spoofDefs = SpoofDef.fromNonceTuples(spoofNonces, this.#type);
73
+
74
+ // Working only with property spoofs.
75
+ let propertySpoofs = Array.from(spoofDefs)
76
+ .filter(x => x.isPropertySpoof);
77
+
78
+ // Stripping spoofs of any sigils.
79
+ propertySpoofs.forEach(x => x.method = NameAnalyzer.plainNameOf(x.method));
80
+
81
+ // Storing new values for setting.
82
+ this.#settables = propertySpoofs;
83
+
84
+ // Storing original values for restoring later.
85
+ this.#anyOriginalPropertyGetting(this.#target, this.#type, this.#settables);
86
+
87
+ // Actually spoofing with new values.
88
+ this.#anyPropertySetting(this.#target, this.#type, this.#settables);
89
+ }
90
+
91
+ /* Spoofed properties on test.target are restored to their original values.
92
+ Necessary at the least to remove spoofed values before next test. */
93
+ unspoof() /* passed */ {
94
+ // Actually unspoofing.
95
+ this.#anyPropertyUnsetting(this.#target, this.#type, this.#unsettables);
96
+
97
+ // Letting next call of spoof() start from scratch.
98
+ this.removeValues();
99
+ }
100
+
101
+ // region Dependencies of spoof()
102
+
103
+ #anyOriginalPropertyGetting(target, type, settables) /* verified */ {
104
+ let unsettables = [ ];
105
+
106
+ for (let settable of settables) {
107
+ let name = settable.of;
108
+
109
+ // Retaining original.
110
+ let original
111
+ = TypeAnalyzer.isInstanceMember(type, name)
112
+ ? target[name]
113
+ : type[name];
114
+
115
+ let unsettable = { of: name, as: original };
116
+ unsettables.push(unsettable);
117
+ }
118
+
119
+ this.#unsettables = unsettables;
120
+ }
121
+
122
+ // endregion Dependencies of spoof()
123
+
124
+ // region Dependencies of unspoof()
125
+
126
+ #anyPropertyUnsetting(target, type, unsettables) /* verified */ {
127
+ // Unsetting is the same as setting,
128
+ // but with tuples of original values.
129
+ return this.#anyPropertySetting(target, type, unsettables);
130
+ }
131
+
132
+ // Removes spoof values, useful since this instance is reused,
133
+ // so they won't be used in tests when they shouldn't be.
134
+ removeValues() /* verified */ {
135
+ this.#settables = [ ];
136
+ this.#unsettables = [ ];
137
+ }
138
+
139
+ // endregion Dependencies of unspoof()
140
+
141
+ // region Dependencies of both spoof() and unspoof()
142
+
143
+ #anyPropertySetting(target, type, settables) /* verified */ {
144
+ for (let settable of settables) {
145
+ let name = settable.of;
146
+ let output = settable.as;
147
+
148
+ // Actually setting property.
149
+ TypeAnalyzer.isInstanceMember(type, name)
150
+ ? target[name] = output
151
+ : type[name] = output;
152
+ }
153
+ }
154
+
155
+ // endregion Dependencies of both spoof() and unspoof()
156
+ }
package/system/Risei.js CHANGED
@@ -10,17 +10,17 @@
10
10
 
11
11
  // region Test-running dependencies
12
12
 
13
- import { TestRunner } from "./TestRunner.js";
14
- import { LocalCaller } from "./LocalCaller.js";
15
- import { TerminalReporter } from "./TerminalReporter.js";
16
- import { TestFinder } from "./TestFinder.js";
13
+ import TestRunner from "./TestRunner.js";
14
+ import LocalCaller from "./LocalCaller.js";
15
+ import TerminalReporter from "./TerminalReporter.js";
16
+ import TestFinder from "./TestFinder.js";
17
17
 
18
18
  // endregion Test-running dependencies
19
19
 
20
20
  // region Display dependencies
21
21
 
22
22
  import chalk from "chalk";
23
- import { Moment } from "./Moment.js";
23
+ import Moment from "./Moment.js";
24
24
 
25
25
  // endregion Display dependencies
26
26