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.
- package/README.md +236 -339
- package/index.js +8 -8
- package/package.json +23 -9
- package/{public/javascript → system}/ASpoofingFixture.js +1 -1
- package/{public/javascript → system}/ChosenTestFinder.js +4 -3
- package/{public/javascript → system}/SpoofClassMethodsFixture.js +38 -22
- package/system/SpoofObjectMethodsFixture.js +58 -0
- package/{public/javascript → system}/SpoofTuple.js +14 -1
- package/{public/javascript → system}/TerminalReporter.js +249 -222
- package/system/TestFrame.js +187 -0
- package/system/TestFrameChooser.js +54 -0
- package/system/TestFrames.js +232 -0
- package/system/TestResult.js +187 -0
- package/system/TestRunner.js +280 -0
- package/system/TestStages.js +278 -0
- package/{public/javascript → system}/TestTuple.js +132 -13
- package/{public/javascript → system}/TotalComparer.js +12 -0
- package/system/TotalCopier.js +79 -0
- package/system/TotalDisplayer.js +143 -0
- package/system/TypeAnalyzer.js +103 -0
- package/system/TypeIdentifier.js +70 -0
- package/system/Types.js +17 -0
- package/tests/other-tests/ASpoofingFixture.tests.js +242 -0
- package/tests/other-tests/SpoofClassesFixture.tests.js +130 -0
- package/tests/other-tests/SpoofObjectsFixture.tests.js +95 -0
- package/tests/other-tests/SpoofTuple.tests.js +93 -0
- package/tests/other-tests/TotalComparer.tests.js +920 -0
- package/tests/other-tests/package.json +7 -0
- package/tests/risei-tests/ASpoofingFixtureTests.rt.js +51 -0
- package/tests/risei-tests/MomentTests.rt.js +103 -0
- package/tests/risei-tests/SpoofTupleTests.rt.js +274 -0
- package/tests/risei-tests/TestFrameChooserTests.rt.js +74 -0
- package/tests/risei-tests/TestFrameTests.rt.js +84 -0
- package/tests/risei-tests/TestStagesTests.rt.js +99 -0
- package/tests/risei-tests/TestTupleTests.rt.js +140 -0
- package/tests/risei-tests/TotalComparerTests.rt.js +184 -0
- package/tests/risei-tests/TotalCopierTests.rt.js +74 -0
- package/tests/risei-tests/TotalDisplayerTests.rt.js +186 -0
- package/tests/risei-tests/TypeAnalyzerTests.rt.js +29 -0
- package/tests/risei-tests/TypeIdentifierTests.rt.js +44 -0
- package/tests/self-tests/SelfTests.outward-rt.js +583 -0
- package/tests/target-objects/CompositionModel.js +38 -0
- package/tests/target-objects/ConditionalThrowModel.js +11 -0
- package/tests/target-objects/CountModel.js +46 -0
- package/tests/target-objects/DomModel.js +37 -0
- package/tests/target-objects/MixedContents.js +33 -0
- package/tests/target-objects/MutationModel.js +27 -0
- package/tests/target-objects/ObjectCompositionModel.js +34 -0
- package/tests/target-objects/PolySpoofableInner.js +30 -0
- package/tests/target-objects/PolySpoofableOuter.js +52 -0
- package/tests/target-objects/PropertiesModel.js +47 -0
- package/tests/target-objects/Returner.js +9 -0
- package/tests/target-objects/SearchModel.js +25 -0
- package/tests/target-objects/SortModel.js +91 -0
- package/tests/target-objects/SpoofCaller.js +24 -0
- package/tests/target-objects/Spoofable.js +36 -0
- package/tests/target-objects/SpoofableArgsCaller.js +33 -0
- package/tests/target-objects/StateModel.js +34 -0
- package/tests/target-objects/StaticModel.js +17 -0
- package/tests/target-objects/TestableModel.js +47 -0
- package/tests/topic-tests/TopicTests.outward-rt.js +354 -0
- package/public/javascript/SpoofObjectMethodsFixture.js +0 -52
- package/public/javascript/TestResult.js +0 -338
- package/public/javascript/TestRunner.js +0 -476
- /package/{public/javascript → system}/AComparer.js +0 -0
- /package/{public/javascript → system}/ATestCaller.js +0 -0
- /package/{public/javascript → system}/ATestFinder.js +0 -0
- /package/{public/javascript → system}/ATestFixture.js +0 -0
- /package/{public/javascript → system}/ATestReporter.js +0 -0
- /package/{public/javascript → system}/ATestSource.js +0 -0
- /package/{public/javascript → system}/ClassTestGroup.js +0 -0
- /package/{public/javascript → system}/LocalCaller.js +0 -0
- /package/{public/javascript → system}/MethodTestGroup.js +0 -0
- /package/{public/javascript → system}/Moment.js +0 -0
- /package/{public/javascript → system}/Risei.js +0 -0
- /package/{public/javascript → system}/TestFinder.js +0 -0
- /package/{public/javascript → system}/TestGroup.js +0 -0
- /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 "./
|
|
14
|
-
import { LocalCaller } from "./
|
|
15
|
-
import { TerminalReporter } from "./
|
|
16
|
-
import { TestFinder } from "./
|
|
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 "./
|
|
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 "./
|
|
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 "./
|
|
40
|
-
export * from "./
|
|
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.
|
|
4
|
-
"description": "
|
|
5
|
-
"keywords": [
|
|
6
|
-
|
|
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
|
-
"
|
|
13
|
-
"rtest": "clear; node ./
|
|
23
|
+
"rself": "clear; node system/Risei.js",
|
|
24
|
+
"rtest": "clear; node ./node_modules/risei/index.js",
|
|
14
25
|
"xtest": "clear; mocha **/*.tests.js",
|
|
15
|
-
"
|
|
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
|
}
|
|
@@ -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 {
|
|
7
|
-
import { SelfTests } from "
|
|
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
|
|
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.#
|
|
59
|
+
this.#retainSpoofsByClass(type, spoofTuples);
|
|
55
60
|
|
|
56
61
|
// Storing originals for restoring later.
|
|
57
|
-
this.#
|
|
62
|
+
this.#reserveOriginalsByClass();
|
|
58
63
|
|
|
59
64
|
// Actually spoofing.
|
|
60
|
-
this.#
|
|
65
|
+
this.#spoofMembersByClass();
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
|
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
|
-
#
|
|
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
|
}
|