This document describes the JavaScript test strategy for zhortein/datatable-bundle.
The bundle frontend remains intentionally lightweight:
- vanilla JavaScript;
- Stimulus-based;
- Bootstrap-compatible;
- independent from jQuery;
- independent from DataTables.net;
- independent from Webpack Encore.
Frontend tests protect the behavior of the bundle Stimulus controller.
Frontend tests use:
Vitest
jsdom
@hotwired/stimulus
Vitest is used as the JavaScript test runner.
jsdom provides a DOM-like environment.
Stimulus is started directly in tests to register and exercise the controller with its real identifier:
zhortein--datatable-bundle--datatable
Frontend tests live under:
tests/Frontend/
The Vitest configuration includes:
tests/Frontend/**/*.test.js
The shared setup file is:
tests/Frontend/setup.js
The bundle controller currently tested is:
assets/controllers/datatable_controller.js
Install frontend dependencies:
make frontenddepsRun frontend tests:
make frontendtestWithout the local Docker tooling:
npm ci
npm run test:frontendFor development watch mode:
npm run test:frontend:watchFrontend tests are part of the GitHub Actions quality gates.
The CI workflow runs:
npm ci
npm run test:frontendpackage-lock.json is committed so CI can use reproducible dependency installation with npm ci.
The CI uses Node.js through actions/setup-node.
Covered behavior:
- the datatable controller can be registered by Stimulus;
- the UX-compatible controller identifier is valid.
Covered behavior:
- the controller connects to the rendered datatable element;
autoLoaddefaults to enabled;- initial fragment loading is triggered on connect;
autoLoad=falseprevents initial refresh;- a missing fragments URL displays the error target instead of performing a network call.
Covered behavior:
- header fragment replacement;
- body fragment replacement;
- pagination fragment replacement;
- summary update;
- page and page size state updates from payload;
- invalid payload state is ignored;
- partial payloads do not break refresh;
- failed refreshes display the error target;
- loading state is toggled during refresh.
Covered behavior:
- global search value serialization;
- search debounce before refresh;
- filter serialization through
filters[...]; - empty filters are omitted;
- unchecked checkbox/radio filters are ignored;
- active filter UI state updates;
- page size changes reset the current page;
- invalid page size values are ignored;
- clear filters resets controls, active state and refresh URL.
Covered behavior:
- sorting a new field starts with ascending direction;
- sorting the same field toggles direction;
- sorting another field resets direction to ascending;
- sorting resets the current page to 1;
- invalid sort events are ignored;
- pagination changes the current page;
- invalid page values are ignored;
- current sort state is preserved when navigating pages.
Covered behavior:
- checked column controls are serialized as
visibleColumns[]; - unchecked column controls are serialized as
hiddenColumns[]; - definition-hidden columns are ignored;
- missing column names are ignored;
- column visibility changes reset the current page to 1;
- column visibility refresh is debounced;
- header, body and summary fragments update after refresh.
Covered behavior:
- current export includes page and page size;
- full export omits pagination;
- search state is included;
- filter values are included;
- sort state is included;
- column visibility state is included;
- definition-hidden columns are not serialized;
- custom export URL values are respected;
- link href fallback is supported.
Covered behavior:
- actions without confirmation metadata are ignored;
- blank confirmation messages are ignored;
- confirmed link actions are allowed;
- cancelled link actions are prevented;
- confirmed form submissions are allowed;
- cancelled form submissions are prevented;
- non-HTMLElement event targets are ignored.
Frontend tests now cover XLSX export URL generation.
Covered behavior:
- XLSX current export uses the XLSX endpoint and keeps pagination;
- XLSX full export uses the XLSX endpoint and omits pagination;
- search, filters, sorting and column visibility are preserved;
- link-specific export URL params override the root CSV export URL;
- link href fallback still works when no export URL value is configured.
These tests protect conditional multi-format export controls.
Tests should:
- use the real Stimulus controller;
- register it with the real UX-compatible identifier;
- keep DOM fixtures small but realistic;
- mock
fetchfor Ajax behavior; - mock
window.confirmfor confirmation behavior; - mock navigation for export tests;
- avoid real network calls;
- avoid Bootstrap internals;
- avoid jQuery;
- avoid browser-only assumptions not supported by jsdom.
When the controller behavior is debounced, tests may use fake timers.
When fake timers are used, helpers must not rely on unadvanced setTimeout() calls.
This is not an end-to-end browser test suite.
The frontend tests do not validate:
- real browser layout;
- CSS rendering;
- Bootstrap dropdown internals;
- real file downloads;
- real Symfony routing;
- real backend provider behavior;
- full application integration.
Those remain covered by PHP tests, smoke tests and future E2E testing if needed.
Possible future improvements:
- add a small shared frontend test fixture helper;
- add coverage for additional controller methods when new interactions are added;
- add accessibility-focused assertions for generated controls;
- decide whether browser E2E tests are needed before 1.0;
- consider Playwright only if jsdom becomes insufficient.
For now, Vitest + jsdom provides a good balance between confidence, speed and maintenance cost.