Clone on Gitea
Introduction
Explained by ducks
FAQ
Getting Started
Components
Component Basics
Auto Initialization From DOM
Templates
Children and Parents
Roles
Strictness
Fields
What is a Field
Binding Fields to DOM
Reading and Writing Fields
Value Casting
Flags
Events
Overview
Event Handlers
DOM Events
Custom Events
Propagation and Flow
Advanced Event Control
Beyond Components
States
Overview
StateEngine
DisplayStateEngine
Field Matchers
Ordering and priority
Debugging
Advanced usage
Ajax
ComponentUI
VirtualForm
Unit Testing
Helpers
Overview
Cookies
Arrays

Unit tests

Qite doesn't require any specific test framework for testing your own custom components, and it itself uses Mocha, Chai, a small local Node/Express test server and a few Qite.spec helper functions

...but this is only how Qite tests Qite. It is not a rule for users. You may use any testing stack you prefer as long as it can:

  • run JavaScript modules in a browser-like environment
  • load HTML fixtures
  • dispatch DOM events
  • make assertions about DOM and component state

The main recommendation

Keep your app's component tests separate from Qite's own framework tests. That means:

  • don't add your application's tests into Qite's test/qite.test.js
  • don't treat Qite's internal test suite as your project's test runner
  • instead, create your own test entry points and fixture files in your app

You may still borrow ideas and helpers from Qite's test setup, but your component tests should live in your project and reflect your own components.

What a Qite component test usually needs

In practice, most Qite component tests follow the same shape:

  1. Load some HTML fixture.
  2. Attach it to the DOM.
  3. Let Qite instantiate components for that fixture.
  4. Find the component instance.
  5. Trigger DOM events or component events.
  6. Assert on: DOM changes, field values, flag values, published events child component behavior

That is the core pattern regardless of whether you use Mocha, Vitest, Playwright, Web Test Runner or something else.

A recommended project layout

There is no single required layout, but something like this is a good start:

test/
|
|-- components/
|   |-- my_form.test.js
|   '-- shipping_quote.test.js
|
|-- html/
|   |-- my_form.html
|   '-- shipping_quote.html
|
|-- spec_helpers.js
'-- test_entry.js

Just make sure you keep test files, HTML fixtures, helper functions organized and separate from production code.

A practical setup using Qite's style

If you like Qite's own testing style, you can use a very similar setup in your application:

  • an HTML page that loads Mocha/Chai
  • qiteinit.js
  • one JS test entry file
  • a small local server to serve fixtures and ES modules

That setup is simple and works well because Qite is browser-first anyway. A minimal test runner page might look like this:

<!doctype html>
<html>
<head>
    <link rel="stylesheet" href="/test/mocha.css" />
</head>
<body>
    <div id="mocha"></div>
    <div id="dom-wrapper"></div>

    <script src="/test/node_modules/mocha/mocha.js"></script>
    <script src="/test/chai.js"></script>

    <script>
        expect = chai.expect;
        mocha.setup("bdd");
    </script>

    <script src="/assets/vendor/qite/src/qiteinit.js"></script>
    <script type="module" src="/test/test_entry.js"></script>

    <script type="module">
        mocha.run();
    </script>
</body>
</html>

Again: this is a recommendation, not a requirement.

A minimal test entry file

Your test_entry.js file would import helpers, the Qite core and whichever components are needed by your tests:

import "/assets/vendor/qite/src/qite.js";
import "/assets/vendor/qite/test/spec_helpers.js";

// Your test files:
import "./components/my_form.test.js";

Then, inside your actual test file, don't forget to import the component you wrote with something like:

### JavaScript
import MyFormComponent from "/assets/js/my_form.js";

Using HTML fixtures

For component tests, HTML fixtures are usually the cleanest approach.

Example fixture:

<div data-component="Root" id="root">
    <div data-component="MyForm">
        <button data-component="Button" data-roles="submit">Submit</button>
        <div data-part="message">Hello</div>
    </div>
</div>

This is usually better than constructing long DOM trees manually in test code, because Qite is built around real HTML structure.

A minimal custom component test

Suppose your component looks like this:

import BaseComponent from "/assets/vendor/qite/src/components/base_component.js";

export default class MyFormComponent extends BaseComponent {
    constructor(tree_node) {
        super(tree_node);

        this.events.add([
            ["@click", "submit", () => this.fields.set("status", "submitted")]
        ]);
    }
}

Qite.components.MyForm = MyFormComponent;

Then a test in Qite's style might look like this:

import MyFormComponent from "/assets/js/my_form.js";

describe("MyFormComponent", () => {

    let root, form, submit_el;

    beforeEach(async () => {
        root = await Qite.spec.loadComponentsFrom("html/my_form.html");
        form = root.children[ 0 ];
        submit_el = root.el.querySelector('[data-roles="submit"]');
    });

    afterEach(() => {
        root.remove();
    });

    it("updates status when submit button is clicked", async () => {
        submit_el.click();
        await Qite.spec.flushUi(); // only required if animation is involved
        expect(form.fields.get("status")).to.eq("submitted");
    });

});

So the general pattern of writing a component unit test is:

  • load fixture with Qite.spec.loadComponentsFrom()
  • find component
  • trigger interaction
  • wait for queued UI/state work if needed
  • assert

About Qite.spec helpers

Qite's own tests use helper functions under Qite.spec, for example:

  • loadComponentsFrom(...)
  • loadDom(...)
  • parseDom(...)
  • dispatchEvent(...)
  • flush(...)
  • flushRaf(...)
  • flushUi()

These helpers are not the testing framework itself. They are just convenience utilities that make it easier to load fixtures and wait for Qite's async UI work. In order to use them, you have three reasonable options:

  1. Copy the helpers you need into your own project and adapt them into your own test utilities.
  2. Import them in your test_entry.js from Qite's directory, as shown above, with import "/assets/vendor/qite/test/spec_helpers.js"
  3. Ignore them and use your own helpers instead.

What flushUi() is for

Some Qite behavior is not purely synchronous.

For example:

  • field/flag changes may schedule state reevaluation which triggers showing/hiding certain HTML elements and animation is involved.
  • show() and hide() may involve animation timing
  • requestAnimationFrame may be involved in visibility settling

Because of that, a test sometimes needs to wait briefly before asserting. That is what helpers such as flushUi() are for. If your test stack already has an equivalent waiting utility, use that instead.

Testing strategy: what to assert

For custom Qite components, the most useful assertions are usually:

  • field changes
  • flag changes
  • DOM changes
  • hidden / visible behavior
  • published custom events
  • interaction with child components by role

Try to test behavior from the outside rather than implementation details. For example, instead of asserting that a private helper was called, assert that:

  • a result became visible
  • a field changed
  • a child event was published
  • a button became disabled

That keeps tests stable even when implementation is refactored. Also avoid testing things that Qite itself covered with unit-tests, such as state changes -- you don't need to test that a certain state was entered, this is already covered by Qite's own tests and state is declarative (what you might want in this case is maybe to debug state transitions and see in your browser console what's going on - this is covered on the States/Debugging page).

A note on the local server

Qite's own tests use a small Express server because it is convenient for:

  • serving HTML fixtures
  • serving ES modules
  • serving mock Ajax endpoints

While a good approach for app-level component tests too, especially if your components use Ajax, it's still only one possible approach. Any test runner or dev server that can serve your modules and fixtures is acceptable.

General recommendations

A simple, practical baseline for testing custom Qite components is:

  • browser-based test runner
  • HTML fixtures
  • your own test entry file
  • your own app test directory
  • optional reuse of Qite.spec -style helpers

That gives you a setup that matches how Qite actually runs in production: with real DOM, real HTML, and explicit component loading.