Public
Script
v29
December 10, 2023
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { getRaw } from "https://esm.town/v/karfau/getRaw";
import { sleep } from "https://esm.town/v/stevekrouse/sleep?v=1";
export async function testRunner<
Input extends {
val?: Ref;
},
>(input: Input, ...tests: Test<Input>[]) {
let reportHeader = "";
try {
const [userHandle, valName] = input.val || [];
if (userHandle && valName) {
const version = await getRaw([
userHandle,
valName,
], "version");
if (typeof version === "number") {
reportHeader = `Testing @${userHandle}.${valName} v${version} ${new Date().toISOString()}:\n`;
}
}
}
catch {
}
let failedCount = 0;
let skipCount = 0;
let start = Date.now();
const result = (await Promise.all(tests.map(async (t, index) => {
const name = t.name.replaceAll(/_/g, " ");
if (name.startsWith("skip")) {
skipCount++;
return `${index + 1} [${name}]`;
}
const tstart = Date.now();
try {
const p = t(input);
if (p && p instanceof Promise) {
await Promise.race([
p,
sleep(2000).then(() => {
throw "async test did not complete in time";
}),
]);
}
return `${index + 1} ${name}: passed in ${Date.now() - tstart}ms`;
}
catch (error) {
failedCount++;
return `${index + 1} ${name}: failed after ${Date.now() - tstart}ms\n ${
/^assert/i.test(error.toString()) ? error : error.stack
}`;
}
}))).join("\n").replaceAll(/\033\[[\d;]+m/g, "");
if (failedCount) {
throw `${reportHeader}${failedCount} of ${tests.length} tests failed ${
skipCount ? `, ${skipCount} skipped` : ""
} (${Date.now() - start}ms):\n${result}`;
}
return `${reportHeader}${tests.length - skipCount} tests passed ${skipCount ? `, ${skipCount} skipped` : ""} (${
Date.now() - start
}ms):\n${result}`;
}
type Ref = [
userHandle: string,
valName: string,
];
type Test<
Input extends {
val?: Ref;
},
> = ((input: Input) => void) | ((input: Input) => Promise<void>);
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
v29
December 10, 2023
v1 tracks ms each test needs and for all tests and replaces
_
in test names with spaces in the output.v2,v3 improve output to separate test result from name
v4 adds the error stack to the output if the Error is not an "AssertionError" (protytpe name check)
v5 fixes a regression in v4 and switches to a regexpr to see i the error is an assertion error
v6 avoids duplicate output for errors
v10 handle
skip
prefix v7-v9 debugging reference issuehey, karfau, I'm interested to try the tester, but when I click references, it says "This val has not been referenced in public vals or your vals."
can you make at least one or two examples as public vals?
@kajgod Just did that and added a note about two possible usage approaches in the readme.