diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c844038..3cceffc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,9 +1,31 @@ -name: Tests +name: CI on: pull_request: jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Run linter + run: pnpm lint + test: runs-on: ubuntu-latest diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..acd310a --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +pnpm lint +pnpm test diff --git a/eslint.config.js b/eslint.config.js index 6be1776..d7605c1 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -24,7 +24,13 @@ export default defineConfig( '@stylistic/quotes': ['error', 'single', { avoidEscape: true }], '@stylistic/brace-style': ['error', '1tbs', { allowSingleLine: true }], '@stylistic/eol-last': ['error', 'always'], - '@stylistic/no-trailing-spaces': ['error'] + '@stylistic/no-trailing-spaces': ['error'], + '@stylistic/max-len': ['error', { + code: 80, + ignoreUrls: true, + ignoreStrings: true, + ignoreTemplateLiterals: true + }] }, }, { diff --git a/package.json b/package.json index 5d1eb21..0aaabc9 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,39 @@ { - "name": "highcharts-grid-react", - "description": "Monorepo for Highcharts Grid Pro & Lite React libraries.", - "private": true, - "type": "module", - "scripts": { - "test": "vitest run", - "test:watch": "vitest", - "pretest:e2e": "pnpm build", - "test:e2e": "vitest run --config vitest.e2e.config.ts", - "test:all": "pnpm test && pnpm test:e2e", - "check": "pnpm lint && pnpm test", - "build": "pnpm -r --filter './packages/*' run build", - "lint": "pnpm -r --filter './packages/*' run lint", - "clean": "pnpm -r --filter './{packages,examples}/*' run clean && rimraf node_modules", - "release:preflight": "pnpm check && pnpm build", - "release:prepare": "node scripts/release.js", - "release": "pnpm release:preflight && pnpm publish -r --access public" - }, - "packageManager": "pnpm@10.27.0", - "devDependencies": { - "@eslint/js": "^9.39.1", - "@stylistic/eslint-plugin": "^5.6.1", - "@testing-library/react": "^16.3.1", - "@types/node": "^20.0.0", - "@vitest/browser": "^4.0.16", - "@vitest/browser-playwright": "^4.0.16", - "eslint": "^9.39.1", - "globals": "^17.0.0", - "playwright": "^1.57.0", - "rimraf": "^6.1.2", - "typescript": "^5.9.3", - "typescript-eslint": "^8.48.0", - "vitest": "^4.0.16" - } + "name": "highcharts-grid-react", + "description": "Monorepo for Highcharts Grid Pro & Lite React libraries.", + "private": true, + "type": "module", + "scripts": { + "test": "vitest run", + "pretest": "pnpm build", + "test:watch": "vitest", + "pretest:e2e": "pnpm build", + "test:e2e": "vitest run --config vitest.e2e.config.ts", + "test:all": "pnpm test && pnpm test:e2e", + "check": "pnpm lint && pnpm test", + "build": "pnpm -r --filter './packages/*' run build", + "lint": "pnpm -r --filter './packages/*' run lint", + "clean": "pnpm -r --filter './{packages,examples}/*' run clean && rimraf node_modules", + "release:preflight": "pnpm check && pnpm build", + "release:prepare": "node scripts/release.js", + "release": "pnpm release:preflight && pnpm publish -r --access public", + "prepare": "husky" + }, + "packageManager": "pnpm@10.27.0", + "devDependencies": { + "@eslint/js": "^9.39.1", + "@stylistic/eslint-plugin": "^5.6.1", + "@testing-library/react": "^16.3.1", + "@types/node": "^20.0.0", + "@vitest/browser": "^4.0.16", + "@vitest/browser-playwright": "^4.0.16", + "eslint": "^9.39.1", + "globals": "^17.0.0", + "husky": "^9.1.7", + "playwright": "^1.57.0", + "rimraf": "^6.1.2", + "typescript": "^5.9.3", + "typescript-eslint": "^8.48.0", + "vitest": "^4.0.16" + } } diff --git a/packages/grid-lite-react/src/Grid.tsx b/packages/grid-lite-react/src/Grid.tsx index aa47803..44b5643 100644 --- a/packages/grid-lite-react/src/Grid.tsx +++ b/packages/grid-lite-react/src/Grid.tsx @@ -22,7 +22,8 @@ export default function GridLite(props: GridProps) { const { gridRef, children, options, ...gridProps } = props; const childOptions = useMemo(() => getChildProps(children), [children]); const columnKey = useMemo(() => { - const columns = childOptions.columns as Array<{ id?: string }> | undefined; + const columns = childOptions.columns as + Array<{ id?: string }> | undefined; return columns?.map((column) => column.id).join('\0') ?? ''; }, [childOptions]); diff --git a/packages/grid-lite-react/src/__tests__/Grid.test.tsx b/packages/grid-lite-react/tests/Grid.test.tsx similarity index 72% rename from packages/grid-lite-react/src/__tests__/Grid.test.tsx rename to packages/grid-lite-react/tests/Grid.test.tsx index 770322a..140e4eb 100644 --- a/packages/grid-lite-react/src/__tests__/Grid.test.tsx +++ b/packages/grid-lite-react/tests/Grid.test.tsx @@ -1,5 +1,5 @@ -import { createGridTests } from '@highcharts/grid-shared-react/src/test/createGridTests'; -import { Grid, GridOptions } from '../index'; +import { createGridTests } from '@highcharts/grid-shared-react/tests/createGridTests'; +import { Grid, GridOptions } from '../src/index'; createGridTests( 'Grid Lite', diff --git a/packages/grid-pro-react/src/Grid.tsx b/packages/grid-pro-react/src/Grid.tsx index c236cfd..c9e596f 100644 --- a/packages/grid-pro-react/src/Grid.tsx +++ b/packages/grid-pro-react/src/Grid.tsx @@ -22,7 +22,8 @@ export default function GridPro(props: GridProps) { const { gridRef, children, options, ...gridProps } = props; const childOptions = useMemo(() => getChildProps(children), [children]); const columnKey = useMemo(() => { - const columns = childOptions.columns as Array<{ id?: string }> | undefined; + const columns = childOptions.columns as + Array<{ id?: string }> | undefined; return columns?.map((column) => column.id).join('\0') ?? ''; }, [childOptions]); diff --git a/packages/grid-pro-react/src/__tests__/Grid.test.tsx b/packages/grid-pro-react/tests/Grid.test.tsx similarity index 72% rename from packages/grid-pro-react/src/__tests__/Grid.test.tsx rename to packages/grid-pro-react/tests/Grid.test.tsx index e44d6d9..65e49d7 100644 --- a/packages/grid-pro-react/src/__tests__/Grid.test.tsx +++ b/packages/grid-pro-react/tests/Grid.test.tsx @@ -1,5 +1,5 @@ -import { createGridTests } from '@highcharts/grid-shared-react/src/test/createGridTests'; -import { Grid, GridOptions } from '../index'; +import { createGridTests } from '@highcharts/grid-shared-react/tests/createGridTests'; +import { Grid, GridOptions } from '../src/index'; createGridTests( 'Grid Pro', diff --git a/packages/grid-shared-react/src/components/BaseGridOptions.ts b/packages/grid-shared-react/src/components/BaseGridOptions.ts index 9440edc..aabeb10 100644 --- a/packages/grid-shared-react/src/components/BaseGridOptions.ts +++ b/packages/grid-shared-react/src/components/BaseGridOptions.ts @@ -8,7 +8,8 @@ */ /** - * Metadata attached to declarative option components rendered as BaseGrid children. + * Metadata attached to declarative option components + * rendered as BaseGrid children. */ export interface BaseGridOptions { type: 'Grid_Option'; @@ -25,7 +26,8 @@ export interface BaseGridOptions { } /** - * A React component that maps JSX props to a Grid options path via `_GridReact`. + * A React component that maps JSX props to a Grid options path + * via `_GridReact`. */ export interface BaseGridOptionsComponent { _GridReact: BaseGridOptions; diff --git a/packages/grid-shared-react/src/hooks/useGrid.ts b/packages/grid-shared-react/src/hooks/useGrid.ts index c5b752f..f5e1756 100644 --- a/packages/grid-shared-react/src/hooks/useGrid.ts +++ b/packages/grid-shared-react/src/hooks/useGrid.ts @@ -24,7 +24,11 @@ export interface GridInstance { * directly depending on their types. */ export interface GridType { - grid(container: HTMLDivElement, options?: TOptions, async?: boolean): GridInstance | Promise>; + grid( + container: HTMLDivElement, + options?: TOptions, + async?: boolean + ): GridInstance | Promise>; } export interface UseGridOptions { @@ -62,7 +66,8 @@ export function useGrid({ return; } - // StrictMode cleanup runs before re-mount; allow init to complete if re-mounted. + // StrictMode cleanup runs before re-mount; + // allow init to complete if re-mounted. destroyOnInitRef.current = false; // Prevent double initialization @@ -73,21 +78,24 @@ export function useGrid({ const initGrid = async () => { try { - // Use pending options if available (from rapid updates during init) + // Use pending options if available + // (from rapid updates during init) const initOptions = pendingOptionsRef.current ?? options; pendingOptionsRef.current = void 0; const grid = await Grid.grid(container, initOptions, true); if (destroyOnInitRef.current) { - // Component unmounted while we were initializing - destroy immediately + // Component unmounted while initializing - + // destroy immediately grid.destroy(); return; } currGridRef.current = grid; - // Apply any pending options that came in while we were initializing + // Apply pending options that came in + // while we were initializing if (pendingOptionsRef.current !== void 0) { grid.update(pendingOptionsRef.current, true, true); pendingOptionsRef.current = void 0; @@ -122,7 +130,8 @@ export function useGrid({ } if (currGridRef.current) { - // Declarative React options replace the previous snapshot (oneToOne). + // Declarative React options replace the previous + // snapshot (oneToOne). currGridRef.current.update(options, true, true); } else { // Grid still initializing, queue the update diff --git a/packages/grid-shared-react/src/utils/getChildProps.ts b/packages/grid-shared-react/src/utils/getChildProps.ts index cc4880d..bc1c5a6 100644 --- a/packages/grid-shared-react/src/utils/getChildProps.ts +++ b/packages/grid-shared-react/src/utils/getChildProps.ts @@ -59,7 +59,9 @@ function getOptionComponent(type: unknown): BaseGridOptionsComponent | null { return component._GridReact ? type as BaseGridOptionsComponent : null; } -function getChildPropsFromElement(child: ReactElement): Record { +function getChildPropsFromElement( + child: ReactElement +): Record { return (child.props ?? {}) as Record; } @@ -87,7 +89,8 @@ function flattenChildren(childNodes: ReactNode): ReactNode[] { } if (isReactElement(childNodes) && childNodes.type === Fragment) { - return flattenChildren((childNodes.props as { children?: ReactNode }).children); + const fragmentProps = childNodes.props as { children?: ReactNode }; + return flattenChildren(fragmentProps.children); } return [childNodes]; @@ -115,7 +118,15 @@ function getEffectiveMeta( } function parseColumnElement(child: ReactElement): Record { - const { children: _ignored, columnId, id: _cssId, ...props } = getChildPropsFromElement(child); + const { + children, + id, + columnId, + ...props + } = getChildPropsFromElement(child); + void children; + void id; + const options = normalizeColumnOptions(props); // columnId selects the column; Core expects the same value as `id`. @@ -178,7 +189,10 @@ export function getChildProps(children: ReactNode): Record { } } - function handleChild(child: ReactElement, parentMeta?: BaseGridOptions): void { + function handleChild( + child: ReactElement, + parentMeta?: BaseGridOptions + ): void { const component = getOptionComponent(child.type); if (!component) { @@ -206,18 +220,17 @@ export function getChildProps(children: ReactNode): Record { if (meta.gridOption === 'pagination') { const pagination = normalizePaginationOptions(props); - pagination.position = isTopPaginationChild(child, resolvedChildren) ? - 'top' : - 'bottom'; + pagination.position = isTopPaginationChild( + child, + resolvedChildren + ) ? 'top' : 'bottom'; optionsFromChildren.pagination = pagination; return; } if (meta.gridOption === 'header') { - const { header, children: _ignored } = props; - - if (header !== void 0) { - optionsFromChildren.header = header; + if (props.header !== void 0) { + optionsFromChildren.header = props.header; } return; } @@ -226,7 +239,9 @@ export function getChildProps(children: ReactNode): Record { optionsFromChildren[meta.gridOption] = meta.isArrayType ? [] : {} ); const parentIsArray = Array.isArray(optionParent); - const insertInto = parentIsArray ? {} : optionParent as Record; + const insertInto = parentIsArray + ? {} + : optionParent as Record; if (meta.defaultOptions) { Object.assign(insertInto, meta.defaultOptions); @@ -243,7 +258,10 @@ export function getChildProps(children: ReactNode): Record { } if (parentIsArray) { - (optionsFromChildren[meta.gridOption] as unknown[]).push(insertInto); + const optionItems = optionsFromChildren[ + meta.gridOption + ] as unknown[]; + optionItems.push(insertInto); } } @@ -258,7 +276,8 @@ export function getChildProps(children: ReactNode): Record { /** * When declarative `` components are present, only those columns - * should render unless `data.autogenerateColumns` is set explicitly on ``. + * should render unless `data.autogenerateColumns` is set + * explicitly on ``. */ function applyDeclarativeColumnDefaults( optionsFromChildren: Record @@ -291,7 +310,11 @@ function isTopPaginationChild( return children .slice(0, childIndex) - .every((candidate) => getOptionComponent(candidate.type)?._GridReact.gridOption === 'pagination'); + .every((candidate) => { + const gridOption = getOptionComponent(candidate.type) + ?._GridReact.gridOption; + return gridOption === 'pagination'; + }); } function isOptionElement(child: ReactElement): boolean { @@ -313,9 +336,10 @@ function resolveOptionChild(child: ReactNode): ReactElement | null { return null; } - const rendered = (child.type as (props: Record) => ReactNode)( - getChildPropsFromElement(child) - ); + const renderChild = child.type as ( + props: Record + ) => ReactNode; + const rendered = renderChild(getChildPropsFromElement(child)); if (isReactElement(rendered) && getOptionComponent(rendered.type)) { return rendered; diff --git a/packages/grid-shared-react/src/utils/mappers/mapPrefixedProps.ts b/packages/grid-shared-react/src/utils/mappers/mapPrefixedProps.ts index 9fdd271..82418e3 100644 --- a/packages/grid-shared-react/src/utils/mappers/mapPrefixedProps.ts +++ b/packages/grid-shared-react/src/utils/mappers/mapPrefixedProps.ts @@ -27,11 +27,15 @@ export function mapPrefixedProps( ): Record { const result = { ...props }; const groups: Record> = {}; - const prefixes = Object.keys(prefixToGroup).sort((a, b) => b.length - a.length); + const prefixes = Object.keys(prefixToGroup) + .sort((a, b) => b.length - a.length); for (const flatKey of Object.keys(result)) { const prefix = prefixes.find( - (candidate) => flatKey.startsWith(candidate) && flatKey.length > candidate.length + (candidate) => ( + flatKey.startsWith(candidate) + && flatKey.length > candidate.length + ) ); if (!prefix) { diff --git a/packages/grid-shared-react/src/test/createGridTests.tsx b/packages/grid-shared-react/tests/createGridTests.tsx similarity index 95% rename from packages/grid-shared-react/src/test/createGridTests.tsx rename to packages/grid-shared-react/tests/createGridTests.tsx index 1faed12..acf05db 100644 --- a/packages/grid-shared-react/src/test/createGridTests.tsx +++ b/packages/grid-shared-react/tests/createGridTests.tsx @@ -5,12 +5,13 @@ import { type ComponentType } from 'react'; import { describe, it, expect, vi } from 'vitest'; -import { GridProps, GridRefHandle } from '../components/BaseGrid'; -import { GridInstance } from '../hooks/useGrid'; +import { GridProps, GridRefHandle } from '../src/components/BaseGrid'; +import { GridInstance } from '../src/hooks/useGrid'; /** * Creates a standard test suite for a Grid component. - * Use this to avoid duplicating tests between grid-lite-react and grid-pro-react. + * Use this to avoid duplicating tests between + * grid-lite-react and grid-pro-react. */ export function createGridTests( name: string, diff --git a/packages/grid-shared-react/tests/options/Caption.test.tsx b/packages/grid-shared-react/tests/options/Caption.test.tsx new file mode 100644 index 0000000..832944e --- /dev/null +++ b/packages/grid-shared-react/tests/options/Caption.test.tsx @@ -0,0 +1,21 @@ +import { describe, it, expect } from 'vitest'; +import { Caption } from '../../src/components/options/caption/Caption'; +import { getChildProps } from '../../src/utils/getChildProps'; + +describe('Caption', () => { + it('maps caption props and children into options.caption', () => { + expect( + getChildProps( + + Sales table + + ) + ).toEqual({ + caption: { + className: 'grid-caption', + htmlTag: 'h2', + text: 'Sales table' + } + }); + }); +}); diff --git a/packages/grid-shared-react/tests/options/Column.test.tsx b/packages/grid-shared-react/tests/options/Column.test.tsx new file mode 100644 index 0000000..f52c073 --- /dev/null +++ b/packages/grid-shared-react/tests/options/Column.test.tsx @@ -0,0 +1,54 @@ +import { describe, it, expect } from 'vitest'; +import { Column } from '../../src/components/options/columns/Column'; +import { getChildProps } from '../../src/utils/getChildProps'; + +describe('Column', () => { + it('maps column props into options.columns', () => { + expect( + getChildProps( + + ) + ).toEqual({ + columns: [{ + width: 120, + sorting: { + enabled: true, + order: 'asc' + }, + header: { + format: '{value} USD' + }, + id: 'price' + }], + data: { + autogenerateColumns: false + } + }); + }); + + it('maps multiple columns into options.columns array', () => { + expect( + getChildProps( + <> + + + + ) + ).toEqual({ + columns: [ + { width: 200, id: 'product' }, + { width: 120, id: 'price' } + ], + data: { + autogenerateColumns: false + } + }); + }); +}); diff --git a/packages/grid-shared-react/tests/options/ColumnDefaults.test.tsx b/packages/grid-shared-react/tests/options/ColumnDefaults.test.tsx new file mode 100644 index 0000000..1a43555 --- /dev/null +++ b/packages/grid-shared-react/tests/options/ColumnDefaults.test.tsx @@ -0,0 +1,27 @@ +import { describe, it, expect } from 'vitest'; +import { ColumnDefaults } from '../../src/components/options/columns/ColumnDefaults'; +import { getChildProps } from '../../src/utils/getChildProps'; + +describe('ColumnDefaults', () => { + it('maps column defaults props into options.columnDefaults', () => { + expect( + getChildProps( + + ) + ).toEqual({ + columnDefaults: { + width: 160, + sorting: { + enabled: true + }, + cells: { + format: '{value}' + } + } + }); + }); +}); diff --git a/packages/grid-shared-react/tests/options/Data.test.tsx b/packages/grid-shared-react/tests/options/Data.test.tsx new file mode 100644 index 0000000..a6f165a --- /dev/null +++ b/packages/grid-shared-react/tests/options/Data.test.tsx @@ -0,0 +1,38 @@ +import { describe, it, expect } from 'vitest'; +import { Data } from '../../src/components/options/data/Data'; +import { getChildProps } from '../../src/utils/getChildProps'; + +describe('Data', () => { + it('maps columns to options.data.columns', () => { + const columns = { + product: ['Apples', 'Oranges'], + price: [1.2, 2.4] + }; + + expect( + getChildProps( + + ) + ).toEqual({ + data: { + columns, + providerType: 'local', + autogenerateColumns: true + } + }); + }); + + it('maps dataTable to options.data.dataTable', () => { + const dataTable = { id: 'table-1', rows: [] }; + + expect(getChildProps()).toEqual({ + data: { + dataTable + } + }); + }); +}); diff --git a/packages/grid-shared-react/tests/options/Description.test.tsx b/packages/grid-shared-react/tests/options/Description.test.tsx new file mode 100644 index 0000000..145a800 --- /dev/null +++ b/packages/grid-shared-react/tests/options/Description.test.tsx @@ -0,0 +1,20 @@ +import { describe, it, expect } from 'vitest'; +import { Description } from '../../src/components/options/description/Description'; +import { getChildProps } from '../../src/utils/getChildProps'; + +describe('Description', () => { + it('maps description props and children into options.description', () => { + expect( + getChildProps( + + Monthly sales overview + + ) + ).toEqual({ + description: { + className: 'grid-description', + text: 'Monthly sales overview' + } + }); + }); +}); diff --git a/packages/grid-shared-react/tests/options/Header.test.tsx b/packages/grid-shared-react/tests/options/Header.test.tsx new file mode 100644 index 0000000..58fa656 --- /dev/null +++ b/packages/grid-shared-react/tests/options/Header.test.tsx @@ -0,0 +1,13 @@ +import { describe, it, expect } from 'vitest'; +import { Header } from '../../src/components/options/header/Header'; +import { getChildProps } from '../../src/utils/getChildProps'; + +describe('Header', () => { + it('maps header prop to options.header', () => { + const header = ['product', { columnId: 'price', format: '{value} USD' }]; + + expect(getChildProps(
)).toEqual({ + header + }); + }); +}); diff --git a/packages/grid-shared-react/tests/options/Pagination.test.tsx b/packages/grid-shared-react/tests/options/Pagination.test.tsx new file mode 100644 index 0000000..1608d8d --- /dev/null +++ b/packages/grid-shared-react/tests/options/Pagination.test.tsx @@ -0,0 +1,63 @@ +import { describe, it, expect } from 'vitest'; +import { Data } from '../../src/components/options/data/Data'; +import { Pagination } from '../../src/components/options/pagination/Pagination'; +import { getChildProps } from '../../src/utils/getChildProps'; + +describe('Pagination', () => { + it('normalizes pagination props into options.pagination', () => { + expect( + getChildProps( + + ) + ).toEqual({ + pagination: { + enabled: false, + page: 2, + pageSize: 25, + align: 'center', + position: 'top', + controls: { + pageInfo: true, + pageSizeSelector: { + enabled: true, + options: [10, 25, 50] + }, + pageButtons: { + enabled: true, + count: 5 + }, + firstLastButtons: true, + previousNextButtons: false + } + } + }); + }); + + it('sets position to top for the first pagination and bottom after other options', () => { + const top = getChildProps( + <> + + + + ); + const bottom = getChildProps( + <> + + + + ); + + expect(top.pagination).toMatchObject({ position: 'top' }); + expect(bottom.pagination).toMatchObject({ position: 'bottom' }); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ff81d18..648ccc3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,9 @@ importers: globals: specifier: ^17.0.0 version: 17.0.0 + husky: + specifier: ^9.1.7 + version: 9.1.7 playwright: specifier: ^1.57.0 version: 1.57.0 @@ -1532,6 +1535,11 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} + engines: {node: '>=18'} + hasBin: true + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -3282,6 +3290,8 @@ snapshots: - supports-color optional: true + husky@9.1.7: {} + ignore@5.3.2: {} ignore@7.0.5: {} diff --git a/vitest.config.ts b/vitest.config.ts index 8ad4fee..e23f4e9 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,7 +3,10 @@ import { playwright } from '@vitest/browser-playwright'; export default defineConfig({ test: { - include: ['packages/*/src/**/*.test.{ts,tsx}'], + include: [ + 'packages/*/src/**/*.test.{ts,tsx}', + 'packages/*/tests/**/*.test.{ts,tsx}' + ], globals: true, css: true, browser: {