Files
Ashley Hunter 1b743f8019 test: migrate from jest to vitest with browser testing for brain/helm
Replace Jest with Vitest across the workspace. The brain and helm Angular suites
now run in a real browser (Playwright/Chromium via Vitest browser mode) so they
exercise real layout, focus, pointer events and computed styles that jsdom could
not. The cli, tools, mcp, registry and cli-smoke suites run on Vitest's node
environment.

- Add per-project vite configs and switch test targets to @nx/vitest:test
- Convert jest APIs to vi.* and jest module mocks to vi.mock with importOriginal
- Replace jest-axe with a browser-native axe-core helper and toHaveNoViolations
- Regenerate snapshots in vitest format (content unchanged, format-only)
- Remove all jest packages, configs, the preset and the @nx/jest target default
- Install Playwright Chromium in the CI unit job for the browser suites

Also fixes a brain avatar test that asserted inside a fire-and-forget setTimeout,
which passed vacuously under jsdom and only surfaced once a real browser loaded
the image.
2026-06-13 15:16:45 +01:00

119 lines
2.9 KiB
JavaScript

const nx = require('@nx/eslint-plugin');
module.exports = [
...nx.configs['flat/base'],
...nx.configs['flat/typescript'],
...nx.configs['flat/javascript'],
{
ignores: ['**/dist', '**/vite.config.ts', '**/vite.config.*.timestamp*', '**/vitest.config.*.timestamp*'],
},
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: process.cwd(),
},
},
rules: {
'@nx/enforce-module-boundaries': [
'error',
{
enforceBuildableLibDependency: true,
allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'],
depConstraints: [
{
sourceTag: '*',
onlyDependOnLibsWithTags: ['*'],
},
],
},
],
'@typescript-eslint/no-unused-vars': [
'error',
{
args: 'after-used',
argsIgnorePattern: '^_',
caughtErrors: 'none',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-unused-expressions': 'off',
'@typescript-eslint/prefer-readonly': 'error',
'@typescript-eslint/explicit-member-accessibility': [
'error',
{
overrides: {
accessors: 'explicit',
constructors: 'no-public',
methods: 'off',
properties: 'explicit',
parameterProperties: 'off',
},
},
],
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'classProperty',
modifiers: ['private'],
format: ['camelCase'],
leadingUnderscore: 'require',
},
{
selector: 'classProperty',
modifiers: ['public'],
format: ['camelCase'],
leadingUnderscore: 'forbid',
},
{
selector: 'classProperty',
modifiers: ['protected'],
format: ['camelCase'],
leadingUnderscore: 'require',
},
{
selector: 'variable',
format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
},
],
// this should be enabled when we move to signals
'@nx/workspace-prefer-rxjs-operator-compat': 'error',
'@nx/workspace-component-directive-key-order': 'error',
},
},
{
files: ['**/*.json'],
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: [
'{projectRoot}/eslint.config.{js,cjs,mjs}',
'{projectRoot}/vite.config.{ts,mts}',
'{projectRoot}/**/test-setup.ts',
'{projectRoot}/**/*.spec.ts',
'{projectRoot}/**/*.stories.ts',
],
},
],
},
languageOptions: {
parser: require('jsonc-eslint-parser'),
},
},
{
// Vitest's `importOriginal<typeof import('mod')>()` mock pattern relies on inline `import()`
// type annotations, so allow them in spec files (the rule still enforces type-only imports).
files: ['**/*.spec.ts'],
rules: {
'@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false }],
},
},
];