documentation/content/developer/reference/javascript/testing.rst
Simon Genin (ges) fd28f72c68 wip
2021-10-12 12:06:37 +02:00

142 lines
5.0 KiB
ReStructuredText

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:
.. code-block::
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:
#. create a new file named ``something_test.ts`` in the ``static/tests`` folder
#. import your file in ``static/tests/main.ts`` (so it will be added to the test bundle)
#. add your tests inside your new file.
Here is a simple example of a test file to test a component:
.. code-block:: 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.