@temperlang/std 0.2.1 → 0.4.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/index.js +2 -0
- package/json.js +2033 -0
- package/json.js.map +1 -0
- package/package.json +4 -2
- package/regex.js +1040 -807
- package/regex.js.map +1 -1
- package/strings.js +1 -0
- package/strings.js.map +1 -0
- package/temporal.js +90 -38
- package/temporal.js.map +1 -1
- package/testing.js +117 -147
- package/testing.js.map +1 -1
package/testing.js
CHANGED
|
@@ -1,223 +1,193 @@
|
|
|
1
1
|
import {
|
|
2
|
-
globalConsole as
|
|
2
|
+
globalConsole as globalConsole__320, type as type__348, listBuilderAdd as listBuilderAdd_327, listBuilderToList as listBuilderToList_337, listedJoin as listedJoin_346, pairConstructor as pairConstructor_363, listedMap as listedMap_364, listedGet as listedGet_372
|
|
3
3
|
} from "@temperlang/core";
|
|
4
4
|
import {
|
|
5
|
-
strict as
|
|
5
|
+
strict as strict__333
|
|
6
6
|
} from "assert";
|
|
7
|
-
/** @type {
|
|
8
|
-
const
|
|
9
|
-
export class Test {
|
|
7
|
+
/** @type {Console_321} */
|
|
8
|
+
const console_319 = globalConsole__320;
|
|
9
|
+
export class Test extends type__348() {
|
|
10
10
|
/**
|
|
11
|
-
* @param {boolean}
|
|
12
|
-
* @param {() => string}
|
|
11
|
+
* @param {boolean} success_323
|
|
12
|
+
* @param {() => string} message_324
|
|
13
13
|
*/
|
|
14
|
-
assert(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
assert(success_323, message_324) {
|
|
15
|
+
let t_325;
|
|
16
|
+
if (! success_323) {
|
|
17
|
+
this.#_passing_326 = false;
|
|
18
|
+
t_325 = message_324();
|
|
19
|
+
listBuilderAdd_327(this.#_messages_328, t_325);
|
|
20
20
|
}
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
|
-
* @param {boolean}
|
|
25
|
-
* @param {() => string}
|
|
24
|
+
* @param {boolean} success_330
|
|
25
|
+
* @param {() => string} message_331
|
|
26
26
|
* @returns {void}
|
|
27
27
|
*/
|
|
28
|
-
assertHard(
|
|
29
|
-
this.assert(
|
|
30
|
-
if (!
|
|
31
|
-
this.#
|
|
32
|
-
|
|
33
|
-
} else {
|
|
34
|
-
void 0;
|
|
28
|
+
assertHard(success_330, message_331) {
|
|
29
|
+
this.assert(success_330, message_331);
|
|
30
|
+
if (! success_330) {
|
|
31
|
+
this.#_failedOnAssert_332 = true;
|
|
32
|
+
strict__333.fail(this.messagesCombined());
|
|
35
33
|
}
|
|
36
34
|
return;
|
|
37
35
|
}
|
|
38
36
|
/** @returns {void} */
|
|
39
37
|
softFailToHard() {
|
|
40
38
|
if (this.hasUnhandledFail) {
|
|
41
|
-
this.#
|
|
42
|
-
|
|
43
|
-
} else {
|
|
44
|
-
void 0;
|
|
39
|
+
this.#_failedOnAssert_332 = true;
|
|
40
|
+
strict__333.fail(this.messagesCombined());
|
|
45
41
|
}
|
|
46
42
|
return;
|
|
47
43
|
}
|
|
48
44
|
/** @returns {boolean} */
|
|
49
45
|
get passing() {
|
|
50
|
-
return this.#
|
|
46
|
+
return this.#_passing_326;
|
|
51
47
|
}
|
|
52
48
|
/** @returns {Array<string>} */
|
|
53
49
|
messages() {
|
|
54
|
-
return
|
|
50
|
+
return listBuilderToList_337(this.#_messages_328);
|
|
55
51
|
}
|
|
56
52
|
/** @returns {boolean} */
|
|
57
53
|
get failedOnAssert() {
|
|
58
|
-
return this.#
|
|
54
|
+
return this.#_failedOnAssert_332;
|
|
59
55
|
}
|
|
60
56
|
/** @returns {boolean} */
|
|
61
57
|
get hasUnhandledFail() {
|
|
62
|
-
let
|
|
63
|
-
if (this.#
|
|
64
|
-
|
|
58
|
+
let t_340;
|
|
59
|
+
if (this.#_failedOnAssert_332) {
|
|
60
|
+
t_340 = true;
|
|
65
61
|
} else {
|
|
66
|
-
|
|
62
|
+
t_340 = this.#_passing_326;
|
|
67
63
|
}
|
|
68
|
-
return !
|
|
64
|
+
return ! t_340;
|
|
69
65
|
}
|
|
70
66
|
/** @returns {string | null} */
|
|
71
67
|
messagesCombined() {
|
|
72
|
-
let
|
|
73
|
-
let
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return_250 = null;
|
|
68
|
+
let return_342;
|
|
69
|
+
let t_343;
|
|
70
|
+
if (! this.#_messages_328.length) {
|
|
71
|
+
return_342 = null;
|
|
77
72
|
} else {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return it_254;
|
|
73
|
+
function fn_344(it_345) {
|
|
74
|
+
return it_345;
|
|
81
75
|
}
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
t_343 = listedJoin_346(this.#_messages_328, ", ", fn_344);
|
|
77
|
+
return_342 = t_343;
|
|
84
78
|
}
|
|
85
|
-
return
|
|
79
|
+
return return_342;
|
|
86
80
|
}
|
|
87
81
|
/** @type {boolean} */
|
|
88
|
-
#
|
|
82
|
+
#_failedOnAssert_332;
|
|
89
83
|
/** @type {boolean} */
|
|
90
|
-
#
|
|
84
|
+
#_passing_326;
|
|
91
85
|
/** @type {Array<string>} */
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
let t_258;
|
|
100
|
-
if (!(_failedOnAssert_255 !== void 0)) {
|
|
101
|
-
_failedOnAssert_255 = false;
|
|
102
|
-
}
|
|
103
|
-
if (!(_passing_256 !== void 0)) {
|
|
104
|
-
_passing_256 = true;
|
|
105
|
-
}
|
|
106
|
-
if (!(_messages_257 !== void 0)) {
|
|
107
|
-
t_258 = [];
|
|
108
|
-
_messages_257 = t_258;
|
|
109
|
-
}
|
|
110
|
-
this.#_failedOnAssert_240 = _failedOnAssert_255;
|
|
111
|
-
this.#_passing_235 = _passing_256;
|
|
112
|
-
this.#_messages_236 = _messages_257;
|
|
86
|
+
#_messages_328;
|
|
87
|
+
constructor() {
|
|
88
|
+
super ();
|
|
89
|
+
this.#_failedOnAssert_332 = false;
|
|
90
|
+
this.#_passing_326 = true;
|
|
91
|
+
let t_347 = [];
|
|
92
|
+
this.#_messages_328 = t_347;
|
|
113
93
|
return;
|
|
114
94
|
}
|
|
115
95
|
};
|
|
116
|
-
/** @type {
|
|
96
|
+
/** @type {Type_349} */
|
|
117
97
|
export const TestName = "String: Type";
|
|
118
|
-
/** @type {
|
|
98
|
+
/** @type {Type_349} */
|
|
119
99
|
export const TestFun = "fn (Test): (Void | Bubble): Type";
|
|
120
|
-
/** @type {
|
|
100
|
+
/** @type {Type_349} */
|
|
121
101
|
export const TestCase = "Pair\u003cString, fn (Test): (Void | Bubble)\u003e: Type";
|
|
122
|
-
/** @type {
|
|
102
|
+
/** @type {Type_349} */
|
|
123
103
|
export const TestFailureMessage = "String: Type";
|
|
124
|
-
/** @type {
|
|
104
|
+
/** @type {Type_349} */
|
|
125
105
|
export const TestResult = "Pair\u003cString, List\u003cString\u003e\u003e: Type";
|
|
126
106
|
/**
|
|
127
|
-
* @param {Array<
|
|
128
|
-
* @returns {Array<
|
|
107
|
+
* @param {Array<Pair_365<string, (arg0: Test) => void>>} testCases_350
|
|
108
|
+
* @returns {Array<Pair_365<string, Array<string>>>}
|
|
129
109
|
*/
|
|
130
|
-
export function processTestCases(
|
|
131
|
-
function
|
|
132
|
-
let
|
|
133
|
-
let
|
|
134
|
-
let
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
let
|
|
110
|
+
export function processTestCases(testCases_350) {
|
|
111
|
+
function fn_351(testCase_352) {
|
|
112
|
+
let t_353;
|
|
113
|
+
let t_354;
|
|
114
|
+
let t_355;
|
|
115
|
+
const key_356 = testCase_352.key;
|
|
116
|
+
const fun_357 = testCase_352.value;
|
|
117
|
+
const test_358 = new Test();
|
|
118
|
+
let hadBubble_359;
|
|
139
119
|
try {
|
|
140
|
-
|
|
141
|
-
|
|
120
|
+
fun_357(test_358);
|
|
121
|
+
hadBubble_359 = false;
|
|
142
122
|
} catch {
|
|
143
|
-
|
|
123
|
+
hadBubble_359 = true;
|
|
144
124
|
}
|
|
145
|
-
const
|
|
146
|
-
let
|
|
147
|
-
if (
|
|
148
|
-
|
|
125
|
+
const messages_360 = test_358.messages();
|
|
126
|
+
let failures_361;
|
|
127
|
+
if (test_358.passing) {
|
|
128
|
+
failures_361 = Object.freeze([]);
|
|
149
129
|
} else {
|
|
150
|
-
if (
|
|
151
|
-
|
|
152
|
-
|
|
130
|
+
if (hadBubble_359) {
|
|
131
|
+
t_353 = test_358.failedOnAssert;
|
|
132
|
+
t_355 = ! t_353;
|
|
153
133
|
} else {
|
|
154
|
-
|
|
134
|
+
t_355 = false;
|
|
155
135
|
}
|
|
156
|
-
if (
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
136
|
+
if (t_355) {
|
|
137
|
+
const allMessages_362 = messages_360.slice();
|
|
138
|
+
listBuilderAdd_327(allMessages_362, "Bubble");
|
|
139
|
+
t_354 = listBuilderToList_337(allMessages_362);
|
|
140
|
+
failures_361 = t_354;
|
|
161
141
|
} else {
|
|
162
|
-
|
|
142
|
+
failures_361 = messages_360;
|
|
163
143
|
}
|
|
164
144
|
}
|
|
165
|
-
return
|
|
145
|
+
return pairConstructor_363(key_356, failures_361);
|
|
166
146
|
}
|
|
167
|
-
return
|
|
147
|
+
return listedMap_364(testCases_350, fn_351);
|
|
168
148
|
};
|
|
169
|
-
/** @param {Array<
|
|
170
|
-
export function reportTestResults(
|
|
171
|
-
let
|
|
172
|
-
let
|
|
173
|
-
let
|
|
174
|
-
let
|
|
175
|
-
let
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
console_229.log(strCat_127(t_280, ": Passed"));
|
|
191
|
-
} else {
|
|
192
|
-
function fn_286(it_287) {
|
|
193
|
-
return it_287;
|
|
194
|
-
}
|
|
195
|
-
const message_288 = listJoin_97(failureMessages_285, ", ", fn_286);
|
|
196
|
-
t_279 = testResult_284.key;
|
|
197
|
-
console_229.log(strCat_127(t_279, ": Failed ", message_288));
|
|
198
|
-
}
|
|
199
|
-
i_282 = i_282 + 1;
|
|
200
|
-
} else {
|
|
201
|
-
return_277 = void 0;
|
|
202
|
-
break s__1281_283;
|
|
149
|
+
/** @param {Array<Pair_365<string, Array<string>>>} testResults_366 */
|
|
150
|
+
export function reportTestResults(testResults_366) {
|
|
151
|
+
let t_367;
|
|
152
|
+
let t_368;
|
|
153
|
+
let t_369;
|
|
154
|
+
let t_370;
|
|
155
|
+
let i_371 = 0;
|
|
156
|
+
while (true) {
|
|
157
|
+
t_367 = testResults_366.length;
|
|
158
|
+
if (!(i_371 < t_367)) {
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
t_370 = listedGet_372(testResults_366, i_371);
|
|
162
|
+
const testResult_373 = t_370;
|
|
163
|
+
const failureMessages_374 = testResult_373.value;
|
|
164
|
+
if (! failureMessages_374.length) {
|
|
165
|
+
t_368 = testResult_373.key;
|
|
166
|
+
console_319.log(String(t_368) + ": Passed");
|
|
167
|
+
} else {
|
|
168
|
+
function fn_375(it_376) {
|
|
169
|
+
return it_376;
|
|
203
170
|
}
|
|
171
|
+
const message_377 = listedJoin_346(failureMessages_374, ", ", fn_375);
|
|
172
|
+
t_369 = testResult_373.key;
|
|
173
|
+
console_319.log(String(t_369) + ": Failed " + message_377);
|
|
204
174
|
}
|
|
205
|
-
|
|
175
|
+
i_371 = i_371 + 1;
|
|
206
176
|
}
|
|
207
|
-
return
|
|
177
|
+
return;
|
|
208
178
|
};
|
|
209
|
-
/** @param {Array<
|
|
210
|
-
export function runTestCases(
|
|
211
|
-
reportTestResults(processTestCases(
|
|
179
|
+
/** @param {Array<Pair_365<string, (arg0: Test) => void>>} testCases_378 */
|
|
180
|
+
export function runTestCases(testCases_378) {
|
|
181
|
+
reportTestResults(processTestCases(testCases_378));
|
|
212
182
|
return;
|
|
213
183
|
};
|
|
214
184
|
/**
|
|
215
|
-
* @param {(arg0: Test) => void}
|
|
185
|
+
* @param {(arg0: Test) => void} testFun_379
|
|
216
186
|
* @returns {void}
|
|
217
187
|
*/
|
|
218
|
-
export function runTest(
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
188
|
+
export function runTest(testFun_379) {
|
|
189
|
+
const test_380 = new Test();
|
|
190
|
+
testFun_379(test_380);
|
|
191
|
+
test_380.softFailToHard();
|
|
222
192
|
return;
|
|
223
193
|
};
|
package/testing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "version": 3, "file": "js/std/testing.js", "sources": [ "std/testing.temper.md" ], "sourcesContent": [ "# Temper test framework\n\n## Test instance\n\nWe currently convert assert and check macro calls into method calls on a `Test`\ninstance.\n\n export class Test {\n\nRecommended default Temper assert is soft, meaning that it records failures for\nreporting but doesn't immediately end test execution on a false value. This lets\nyou check multiple conditions more easily.\n\n @connected(\u0022Test::assert\u0022)\n public assert(success: Boolean, message: fn (): String): Void {\n if (!success) {\n _passing = false;\n _messages.add(message());\n }\n }\n\nTypical hard asserts that end the test on false condition also are available.\n\n @connected(\u0022Test::assertHard\u0022)\n public assertHard(\n success: Boolean,\n message: fn (): String,\n ): Void | Bubble {\n assert(success, message);\n if (!success) {\n // Attempt to distinguish assert fails from others.\n // Sadly, they can still orelse an assert failure, so this isn't\n // flawless.\n _failedOnAssert = true;\n bail();\n }\n }\n\nHarden and end current test on any pending failure if not previously hardened.\nBackends typically insert calls to this if needed, but you can also call it\nmanually at any desired point in your test.\n\n public softFailToHard(): Void | Bubble {\n if (hasUnhandledFail) {\n _failedOnAssert = true;\n bail();\n }\n }\n\nProvide a bailing `Bubble` method here that enables backends to customize\nmessage delivery on failure.\n\n @connected(\u0022Test::bail\u0022)\n bail(): Bubble {\n bubble()\n }\n\nYou can check the current passing state of the test at any time. A test is\ncurrently passing if all soft checks and hard asserts have been succesful.\n\nTODO Does this need to be function call syntax for macro purposes?\n\n @connected(\u0022Test::passing\u0022)\n public get passing(): Boolean { _passing }\n\nMessages access is presented as a function because it likely allocates. Also,\nmessages might be automatically constructed in some cases, so it's possibly\nunwise to depend on their exact formatting.\n\n @connected(\u0022Test::messages\u0022)\n public messages(): List\u003cString\u003e { _messages.toList() }\n\n### Backend helper methods\n\nAvoid using backend helper methods in user code. Their behavior might be\nunreliable on some backends and/or have high risk of changing in future releases\nof Temper.\n\n @connected(\u0022Test::failedOnAssert\u0022)\n public get failedOnAssert(): Boolean { _failedOnAssert }\n\nAdditional helper methods to simplify backend code generation in some contexts.\n\n public get hasUnhandledFail(): Boolean { !(_failedOnAssert || _passing) }\n\nSimple helper to get multiple messages combined for now. We probably want to do\nfancier things in the future, but this can simplify backends for now.\n\n public messagesCombined(): String | Null {\n if (_messages.isEmpty) {\n // Unexpected, but most backends can do something with null.\n null\n } else {\n _messages.join(\u0022, \u0022) { (it);; it }\n }\n }\n\n private var _failedOnAssert: Boolean = false;\n private var _passing: Boolean = true;\n private _messages: ListBuilder\u003cString\u003e = new ListBuilder\u003cString\u003e();\n }\n\n## Interpreter testing support\n\nNOTICE: Don't directly anything in this section. It just exists for the\nimplementation of testing within the interpreter.\n\n export let TestCase = Pair\u003cTestName, TestFun\u003e;\n export let TestFailureMessage = String;\n export let TestFun = fn (Test): Void | Bubble;\n export let TestName = String;\n export let TestResult = Pair\u003cTestName, List\u003cTestFailureMessage\u003e\u003e;\n\n @connected(\u0022::processTestCases\u0022)\n export let processTestCases(testCases: List\u003cTestCase\u003e): List\u003cTestResult\u003e {\n testCases.map { (testCase): TestResult;;\n let { key, value as fun } = testCase;\n let test = new Test();\n // Actually call the test.\n let hadBubble = do {\n fun(test);\n false\n } orelse true;\n // Now get the messages.\n let messages = test.messages();\n let failures: List\u003cTestFailureMessage\u003e = if (test.passing) {\n []\n } else if (hadBubble \u0026\u0026 !test.failedOnAssert) {\n // Despite having 1+ failure messages, we seem to have failed on some\n // Bubble separate from asserts, so add that on.\n let allMessages = messages.toListBuilder();\n allMessages.add(\u0022Bubble\u0022);\n allMessages.toList()\n } else {\n messages\n };\n // Package up with test name.\n new Pair(key, failures)\n }\n }\n\n @connected(\u0022::reportTestResults\u0022)\n export let reportTestResults(testResults: List\u003cTestResult\u003e): Void {\n // TODO Write as junit xml (or tap if we switch to that).\n for (var i = 0; i \u003c testResults.length; i += 1) {\n let testResult = testResults[i];\n let failureMessages = testResult.value;\n if (failureMessages.isEmpty) {\n console.log(\u0022\u0024{testResult.key}: Passed\u0022);\n } else {\n let message = failureMessages.join(\u0022, \u0022) { (it);; it };\n console.log(\u0022\u0024{testResult.key}: Failed \u0024{message}\u0022);\n }\n }\n }\n\n @connected(\u0022::runTestCases\u0022)\n export let runTestCases(testCases: List\u003cTestCase\u003e): Void {\n reportTestResults(processTestCases(testCases));\n }\n\nTODO Is this a better idea than inlining each case? We'd need to generate\n`fun testFunction() { runTest(originalFunctionAsCallback) }` or some such.\n\n export let runTest(testFun: TestFun): Void | Bubble {\n let test = new Test();\n testFun(test);\n test.softFailToHard();\n }\n" ], "names": [ "Test", "success", "message", "_passing", "_messages", "_failedOnAssert", "return", "fn", "it", "TestName", "TestFun", "TestCase", "TestFailureMessage", "TestResult", "processTestCases", "testCases", "testCase", "key", "fun", "test", "hadBubble", "messages", "failures", "allMessages", "reportTestResults", "testResults", "i", "testResult", "failureMessages", "runTestCases", "runTest", "testFun" ], "mappings": "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" }
|
|
1
|
+
{ "version": 3, "file": "js/std/testing.js", "sources": [ "std/testing.temper.md" ], "sourcesContent": [ "# Temper test framework\n\n## Test instance\n\nWe currently convert assert and check macro calls into method calls on a `Test`\ninstance.\n\n export class Test {\n\nRecommended default Temper assert is soft, meaning that it records failures for\nreporting but doesn't immediately end test execution on a false value. This lets\nyou check multiple conditions more easily.\n\n @connected(\u0022Test::assert\u0022)\n public assert(success: Boolean, message: fn (): String): Void {\n if (!success) {\n _passing = false;\n _messages.add(message());\n }\n }\n\nTypical hard asserts that end the test on false condition also are available.\n\n @connected(\u0022Test::assertHard\u0022)\n public assertHard(\n success: Boolean,\n message: fn (): String,\n ): Void | Bubble {\n assert(success, message);\n if (!success) {\n // Attempt to distinguish assert fails from others.\n // Sadly, they can still orelse an assert failure, so this isn't\n // flawless.\n _failedOnAssert = true;\n bail();\n }\n }\n\nHarden and end current test on any pending failure if not previously hardened.\nBackends typically insert calls to this if needed, but you can also call it\nmanually at any desired point in your test.\n\n public softFailToHard(): Void | Bubble {\n if (hasUnhandledFail) {\n _failedOnAssert = true;\n bail();\n }\n }\n\nProvide a bailing `Bubble` method here that enables backends to customize\nmessage delivery on failure.\n\n @connected(\u0022Test::bail\u0022)\n private bail(): Bubble {\n bubble()\n }\n\nYou can check the current passing state of the test at any time. A test is\ncurrently passing if all soft checks and hard asserts have been succesful.\n\nTODO Does this need to be function call syntax for macro purposes?\n\n @connected(\u0022Test::passing\u0022)\n public get passing(): Boolean { _passing }\n\nMessages access is presented as a function because it likely allocates. Also,\nmessages might be automatically constructed in some cases, so it's possibly\nunwise to depend on their exact formatting.\n\n @connected(\u0022Test::messages\u0022)\n public messages(): List\u003cString\u003e { _messages.toList() }\n\n### Backend helper methods\n\nAvoid using backend helper methods in user code. Their behavior might be\nunreliable on some backends and/or have high risk of changing in future releases\nof Temper.\n\n @connected(\u0022Test::failedOnAssert\u0022)\n public get failedOnAssert(): Boolean { _failedOnAssert }\n\nAdditional helper methods to simplify backend code generation in some contexts.\n\n public get hasUnhandledFail(): Boolean { !(_failedOnAssert || _passing) }\n\nSimple helper to get multiple messages combined for now. We probably want to do\nfancier things in the future, but this can simplify backends for now.\n\n public messagesCombined(): String | Null {\n if (_messages.isEmpty) {\n // Unexpected, but most backends can do something with null.\n null\n } else {\n _messages.join(\u0022, \u0022) { (it);; it }\n }\n }\n\n private var _failedOnAssert: Boolean = false;\n private var _passing: Boolean = true;\n private _messages: ListBuilder\u003cString\u003e = new ListBuilder\u003cString\u003e();\n }\n\n## Interpreter testing support\n\nNOTICE: Don't directly use anything in this section. It just exists for the\nimplementation of testing within the interpreter.\n\n export let TestCase = Pair\u003cTestName, TestFun\u003e;\n export let TestFailureMessage = String;\n export let TestFun = fn (Test): Void | Bubble;\n export let TestName = String;\n export let TestResult = Pair\u003cTestName, List\u003cTestFailureMessage\u003e\u003e;\n\n @connected(\u0022::processTestCases\u0022)\n export let processTestCases(testCases: List\u003cTestCase\u003e): List\u003cTestResult\u003e {\n testCases.map { (testCase): TestResult;;\n let { key, value as fun } = testCase;\n let test = new Test();\n // Actually call the test.\n let hadBubble = do {\n fun(test);\n false\n } orelse true;\n // Now get the messages.\n let messages = test.messages();\n let failures: List\u003cTestFailureMessage\u003e = if (test.passing) {\n []\n } else if (hadBubble \u0026\u0026 !test.failedOnAssert) {\n // Despite having 1+ failure messages, we seem to have failed on some\n // Bubble separate from asserts, so add that on.\n let allMessages = messages.toListBuilder();\n allMessages.add(\u0022Bubble\u0022);\n allMessages.toList()\n } else {\n messages\n };\n // Package up with test name.\n new Pair(key, failures)\n }\n }\n\n @connected(\u0022::reportTestResults\u0022)\n export let reportTestResults(testResults: List\u003cTestResult\u003e): Void {\n // TODO Write as junit xml (or tap if we switch to that).\n for (var i = 0; i \u003c testResults.length; i += 1) {\n let testResult = testResults[i];\n let failureMessages = testResult.value;\n if (failureMessages.isEmpty) {\n console.log(\u0022\u0024{testResult.key}: Passed\u0022);\n } else {\n let message = failureMessages.join(\u0022, \u0022) { (it);; it };\n console.log(\u0022\u0024{testResult.key}: Failed \u0024{message}\u0022);\n }\n }\n }\n\n @connected(\u0022::runTestCases\u0022)\n export let runTestCases(testCases: List\u003cTestCase\u003e): Void {\n reportTestResults(processTestCases(testCases));\n }\n\nTODO Is this a better idea than inlining each case? We'd need to generate\n`fn testFunction() { runTest(originalFunctionAsCallback) }` or some such.\n\n export let runTest(testFun: TestFun): Void | Bubble {\n let test = new Test();\n testFun(test);\n test.softFailToHard();\n }\n" ], "names": [ "Test", "success", "message", "_passing", "_messages", "_failedOnAssert", "return", "fn", "it", "TestName", "TestFun", "TestCase", "TestFailureMessage", "TestResult", "processTestCases", "testCases", "testCase", "key", "fun", "test", "hadBubble", "messages", "failures", "allMessages", "reportTestResults", "testResults", "i", "testResult", "failureMessages", "runTestCases", "runTest", "testFun" ], "mappings": "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" }
|