risei 1.0.3 → 1.1.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.
@@ -1,222 +1,249 @@
1
- /**/
2
-
3
- /* TerminalReporter is an ATestReporter that sends each result to the terminal / console for display. */
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";
11
-
12
- import chalk from "chalk";
13
-
14
- export class TerminalReporter extends ATestReporter {
15
- // region Private fields
16
-
17
- /* Foreground-colors using dependency calls and hex. */
18
- #trueWhite = chalk.hex("FFFFFF");
19
- #trueBlack = chalk.hex("000000");
20
-
21
- /* Background colors as hex for dependency
22
- calls to use, needed syntactically. */
23
- #blue = "0000CD";
24
- #aqua = "00BFFF";
25
- #paleGreen = "90EE90";
26
- #paleRed = "F08080";
27
-
28
- /* Full fore- and background color output styles. */
29
-
30
- #classGroup = this.#trueWhite.bgHex(this.#blue).bold;
31
- #methodGroup = this.#trueWhite.bgHex(this.#aqua).bold;
32
- #passed = this.#trueBlack.bgHex(this.#paleGreen);
33
- #failed = this.#trueBlack.bgHex(this.#paleRed);
34
- #passedSummary = this.#trueBlack.bgHex(this.#paleGreen).bold;
35
- #failedSummary = this.#trueBlack.bgHex(this.#paleRed).bold;
36
- #summary = chalk.hex("000080").bgHex("FAFAD2").bold;
37
-
38
- // Count of characters used for indent
39
- // and text to the left of each test.
40
- #preUsedWidth = 20;
41
-
42
- // endregion PrivateFields
43
-
44
- // region ATestReporter
45
-
46
- reportNext(result) {
47
- // The next result introduces a group of tests.
48
- if (result instanceof TestGroup) {
49
- this.reportGroup(result);
50
- return;
51
- }
52
-
53
- // The next result is from one test.
54
- if (result instanceof TestResult) {
55
- this.#reportTestResult(result);
56
- return;
57
- }
58
-
59
- // The next result is the summary of all tests.
60
- if (result instanceof TestSummary) {
61
- this.reportSummary(result);
62
- return;
63
- }
64
- }
65
-
66
- reportGroup(result) {
67
- if (result instanceof ClassTestGroup) {
68
- console.log(this.#classGroup(` ${ result.group }: `));
69
- }
70
-
71
- if (result instanceof MethodTestGroup) {
72
- console.log(" " + this.#methodGroup(` ${ result.group }(): `));
73
- }
74
- }
75
-
76
- // region Private dependencies of reportNext()
77
-
78
- #reportTestResult(result) {
79
- if (result.didPass) {
80
- this.reportPassed(result);
81
- }
82
-
83
- if (!result.didPass) {
84
- this.reportFailed(result);
85
- }
86
- }
87
-
88
- // endregion Private dependencies of reportNext()
89
-
90
- reportPassed(result) {
91
- this.#reportOneTestResult(result, "Passed", this.#passed);
92
- }
93
-
94
- reportFailed(result) {
95
- this.#reportOneTestResult(result, "Failed", this.#failed);
96
- }
97
-
98
- // region Private dependencies of reportPassed() and reportFailed()
99
-
100
- /* cruft, changes here */
101
- #reportOneTestResult(result, net, styler) {
102
- let { lineOne, lineTwo, lineThree } = this.#calculateResultDisplay(result);
103
-
104
- console.log(
105
- "\t" + styler(` ${ net }: ${ lineOne }`)
106
- );
107
-
108
- if (lineTwo) {
109
- console.log(
110
- "\t\t " + styler(` ${ lineTwo }`)
111
- );
112
- }
113
-
114
- if (lineThree) {
115
- console.log(
116
- "\t\t " + styler(` ${ lineThree }`)
117
- );
118
- }
119
- }
120
-
121
- /* &cruft, changes here and/or factoring
122
- to lengths and tactics branching */
123
- #calculateResultDisplay(result) {
124
- /* Getting lengths to determine if output should
125
- * be split to multiple lines to fit the window. */
126
-
127
- let forInputsLength
128
- = this.#preUsedWidth
129
- + result.identityText.length
130
- + result.inputsText.length;
131
-
132
- let allLength
133
- = forInputsLength
134
- + result.expectedText.length
135
- + result.actualText.length;
136
-
137
- /* Splitting as much as is needed. */
138
-
139
- let identityText = result.identityText;
140
- let inputsText = result.inputsText;
141
- let expectedText = result.expectedText;
142
- let actualText = result.actualText;
143
-
144
- if (forInputsLength >= process.stdout.columns) {
145
- return this.#threeLineTactic(identityText, inputsText, expectedText, actualText);
146
- }
147
-
148
- if (allLength >= process.stdout.columns) {
149
- return this.#twoLineTactic(identityText, inputsText, expectedText, actualText);
150
- }
151
-
152
- return this.#oneLineTactic(identityText, inputsText, expectedText, actualText);
153
- }
154
-
155
- // region Private dependencies of #calculateResultDisplay()
156
-
157
- #threeLineTactic(identityText, inputsText, expectedText, actualText) {
158
- // Each line, with two spaces between phrases on same line.
159
- let lineOne = identityText;
160
- let lineTwo = inputsText;
161
- let lineThree = expectedText + " " + actualText;
162
-
163
- return { lineOne, lineTwo, lineThree };
164
- }
165
-
166
- #twoLineTactic(identityText, inputsText, expectedText, actualText) {
167
- // Each line, with two spaces between phrases on same line.
168
- let lineOne = identityText + " " + inputsText;
169
- let lineTwo = expectedText + " " + actualText;
170
-
171
- // Left undefined.
172
- let lineThree;
173
-
174
- return { lineOne, lineTwo, lineThree };
175
- }
176
-
177
- #oneLineTactic(identityText, inputsText, expectedText, actualText) {
178
- // Single line, with two spaces between all phrases.
179
- let lineOne
180
- = identityText
181
- + " "
182
- + inputsText
183
- + " "
184
- + expectedText
185
- + " "
186
- + actualText;
187
-
188
- // Left undefined.
189
- let lineTwo, lineThree;
190
-
191
- return { lineOne, lineTwo, lineThree };
192
- }
193
-
194
- // endregion Private dependencies of #calculateResultDisplay()
195
-
196
- // endregion Private dependencies of reportPassed() and reportFailed()
197
-
198
- reportSummary(summary) {
199
- console.log();
200
-
201
- if (summary.anyWereRun) {
202
- if (summary.allDidPass) {
203
- console.log(this.#passedSummary(this.#toFullWidth(" Test run succeeded.")));
204
- }
205
- else {
206
- console.log(this.#failedSummary(this.#toFullWidth(" Test run failed.")));
207
- }
208
- }
209
-
210
- console.log(this.#summary(this.#toFullWidth(` ${ summary.summary }`)));
211
- }
212
-
213
- #toFullWidth(text) {
214
- text = text || "";
215
- let width = process.stdout.columns;
216
-
217
- return text.padEnd(width, "\u00A0");
218
- }
219
-
220
- // endregion ATestReporter
221
-
222
- }
1
+ /**/
2
+
3
+ /* TerminalReporter is an ATestReporter that sends each result to the terminal / console for display. */
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";
11
+
12
+ import chalk from "chalk";
13
+
14
+ export class TerminalReporter extends ATestReporter {
15
+ // region Private fields
16
+
17
+ /* Foreground-colors using dependency calls and hex. */
18
+ #trueWhite = chalk.hex("FFFFFF");
19
+ #trueBlack = chalk.hex("000000");
20
+
21
+ /* Background colors as hex for dependency
22
+ calls to use, needed syntactically. */
23
+ #blue = "0000CD";
24
+ #aqua = "00BFFF";
25
+ #paleGreen = "90EE90";
26
+ #paleRed = "F08080";
27
+
28
+ /* Full fore- and background color output styles. */
29
+
30
+ #classGroup = this.#trueWhite.bgHex(this.#blue).bold;
31
+ #methodGroup = this.#trueWhite.bgHex(this.#aqua).bold;
32
+ #passed = this.#trueBlack.bgHex(this.#paleGreen);
33
+ #failed = this.#trueBlack.bgHex(this.#paleRed);
34
+ #passedSummary = this.#trueBlack.bgHex(this.#paleGreen).bold;
35
+ #failedSummary = this.#trueBlack.bgHex(this.#paleRed).bold;
36
+ #summary = chalk.hex("000080").bgHex("FAFAD2").bold;
37
+
38
+ // Count of characters used for indent
39
+ // and text to the left of each test.
40
+ #preUsedWidth = 20;
41
+
42
+ // endregion PrivateFields
43
+
44
+ // region ATestReporter
45
+
46
+ reportNext(result) {
47
+ // The next result introduces a group of tests.
48
+ if (result instanceof TestGroup) {
49
+ this.reportGroup(result);
50
+ return;
51
+ }
52
+
53
+ // The next result is from one test.
54
+ if (result instanceof TestResult) {
55
+ this.#reportTestResult(result);
56
+ return;
57
+ }
58
+
59
+ // The next result is the summary of all tests.
60
+ if (result instanceof TestSummary) {
61
+ this.reportSummary(result);
62
+ return;
63
+ }
64
+ }
65
+
66
+ reportGroup(result) {
67
+ if (result instanceof ClassTestGroup) {
68
+ console.log(this.#classGroup(` ${ result.group }: `));
69
+ }
70
+
71
+ if (result instanceof MethodTestGroup) {
72
+ console.log(" " + this.#methodGroup(` ${ result.group }(): `));
73
+ }
74
+ }
75
+
76
+ // region Private dependencies of reportNext()
77
+
78
+ #reportTestResult(result) {
79
+ if (result.didPass) {
80
+ this.reportPassed(result);
81
+ }
82
+
83
+ if (!result.didPass) {
84
+ this.reportFailed(result);
85
+ }
86
+ }
87
+
88
+ // endregion Private dependencies of reportNext()
89
+
90
+ reportPassed(result) {
91
+ this.#reportOneTestResult(result, "Passed", this.#passed);
92
+ }
93
+
94
+ reportFailed(result) {
95
+ this.#reportOneTestResult(result, "Failed", this.#failed);
96
+ }
97
+
98
+ // region Private dependencies of reportPassed() and reportFailed()
99
+
100
+ /* &cruft, changes here / in dependencies
101
+ for better splitting to multiple lines */
102
+ #reportOneTestResult(result, net, styler) {
103
+ let { lineOne, lineTwo, lineThree, lineFour } = this.#calculateResultDisplay(result);
104
+
105
+ console.log(
106
+ "\t" + styler(` ${ net }: ${ lineOne }`)
107
+ );
108
+
109
+ if (lineTwo) {
110
+ console.log(
111
+ "\t\t " + styler(` ${ lineTwo }`)
112
+ );
113
+ }
114
+
115
+ if (lineThree) {
116
+ console.log(
117
+ "\t\t " + styler(` ${ lineThree }`)
118
+ );
119
+ }
120
+
121
+ if (lineFour) {
122
+ console.log(
123
+ "\t\t " + styler(` ${ lineFour }`)
124
+ );
125
+ }
126
+ }
127
+
128
+ #calculateResultDisplay(result) {
129
+ /* Getting lengths to determine if output should
130
+ * be split to multiple lines to fit the window. */
131
+
132
+ let forInputsLength
133
+ = this.#preUsedWidth
134
+ + result.identityText.length
135
+ + result.inputsText.length;
136
+
137
+ let allLength
138
+ = forInputsLength
139
+ + result.expectedText.length
140
+ + result.actualText.length;
141
+
142
+ let forOutputsLength
143
+ = this.#preUsedWidth
144
+ + result.expectedText.length
145
+ + result.actualText.length;
146
+
147
+ /* Splitting as much as is needed. */
148
+
149
+ let identityText = result.identityText;
150
+ let inputsText = result.inputsText;
151
+ let expectedText = result.expectedText;
152
+ let actualText = result.actualText;
153
+
154
+ if (forOutputsLength >= process.stdout.columns) {
155
+ return this.#fourLineTactic(identityText, inputsText, expectedText, actualText);
156
+ }
157
+
158
+ if (forInputsLength >= process.stdout.columns) {
159
+ return this.#threeLineTactic(identityText, inputsText, expectedText, actualText);
160
+ }
161
+
162
+ if (allLength >= process.stdout.columns) {
163
+ return this.#twoLineTactic(identityText, inputsText, expectedText, actualText);
164
+ }
165
+
166
+ return this.#oneLineTactic(identityText, inputsText, expectedText, actualText);
167
+ }
168
+
169
+ // region Private dependencies of #calculateResultDisplay()
170
+
171
+ #fourLineTactic(identityText, inputsText, expectedText, actualText) {
172
+ // Each line on its own.
173
+ let lineOne = identityText;
174
+ let lineTwo = inputsText;
175
+ let lineThree = expectedText;
176
+ let lineFour = actualText;
177
+
178
+ return { lineOne, lineTwo, lineThree, lineFour };
179
+ }
180
+
181
+ #threeLineTactic(identityText, inputsText, expectedText, actualText) {
182
+ // Each line, with two spaces between phrases on same line.
183
+ let lineOne = identityText;
184
+ let lineTwo = inputsText;
185
+ let lineThree = expectedText + " " + actualText;
186
+
187
+ // Left undefined.
188
+ let lineFour;
189
+
190
+ return { lineOne, lineTwo, lineThree, lineFour };
191
+ }
192
+
193
+ #twoLineTactic(identityText, inputsText, expectedText, actualText) {
194
+ // Each line, with two spaces between phrases on same line.
195
+ let lineOne = identityText + " " + inputsText;
196
+ let lineTwo = expectedText + " " + actualText;
197
+
198
+ // Left undefined.
199
+ let lineThree, lineFour;
200
+
201
+ return { lineOne, lineTwo, lineThree, lineFour };
202
+ }
203
+
204
+ #oneLineTactic(identityText, inputsText, expectedText, actualText) {
205
+ // Single line, with two spaces between all phrases.
206
+ let lineOne
207
+ = identityText
208
+ + " "
209
+ + inputsText
210
+ + " "
211
+ + expectedText
212
+ + " "
213
+ + actualText;
214
+
215
+ // Left undefined.
216
+ let lineTwo, lineThree, lineFour;
217
+
218
+ return { lineOne, lineTwo, lineThree, lineFour };
219
+ }
220
+
221
+ // endregion Private dependencies of #calculateResultDisplay()
222
+
223
+ // endregion Private dependencies of reportPassed() and reportFailed()
224
+
225
+ reportSummary(summary) {
226
+ console.log();
227
+
228
+ if (summary.anyWereRun) {
229
+ if (summary.allDidPass) {
230
+ console.log(this.#passedSummary(this.#toFullWidth(" Test run succeeded.")));
231
+ }
232
+ else {
233
+ console.log(this.#failedSummary(this.#toFullWidth(" Test run failed.")));
234
+ }
235
+ }
236
+
237
+ console.log(this.#summary(this.#toFullWidth(` ${ summary.summary }`)));
238
+ }
239
+
240
+ #toFullWidth(text) {
241
+ text = text || "";
242
+ let width = process.stdout.columns;
243
+
244
+ return text.padEnd(width, "\u00A0");
245
+ }
246
+
247
+ // endregion ATestReporter
248
+
249
+ }
@@ -0,0 +1,95 @@
1
+ /**/
2
+
3
+ export class TestFrameChooser {
4
+ // Used for special test cases.
5
+ constructorName = "constructor";
6
+ staticName = "static";
7
+ throwName = "throw";
8
+
9
+ frames;
10
+
11
+ constructor(frameSource) /* verified */ {
12
+ this.frames = frameSource;
13
+ }
14
+
15
+ supplyTestFrame(test) /* passed */ {
16
+ // If `.and` includes "static", a call of a static member
17
+ // is made, and the actual is its return value.
18
+ if (this.doesAddressStatics(test)) {
19
+ if (this.isThrowTest(test)) {
20
+ return this.frames.testThrowResultAfterStaticCall;
21
+ }
22
+
23
+ // If .from, a static call is made, then the actual is
24
+ // retrieved from a named code element or custom code.
25
+ if (this.isRetrievalTest(test)) {
26
+ return this.frames.testCodeElementAfterStaticCall;
27
+ }
28
+
29
+ // Otherwise, the return value
30
+ // of the static call is used.
31
+ return this.frames.testReturnValueOfStaticCall;
32
+ }
33
+
34
+ // Constructors are a special case; no second call should
35
+ // be made, and actual must be retrieved from property.
36
+ if (test.of === this.constructorName) {
37
+ return this.frames.testCodeElementAfterConstruction;
38
+ }
39
+
40
+ if (this.isThrowTest(test)) {
41
+ return this.frames.testThrowResultAfterCall;
42
+ }
43
+
44
+ // If .from, a call of the target is made, then the actual
45
+ // is retrieved from a named code element or custom code.
46
+ if (this.isRetrievalTest(test)) {
47
+ return this.frames.testCodeElementAfterCall;
48
+ }
49
+
50
+ // The most common case: the target is called,
51
+ // and the actual is its return value.
52
+ return this.frames.testReturnValueOfCall;
53
+ }
54
+
55
+ doesAddressStatics(test) /* passed */ {
56
+ if (typeof test.and === "string") {
57
+ if (test.and.includes(this.staticName)) {
58
+ return true;
59
+ }
60
+ }
61
+
62
+ return false;
63
+ }
64
+
65
+ isThrowTest(test) /* passed */ {
66
+ if (typeof test.and === "string") {
67
+ if (test.and.includes(this.throwName)) {
68
+ return true;
69
+ }
70
+ }
71
+
72
+ return false;
73
+ }
74
+
75
+ isRetrievalTest(test) /* passed */ {
76
+ // Falsy code elements never are a retrieval.
77
+ if (!test.from) {
78
+ return false;
79
+ }
80
+
81
+ // If a (non-falsy) string, must be a retrieval.
82
+ if (typeof test.from === "string") {
83
+ return true;
84
+ }
85
+
86
+ // If a function, is a retrieval.
87
+ if (test.from instanceof Function) {
88
+ return true;
89
+ }
90
+
91
+ // Anything else is not a retrieval.
92
+ return false;
93
+ }
94
+
95
+ }