Skip to content

[PRO-858] Theme API: data-driven E2E expectations per theme (design tokens)#12239

Closed
qunabu wants to merge 5 commits intodevelopfrom
feature/PRO-858_Theme-API-e2e-test-data-driven-for-each-theme
Closed

[PRO-858] Theme API: data-driven E2E expectations per theme (design tokens)#12239
qunabu wants to merge 5 commits intodevelopfrom
feature/PRO-858_Theme-API-e2e-test-data-driven-for-each-theme

Conversation

@qunabu
Copy link
Copy Markdown
Contributor

@qunabu qunabu commented Mar 30, 2026

Context

Handsontable ships multiple themes (classic, main, horizon) with different typography, spacing, and density. Many E2E and plugin specs asserted pixel-perfect dimensions as hardcoded numbers for a single theme, which made those tests fragile when the loaded theme changed and did not document the relationship to our design system.

This change aligns with AGENTS.md testing guidance: calculate expectations from design tokens (and documented formulas) where possible, and isolate remaining Chromium-only layout measurements as explicit fixture values.

What this PR does

  1. handsontable/test/helpers/designTokens.js

    • Resolves values from the same sources as the product: sizing, density, and per-theme token maps (classic / main / horizon).
    • Exposes helpers such as calcRowHeight, calcColHeaderHeight, getTokenValue, and many calcE2e* functions used by specs.
    • Token-derived expectations: several former per-theme literals are expressed as calcRowHeight / calcColHeaderHeight / getTokenValue plus small, documented E2E fixture deltas (browser/layout margins that are not individual Figma tokens).
    • calcE2eMinMasterCellOuterWidth: uses the documented default column width (50px, per meta schema) adjusted by horizontal cell padding vs classic, with a Horizon-only empirical adjustment where the DOM still differs from a pure padding delta.
    • Module documentation clarifies that some calcE2e* values remain intentional Chromium measurements (e.g. large scroll positions, auto-sized column widths from content) where a stable token-only formula does not exist.
  2. handsontable/babel.config.js

    • Allows the E2E webpack bundle to transpile imports from theme static variable modules (sizing, density, theme token files) used by designTokens.js, so helpers run inside the E2E test bundle.
  3. E2E and plugin *.spec.js updates

    • Specs that asserted fixed pixel values now use spec() / theme helpers from test/helpers/designTokens.js (and existing test infrastructure) so expectations vary correctly with getLoadedTheme() for classic, main, and horizon.

What this PR does not do

  • It does not change public Handsontable runtime APIs, default settings, or CSS class names (per breaking changes policy in AGENTS.md).
  • It does not replace every numeric assertion with a token formula: values that are purely content- and layout-dependent stay as explicit fixture maps, with the token layer used where we proved a stable relationship.

How has this been tested?

  • ESLint on touched files.
  • npm run test:e2e.dump in handsontable/ — confirms the E2E webpack bundle builds with designTokens and theme variable imports.
  • Recommended before merge: pnpm --filter handsontable run test:e2e (or targeted Puppeteer specs for the areas touched).

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature or improvement (non-breaking change which adds functionality) — test infrastructure and maintainability; no new product API
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Additional language file or change to the existing one (translations)

Related issue(s):

  1. PRO-858 (Theme API — data-driven E2E per theme)

Affected project(s):

  • handsontable
  • @handsontable/angular-wrapper
  • @handsontable/react-wrapper
  • @handsontable/vue3

Checklist:

  • I have reviewed the guidelines about Contributing to Handsontable and I confirm that my code follows the code style of this project.
  • I have signed the Contributor License Agreement
  • My change requires a change to the documentation. — No user-facing API or behavior change; internal test helpers only. JSDoc in designTokens.js documents the approach.

Additional (AGENTS.md)

  • Add a changelog entry via bin/changelog entry before merge if required for test-only changes in handsontable/.

[skip changelog]


Note

Low Risk
Changes are limited to test infrastructure, build scripts, and E2E expectations; no production runtime behavior or public API is modified. Main risk is CI noise if any token-to-DOM mapping or Chromium fixture value is off, causing flaky E2E failures.

Overview
Refactors a large set of Handsontable E2E/plugin specs to replace hardcoded pixel assertions with theme-aware calculations (e.g. calcRowHeight, getTokenValue, and calcE2e* helpers), making expectations consistent across classic, main, and horizon.

Adds a new test/helpers/designTokens.js resolver that reads generated theme token/density/sizing modules and exposes both token-derived formulas and a small set of explicit Chromium fixture values (e.g. scrollbar width/empirical deltas) used by the updated specs. Build/test wiring is updated to support these imports (Babel allowlist + new build:design-tokens script), and testing docs now include a runtime --spec filter flow for running a single E2E suite.

Written by Cursor Bugbot for commit bc10408. This will update automatically on new commits. Configure here.

qunabu and others added 4 commits March 30, 2026 14:04
- Add figma token conversion tool at handsontable/src/themes/figma/
- Store design tokens JSON as tokens.json (single source of truth)
- Tool outputs CSS and JS variable files directly to src/themes/static/
- Add npm script: npm run build:design-tokens
- Use .mjs extensions for ES module support within CommonJS package
- Absolute paths via import.meta.url for CWD-independent execution

Workflow: Export tokens from Figma → save as tokens.json → run build:design-tokens

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New test helper: designTokens.js resolves token references to numeric px values
- Exported functions: token(), tokenForThemes(), getTokenValue(),
  calcRowHeight(), calcColHeaderHeight(), forAllThemes()
- Token resolution chain: tokens → density → sizing → px value
- Registered as global test helper via test/helpers/index.js

Enables tests to calculate expected dimensions from design tokens
instead of using hardcoded magic numbers per theme.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tests

Convert .forThemes blocks in 16 test/e2e spec files to calculate expected
dimensions from design tokens instead of using magic numbers.

Formulas: calcRowHeight(t), calcColHeaderHeight(t), forAllThemes()
- Row height = lineHeight + (cellVerticalPadding * 2) + 1px border
- Col header height = lineHeight + (cellVerticalPadding * 2)

Files converted:
- fixedRowsBottom, fixedRowsTop, scrollToFocusedCell, scrollViewportTo
- viewportScroll, refreshDimensions, batch, getRowHeight
- ColHeader, Core_view, Core_resize, Core_reCreate
- beforeViewportScrollVertically, modifyRowHeightByOverlayName
- beforeRefreshDimensions, afterRefreshDimensions

Note: 65 plugin spec files remain to be converted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extend designTokens with token resolution and calcE2e* helpers
- Allow E2E bundle to import theme sizing/density/token modules (babel)
- Update E2E and plugin specs for classic, main, and horizon themes

Made-with: Cursor
@qunabu
Copy link
Copy Markdown
Contributor Author

qunabu commented Mar 30, 2026

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 30, 2026

More templates

npm i https://pkg.pr.new/handsontable@12239
npm i https://pkg.pr.new/@handsontable/react-wrapper@12239
npm i https://pkg.pr.new/@handsontable/vue3@12239
npm i https://pkg.pr.new/@handsontable/angular-wrapper@12239

commit: bc10408

@qunabu qunabu marked this pull request as ready for review March 31, 2026 09:14
@qunabu qunabu requested a review from adrianspdev March 31, 2026 09:14
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

main: fn('main'),
horizon: fn('horizon'),
};
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exported helper functions never used anywhere in codebase

Low Severity

tokenForThemes (line 165) and forAllThemes (line 212) are exported but have zero call sites in the codebase — the only grep matches are their own definitions. Since index.js calls exportToWindow(designTokens), these get assigned to window at test bundle time, unnecessarily polluting the global namespace and adding dead code to the test bundle.

Fix in Cursor Fix in Web

@qunabu qunabu marked this pull request as draft April 2, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants