as-test 0.2.0 → 0.3.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.
Files changed (54) hide show
  1. package/.github/workflows/as-test.yml +3 -0
  2. package/CHANGELOG.md +4 -1
  3. package/README.md +73 -67
  4. package/as-test.config.json +7 -10
  5. package/assembly/__tests__/array.spec.ts +19 -0
  6. package/assembly/__tests__/math.spec.ts +16 -0
  7. package/assembly/__tests__/sleep.spec.ts +28 -0
  8. package/assembly/index.ts +181 -165
  9. package/assembly/src/expectation.ts +119 -112
  10. package/assembly/src/log.ts +19 -0
  11. package/assembly/src/suite.ts +99 -0
  12. package/assembly/src/tests.ts +10 -0
  13. package/assembly/tsconfig.json +1 -1
  14. package/assembly/util/helpers.ts +0 -33
  15. package/assembly/util/term.ts +55 -0
  16. package/assets/img/download.png +0 -0
  17. package/bin/about.js +135 -0
  18. package/bin/build.js +72 -131
  19. package/bin/index.js +70 -112
  20. package/bin/init.js +211 -39
  21. package/bin/reporter.js +1 -0
  22. package/bin/run.js +226 -68
  23. package/bin/types.js +25 -31
  24. package/bin/util.js +44 -20
  25. package/cli/build.ts +70 -109
  26. package/cli/index.ts +148 -159
  27. package/cli/init.ts +235 -34
  28. package/cli/reporter.ts +1 -0
  29. package/cli/run.ts +266 -57
  30. package/cli/types.ts +6 -11
  31. package/cli/util.ts +35 -0
  32. package/package.json +6 -2
  33. package/run/package.json +27 -0
  34. package/tests/array.run.js +7 -0
  35. package/tests/math.run.js +7 -0
  36. package/tests/sleep.run.js +7 -0
  37. package/transform/lib/coverage.js +325 -319
  38. package/transform/lib/index.js +51 -31
  39. package/transform/lib/index.js.map +1 -1
  40. package/transform/lib/mock.js +61 -55
  41. package/transform/lib/mock.js.map +1 -1
  42. package/transform/package.json +1 -1
  43. package/transform/src/index.ts +22 -3
  44. package/transform/src/mock.ts +1 -1
  45. package/asconfig.json +0 -31
  46. package/assembly/__tests__/example.spec.ts +0 -79
  47. package/assembly/reporters/tap.ts +0 -30
  48. package/assembly/src/group.ts +0 -44
  49. package/assembly/src/node.ts +0 -13
  50. package/test.config.json +0 -0
  51. package/tests/test.tap +0 -14
  52. package/unision +0 -38
  53. package/unision.pub +0 -1
  54. package/utils.ts +0 -1
package/assembly/index.ts CHANGED
@@ -1,25 +1,26 @@
1
1
  import { rainbow } from "as-rainbow";
2
- import { TestGroup } from "./src/group";
2
+ import { Suite } from "./src/suite";
3
3
  import { Expectation } from "./src/expectation";
4
- import { formatTime } from "./util/helpers";
5
4
  import { stringify } from "as-console/stringify";
6
5
  import { __COVER, __HASHES, __POINTS } from "as-test/assembly/coverage";
7
- import { createTable } from "table-as";
6
+ import { JSON } from "json-as";
7
+ import { term, TermLine } from "./util/term";
8
+ import { Log } from "./src/log";
8
9
 
9
- /**
10
- * Enumeration representing the verdict of a test case.
11
- */
12
- export enum Verdict {
13
- Unreachable,
14
- Ok,
15
- Fail,
16
- }
10
+ let entrySuites: Suite[] = [];
17
11
 
12
+ // @ts-ignore
13
+ const FILE = isDefined(ENTRY_FILE) ? ENTRY_FILE : "unknown";
18
14
  // Globals
19
- let current_group: TestGroup | null = null;
20
- let groups: TestGroup[] = [];
21
-
15
+ // @ts-ignore
16
+ @global let suites: Suite[] = [];
17
+ // @ts-ignore
18
+ @global let depth: i32 = -1;
19
+ // @ts-ignore
20
+ @global let current_suite: Suite | null = null;
21
+ // @ts-ignore
22
22
  let before_all_callback: (() => void) | null = null;
23
+ // @ts-ignore
23
24
  let after_all_callback: (() => void) | null = null;
24
25
 
25
26
  export let before_each_callback: (() => void) | null = null;
@@ -41,10 +42,21 @@ let __test_options!: RunOptions;
41
42
  * ```
42
43
  */
43
44
  export function describe(description: string, callback: () => void): void {
44
- const group = new TestGroup(description, callback);
45
+ const suite = new Suite(description, callback, "describe");
45
46
 
46
- current_group = group;
47
- groups.push(group);
47
+ if (depth >= 0) {
48
+ const _suite = suites[depth];
49
+ if (_suite.depth == depth) {
50
+ _suite.addSuite(suite);
51
+ } else {
52
+ suite.depth = ++depth;
53
+ suites.push(suite);
54
+ }
55
+ } else {
56
+ suite.file = FILE;
57
+ entrySuites.push(suite);
58
+ suites.push(suite);
59
+ }
48
60
  }
49
61
 
50
62
  /**
@@ -62,10 +74,21 @@ export function describe(description: string, callback: () => void): void {
62
74
  * ```
63
75
  */
64
76
  export function test(description: string, callback: () => void): void {
65
- const group = new TestGroup(description, callback);
77
+ const suite = new Suite(description, callback, "test");
66
78
 
67
- current_group = group;
68
- groups.push(group);
79
+ if (depth >= 0) {
80
+ const _suite = suites[depth];
81
+ if (_suite.depth == depth) {
82
+ _suite.addSuite(suite);
83
+ } else {
84
+ suite.depth = ++depth;
85
+ suites.push(suite);
86
+ }
87
+ } else {
88
+ suite.file = FILE;
89
+ entrySuites.push(suite);
90
+ suites.push(suite);
91
+ }
69
92
  }
70
93
 
71
94
  /**
@@ -83,10 +106,21 @@ export function test(description: string, callback: () => void): void {
83
106
  * ```
84
107
  */
85
108
  export function it(description: string, callback: () => void): void {
86
- const group = new TestGroup(description, callback);
109
+ const suite = new Suite(description, callback, "it");
87
110
 
88
- current_group = group;
89
- groups.push(group);
111
+ if (depth >= 0) {
112
+ const _suite = suites[depth];
113
+ if (_suite.depth == depth) {
114
+ _suite.addSuite(suite);
115
+ } else {
116
+ suite.depth = ++depth;
117
+ suites.push(suite);
118
+ }
119
+ } else {
120
+ suite.file = FILE;
121
+ entrySuites.push(suite);
122
+ suites.push(suite);
123
+ }
90
124
  }
91
125
 
92
126
  /**
@@ -108,10 +142,13 @@ export function it(description: string, callback: () => void): void {
108
142
  * ```
109
143
  */
110
144
  export function expect<T>(value: T): Expectation<T> {
111
- const result = new Expectation<T>(value);
112
- current_group!.addExpectation(result);
145
+ const test = new Expectation<T>(value);
146
+
147
+ if (current_suite) {
148
+ current_suite!.addExpectation(test);
149
+ }
113
150
 
114
- return result;
151
+ return test;
115
152
  }
116
153
 
117
154
  /**
@@ -133,9 +170,11 @@ export function log<T>(data: T): void {
133
170
  const lines = formatted.split("\n");
134
171
  for (let i = 0; i < lines.length; i++) {
135
172
  const line = unchecked(lines[i]);
136
- console.log(" " + rainbow.bgYellow(" LOG ") + " " + line);
173
+ if (current_suite) {
174
+ current_suite!.addLog(new Log(line));
175
+ }
137
176
  }
138
- console.log("");
177
+ term.write("\n");
139
178
  }
140
179
  }
141
180
 
@@ -176,7 +215,7 @@ export function afterEach(callback: () => void): void {
176
215
  }
177
216
 
178
217
  /**
179
- * Overrides all references to an existing function to instead point to this
218
+ * Overrides all references to an existing function in local scope to instead point to new function
180
219
  * @param {string} fn - name of function to override
181
220
  * @param {() => returnType} callback - the function to substitute it with
182
221
  */
@@ -185,6 +224,18 @@ export function mockFn<returnType>(
185
224
  callback: (...args: any[]) => returnType,
186
225
  ): void {}
187
226
 
227
+ /**
228
+ * Unmock all references to an existing function to instead point to the original function
229
+ * @param {string} fn - name of function to override
230
+ */
231
+ export function unmockFn(fn: string): void {}
232
+
233
+ /**
234
+ * Re-mock all references to an existing function to instead point to the declared function
235
+ * @param {string} fn - name of function to override
236
+ */
237
+ export function remockFn(fn: string): void {}
238
+
188
239
  /**
189
240
  * Class defining options that can be passed to the `run` function.
190
241
  *
@@ -218,153 +269,118 @@ class RunOptions {
218
269
  * ```
219
270
  */
220
271
  export function run(options: RunOptions = new RunOptions()): void {
272
+ // const buf = new ArrayBuffer(20);
273
+ // const bytes = process.stdin.read(buf);
274
+ // const stdinLn = term.write(String.UTF8.decodeUnsafe(changetype<usize>(buf), bytes) + "\n");
221
275
  __test_options = options;
222
- console.log(
223
- rainbow.boldMk(
224
- rainbow.blueBright(` _____ _____ _____ _____ _____ _____ `),
225
- ),
226
- );
227
- console.log(
228
- rainbow.boldMk(
229
- rainbow.blueBright(`| _ || __| ___|_ _|| __|| __||_ _|`),
230
- ),
276
+ const time = new Time();
277
+ const fileLn = term.write(
278
+ `${rainbow.bgCyanBright(" FILE ")} ${rainbow.dimMk(FILE)}\n`,
231
279
  );
232
- console.log(
233
- rainbow.boldMk(
234
- rainbow.blueBright(`| ||__ ||___| | | | __||__ | | | `),
235
- ),
236
- );
237
- console.log(
238
- rainbow.boldMk(
239
- rainbow.blueBright(`|__|__||_____| |_| |_____||_____| |_| `),
240
- ),
241
- );
242
- console.log(
243
- rainbow.dimMk("\n------------------- v0.2.0 -------------------\n"),
280
+ term.write("\n");
281
+ time.start = performance.now();
282
+ for (let i = 0; i < entrySuites.length; i++) {
283
+ // @ts-ignore
284
+ const suite = unchecked(entrySuites[i]);
285
+ suites = [suite];
286
+
287
+ current_suite = suite;
288
+ depth = -1;
289
+ current_suite = null;
290
+
291
+ suite.run();
292
+
293
+ suites = [];
294
+ depth = -1;
295
+ current_suite = null;
296
+ }
297
+ time.end = performance.now();
298
+ fileLn.edit(
299
+ `${rainbow.bgCyanBright(" FILE ")} ${rainbow.dimMk(FILE)} ${rainbow.dimMk(time.format())}`,
244
300
  );
245
- // @ts-ignore
246
- if (isDefined(COVERAGE_USE)) {
247
- console.log(
248
- rainbow.bgBlueBright(" PLUGIN ") +
249
- " " +
250
- rainbow.dimMk("Using Code Coverage") +
251
- "\n",
252
- );
301
+ const reportText = JSON.stringify(entrySuites);
302
+ const chunk_size = 48;
303
+ let chunks = reportText.length / chunk_size;
304
+ let index = 0;
305
+ term.write("\x1B[8m\n").clear(); // Hide text (so that the cursor doesn't flash for a moment)
306
+ while (chunks--) {
307
+ term
308
+ .write(
309
+ "READ_LINE" +
310
+ reportText.slice(index, (index += chunk_size)) +
311
+ "END_LINE\n",
312
+ )
313
+ .clear(); // Write a line and then clear it, making it invisible
253
314
  }
254
- const suites = groups.length;
255
- let failed = 0;
256
- let tests = 0;
257
- let failed_tests = 0;
258
- let failed_suite_logs = "";
259
- const start = performance.now();
260
- for (let i = 0; i < groups.length; i++) {
261
- if (before_all_callback) before_all_callback();
262
- const suite = unchecked(groups[i]);
263
- suite.run();
264
- for (let i = 0; i < suite.results.length; i++) {
265
- const expectation = unchecked(suite.results[i]);
266
- const verdict = expectation.verdict;
267
- tests++;
268
- if (verdict == Verdict.Ok) {
269
- suite.passed++;
270
- } else if (verdict == Verdict.Fail) {
271
- suite.verdict = Verdict.Fail;
272
- suite.failed++;
273
- failed_tests++;
274
- }
275
- }
276
- if (suite.verdict == Verdict.Unreachable) {
277
- suite.verdict = Verdict.Ok;
278
- console.log(
279
- rainbow.bgGreenBright(" PASS ") +
280
- " " +
281
- rainbow.dimMk(suite.description) +
282
- "\n",
283
- );
284
- } else {
285
- failed++;
286
- const txt =
287
- rainbow.bgRed(" FAIL ") + " " + rainbow.dimMk(suite.description) + "\n";
288
- failed_suite_logs += txt;
289
- console.log(txt);
290
- }
315
+ if (index < reportText.length) {
316
+ term.write("READ_LINE" + reportText.slice(index) + "END_LINE\n").clear();
317
+ }
318
+ term.write("\x1B[0m\n").clear(); // Un-hide text
319
+ }
291
320
 
292
- const report = suite.getLogs();
293
- if (report) {
294
- if (report.passed) console.log(report.passed!);
295
- if (report.failed) failed_suite_logs += report.failed!;
321
+ export class Result {
322
+ public name: string;
323
+ public arg1: i32;
324
+ public arg2: i32;
325
+ constructor(name: string, arg1: i32, arg2: i32) {
326
+ this.name = name;
327
+ this.arg1 = arg1;
328
+ this.arg2 = arg2;
329
+ }
330
+ display(): string {
331
+ let out = "";
332
+ out += `${rainbow.boldMk(this.name)} `;
333
+ if (this.arg1) {
334
+ out += `${rainbow.boldMk(rainbow.red(this.arg1.toString() + " " + "failed"))}`;
335
+ } else {
336
+ out += `${rainbow.boldMk(rainbow.green("0 failed"))}`;
296
337
  }
297
- if (after_all_callback) after_all_callback();
338
+ out += ` ${this.arg1 + this.arg2} total\n`;
339
+ return out;
340
+ }
341
+ serialize(): string {
342
+ return JSON.stringify(this);
298
343
  }
344
+ }
345
+
299
346
 
300
- if (failed) {
301
- console.log(
302
- rainbow.red("------------------ [FAILED] ------------------\n"),
303
- );
304
- console.log(failed_suite_logs);
347
+ @json
348
+ export class Time {
349
+ start: f64 = 0;
350
+ end: f64 = 0;
351
+ format(): string {
352
+ return formatTime(this.end - this.start);
305
353
  }
354
+ }
355
+
356
+ class Unit {
357
+ name: string;
358
+ divisor: number;
359
+ }
360
+
361
+ function formatTime(time: f64): string {
362
+ if (time < 0) return "0.00μs";
363
+
364
+ const us = time * 1000;
306
365
 
307
- // @ts-ignore
308
- if (isDefined(COVERAGE_USE) && isDefined(COVERAGE_SHOW) && __HASHES().size) {
309
- console.log(
310
- rainbow.dimMk("----------------- [COVERAGE] -----------------\n"),
311
- );
312
- const points = __HASHES().values();
313
-
314
- const table: string[][] = [["Location", "Type", "Hash"]];
315
-
316
- for (let i = 0; i < points.length; i++) {
317
- const point = unchecked(points[i]);
318
- const file = point.file;
319
- const reference =
320
- point.file +
321
- ":" +
322
- point.line.toString() +
323
- ":" +
324
- point.column.toString();
325
- const type = point.type;
326
- const hash = point.hash;
327
- table.push([rainbow.underlineMk(reference), type, "#" + hash]);
366
+ const units: Unit[] = [
367
+ { name: "μs", divisor: 1 },
368
+ { name: "ms", divisor: 1000 },
369
+ { name: "s", divisor: 1000 * 1000 },
370
+ { name: "m", divisor: 60 * 1000 * 1000 },
371
+ { name: "h", divisor: 60 * 60 * 1000 * 1000 },
372
+ { name: "d", divisor: 24 * 60 * 60 * 1000 * 1000 },
373
+ ];
374
+
375
+ for (let i = units.length - 1; i >= 0; i--) {
376
+ const unit = units[i];
377
+ if (us >= unit.divisor) {
378
+ const value = (Math.round((us / unit.divisor) * 100) / 100).toString();
379
+ return `${value}${unit.name}`;
328
380
  }
329
- console.log(rainbow.dimMk(createTable(table)) + "\n");
330
381
  }
331
382
 
332
- console.log(
333
- rainbow.dimMk("----------------- [RESULTS] ------------------\n"),
334
- );
335
- const ms = performance.now() - start;
336
- console.log(
337
- rainbow.boldMk("Test Suites: ") +
338
- (failed
339
- ? rainbow.boldMk(rainbow.red(failed.toString() + " failed"))
340
- : rainbow.boldMk(rainbow.green("0 failed"))) +
341
- ", " +
342
- suites.toString() +
343
- " total",
344
- );
345
- console.log(
346
- rainbow.boldMk("Tests: ") +
347
- (failed_tests
348
- ? rainbow.boldMk(rainbow.red(failed_tests.toString() + " failed"))
349
- : rainbow.boldMk(rainbow.green("0 failed"))) +
350
- ", " +
351
- tests.toString() +
352
- " total",
353
- );
354
- // @ts-ignore
355
- if (isDefined(COVERAGE_USE))
356
- console.log(
357
- rainbow.boldMk("Coverage: ") +
358
- (__HASHES().size
359
- ? rainbow.boldMk(rainbow.red(__HASHES().size.toString() + " failed"))
360
- : rainbow.boldMk(rainbow.green("0 failed"))) +
361
- ", " +
362
- __POINTS().toString() +
363
- " total",
364
- );
365
- console.log(rainbow.boldMk("Snapshots: ") + "0 total");
366
- console.log(rainbow.boldMk("Time: ") + formatTime(ms));
367
- if (failed) {
368
- process.exit(1);
369
- }
383
+ const _us = (Math.round(us * 100) / 100).toString();
384
+
385
+ return `${_us}μs`;
370
386
  }