Jest setup
The package is ESM only: its exports map has an import condition and no require or
default. Bundlers and Vitest handle that. Jest, which resolves modules the CommonJS way,
reports that it cannot find @beyul/sulmu-ui.
Two settings fix it. This is the configuration in the frontend’s shared preset
(packages/test-utils/jest-preset.cjs).
1. Map the package to its built file
Section titled “1. Map the package to its built file”const path = require('node:path')
// @beyul/sulmu-ui only publishes an ESM "import" entry, which Jest's CommonJS resolver// cannot see: point at the built file.const sulmuUi = path.resolve(__dirname, '../../node_modules/@beyul/sulmu-ui/dist/index.js')
module.exports = { moduleNameMapper: { '^@beyul/sulmu-ui$': sulmuUi, },}2. Let the transformer process it
Section titled “2. Let the transformer process it”The built file is an ES module, so it has to go through the same transform as the app’s code.
By default Jest skips everything in node_modules; make an exception for the @beyul scope:
module.exports = { transform: { '^.+\\.(js|jsx|ts|tsx)$': [require.resolve('@swc/jest')], }, transformIgnorePatterns: ['/node_modules/(?!(@beyul))'],}Add @beyul to the existing list if the pattern already has exceptions.
3. Stub the stylesheet
Section titled “3. Stub the stylesheet”If a file under test imports @beyul/sulmu-ui/styles.css, map CSS files to an empty module,
as most Jest setups already do:
moduleNameMapper: { '\\.css$': '<rootDir>/test/fileMock.js',}What tests see
Section titled “What tests see”-
Components render real markup. Query them the way a user would:
getByRole('button', { name: 'Log In' }),getByLabelText('Email'). -
No styles are applied, so do not assert on computed styles. Variant classes are on the elements if a test really needs them (
su-button--variant_secondary). -
Popups (Select, Menu, Dialog) render in a portal in
document.body;screenqueries find them. -
jsdom lacks a few browser APIs that the floating components use. If a test that opens a popup fails on one, add these to the Jest setup file, as the library’s own test setup does:
class ResizeObserverStub {observe() {}unobserve() {}disconnect() {}}globalThis.ResizeObserver ??= ResizeObserverStubElement.prototype.scrollIntoView ??= () => {}Element.prototype.scrollTo ??= () => {}
Vitest
Section titled “Vitest”Vitest resolves ES modules natively and needs none of this.