risei 2.0.0 → 3.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.
- package/README.md +123 -220
- package/package.json +2 -2
- package/system/ATestReporter.js +26 -26
- package/system/ClassTestGroup.js +8 -8
- package/system/LocalCaller.js +2 -2
- package/system/MethodSpoofer.js +2 -2
- package/system/MethodTestGroup.js +8 -8
- package/system/Moment.js +29 -29
- package/system/NameAnalyzer.js +26 -26
- package/system/PropertySpoofer.js +1 -1
- package/system/SpoofDef.js +0 -5
- package/system/TestDef.js +14 -13
- package/system/TestFrame.js +8 -10
- package/system/TestGroup.js +25 -25
- package/system/TestRunner.js +8 -6
- package/system/TestStages.js +66 -10
- package/system/TestSummary.js +37 -37
- package/system/TypeAnalyzer.js +79 -26
- package/Read-me reduced.md +0 -294
- package/Read-me redux.md +0 -581
- package/system/ChosenTestFinder.js +0 -31
- package/system/Risei.js +0 -118
- package/test-target-objects/ConditionalThrowTarget.js +0 -11
- package/test-target-objects/Counter.js +0 -46
- package/test-target-objects/DomTarget.js +0 -37
- package/test-target-objects/InterSpoofer.js +0 -230
- package/test-target-objects/MixedContents.js +0 -33
- package/test-target-objects/MutationTarget.js +0 -37
- package/test-target-objects/ObjectComposer.js +0 -34
- package/test-target-objects/PolySpoofableInner.js +0 -29
- package/test-target-objects/PolySpoofableOuter.js +0 -52
- package/test-target-objects/PropertiesTarget.js +0 -98
- package/test-target-objects/Returner.js +0 -7
- package/test-target-objects/Searcher.js +0 -25
- package/test-target-objects/Sorter.js +0 -91
- package/test-target-objects/Spoofable.js +0 -36
- package/test-target-objects/StateTarget.js +0 -34
- package/test-target-objects/StaticTarget.js +0 -17
- package/test-target-objects/TestableTarget.js +0 -57
- package/trial-tests/SelfTests.outward-rt.js +0 -511
- package/trial-tests/TopicTests.outward-rt.js +0 -313
- package/usage-examples/Gold-bar-example.png +0 -0
- package/usage-examples/Output-example.png +0 -0
- package/usage-examples/Summary-example.png +0 -0
- package/usage-examples/Syntax-example.png +0 -0
- package/usage-examples/Title-example.png +0 -0
- package/xternal-tests/ASpoofingFixture.tests.js +0 -242
- package/xternal-tests/MethodSpoofer.tests.js +0 -130
- package/xternal-tests/SpoofDef.tests.js +0 -91
- package/xternal-tests/TotalComparer.tests.js +0 -1055
- package/xternal-tests/package.json +0 -7
package/system/Risei.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
/* Copyright (c) 2023-2024 Ed Fallin. Published under the terms of the MIT license. */
|
|
4
|
-
|
|
5
|
-
/* This index.js is the entry point for running Risei tests from
|
|
6
|
-
other code. It imports other modules to perform its work.
|
|
7
|
-
It also exports modules that should / can be subclassed. */
|
|
8
|
-
|
|
9
|
-
// region Imports
|
|
10
|
-
|
|
11
|
-
// region Test-running dependencies
|
|
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";
|
|
17
|
-
|
|
18
|
-
// endregion Test-running dependencies
|
|
19
|
-
|
|
20
|
-
// region Display dependencies
|
|
21
|
-
|
|
22
|
-
import chalk from "chalk";
|
|
23
|
-
import Moment from "./Moment.js";
|
|
24
|
-
|
|
25
|
-
// endregion Display dependencies
|
|
26
|
-
|
|
27
|
-
// endregion Imports
|
|
28
|
-
|
|
29
|
-
// region Named styles
|
|
30
|
-
|
|
31
|
-
/* Display styles for the start title and other general needs. */
|
|
32
|
-
const title = chalk.hex("FFFFFF").bgHex("191970").bold;
|
|
33
|
-
const fails = chalk.hex("000000").bgHex("FFD700").bold;
|
|
34
|
-
|
|
35
|
-
// endregion Named styles
|
|
36
|
-
|
|
37
|
-
// region Styling for color stripes
|
|
38
|
-
|
|
39
|
-
let wide = (text) => {
|
|
40
|
-
let width = process.stdout.columns;
|
|
41
|
-
text = text || "";
|
|
42
|
-
|
|
43
|
-
return text.padEnd(width, "\u00A0");
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// endregion Styling for color stripes
|
|
47
|
-
|
|
48
|
-
// region Key callable and its scripted call
|
|
49
|
-
|
|
50
|
-
async function runRiseiMetaTests(testFinderPath) {
|
|
51
|
-
// region Converting test-finder from path to class
|
|
52
|
-
|
|
53
|
-
testFinderPath = testFinderPath || "./TestFinder.js";
|
|
54
|
-
let finderModule = await import(testFinderPath);
|
|
55
|
-
|
|
56
|
-
let moduleKeys = Object.keys(finderModule);
|
|
57
|
-
let classKey = moduleKeys[0];
|
|
58
|
-
let finderClass = finderModule[classKey];
|
|
59
|
-
|
|
60
|
-
// endregion Converting test-finder from path to class
|
|
61
|
-
|
|
62
|
-
// region Intro / title
|
|
63
|
-
|
|
64
|
-
console.clear();
|
|
65
|
-
console.log();
|
|
66
|
-
console.log(title(wide()));
|
|
67
|
-
|
|
68
|
-
let now = new Date();
|
|
69
|
-
now = new Moment(now);
|
|
70
|
-
|
|
71
|
-
console.log(title(wide(` Risei tests run on ${ now.asReadable() } local time.`)));
|
|
72
|
-
console.log(title(wide()));
|
|
73
|
-
|
|
74
|
-
console.log();
|
|
75
|
-
|
|
76
|
-
// endregion Intro / title
|
|
77
|
-
|
|
78
|
-
// region Running tests
|
|
79
|
-
|
|
80
|
-
// Test-system objects and their relationships.
|
|
81
|
-
const finder = new finderClass.prototype.constructor();
|
|
82
|
-
finder.sourceBySearch = () => { return { tests: "**.outward-rt.js" }; };
|
|
83
|
-
|
|
84
|
-
const runner = new TestRunner();
|
|
85
|
-
const reporter = new TerminalReporter();
|
|
86
|
-
|
|
87
|
-
const caller = new LocalCaller(finder, runner, reporter);
|
|
88
|
-
|
|
89
|
-
// Actually running the tests using this system.
|
|
90
|
-
await caller.runAllTests();
|
|
91
|
-
|
|
92
|
-
// endregion Running tests
|
|
93
|
-
|
|
94
|
-
// region Trailing display of test-loading issues
|
|
95
|
-
|
|
96
|
-
if (finder.thrown.length !== 0) {
|
|
97
|
-
let loadFails = finder.thrown;
|
|
98
|
-
|
|
99
|
-
for (let fail of loadFails) {
|
|
100
|
-
console.log(fails(wide(` ${ fail }`)));
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// endregion Trailing display of test-loading issues
|
|
105
|
-
|
|
106
|
-
// region Trailing formatting
|
|
107
|
-
|
|
108
|
-
console.log();
|
|
109
|
-
console.log();
|
|
110
|
-
|
|
111
|
-
// endregion Trailing formatting
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/* Runs tests now. */
|
|
115
|
-
await runRiseiMetaTests();
|
|
116
|
-
|
|
117
|
-
// endregion Key callable and its scripted call
|
|
118
|
-
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class Counter {
|
|
4
|
-
constructor() {
|
|
5
|
-
/* No operations. */
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
howMany(subject, target) /* passed */ {
|
|
9
|
-
// Bad-call edge case.
|
|
10
|
-
if (arguments.length < 2) {
|
|
11
|
-
return 0;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// Bad-arg edge cases.
|
|
15
|
-
if (this.#isEdgeCase(subject, target)) {
|
|
16
|
-
return 0;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Initial values and ops reducer.
|
|
20
|
-
let at = 0;
|
|
21
|
-
let count = 0;
|
|
22
|
-
let span = target.length;
|
|
23
|
-
|
|
24
|
-
// Tracking found site and jumping past it each time the target is found.
|
|
25
|
-
while ((at = subject.indexOf(target, at)) !== -1) {
|
|
26
|
-
count++;
|
|
27
|
-
at += span;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Back to caller.
|
|
31
|
-
return count;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
#isEdgeCase(subject, target) /* verified */ {
|
|
35
|
-
if (subject === null || target === null) {
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (target === "") {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class DomTarget {
|
|
4
|
-
// region Private fields
|
|
5
|
-
|
|
6
|
-
#id;
|
|
7
|
-
#node;
|
|
8
|
-
|
|
9
|
-
// endregion Private fields
|
|
10
|
-
|
|
11
|
-
// region Properties
|
|
12
|
-
|
|
13
|
-
get id() {
|
|
14
|
-
return this.#id;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
get node() {
|
|
18
|
-
return this.#node;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// endregion Properties
|
|
22
|
-
|
|
23
|
-
constructor(id) {
|
|
24
|
-
this.#id = id;
|
|
25
|
-
this.#node = this.domNodeFrom(id);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
domNodeFrom(id) {
|
|
29
|
-
let node = document.getElementById(id);
|
|
30
|
-
return node;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
changeDomItem(id) {
|
|
34
|
-
this.#id = id;
|
|
35
|
-
this.#node = this.domNodeFrom(id);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
import MethodSpoofer from "../system/MethodSpoofer.js";
|
|
4
|
-
import PropertySpoofer from "../system/PropertySpoofer.js";
|
|
5
|
-
import PropertiesTarget from "./PropertiesTarget.js";
|
|
6
|
-
|
|
7
|
-
/* &cruft, maybe drop this after direct testing of groundwork
|
|
8
|
-
and reversing it is possible with .do / .undo */
|
|
9
|
-
export default class InterSpoofer {
|
|
10
|
-
// region Components
|
|
11
|
-
|
|
12
|
-
#methodSpoofer = new MethodSpoofer();
|
|
13
|
-
#propSpoofer = new PropertySpoofer();
|
|
14
|
-
|
|
15
|
-
// endregion Components
|
|
16
|
-
|
|
17
|
-
// region Gathered names of all spoofables
|
|
18
|
-
|
|
19
|
-
static staticProps = [ "staticBaseValueProp", "staticBaseAccessorProp", "staticValueProp", "staticAccessorProp" ];
|
|
20
|
-
static staticMethods = [ "staticBaseMethod", "staticMethod" ];
|
|
21
|
-
static props = [ "instanceBaseValueProp", "instanceBaseAccessorProp", "valueProp", "accessorProp" ];
|
|
22
|
-
static methods = [ "instanceBaseMethod", "instanceMethod" ];
|
|
23
|
-
|
|
24
|
-
static allMethods = [ InterSpoofer.staticMethods, InterSpoofer.methods ];
|
|
25
|
-
static allNames = [ InterSpoofer.staticProps, InterSpoofer.staticMethods, InterSpoofer.props, InterSpoofer.methods ];
|
|
26
|
-
|
|
27
|
-
// endregion Gathered names of all spoofables
|
|
28
|
-
|
|
29
|
-
// region Gathered original method defs and values
|
|
30
|
-
|
|
31
|
-
static #origDefs = InterSpoofer.#bundleDefs(
|
|
32
|
-
PropertiesTarget, new PropertiesTarget(), ...InterSpoofer.allMethods
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
static #origValues = InterSpoofer.#bundleValues(
|
|
36
|
-
PropertiesTarget, new PropertiesTarget(), ...InterSpoofer.allNames
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
// endregion Gathered original method defs and values
|
|
40
|
-
|
|
41
|
-
// region Methods to test spoofers
|
|
42
|
-
|
|
43
|
-
/* If these methods all pass, then the spoofers work
|
|
44
|
-
together without breaking each other's changes. */
|
|
45
|
-
|
|
46
|
-
spoofMethodsThenProps(test) /* passed */ {
|
|
47
|
-
this.#methodSpoofer.spoof(test);
|
|
48
|
-
this.#propSpoofer.spoof(test);
|
|
49
|
-
|
|
50
|
-
let type = test.type;
|
|
51
|
-
let target = test.target;
|
|
52
|
-
|
|
53
|
-
let values = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
54
|
-
|
|
55
|
-
this.reverseAllSpoofs(type, target);
|
|
56
|
-
|
|
57
|
-
return values;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
spoofPropsThenMethods(test) /* passed */ {
|
|
61
|
-
this.#propSpoofer.spoof(test);
|
|
62
|
-
this.#methodSpoofer.spoof(test);
|
|
63
|
-
|
|
64
|
-
let type = test.type;
|
|
65
|
-
let target = test.target;
|
|
66
|
-
|
|
67
|
-
let values = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
68
|
-
|
|
69
|
-
this.reverseAllSpoofs(type, target);
|
|
70
|
-
|
|
71
|
-
return values;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
spoofAndUnspoofMethodsThenProps(test) /* passed */ {
|
|
75
|
-
this.#methodSpoofer.spoof(test);
|
|
76
|
-
this.#propSpoofer.spoof(test);
|
|
77
|
-
|
|
78
|
-
let type = test.type;
|
|
79
|
-
let target = test.target;
|
|
80
|
-
|
|
81
|
-
let before = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
82
|
-
|
|
83
|
-
this.#methodSpoofer.unspoof(test);
|
|
84
|
-
this.#propSpoofer.unspoof(test);
|
|
85
|
-
|
|
86
|
-
let after = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
87
|
-
|
|
88
|
-
this.reverseAllSpoofs(type, target);
|
|
89
|
-
|
|
90
|
-
return { before, after };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
spoofAndUnspoofPropsThenMethods(test) /* passed */ {
|
|
94
|
-
this.#propSpoofer.spoof(test);
|
|
95
|
-
this.#methodSpoofer.spoof(test);
|
|
96
|
-
|
|
97
|
-
let type = test.type;
|
|
98
|
-
let target = test.target;
|
|
99
|
-
|
|
100
|
-
let before = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
101
|
-
|
|
102
|
-
this.#propSpoofer.unspoof(test);
|
|
103
|
-
this.#methodSpoofer.unspoof(test);
|
|
104
|
-
|
|
105
|
-
let after = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
106
|
-
|
|
107
|
-
this.reverseAllSpoofs(type, target);
|
|
108
|
-
|
|
109
|
-
return { before, after };
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
spoofMethodsFirstAndUnspoofThemLast(test) /* passed */ {
|
|
113
|
-
this.#methodSpoofer.spoof(test);
|
|
114
|
-
this.#propSpoofer.spoof(test);
|
|
115
|
-
|
|
116
|
-
let type = test.type;
|
|
117
|
-
let target = test.target;
|
|
118
|
-
|
|
119
|
-
let before = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
120
|
-
|
|
121
|
-
this.#propSpoofer.unspoof(test);
|
|
122
|
-
this.#methodSpoofer.unspoof(test);
|
|
123
|
-
|
|
124
|
-
let after = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
125
|
-
|
|
126
|
-
this.reverseAllSpoofs(type, target);
|
|
127
|
-
|
|
128
|
-
return { before, after };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
spoofPropsFirstAndUnspoofThemLast(test) /* passed */ {
|
|
132
|
-
this.#propSpoofer.spoof(test);
|
|
133
|
-
this.#methodSpoofer.spoof(test);
|
|
134
|
-
|
|
135
|
-
let type = test.type;
|
|
136
|
-
let target = test.target;
|
|
137
|
-
|
|
138
|
-
let before = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
139
|
-
|
|
140
|
-
this.#methodSpoofer.unspoof(test);
|
|
141
|
-
this.#propSpoofer.unspoof(test);
|
|
142
|
-
|
|
143
|
-
let after = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
144
|
-
|
|
145
|
-
this.reverseAllSpoofs(type, target);
|
|
146
|
-
|
|
147
|
-
return { before, after };
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// endregion Methods to test spoofers
|
|
151
|
-
|
|
152
|
-
/* To ensure topic class isolated between tests. */
|
|
153
|
-
reverseAllSpoofs(type, target) /* verified */ {
|
|
154
|
-
/* Setting known properties and methods of target type
|
|
155
|
-
back to their stored original definitions / values. */
|
|
156
|
-
|
|
157
|
-
for (let name of InterSpoofer.staticProps) {
|
|
158
|
-
type[name] = InterSpoofer.#origValues[name];
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
for (let name of InterSpoofer.staticMethods) {
|
|
162
|
-
type[name] = InterSpoofer.#origDefs[name];
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/* Plain instance properties shouldn't need to be reversed. */
|
|
166
|
-
|
|
167
|
-
for (let name of InterSpoofer.methods) {
|
|
168
|
-
type.prototype[name] = InterSpoofer.#origDefs[name];
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
for (let name of InterSpoofer.props) {
|
|
172
|
-
target[name] = InterSpoofer.#origValues[name];
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
let reversed = InterSpoofer.#bundleValues(type, target, ...InterSpoofer.allNames);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// region Internals
|
|
179
|
-
|
|
180
|
-
static #bundleDefs(type, target, staticMethods, methods) /* verified */ {
|
|
181
|
-
/* All callables asked for are stored as copies for restoring. */
|
|
182
|
-
|
|
183
|
-
let output = { };
|
|
184
|
-
|
|
185
|
-
for (let name of staticMethods) {
|
|
186
|
-
output[name] = InterSpoofer.#copyMethod(type[name]);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
for (let name of methods) {
|
|
190
|
-
output[name] = InterSpoofer.#copyMethod(target[name]);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return output;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
static #bundleValues(type, target, staticProps, staticMethods, props, methods) /* verified */ {
|
|
197
|
-
/* Everything asked for is dropped into an object, either
|
|
198
|
-
property values or return values of calling methods. */
|
|
199
|
-
|
|
200
|
-
let output = { };
|
|
201
|
-
|
|
202
|
-
for (let name of staticProps) {
|
|
203
|
-
output[name] = type[name];
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
for (let name of staticMethods) {
|
|
207
|
-
output[name] = type[name]();
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
for (let name of props) {
|
|
211
|
-
output[name] = target[name];
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
for (let name of methods) {
|
|
215
|
-
output[name] = target[name]();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return output;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
static #copyMethod(method) /* verified */ {
|
|
222
|
-
let passer = [ method ];
|
|
223
|
-
passer = [ ...passer ];
|
|
224
|
-
let copy = passer[0];
|
|
225
|
-
|
|
226
|
-
return copy;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// endregion Internals
|
|
230
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class MixedContents {
|
|
4
|
-
first = 1;
|
|
5
|
-
second = "2";
|
|
6
|
-
third = { three: 3 };
|
|
7
|
-
|
|
8
|
-
static fourth = 4;
|
|
9
|
-
static fifth = "5";
|
|
10
|
-
|
|
11
|
-
getInstanceValueOf(name) {
|
|
12
|
-
return this[name];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
getInstanceProduct() {
|
|
16
|
-
let a = this.first;
|
|
17
|
-
let b = Number(this.second);
|
|
18
|
-
let c = this.third.three;
|
|
19
|
-
|
|
20
|
-
return a * b * c;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
static getStaticValueOf(name) {
|
|
24
|
-
return MixedContents[name];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
static getStaticProduct() {
|
|
28
|
-
let a = MixedContents.fourth;
|
|
29
|
-
let b = Number(MixedContents.fifth);
|
|
30
|
-
|
|
31
|
-
return a * b;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class MutationTarget {
|
|
4
|
-
#map;
|
|
5
|
-
#array;
|
|
6
|
-
|
|
7
|
-
constructor(map, array) {
|
|
8
|
-
this.#map = map;
|
|
9
|
-
this.#array = array;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
mutateInitors() {
|
|
13
|
-
// Map mutation allows for consecutive mutations.
|
|
14
|
-
let rawKey = this.#map.size + 1;
|
|
15
|
-
this.#map.set(rawKey.toString(), "C");
|
|
16
|
-
this.#array.shift();
|
|
17
|
-
|
|
18
|
-
return { map: this.#map, array: this.#array };
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
mutateArgs(array, tuple) {
|
|
22
|
-
array.push(10);
|
|
23
|
-
tuple.changes += 10;
|
|
24
|
-
|
|
25
|
-
return { array, tuple };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
replaceArg(array, index, replacement) {
|
|
29
|
-
// The previous element is added at the end for comparison.
|
|
30
|
-
array.push(array[index].toString());
|
|
31
|
-
|
|
32
|
-
// The new element is set at the original index.
|
|
33
|
-
array[index] = replacement;
|
|
34
|
-
|
|
35
|
-
return array;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class ObjectComposer {
|
|
4
|
-
constructor() {
|
|
5
|
-
/* No operations. */
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/* Target of spoofing. */
|
|
9
|
-
supplySomeObject() {
|
|
10
|
-
throw new Error("supplyObjectA() must be spoofed in tests.");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
enact(chain, method) {
|
|
14
|
-
// Invoke the method to be spoofed.
|
|
15
|
-
let target = this.supplySomeObject();
|
|
16
|
-
|
|
17
|
-
// Traverse the spoofed return
|
|
18
|
-
// value's object tree.
|
|
19
|
-
for (let link of chain) {
|
|
20
|
-
target = target[link];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Invoke the method at chain end for its return value.
|
|
24
|
-
let output = target[method]();
|
|
25
|
-
return output;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
doubleEnact(chainOne, methodOne, chainTwo, methodTwo) {
|
|
29
|
-
let outputOne = this.enact(chainOne, methodOne);
|
|
30
|
-
let outputTwo = this.enact(chainTwo, methodTwo);
|
|
31
|
-
|
|
32
|
-
return [ outputOne, outputTwo ];
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
export default class PolySpoofableInner {
|
|
4
|
-
constructor() {
|
|
5
|
-
/* No operations. */
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/* Spoofing target. */
|
|
9
|
-
addOrTimes(numbers) {
|
|
10
|
-
let a = numbers.supplyA();
|
|
11
|
-
let b = numbers.supplyB();
|
|
12
|
-
|
|
13
|
-
return a + b;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/* Spoofing target. */
|
|
17
|
-
minusOrOver(numbers) {
|
|
18
|
-
let a = numbers.supplyA();
|
|
19
|
-
let b = numbers.supplyB();
|
|
20
|
-
|
|
21
|
-
return a - b;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* Spoofing target. Nested object. */
|
|
25
|
-
numberHost = {
|
|
26
|
-
supplyC: () => { return 15; },
|
|
27
|
-
supplyD: () => { return 18; }
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**/
|
|
2
|
-
|
|
3
|
-
import PolySpoofableInner from "./PolySpoofableInner.js";
|
|
4
|
-
|
|
5
|
-
export default class PolySpoofableOuter {
|
|
6
|
-
/* Spoofing target. */
|
|
7
|
-
#inner;
|
|
8
|
-
|
|
9
|
-
constructor() {
|
|
10
|
-
this.#inner = new PolySpoofableInner();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/* Not intended to be spoofed, but to use spoofs. */
|
|
14
|
-
combinedNumbers(numbers) {
|
|
15
|
-
let first = this.#inner.addOrTimes(numbers);
|
|
16
|
-
let second = this.#inner.minusOrOver(numbers);
|
|
17
|
-
|
|
18
|
-
let combined = this.combiner(first, second);
|
|
19
|
-
return combined;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/* Spoofing target. */
|
|
23
|
-
combiner(first, second) {
|
|
24
|
-
let combined = Math.pow(first, second);
|
|
25
|
-
return combined;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/* Not intended to be spoofed, but to use spoofs. */
|
|
29
|
-
combinedPlusHosted(numbers) {
|
|
30
|
-
let combined = this.combinedNumbers(numbers);
|
|
31
|
-
let third = this.#inner.numberHost.supplyC();
|
|
32
|
-
let fourth = this.#inner.numberHost.supplyD();
|
|
33
|
-
|
|
34
|
-
return combined + third - fourth;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/* Not intended to be spoofed, but to use arg with spoofs. */
|
|
38
|
-
combinedArgAAndB(inner) {
|
|
39
|
-
let first = inner.supplyA();
|
|
40
|
-
let second = inner.supplyB();
|
|
41
|
-
|
|
42
|
-
return first + second;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/* Not intended to be spoofed, but to use arg with spoofs. */
|
|
46
|
-
combinedArgHostedCAndD(inner) {
|
|
47
|
-
let third = inner.numberHost.supplyC();
|
|
48
|
-
let fourth = inner.numberHost.supplyD();
|
|
49
|
-
|
|
50
|
-
return third - fourth;
|
|
51
|
-
}
|
|
52
|
-
}
|