documentation/wowl_markdown_doc/testing.md
Géry Debongnie eff7c05465 [DOC] add master-wowl doc (UNFINISHED)
I know, the doc is still in md, it was only temporary. we will convert
it to rst someday
2021-05-31 15:29:27 +02:00

4.8 KiB

Testing

We take very seriously code quality. Tests is an important part of a solid and robust application. Each feature should be (if reasonable) tested properly, in the QUnit test suite (available in the route /wowl/tests)

In a few sentences, here is how the test suite is organized:

  • tests are written in the static/tests folder.
  • the main entry point for the suite is static/tests/main.ts, which is the code that setup the test suite environment.
  • some helpers are available in static/tests/helpers.ts.
  • to access the test suite, one needs to have an odoo server running and then open /wowl/tests in a browser

The test suite file structure looks like this:

static/
  ...
  tests/
    components/
      navbar_tests.ts
      ...
    services/
      router_tests.ts
      ...
    helpers.ts    <-- helpers that will probably be imported in each test file
    main.ts       <-- main file, used to generate the test bundle
    qunit.ts      <-- qunit config file. No test should import this

Test helpers

  • mount(SomeComponent, {env, target}): create a component with the env provided, and mount it to the target html element. This method is asynchronous, and returns the instance of the component

  • makeTestEnv(params?: Params): create asynchronously a test environment. By default, a test environment has no service, components or browser access. It can be optionally customized with the params argument:

    • services (optional, Registry<Service>): a registry of services
    • Components (optional, Registry<Component>)) main component registry
    • browser (optional, object): the browser object that will be used for the test environment.
  • getFixture(): HTMLElement: return an html element to use as a DOM node for tests (only applies to code that needs to interact with the DOM, obviously).

  • nextTick(): Promise<void>: helper to wait for the next animation frame. This is extremely useful while writing tests involving components updating the DOM.

  • click(el: HTMLElement, selector?: string): Promise<void>: helper to click on an element, given the element itself, or an element and a selector that matches a single element inside it. The helper will crash when called with a selector that have no match, or more than 1 match. It returns a promise resolved after the next animation frame, i.e. after potential DOM updates have been applied.

QUnit custom assertions

QUnit provides several built-in assertions, available on the QUnit.assert object. Alongside them, we provide custom assertions.

  • assert.containsN(el: HTMLElement, selector: string, n: number, msg?: string): check that a target element el contains exactly n matches for the given selector, with msg being an optional short description of the assertion

  • assert.containsNone(el: HTMLElement, selector: string, msg?: string): check that a target element el contains no match for the given selector

  • assert.containsOnce(el: HTMLElement, selector: string, msg?: string): check that a target element el contains exactly one match for the given selector

  • assert.hasClass(el: HTMLElement, classNames: string, msg?: string): check that a target element el has the given classNames

  • assert.doesNotHaveClass(el: HTMLElement, classNames: string, msg?: string): check that a target element el does not have the given classNames.

Adding a new test

To add a new test file to the QUnit suite, the following steps need to be done:

  1. create a new file named something_test.ts in the static/tests folder
  2. import your file in static/tests/main.ts (so it will be added to the test bundle)
  3. add your tests inside your new file.

Here is a simple example of a test file to test a component:

import * as QUnit from "qunit";
import { MyComponent } from "../../src/components/...";
import { getFixture, makeTestEnv, mount, OdooEnv } from "../helpers";

let target: HTMLElement;
let env: OdooEnv;
QUnit.module("MyComponent", {
    beforeEach() {
        target = getFixture();
        env = makeTestEnv();
    }
});

QUnit.test("can be rendered", async (assert) => {
    assert.expect(1);
    const myComponent = await mount(MyComponent, { env, target });
    // perform some assertion/actions
});

Debugging a test

Sometimes, changes in the code make tests fail. Understanding why assertions fail reading the logs might be tedious. Hopefully, one can use our custom QUnit.debug function instead of QUnit.test (basically, rename ŧest into debug for the failing test). With this, the target returned by getFixture will be document.body, so that what has been inserted into the DOM is visible, and can be directly interacted with.