Use when writing or modifying Jasmine/Puppeteer E2E tests (*.spec.js) for Handsontable, or when a bug fix or feature change needs E2E test coverage - covers the standard boilerplate, global test helpers, async/await requirements, mouse and keyboard event simulation, and plugin lifecycle testing patterns
Every E2E test file must use this structure exactly:
describe('MyFeature', () => {
const id = 'testContainer';
beforeEach(function() {
this.$container = $(`<div id="${id}"></div>`).appendTo('body');
});
afterEach(function() {
if (this.$container) {
destroy();
this.$container.remove();
}
});
it('should do something', async() => {
handsontable({ data: createSpreadsheetData(5, 5) });
await selectCell(0, 0);
expect(getDataAtCell(0, 0)).toBe('A1');
});
});
it() callbacks MUST be async.await-ed (~50+ methods).These are injected automatically. Do not import them manually.
handsontable(), destroy(), updateSettings(), render()createSpreadsheetData(), getDataAtCell(), getData(), setDataAtCell()selectCell(), selectCells(), getSelected()getCell(), spec(), hot()getPlugin()test/helpers/common.js.mouseDown(), mouseUp(), mouseOver(), mouseClick(), mouseDoubleClick() from test/helpers/mouseEvents.jskeyDown(), keyUp(), keyDownUp() from test/helpers/keyboardEvents.jstriggerTouchEvent(type, target), simulateTouch(target) from test/helpers/common.js
triggerTouchEvent('touchstart', element) / triggerTouchEvent('touchend', element) — dispatches a single touch eventsimulateTouch(element) — full Android sequence: touchstart → touchend → mousedown → mouseup → click (with preventDefault handling)await-ed in spec filesWhen testing touch interactions (editors opening on double-tap, outside-click after touch, etc.):
it('should open editor on double-tap', async() => {
handsontable({ data: createSpreadsheetData(5, 5) });
const cell = getCell(0, 0);
// First tap — select
await triggerTouchEvent('touchstart', cell);
await triggerTouchEvent('touchend', cell);
// Second tap — open editor
await triggerTouchEvent('touchstart', cell);
await triggerTouchEvent('touchend', cell);
// Assert editor opened
});
Use simulateTouch(target) when you need to test the full Android event sequence including synthetic mouse events.
Use it.flaky() for timing-sensitive tests (auto-retries up to 3 times).
handsontable({ myPlugin: true })updateSettings({ myPlugin: false })getPlugin('myPlugin').enablePlugin() / .disablePlugin()npm run test:e2e --prefix handsontablenpm run test:e2e --testPathPattern=<regex> --prefix handsontable -- the pattern is matched against test file paths during the webpack .dump step (e.g. collapsibleColumns, ghostTable, textEditor, nestedHeaders/__tests__/hidingColumns)npm run test:e2e --testPathPattern=<regex> --theme=horizon --prefix handsontable (available themes: classic, main, horizon; default when --theme is omitted: main)dist/handsontable.js. After changing src/**, run npm run build --prefix handsontable before running E2E tests.Important: Do NOT use -- before --testPathPattern. The flag is consumed by npm during the .dump step (webpack build), not by Puppeteer. Using npm run test:e2e -- --testPathPattern=... passes it only to the Puppeteer runner, which doesn't support it.
src/plugins/{name}/__tests__/*.spec.jstest/e2e/ and test/e2e/hooks/See src/plugins/pagination/__tests__/ for reference -- separate dirs for options, methods, hooks, and strategies.
async on it() callbacks.updateSettings() cycle.Reference .ai/TESTING.md for full testing docs. Key files: test/helpers/common.js, test/helpers/mouseEvents.js, test/helpers/keyboardEvents.js.