tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_group.spec.ts (10311B)


      1 /* eslint-disable @typescript-eslint/require-await */
      2 export const description = `
      3 Unit tests for TestGroup.
      4 `;
      5 
      6 import { Fixture } from '../common/framework/fixture.js';
      7 import { makeTestGroup } from '../common/framework/test_group.js';
      8 import { TestQueryMultiFile } from '../common/internal/query/query.js';
      9 import { kQueryMaxLength, makeTestGroupForUnitTesting } from '../common/internal/test_group.js';
     10 import { assert } from '../common/util/util.js';
     11 
     12 import { TestGroupTest } from './test_group_test.js';
     13 import { UnitTest } from './unit_test.js';
     14 
     15 export const g = makeTestGroup(TestGroupTest);
     16 
     17 g.test('UnitTest_fixture').fn(async t0 => {
     18  let seen = 0;
     19  function count(_t: Fixture): void {
     20    seen++;
     21  }
     22 
     23  const g = makeTestGroupForUnitTesting(UnitTest);
     24 
     25  g.test('test').fn(count);
     26  g.test('testp')
     27    .paramsSimple([{ a: 1 }])
     28    .fn(count);
     29 
     30  await t0.run(g);
     31  t0.expect(seen === 2);
     32 });
     33 
     34 g.test('custom_fixture').fn(async t0 => {
     35  let seen = 0;
     36  class Counter extends UnitTest {
     37    count(): void {
     38      seen++;
     39    }
     40  }
     41 
     42  const g = makeTestGroupForUnitTesting(Counter);
     43 
     44  g.test('test').fn(t => {
     45    t.count();
     46  });
     47  g.test('testp')
     48    .paramsSimple([{ a: 1 }])
     49    .fn(t => {
     50      t.count();
     51    });
     52 
     53  await t0.run(g);
     54  t0.expect(seen === 2);
     55 });
     56 
     57 g.test('stack').fn(async t0 => {
     58  const g = makeTestGroupForUnitTesting(UnitTest);
     59 
     60  const doNestedThrow1 = () => {
     61    throw new Error('goodbye');
     62  };
     63 
     64  const doNestedThrow2 = () => doNestedThrow1();
     65 
     66  g.test('fail').fn(t => {
     67    t.fail();
     68  });
     69  g.test('throw').fn(_t => {
     70    throw new Error('hello');
     71  });
     72  g.test('throw_nested').fn(_t => {
     73    doNestedThrow2();
     74  });
     75 
     76  const res = await t0.run(g);
     77 
     78  const search = /unittests[/\\]test_group\.spec\.[tj]s/;
     79  t0.expect(res.size > 0);
     80  for (const { logs } of res.values()) {
     81    assert(logs !== undefined, 'expected logs');
     82    t0.expect(logs.some(l => search.test(l.toJSON())));
     83    t0.expect(search.test(logs[logs.length - 1].toJSON()));
     84  }
     85 });
     86 
     87 g.test('no_fn').fn(t => {
     88  const g = makeTestGroupForUnitTesting(UnitTest);
     89 
     90  g.test('missing');
     91 
     92  t.shouldThrow('Error', () => {
     93    g.validate(new TestQueryMultiFile('s', ['f']));
     94  });
     95 });
     96 
     97 g.test('duplicate_test_name').fn(t => {
     98  const g = makeTestGroupForUnitTesting(UnitTest);
     99  g.test('abc').fn(() => {});
    100 
    101  t.shouldThrow('Error', () => {
    102    g.test('abc').fn(() => {});
    103  });
    104 });
    105 
    106 g.test('duplicate_test_params,none').fn(() => {
    107  {
    108    const g = makeTestGroupForUnitTesting(UnitTest);
    109    g.test('abc')
    110      .paramsSimple([])
    111      .fn(() => {});
    112    g.validate(new TestQueryMultiFile('s', ['f']));
    113  }
    114 
    115  {
    116    const g = makeTestGroupForUnitTesting(UnitTest);
    117    g.test('abc').fn(() => {});
    118    g.validate(new TestQueryMultiFile('s', ['f']));
    119  }
    120 
    121  {
    122    const g = makeTestGroupForUnitTesting(UnitTest);
    123    g.test('abc')
    124      .paramsSimple([
    125        { a: 1 }, //
    126      ])
    127      .fn(() => {});
    128    g.validate(new TestQueryMultiFile('s', ['f']));
    129  }
    130 });
    131 
    132 g.test('duplicate_test_params,basic').fn(t => {
    133  {
    134    const g = makeTestGroupForUnitTesting(UnitTest);
    135    const builder = g.test('abc');
    136    t.shouldThrow('Error', () => {
    137      builder.paramsSimple([
    138        { a: 1 }, //
    139        { a: 1 },
    140      ]);
    141      g.validate(new TestQueryMultiFile('s', ['f']));
    142    });
    143  }
    144  {
    145    const g = makeTestGroupForUnitTesting(UnitTest);
    146    g.test('abc')
    147      .params(u =>
    148        u.expandWithParams(() => [
    149          { a: 1 }, //
    150          { a: 1 },
    151        ])
    152      )
    153      .fn(() => {});
    154    t.shouldThrow('Error', () => {
    155      g.validate(new TestQueryMultiFile('s', ['f']));
    156    });
    157  }
    158  {
    159    const g = makeTestGroupForUnitTesting(UnitTest);
    160    g.test('abc')
    161      .paramsSimple([
    162        { a: 1, b: 3 }, //
    163        { b: 3, a: 1 },
    164      ])
    165      .fn(() => {});
    166    t.shouldThrow('Error', () => {
    167      g.validate(new TestQueryMultiFile('s', ['f']));
    168    });
    169  }
    170 });
    171 
    172 g.test('duplicate_test_params,with_different_private_params').fn(t => {
    173  {
    174    const g = makeTestGroupForUnitTesting(UnitTest);
    175    const builder = g.test('abc');
    176    t.shouldThrow('Error', () => {
    177      builder.paramsSimple([
    178        { a: 1, _b: 1 }, //
    179        { a: 1, _b: 2 },
    180      ]);
    181    });
    182  }
    183  {
    184    const g = makeTestGroupForUnitTesting(UnitTest);
    185    g.test('abc')
    186      .params(u =>
    187        u.expandWithParams(() => [
    188          { a: 1, _b: 1 }, //
    189          { a: 1, _b: 2 },
    190        ])
    191      )
    192      .fn(() => {});
    193    t.shouldThrow('Error', () => {
    194      g.validate(new TestQueryMultiFile('s', ['f']));
    195    });
    196  }
    197 });
    198 
    199 g.test('invalid_test_name').fn(t => {
    200  const g = makeTestGroupForUnitTesting(UnitTest);
    201 
    202  const badChars = Array.from('"`~@#$+=\\|!^&*[]<>{}-\'. ');
    203  for (const char of badChars) {
    204    const name = 'a' + char + 'b';
    205    t.shouldThrow(
    206      'Error',
    207      () => {
    208        g.test(name).fn(() => {});
    209      },
    210      { message: name }
    211    );
    212  }
    213 });
    214 
    215 g.test('long_test_query,long_test_name').fn(t => {
    216  const g = makeTestGroupForUnitTesting(UnitTest);
    217 
    218  const long = Array(kQueryMaxLength - 5).join('a');
    219 
    220  const fileQuery = new TestQueryMultiFile('s', ['f']);
    221  g.test(long).unimplemented();
    222  g.validate(fileQuery);
    223 
    224  g.test(long + 'a').unimplemented();
    225  t.shouldThrow(
    226    'Error',
    227    () => {
    228      g.validate(fileQuery);
    229    },
    230    { message: long }
    231  );
    232 });
    233 
    234 g.test('long_case_query,long_test_name').fn(t => {
    235  const g = makeTestGroupForUnitTesting(UnitTest);
    236 
    237  const long = Array(kQueryMaxLength - 5).join('a');
    238 
    239  const fileQuery = new TestQueryMultiFile('s', ['f']);
    240  g.test(long).fn(() => {});
    241  g.validate(fileQuery);
    242 
    243  g.test(long + 'a').fn(() => {});
    244  t.shouldThrow(
    245    'Error',
    246    () => {
    247      g.validate(fileQuery);
    248    },
    249    { message: long }
    250  );
    251 });
    252 
    253 g.test('long_case_query,long_case_name').fn(t => {
    254  const g = makeTestGroupForUnitTesting(UnitTest);
    255 
    256  const long = Array(kQueryMaxLength - 9).join('a');
    257 
    258  const fileQuery = new TestQueryMultiFile('s', ['f']);
    259  g.test('t')
    260    .paramsSimple([{ x: long }])
    261    .fn(() => {});
    262  g.validate(fileQuery);
    263 
    264  g.test('u')
    265    .paramsSimple([{ x: long + 'a' }])
    266    .fn(() => {});
    267  t.shouldThrow(
    268    'Error',
    269    () => {
    270      g.validate(fileQuery);
    271    },
    272    { message: long }
    273  );
    274 });
    275 
    276 g.test('param_value,valid').fn(() => {
    277  const g = makeTestGroup(UnitTest);
    278  g.test('a').paramsSimple([{ x: JSON.stringify({ a: 1, b: 2 }) }]);
    279 });
    280 
    281 g.test('param_value,invalid').fn(t => {
    282  for (const badChar of ';=*') {
    283    const g = makeTestGroupForUnitTesting(UnitTest);
    284    const builder = g.test('a');
    285    t.shouldThrow('Error', () => {
    286      builder.paramsSimple([{ badChar }]);
    287    });
    288  }
    289 });
    290 
    291 g.test('subcases').fn(async t0 => {
    292  const g = makeTestGroupForUnitTesting(UnitTest);
    293  g.test('a')
    294    .paramsSubcasesOnly(u =>
    295      u //
    296        .combineWithParams([{ a: 1 }])
    297    )
    298    .fn(t => {
    299      t.expect(t.params.a === 1, 'a must be 1');
    300    });
    301 
    302  function* gen({ a, b }: { a?: number; b?: number }) {
    303    if (b === 2) {
    304      yield { ret: 2 };
    305    } else if (a === 1) {
    306      yield { ret: 1 };
    307    } else {
    308      yield { ret: -1 };
    309    }
    310  }
    311  g.test('b')
    312    .params(u =>
    313      u
    314        .combineWithParams([{ a: 1 }, { b: 2 }])
    315        .beginSubcases()
    316        .expandWithParams(gen)
    317    )
    318    .fn(t => {
    319      const { a, b, ret } = t.params;
    320      t.expect((a === 1 && ret === 1) || (b === 2 && ret === 2));
    321    });
    322 
    323  const result = await t0.run(g);
    324  t0.expect(Array.from(result.values()).every(v => v.status === 'pass'));
    325 });
    326 
    327 g.test('subcases,skip')
    328  .desc(
    329    'If all tests are skipped then status is "skip". If at least one test passed, status is "pass"'
    330  )
    331  .params(u => u.combine('allSkip', [false, true]))
    332  .fn(async t0 => {
    333    const { allSkip } = t0.params;
    334    const g = makeTestGroupForUnitTesting(UnitTest);
    335    g.test('a')
    336      .params(u => u.beginSubcases().combine('do', ['pass', 'skip', 'pass']))
    337      .fn(t => {
    338        t.skipIf(allSkip || t.params.do === 'skip');
    339      });
    340    const result = await t0.run(g);
    341    const values = Array.from(result.values());
    342    t0.expect(values.length === 1);
    343    const expectedStatus = allSkip ? 'skip' : 'pass';
    344    t0.expect(
    345      values[0].status === expectedStatus,
    346      `expect: ${values[0].status} === ${expectedStatus}, allSkip: ${allSkip}`
    347    );
    348  });
    349 
    350 g.test('exceptions')
    351  .params(u =>
    352    u
    353      .combine('useSubcases', [false, true]) //
    354      .combine('useDOMException', [false, true])
    355  )
    356  .fn(async t0 => {
    357    const { useSubcases, useDOMException } = t0.params;
    358    const g = makeTestGroupForUnitTesting(UnitTest);
    359 
    360    const b1 = g.test('a');
    361    let b2;
    362    if (useSubcases) {
    363      b2 = b1.paramsSubcasesOnly(u => u);
    364    } else {
    365      b2 = b1.params(u => u);
    366    }
    367    b2.fn(_t => {
    368      if (useDOMException) {
    369        throw new DOMException('Message!', 'Name!');
    370      } else {
    371        throw new Error('Message!');
    372      }
    373    });
    374 
    375    const result = await t0.run(g);
    376    const values = Array.from(result.values());
    377    t0.expect(values.length === 1);
    378    t0.expect(values[0].status === 'fail');
    379  });
    380 
    381 g.test('throws').fn(async t0 => {
    382  const g = makeTestGroupForUnitTesting(UnitTest);
    383 
    384  g.test('a').fn(_t => {
    385    throw new Error();
    386  });
    387 
    388  const result = await t0.run(g);
    389  const values = Array.from(result.values());
    390  t0.expect(values.length === 1);
    391  t0.expect(values[0].status === 'fail');
    392 });
    393 
    394 g.test('shouldThrow').fn(async t0 => {
    395  t0.shouldThrow('TypeError', () => {
    396    throw new TypeError();
    397  });
    398 
    399  const g = makeTestGroupForUnitTesting(UnitTest);
    400 
    401  g.test('a').fn(t => {
    402    t.shouldThrow('Error', () => {
    403      throw new TypeError();
    404    });
    405  });
    406 
    407  const result = await t0.run(g);
    408  const values = Array.from(result.values());
    409  t0.expect(values.length === 1);
    410  t0.expect(values[0].status === 'fail');
    411 });
    412 
    413 g.test('shouldReject').fn(async t0 => {
    414  t0.shouldReject(
    415    'TypeError',
    416    (async () => {
    417      throw new TypeError();
    418    })()
    419  );
    420 
    421  const g = makeTestGroupForUnitTesting(UnitTest);
    422 
    423  g.test('a').fn(t => {
    424    t.shouldReject(
    425      'Error',
    426      (async () => {
    427        throw new TypeError();
    428      })()
    429    );
    430  });
    431 
    432  const result = await t0.run(g);
    433  // Fails even though shouldReject doesn't fail until after the test function ends
    434  const values = Array.from(result.values());
    435  t0.expect(values.length === 1);
    436  t0.expect(values[0].status === 'fail');
    437 });