Skip to main content

Testing

Since v0.20.0, the Halo template uses Jest as the default test runner. This guide will provide you with information on how to write and run tests in this template.

1. Organize your tests#

There are typically two ways to organize your tests. The first approach involves separating your tests from the source code and put them into a dedicated folder(eg: test).

 ... ┣ 📂src ┣ 📂tests ┃ ┣ 📂oauth ┃ ┃ ┣ 📂app ┃ ┃ ┃ ┣ 📜create-app.spec.ts ┃ ┃ ┃ ┗ 📜reset-secret.spec.ts ┃ ┃ ┣ 📂auth ┃ ┃ ┃ ┣ 📜authorize.spec.ts ┃ ┃ ┃ ┣ 📂grant-access ┃ ┃ ┃ ┃ ┣ 📜fixture.ts ┃ ┃ ┃ ┃ ┗ 📜grant_access.spec.ts

Second, you can write your tests alongside the related source code.

📂src ┣ 📂oauth ┃ ┣ 📂app ┃ ┃ ┣ 📂create-app ┃ ┃ ┃ ┣ 📜create-app.cmd.ts ┃ ┃ ┃ ┣ 📜create-app.req.ts ┃ ┃ ┃ ┗ 📜create-app.spec.ts ┃ ┃ ┣ 📂reset-secret ┃ ┃ ┃ ┣ 📜reset-secret.cmd.ts ┃ ┃ ┃ ┣ 📜reset-secret.req.ts ┃ ┃ ┃ ┗ 📜reset-secret.spec.ts ┃ ┣ 📂auth ┃ ┃ ┣ 📂authorize ┃ ┃ ┃ ┣ 📜authorize.spec.ts ┃ ┃ ┃ ┣ 📜authorize.qry.ts ┃ ┃ ┃ ┗ 📜... ┃ ┃ ┣ 📂grant-access ┃ ┃ ┃ ┣ 📂__tests__ ┃ ┃ ┃ ┃ ┣ 📜fixture.ts ┃ ┃ ┃ ┃ ┗ 📜grant_access.spec.ts ┃ ┃ ┃ ┣ 📜grant-access.qry.ts ┃ ┃ ┃ ┗ 📜...
note

If you choose the second method, there are a few things you need to know. CellularJS uses Webpack as a bundler. To prevent your tests from being included in the final bundle, please follow these conventions:

  1. Test file name must end with .{spec,test}.{ts,js}. Eg: create-app.spec.ts.
  2. If you need a more complex structure, create a folder named __tests__ and put all testing-related files into it.

In the Halo template, both methods are used. The first method is used for e2e tests, and the second is used for unit tests.

2. Write unit test#

If you write unit test for service. You can use ServiceFactory for resolving service instance.

// my-info.qry.tsimport { Service } from '@cellularjs/net';
@Service({ scope: 'publish' })export class MyInfoQry {  constructor(    private irq: IRQ,    private userRepo: UserRepository,  ) { }
  handle() {    return 'halo';  }}
// my-info.spec.tsimport { Container } from '@cellularjs/di';import { IRS, ServiceFactory } from '@cellularjs/net';import { RegisterCmd } from './my-info.qry';
describe('User:MyInfoQry', () => {  test('resolve service', async () => {    const myInfoQry = await ServiceFactory.resolve(MyInfoQry, {      /**       * By default, the value is true. If false, service provider will be ignored.       */      includeServiceProvider: true,
      /**       * By default, the value is true. If false, service proxy will be ignored.       */      includeServiceProxy: true,
      /**       * Temporary providers or request providers       */      providers: [        { token: IRQ, useValue: new IRQ({}, {}) },        { token: UserRepository, useValue: mock },      ],
      /**       * A container that holds shared providers for a cell.       * Usually, you don't need to use this container; all providers       * can be provided by using the `providers` property above.       */      rootContainer: new Container(),    });
    const irs = await myInfoQry.handle();
    expect(myInfoQry).toBeInstanceOf(MyInfoQry);    expect(irs).toBeInstanceOf(IRS); // with the help of ServiceFactory, returned data is converted into IRS instance    expect(irs.body).toEqual('halo')  });});

3. Write e2e test#

The Halo template has been preconfigured for Supertest and provides you with a global object called testAgent for testing.

describe('User:SayHelloQry', () => {  test('Say hello', async () => {    await testAgent.get('/').expect(200);  });});
note

Global setup and teardown for e2e tests is located in the test\setup.ts file. You can add stuff like database cleaning here.

Example:

// test\setup.tsimport { clearNetwork } from '@cellularjs/net';import { destroyAllDataSource } from '@cellularjs/typeorm';import supertest from 'supertest';import { initApp } from '$gateway/http/app';
beforeEach(async () => {  global.server = (await initApp()).listen();  global.testAgent = supertest(global.server);});
afterEach(async () => {  await destroyAllDataSource();  await clearNetwork();  global.server?.close();});

4. Run test#

4.1. Run unit test#

$ yarn test

or

$ yarn test --coverage
----------------------|---------|----------|---------|---------|-------------------File                  | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s                                                                                                                        ----------------------|---------|----------|---------|---------|-------------------All files             |    5.81 |        0 |    8.33 |    3.84 |  $app/http            |       0 |        0 |       0 |       0 |   app.ts              |       0 |        0 |       0 |       0 | 1-36  index.ts            |       0 |      100 |       0 |       0 | 1-17  net.ts              |       0 |      100 |       0 |       0 | 1-9  routes.ts           |       0 |      100 |       0 |       0 | 1-10 $share/common        |       0 |      100 |       0 |       0 |   common.module.ts    |       0 |      100 |     100 |       0 | 1-10  index.ts            |       0 |      100 |       0 |       0 | 1 $share/env           |       0 |      100 |     100 |       0 |   index.ts            |       0 |      100 |     100 |       0 | 1-8 $share/express-proxy |       0 |        0 |       0 |       0 |   index.ts            |       0 |        0 |       0 |       0 | 1-36 user                 |       0 |      100 |     100 |       0 |   index.ts            |       0 |      100 |     100 |       0 | 5-13 user/say-hello       |     100 |      100 |     100 |     100 |   say-hello.qry.ts    |     100 |      100 |     100 |     100 | ----------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 totalTests:       1 passed, 1 totalSnapshots:   0 totalTime:        2.488 s, estimated 3 sDone in 3.23s.

4.2. Run e2e test#

$ yarn test:e2e

or

$ yarn test:e2e --coverage
----------------------|---------|----------|---------|---------|-------------------File                   | % Stmts   | % Branch   | % Funcs   | % Lines   | Uncovered Line #s-----------------------|-----------|------------|-----------|-----------|--------------------All files              | 78.61     | 69.23      | 90        | 78.61     |$app/http              | 59.74     | 75         | 75        | 59.74     |app.ts                 | 67.56     | 100        | 100       | 67.56     | 25-36index.ts               | 0         | 0          | 0         | 0         | 1-19net.ts                 | 100       | 100        | 100       | 100       |routes.ts              | 100       | 100        | 100       | 100       |$share/common          | 100       | 100        | 100       | 100       |common.module.ts       | 100       | 100        | 100       | 100       |index.ts               | 100       | 100        | 100       | 100       |$share/env             | 100       | 100        | 100       | 100       |index.ts               | 100       | 100        | 100       | 100       |$share/express-proxy   | 92.1      | 57.14      | 100       | 92.1      |index.ts               | 92.1      | 57.14      | 100       | 92.1      | 23-25user                   | 100       | 100        | 100       | 100       |index.ts               | 100       | 100        | 100       | 100       |user/say-hello         | 100       | 100        | 100       | 100       |say-hello.qry.ts       | 100       | 100        | 100       | 100       |---------------------- | --------- | ---------- | --------- | --------- | -------------------
Test Suites: 1 passed, 1 totalTests:       1 passed, 1 totalSnapshots:   0 totalTime:        1.689 s, estimated 2 sDone in 2.65s.