risei 1.0.4 → 1.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.
Files changed (78) hide show
  1. package/README.md +236 -339
  2. package/index.js +8 -8
  3. package/package.json +23 -9
  4. package/{public/javascript → system}/ASpoofingFixture.js +1 -1
  5. package/{public/javascript → system}/ChosenTestFinder.js +4 -3
  6. package/{public/javascript → system}/SpoofClassMethodsFixture.js +38 -22
  7. package/system/SpoofObjectMethodsFixture.js +58 -0
  8. package/{public/javascript → system}/SpoofTuple.js +14 -1
  9. package/{public/javascript → system}/TerminalReporter.js +249 -222
  10. package/system/TestFrame.js +187 -0
  11. package/system/TestFrameChooser.js +54 -0
  12. package/system/TestFrames.js +232 -0
  13. package/system/TestResult.js +187 -0
  14. package/system/TestRunner.js +280 -0
  15. package/system/TestStages.js +278 -0
  16. package/{public/javascript → system}/TestTuple.js +132 -13
  17. package/{public/javascript → system}/TotalComparer.js +12 -0
  18. package/system/TotalCopier.js +79 -0
  19. package/system/TotalDisplayer.js +143 -0
  20. package/system/TypeAnalyzer.js +103 -0
  21. package/system/TypeIdentifier.js +70 -0
  22. package/system/Types.js +17 -0
  23. package/tests/other-tests/ASpoofingFixture.tests.js +242 -0
  24. package/tests/other-tests/SpoofClassesFixture.tests.js +130 -0
  25. package/tests/other-tests/SpoofObjectsFixture.tests.js +95 -0
  26. package/tests/other-tests/SpoofTuple.tests.js +93 -0
  27. package/tests/other-tests/TotalComparer.tests.js +920 -0
  28. package/tests/other-tests/package.json +7 -0
  29. package/tests/risei-tests/ASpoofingFixtureTests.rt.js +51 -0
  30. package/tests/risei-tests/MomentTests.rt.js +103 -0
  31. package/tests/risei-tests/SpoofTupleTests.rt.js +274 -0
  32. package/tests/risei-tests/TestFrameChooserTests.rt.js +74 -0
  33. package/tests/risei-tests/TestFrameTests.rt.js +84 -0
  34. package/tests/risei-tests/TestStagesTests.rt.js +99 -0
  35. package/tests/risei-tests/TestTupleTests.rt.js +140 -0
  36. package/tests/risei-tests/TotalComparerTests.rt.js +184 -0
  37. package/tests/risei-tests/TotalCopierTests.rt.js +74 -0
  38. package/tests/risei-tests/TotalDisplayerTests.rt.js +186 -0
  39. package/tests/risei-tests/TypeAnalyzerTests.rt.js +29 -0
  40. package/tests/risei-tests/TypeIdentifierTests.rt.js +44 -0
  41. package/tests/self-tests/SelfTests.outward-rt.js +583 -0
  42. package/tests/target-objects/CompositionModel.js +38 -0
  43. package/tests/target-objects/ConditionalThrowModel.js +11 -0
  44. package/tests/target-objects/CountModel.js +46 -0
  45. package/tests/target-objects/DomModel.js +37 -0
  46. package/tests/target-objects/MixedContents.js +33 -0
  47. package/tests/target-objects/MutationModel.js +27 -0
  48. package/tests/target-objects/ObjectCompositionModel.js +34 -0
  49. package/tests/target-objects/PolySpoofableInner.js +30 -0
  50. package/tests/target-objects/PolySpoofableOuter.js +52 -0
  51. package/tests/target-objects/PropertiesModel.js +47 -0
  52. package/tests/target-objects/Returner.js +9 -0
  53. package/tests/target-objects/SearchModel.js +25 -0
  54. package/tests/target-objects/SortModel.js +91 -0
  55. package/tests/target-objects/SpoofCaller.js +24 -0
  56. package/tests/target-objects/Spoofable.js +36 -0
  57. package/tests/target-objects/SpoofableArgsCaller.js +33 -0
  58. package/tests/target-objects/StateModel.js +34 -0
  59. package/tests/target-objects/StaticModel.js +17 -0
  60. package/tests/target-objects/TestableModel.js +47 -0
  61. package/tests/topic-tests/TopicTests.outward-rt.js +354 -0
  62. package/public/javascript/SpoofObjectMethodsFixture.js +0 -52
  63. package/public/javascript/TestResult.js +0 -338
  64. package/public/javascript/TestRunner.js +0 -476
  65. /package/{public/javascript → system}/AComparer.js +0 -0
  66. /package/{public/javascript → system}/ATestCaller.js +0 -0
  67. /package/{public/javascript → system}/ATestFinder.js +0 -0
  68. /package/{public/javascript → system}/ATestFixture.js +0 -0
  69. /package/{public/javascript → system}/ATestReporter.js +0 -0
  70. /package/{public/javascript → system}/ATestSource.js +0 -0
  71. /package/{public/javascript → system}/ClassTestGroup.js +0 -0
  72. /package/{public/javascript → system}/LocalCaller.js +0 -0
  73. /package/{public/javascript → system}/MethodTestGroup.js +0 -0
  74. /package/{public/javascript → system}/Moment.js +0 -0
  75. /package/{public/javascript → system}/Risei.js +0 -0
  76. /package/{public/javascript → system}/TestFinder.js +0 -0
  77. /package/{public/javascript → system}/TestGroup.js +0 -0
  78. /package/{public/javascript → system}/TestSummary.js +0 -0
package/index.js CHANGED
@@ -10,17 +10,17 @@
10
10
 
11
11
  // region Test-running dependencies
12
12
 
13
- import { TestRunner } from "./public/javascript/TestRunner.js";
14
- import { LocalCaller } from "./public/javascript/LocalCaller.js";
15
- import { TerminalReporter } from "./public/javascript/TerminalReporter.js";
16
- import { TestFinder } from "./public/javascript/TestFinder.js";
13
+ import { TestRunner } from "./system/TestRunner.js";
14
+ import { LocalCaller } from "./system/LocalCaller.js";
15
+ import { TerminalReporter } from "./system/TerminalReporter.js";
16
+ import { TestFinder } from "./system/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 "./public/javascript/Moment.js";
23
+ import { Moment } from "./system/Moment.js";
24
24
 
25
25
  // endregion Display dependencies
26
26
 
@@ -30,14 +30,14 @@ import { Moment } from "./public/javascript/Moment.js";
30
30
 
31
31
  // region Classes that users typically subclass
32
32
 
33
- export * from "./public/javascript/ATestSource.js";
33
+ export * from "./system/ATestSource.js";
34
34
 
35
35
  // endregion Classes that users typically subclass
36
36
 
37
37
  // region Classes that users might subclass for uncommon cases
38
38
 
39
- export * from "./public/javascript/ATestFinder.js";
40
- export * from "./public/javascript/ATestReporter.js";
39
+ export * from "./system/ATestFinder.js";
40
+ export * from "./system/ATestReporter.js";
41
41
 
42
42
  // endregion Classes that users might subclass for uncommon cases
43
43
 
package/package.json CHANGED
@@ -1,23 +1,36 @@
1
1
  {
2
2
  "name": "risei",
3
- "version": "1.0.4",
4
- "description": "RiseiJs is the framework that allows you to write unit tests as collections of values in JavaScript objects, so it's easy and fast, and tests don't serve as a drag on redesigns.",
5
- "keywords": [ "unit test", "test", "unit testing", "testing", "easy", "fast", "values", "objects", "declarative" ],
6
- "author": "Ed Fallin <riseijsmaker@gmail.com>",
3
+ "version": "1.1.1",
4
+ "description": "Risei is the framework that allows you to write unit tests as collections of values in JavaScript objects, so it's easy and fast, and tests don't serve as a drag on redesigns.",
5
+ "keywords": [
6
+ "unit test",
7
+ "test",
8
+ "unit testing",
9
+ "testing",
10
+ "easy",
11
+ "fast",
12
+ "simple",
13
+ "values",
14
+ "objects",
15
+ "declarative"
16
+ ],
17
+ "author": "Ed Fallin <riseimaker@gmail.com>",
7
18
  "license": "MIT",
8
19
  "type": "module",
9
20
  "private": false,
10
21
  "scripts": {
11
22
  "start": "node ./bin/www",
12
- "risei": "node ./index.js",
13
- "rtest": "clear; node ./public/javascript/Risei.js",
23
+ "rself": "clear; node system/Risei.js",
24
+ "rtest": "clear; node ./node_modules/risei/index.js",
14
25
  "xtest": "clear; mocha **/*.tests.js",
15
- "test": "clear; mocha **/*.tests.js; node ./public/javascript/Risei.js"
26
+ "mixedtest": "clear; mocha **/*.tests.js; node ./node_modules/risei/index.js",
27
+ "alltest": "clear; mocha **/*.tests.js; node ./node_modules/risei/index.js; node system/Risei.js",
28
+ "test": "clear; node ./node_modules/risei/index.js"
16
29
  },
17
30
  "risei": {
18
31
  "tests": "**.rt.js"
19
32
  },
20
- "exports":{
33
+ "exports": {
21
34
  ".": "./index.js",
22
35
  "./ATestSource": "./public/javascript/ATestSource.js"
23
36
  },
@@ -34,6 +47,7 @@
34
47
  "express": "~4.16.1",
35
48
  "fs": "^0.0.1-security",
36
49
  "mocha": "^10.0.0",
37
- "morgan": "~1.9.1"
50
+ "morgan": "~1.9.1",
51
+ "risei": "^1.1.0"
38
52
  }
39
53
  }
@@ -72,7 +72,7 @@ export class ASpoofingFixture extends ATestFixture {
72
72
  name = names.shift();
73
73
  name = name.replace("()", "");
74
74
 
75
- // Actually spoofing method.
75
+ // Actually spoofing, as method only.
76
76
  let method = this.spoofMethod(output);
77
77
  next[name] = method;
78
78
  }
@@ -3,15 +3,16 @@
3
3
  /* ChosenTestFinder is an ATestFinder that finds tests in the places coded in its constructor. */
4
4
 
5
5
  import { ATestFinder } from "./ATestFinder.js";
6
- import { Tests } from "./topic-tests/Tests.rt.js";
7
- import { SelfTests } from "./self-tests/SelfTests.rt.js";
6
+ import { TopicTests } from "../tests/topic-tests/TopicTests.outward-rt.js";
7
+ import { SelfTests } from "../tests/self-tests/SelfTests.outward-rt.js";
8
8
 
9
9
  export class ChosenTestFinder extends ATestFinder {
10
10
  constructor() {
11
11
  super();
12
12
 
13
- let testSource = new Tests();
13
+ let testSource = new TopicTests();
14
14
  let selfTestSource = new SelfTests();
15
+
15
16
  this.testSources = [ testSource, selfTestSource ];
16
17
  }
17
18
 
@@ -4,6 +4,11 @@ import { ASpoofingFixture } from "./ASpoofingFixture.js";
4
4
  import { SpoofTuple } from "./SpoofTuple.js";
5
5
 
6
6
  export class SpoofClassMethodsFixture extends ASpoofingFixture {
7
+ /* Algorithm: Forward method spoof() looks at spoof definitions in .plus and applies them
8
+ to each class' prototypes after first saving the original member definitions.
9
+ Reverse method unspoof() restores each original member definition.
10
+ Fundamentally different from what SpoofObjectMethodsFixture does. */
11
+
7
12
  // region Private fields
8
13
 
9
14
  #spoofsByClass = new Map();
@@ -51,16 +56,18 @@ export class SpoofClassMethodsFixture extends ASpoofingFixture {
51
56
  let spoofTuples = SpoofTuple.fromNonceTuples(spoofNonces);
52
57
 
53
58
  // Storing spoofing definitions.
54
- this.#targetThese(type, spoofTuples);
59
+ this.#retainSpoofsByClass(type, spoofTuples);
55
60
 
56
61
  // Storing originals for restoring later.
57
- this.#reserveOriginalsForSpoofs();
62
+ this.#reserveOriginalsByClass();
58
63
 
59
64
  // Actually spoofing.
60
- this.#spoofAll();
65
+ this.#spoofMembersByClass();
61
66
  }
62
67
 
63
- #targetThese(type, spoofTuples) {
68
+ // region Dependencies of spoof()
69
+
70
+ #retainSpoofsByClass(type, spoofTuples) {
64
71
  // Map of Maps: by type, then by method.
65
72
  for (let tuple of spoofTuples) {
66
73
  // If no .target, use `type`.
@@ -68,13 +75,7 @@ export class SpoofClassMethodsFixture extends ASpoofingFixture {
68
75
  tuple.target = type;
69
76
  }
70
77
 
71
- // Either the existing Map for this type, or a new one if none yet.
72
- let spoofsByTarget = this.#spoofsByClass.get(tuple.target);
73
-
74
- if (!spoofsByTarget) {
75
- spoofsByTarget = new Map();
76
- this.#spoofsByClass.set(tuple.target, spoofsByTarget);
77
- }
78
+ let spoofsByTarget = this.#supplyMemberMap(this.#spoofsByClass, tuple.target);
78
79
 
79
80
  // A single-method spoof is set for later use.
80
81
  if (tuple.method) {
@@ -95,23 +96,20 @@ export class SpoofClassMethodsFixture extends ASpoofingFixture {
95
96
  }
96
97
  }
97
98
 
98
- #reserveOriginalsForSpoofs() {
99
+ #reserveOriginalsByClass() {
99
100
  /* Any spoofing of multiple methods on each class has already been
100
101
  split up into Map elements, so this code can use those naively. */
101
102
 
102
103
  let types = this.#spoofsByClass.keys();
103
104
 
105
+ // For each class.
104
106
  for (let type of types) {
105
- let originalsByTarget = this.#originalsByClass.get(type);
107
+ let originalsByTarget = this.#supplyMemberMap(this.#originalsByClass, type);
106
108
 
107
- if (!originalsByTarget) {
108
- originalsByTarget = new Map();
109
- this.#originalsByClass.set(type, originalsByTarget);
110
- }
111
-
112
109
  let spoofsByTarget = this.#spoofsByClass.get(type);
113
110
  let names = spoofsByTarget.keys();
114
111
 
112
+ // Saving originals in the Map for later.
115
113
  for (let name of names) {
116
114
  let original = type.prototype[name];
117
115
  originalsByTarget.set(name, original);
@@ -119,16 +117,31 @@ export class SpoofClassMethodsFixture extends ASpoofingFixture {
119
117
  }
120
118
  }
121
119
 
122
- #spoofAll() {
120
+ /* Dependency of #retainSpoofsByClass()
121
+ and #reserveOriginalsByClass(). */
122
+ #supplyMemberMap(source, target) {
123
+ let mapForType = source.get(target);
124
+
125
+ if (!mapForType) {
126
+ mapForType = new Map();
127
+ source.set(target, mapForType);
128
+ }
129
+
130
+ return mapForType;
131
+ }
132
+
133
+ #spoofMembersByClass() {
123
134
  /* Any spoofing of multiple methods on each class has already been
124
135
  split up into Map elements, so this code can use those naively. */
125
136
 
126
137
  let types = this.#spoofsByClass.keys();
127
138
 
139
+ // For each class.
128
140
  for (let type of types) {
129
141
  let spoofsByTarget = this.#spoofsByClass.get(type);
130
142
  let names = spoofsByTarget.keys();
131
143
 
144
+ // Actually spoofing, one by one.
132
145
  for (let name of names) {
133
146
  let spoofSource = spoofsByTarget.get(name);
134
147
  let spoof = super.spoofMethod(spoofSource);
@@ -137,25 +150,28 @@ export class SpoofClassMethodsFixture extends ASpoofingFixture {
137
150
  }
138
151
  }
139
152
 
153
+ // endregion Dependencies of spoof()
154
+
140
155
  // Spoofed methods on any targeted classes
141
156
  // are restored to their original forms.
142
157
  unspoof() {
143
158
  let types = this.#originalsByClass.keys();
144
159
 
160
+ // For each class.
145
161
  for (let target of types) {
146
- let originalsByTarget = this.#originalsByClass.get(target);
147
-
148
162
  let prototype = target.prototype;
149
163
 
164
+ let originalsByTarget = this.#originalsByClass.get(target);
150
165
  let names = originalsByTarget.keys();
151
166
 
167
+ // Actually restoring, one by one.
152
168
  for (let name of names) {
153
169
  let original = originalsByTarget.get(name);
154
170
  target.prototype[name] = original;
155
171
  }
156
172
  }
157
173
  }
158
-
174
+
159
175
  // Removes definitions, useful if this instance is reused,
160
176
  // or else they might be applied when they shouldn't be.
161
177
  removeDefinitions() {
@@ -0,0 +1,58 @@
1
+ /* */
2
+
3
+ import { ASpoofingFixture } from "./ASpoofingFixture.js";
4
+ import { SpoofTuple } from "./SpoofTuple.js";
5
+
6
+ export class SpoofObjectMethodsFixture extends ASpoofingFixture {
7
+ /* Algorithm: Forward method spoof() looks at a test's .with and .in, and replaces entire objects
8
+ in each with spoofed object trees, if the originals are spoof definitions.
9
+ No reverse unspoofing method is needed, since objects are nonces tossed after tests.
10
+ Fundamentally different from much of what SpoofClassMethodsFixture does. */
11
+
12
+ constructor() {
13
+ super("SpoofObjectMethodsFixture", "Construction");
14
+ }
15
+
16
+ /* Spoofs methods of any objects in test.with and test.in
17
+ for which nonce spoof-tuple definitions are provided. */
18
+ spoof(test) {
19
+ // These array test aspects may contain object-spoof definitions.
20
+ let topics = [ test.with, test.in ];
21
+
22
+ // Spoofing each array of test-aspect elements.
23
+ for (let topic of topics) {
24
+ // Replacing whole element with spoof or with unchanged self.
25
+ for (let at = 0; at < topic.length; at++) {
26
+ let target = topic[at];
27
+ topic[at] = this.spoofTarget(target);
28
+ }
29
+ }
30
+ }
31
+
32
+ spoofTarget(target) {
33
+ // Non-spoof targets are returned unchanged.
34
+ if (SpoofTuple.isNotASpoof(target)) {
35
+ return target;
36
+ }
37
+
38
+ // Spoof definition targets are converted.
39
+ let tuple = SpoofTuple.fromNonceTuple(target);
40
+ let ofAsPairs = this.#supplySpoofPairs(tuple);
41
+
42
+ // Returning object with one or more spoofed members.
43
+ let spoofedTarget = super.spoofObjectTree(ofAsPairs);
44
+ return spoofedTarget;
45
+ }
46
+
47
+ #supplySpoofPairs(tuple) {
48
+ // Single-spoof output.
49
+ let ofAsPairs = [{ of: tuple.method, as: tuple.output }];
50
+
51
+ // Poly-spoof output.
52
+ if (!tuple.method) {
53
+ ofAsPairs = tuple.output;
54
+ }
55
+
56
+ return ofAsPairs;
57
+ }
58
+ }
@@ -1,5 +1,7 @@
1
1
  /**/
2
2
 
3
+ import { TypeAnalyzer } from "./TypeAnalyzer.js";
4
+
3
5
  /* Defines what is found in a spoof-definition tuple (SDT). Actual SDTs don't need to be instances of this class. */
4
6
 
5
7
  export class SpoofTuple {
@@ -18,6 +20,12 @@ export class SpoofTuple {
18
20
 
19
21
  // endregion Static fields
20
22
 
23
+ // region Private fields
24
+
25
+ #typeAnalyzer;
26
+
27
+ // endregion Private fields
28
+
21
29
  // region Public fields (long names)
22
30
 
23
31
  /* These long names are clearer and match the constructor's parameter names. */
@@ -76,6 +84,10 @@ export class SpoofTuple {
76
84
 
77
85
  return isSpoofable;
78
86
  }
87
+
88
+ isPropertySpoof() /* passed */ {
89
+ return this.#typeAnalyzer.memberIsProperty(this.method);
90
+ }
79
91
 
80
92
  // endregion Tuple state
81
93
 
@@ -89,6 +101,8 @@ export class SpoofTuple {
89
101
  this.target = target;
90
102
  this.method = method;
91
103
  this.output = output;
104
+
105
+ this.#typeAnalyzer = new TypeAnalyzer(target);
92
106
  }
93
107
 
94
108
  static fromNonceTuples(nonces) {
@@ -162,7 +176,6 @@ export class SpoofTuple {
162
176
  return true;
163
177
  }
164
178
 
165
- /* &cruft, test or drop */
166
179
  static isASpoof(nonce) {
167
180
  return !this.isNotASpoof(nonce);
168
181
  }