documentation/wowl_markdown_doc/testing.md

121 lines
4.8 KiB
Markdown
Raw Permalink Normal View History

# 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](https://api.qunitjs.com/assert/),
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:
```ts
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.