aboutsummaryrefslogtreecommitdiff
path: root/testlib/talertest.ts
blob: 6012eb65717a6106e9ca4a1d4674ebc50e2a3e4f (plain)
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 This file is part of TALER
 (C) 2016 Inria

 TALER is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.

 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 *
 * @author Florian Dold
 */

type TestFn = (t: TestLib) => void | Promise<void>;

interface Test {
  name: string;
  testFn: TestFn;
}

export interface TestLib {
  pass(msg?: string): void;
  fail(msg?: string): void;
  assert(v: any, msg?: string): void;
}

let tests: Test[] = [];
let testRunner: any;


/**
 * Register a test case.
 */
export function test(name: string, testFn: TestFn) {
  tests.push({name, testFn});
}


/**
 * Run all registered test case, producing a TAP stream.
 */
export async function run(statusCallback?: (m: string) => void) {
  console.log(`1..${tests.length}`);
  for (let i in tests) {
    let t = tests[i];
    let passed = false;
    let lastMsg: string|undefined = undefined;
    let p = new Promise((resolve, reject) => {
      let pass = (msg?: string) => {
        if (passed) {
          reject(Error("called pass twice"));
          return;
        }
        passed = true;
        lastMsg = msg;
        resolve();
      };
      let fail = (msg?: string) => {
        lastMsg = msg;
        reject();
        throw Error("test failed");
      };
      let assert = (v: any, msg?: string) => {
        if (!v) {
          lastMsg = msg;
          reject();
          throw Error("test failed");
        }
      };
      // Test might return a promise.  If so, wait for it.
      let r = t.testFn({pass,fail, assert});
      r.then(() => resolve(), (e) => reject(e));
    });

    console.log(`# ${t.name}`);
    statusCallback && statusCallback(`starting test ${t.name}`);

    if (!lastMsg) {
      lastMsg = "-";
    }

    try {
      await p;
      if (!passed) {
        throw Error("test did not call 'pass'");
      }
      console.log(`ok ${Number(i) + 1} ${lastMsg || "-"}`);
      statusCallback && statusCallback(`finished test ${t.name}`);
    } catch (e) {
      console.error(e);
      console.log(`not ok ${Number(i) + 1} ${lastMsg || "-"}`);
      statusCallback && statusCallback(`failed test ${t.name}`);
    }
  }
}