Added tests
This commit is contained in:
parent
9c11b609dc
commit
f058336597
@ -32,7 +32,7 @@ npm install @warkypublic/oranguru
|
||||
This package requires the following peer dependencies:
|
||||
|
||||
```bash
|
||||
npm install react@">= 19.0.0" zustand@">= 5.0.0" @mantine/core@"^8.3.1" @mantine/hooks@"^8.3.1" @warkypublic/artemis-kit@"^1.0.10" @warkypublic/zustandsyncstore@"^0.0.2" use-sync-external-store@">= 1.4.0"
|
||||
npm install react@">= 19.0.0" zustand@">= 5.0.0" @mantine/core@"^8.3.1" @mantine/hooks@"^8.3.1" @warkypublic/artemis-kit@"^1.0.10" @warkypublic/zustandsyncstore@"^0.0.4" use-sync-external-store@">= 1.4.0"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
@ -7,11 +7,12 @@ import reactHooks from 'eslint-plugin-react-hooks';
|
||||
import reactRefresh from 'eslint-plugin-react-refresh';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import perfectionist from 'eslint-plugin-perfectionist';
|
||||
import { globalIgnores } from 'eslint/config';
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
ignores: ['dist'],
|
||||
},
|
||||
[
|
||||
globalIgnores(['dist']),
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
extends: [
|
||||
|
||||
11
package.json
11
package.json
@ -8,6 +8,10 @@
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint ./src",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "vitest",
|
||||
"test:run": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"test:ui": "vitest --ui",
|
||||
"clean": "rm -rf node_modules && rm -rf dist ",
|
||||
"preview": "vite preview",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
@ -57,6 +61,9 @@
|
||||
"@changesets/cli": "^2.29.7",
|
||||
"@eslint/js": "^9.35.0",
|
||||
"@storybook/react-vite": "^9.1.7",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
"@types/node": "^24.4.0",
|
||||
"@types/react": "^19.1.13",
|
||||
"@types/react-dom": "^19.1.9",
|
||||
@ -70,6 +77,7 @@
|
||||
"eslint-plugin-storybook": "^9.1.7",
|
||||
"global": "^4.4.0",
|
||||
"globals": "^16.4.0",
|
||||
"jsdom": "^27.0.0",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-eslint": "^16.4.2",
|
||||
"react-dom": "^19.1.1",
|
||||
@ -78,7 +86,8 @@
|
||||
"typescript-eslint": "^8.43.0",
|
||||
"vite": "^7.1.5",
|
||||
"vite-plugin-dts": "^4.5.4",
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
"vite-tsconfig-paths": "^5.1.4",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mantine/core": "^8.3.1",
|
||||
|
||||
564
pnpm-lock.yaml
564
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
91
src/Gridler/Gridler.test.tsx
Normal file
91
src/Gridler/Gridler.test.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
import { MantineProvider } from '@mantine/core'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { Gridler } from './Gridler'
|
||||
|
||||
// Mock the complex sub-components
|
||||
vi.mock('./GridlerDataGrid', () => ({
|
||||
GridlerDataGrid: () => <div data-testid="gridler-data-grid">Data Grid</div>
|
||||
}))
|
||||
|
||||
vi.mock('../MantineBetterMenu', () => ({
|
||||
MantineBetterMenusProvider: ({ children }: { children: React.ReactNode }) => (
|
||||
<div data-testid="menu-provider">{children}</div>
|
||||
)
|
||||
}))
|
||||
|
||||
// Mock the Store Provider
|
||||
vi.mock('./components/Store', () => ({
|
||||
Provider: ({ children, uniqueid }: { children: React.ReactNode; uniqueid: string }) => (
|
||||
<div data-testid={`store-provider-${uniqueid}`}>{children}</div>
|
||||
)
|
||||
}))
|
||||
|
||||
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<MantineProvider>
|
||||
{children}
|
||||
</MantineProvider>
|
||||
)
|
||||
|
||||
describe('Gridler', () => {
|
||||
const defaultProps = {
|
||||
cols: [
|
||||
{ key: 'id', title: 'ID' },
|
||||
{ key: 'name', title: 'Name' }
|
||||
],
|
||||
uniqueid: 'test-grid'
|
||||
}
|
||||
|
||||
it('renders without crashing', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<Gridler {...defaultProps} />
|
||||
</TestWrapper>
|
||||
)
|
||||
|
||||
expect(screen.getByTestId('gridler-data-grid')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('wraps content with MantineBetterMenusProvider', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<Gridler {...defaultProps} />
|
||||
</TestWrapper>
|
||||
)
|
||||
|
||||
expect(screen.getByTestId('menu-provider')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('creates store provider with unique ID', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<Gridler {...defaultProps} />
|
||||
</TestWrapper>
|
||||
)
|
||||
|
||||
expect(screen.getByTestId('store-provider-test-grid')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders children when provided', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<Gridler {...defaultProps}>
|
||||
<div data-testid="test-child">Custom Child</div>
|
||||
</Gridler>
|
||||
</TestWrapper>
|
||||
)
|
||||
|
||||
expect(screen.getByTestId('test-child')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('handles different uniqueid prop', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<Gridler {...defaultProps} uniqueid="different-grid" />
|
||||
</TestWrapper>
|
||||
)
|
||||
|
||||
expect(screen.getByTestId('store-provider-different-grid')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
51
src/Gridler/utils/range.test.ts
Normal file
51
src/Gridler/utils/range.test.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { range } from './range'
|
||||
|
||||
describe('range utility', () => {
|
||||
describe('single argument (end only)', () => {
|
||||
it('creates range from 0 to n-1', () => {
|
||||
expect(range(5)).toEqual([0, 1, 2, 3, 4])
|
||||
})
|
||||
|
||||
it('handles zero', () => {
|
||||
expect(range(0)).toEqual([])
|
||||
})
|
||||
|
||||
it('handles one', () => {
|
||||
expect(range(1)).toEqual([0])
|
||||
})
|
||||
|
||||
it('handles negative numbers', () => {
|
||||
expect(range(-5)).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('two arguments (start, end)', () => {
|
||||
it('creates range from start to end-1', () => {
|
||||
expect(range(2, 7)).toEqual([2, 3, 4, 5, 6])
|
||||
})
|
||||
|
||||
it('handles start equal to end', () => {
|
||||
expect(range(5, 5)).toEqual([])
|
||||
})
|
||||
|
||||
it('handles start greater than end', () => {
|
||||
expect(range(7, 2)).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('three arguments (start, end, step)', () => {
|
||||
it('creates range with positive step', () => {
|
||||
expect(range(0, 10, 2)).toEqual([0, 2, 4, 6, 8])
|
||||
})
|
||||
|
||||
it('creates range with negative step', () => {
|
||||
expect(range(10, 0, -2)).toEqual([10, 8, 6, 4, 2])
|
||||
})
|
||||
|
||||
it('throws error for zero step', () => {
|
||||
expect(() => range(0, 10, 0)).toThrow('Step cannot be zero')
|
||||
})
|
||||
})
|
||||
})
|
||||
55
src/MantineBetterMenu/MantineBetterMenu.test.tsx
Normal file
55
src/MantineBetterMenu/MantineBetterMenu.test.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import { MantineProvider } from '@mantine/core'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { MantineBetterMenusProvider } from './MantineBetterMenu'
|
||||
|
||||
// Mock the MenuRenderer component since it likely has complex portal logic
|
||||
vi.mock('./MenuRenderer', () => ({
|
||||
MenuRenderer: () => <div data-testid="menu-renderer">Menu Renderer</div>
|
||||
}))
|
||||
|
||||
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<MantineProvider>
|
||||
{children}
|
||||
</MantineProvider>
|
||||
)
|
||||
|
||||
describe('MantineBetterMenusProvider', () => {
|
||||
it('renders children correctly', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<MantineBetterMenusProvider>
|
||||
<div data-testid="test-child">Test Child</div>
|
||||
</MantineBetterMenusProvider>
|
||||
</TestWrapper>
|
||||
)
|
||||
|
||||
expect(screen.getByTestId('test-child')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders MenuRenderer component', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<MantineBetterMenusProvider>
|
||||
<div>Test</div>
|
||||
</MantineBetterMenusProvider>
|
||||
</TestWrapper>
|
||||
)
|
||||
|
||||
expect(screen.getByTestId('menu-renderer')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('accepts providerID prop', () => {
|
||||
render(
|
||||
<TestWrapper>
|
||||
<MantineBetterMenusProvider providerID="test-provider">
|
||||
<div>Test</div>
|
||||
</MantineBetterMenusProvider>
|
||||
</TestWrapper>
|
||||
)
|
||||
|
||||
// Component should render without errors
|
||||
expect(screen.getByTestId('menu-renderer')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
100
src/MantineBetterMenu/Store.test.tsx
Normal file
100
src/MantineBetterMenu/Store.test.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import { act, renderHook } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it } from 'vitest'
|
||||
|
||||
import { MantineBetterMenusStoreProvider, useMantineBetterMenus } from './Store'
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('@warkypublic/artemis-kit', () => ({
|
||||
getUUID: () => 'test-uuid-123'
|
||||
}))
|
||||
|
||||
const createWrapper = () => {
|
||||
return ({ children }: { children: React.ReactNode }) => (
|
||||
<MantineBetterMenusStoreProvider>
|
||||
{children}
|
||||
</MantineBetterMenusStoreProvider>
|
||||
)
|
||||
}
|
||||
|
||||
describe('MantineBetterMenus Store', () => {
|
||||
let wrapper: ReturnType<typeof createWrapper>
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = createWrapper()
|
||||
})
|
||||
|
||||
it('initializes with empty menus array', () => {
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper })
|
||||
|
||||
expect(result.current.menus).toEqual([])
|
||||
})
|
||||
|
||||
it('can show a menu', () => {
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper })
|
||||
|
||||
act(() => {
|
||||
result.current.show('test-menu', {
|
||||
items: [{ label: 'Test Item' }],
|
||||
x: 100,
|
||||
y: 200
|
||||
})
|
||||
})
|
||||
|
||||
expect(result.current.menus).toHaveLength(1)
|
||||
expect(result.current.menus[0]).toMatchObject({
|
||||
id: 'test-menu',
|
||||
items: [{ label: 'Test Item' }],
|
||||
visible: true,
|
||||
x: 100,
|
||||
y: 200
|
||||
})
|
||||
})
|
||||
|
||||
it('can hide a menu', () => {
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper })
|
||||
|
||||
// First show a menu
|
||||
act(() => {
|
||||
result.current.show('test-menu', { x: 100, y: 200 })
|
||||
})
|
||||
|
||||
expect(result.current.menus[0].visible).toBe(true)
|
||||
|
||||
// Then hide it
|
||||
act(() => {
|
||||
result.current.hide('test-menu')
|
||||
})
|
||||
|
||||
expect(result.current.menus[0].visible).toBe(false)
|
||||
})
|
||||
|
||||
it('can update instance state', () => {
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper })
|
||||
|
||||
// Show a menu
|
||||
act(() => {
|
||||
result.current.show('test-menu', { x: 100, y: 200 })
|
||||
})
|
||||
|
||||
// Update its position
|
||||
act(() => {
|
||||
result.current.setInstanceState('test-menu', 'x', 300)
|
||||
})
|
||||
|
||||
expect(result.current.menus[0].x).toBe(300)
|
||||
expect(result.current.menus[0].y).toBe(200) // Should remain unchanged
|
||||
})
|
||||
|
||||
it('handles multiple menus', () => {
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper })
|
||||
|
||||
act(() => {
|
||||
result.current.show('menu-1', { x: 100, y: 200 })
|
||||
result.current.show('menu-2', { x: 300, y: 400 })
|
||||
})
|
||||
|
||||
expect(result.current.menus).toHaveLength(2)
|
||||
expect(result.current.menus.find(m => m.id === 'menu-1')).toBeDefined()
|
||||
expect(result.current.menus.find(m => m.id === 'menu-2')).toBeDefined()
|
||||
})
|
||||
})
|
||||
30
src/test/setup.ts
Normal file
30
src/test/setup.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import '@testing-library/jest-dom'
|
||||
|
||||
// Mock window.matchMedia for Mantine components
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
value: vi.fn().mockImplementation(query => ({
|
||||
addEventListener: vi.fn(),
|
||||
addListener: vi.fn(), // deprecated
|
||||
dispatchEvent: vi.fn(),
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
removeEventListener: vi.fn(),
|
||||
removeListener: vi.fn(), // deprecated
|
||||
})),
|
||||
writable: true,
|
||||
})
|
||||
|
||||
// Mock ResizeObserver
|
||||
global.ResizeObserver = vi.fn().mockImplementation(() => ({
|
||||
disconnect: vi.fn(),
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
}))
|
||||
|
||||
// Mock IntersectionObserver
|
||||
global.IntersectionObserver = vi.fn().mockImplementation(() => ({
|
||||
disconnect: vi.fn(),
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
}))
|
||||
12
vitest.config.ts
Normal file
12
vitest.config.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import react from '@vitejs/plugin-react-swc'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
setupFiles: ['./src/test/setup.ts'],
|
||||
globals: true,
|
||||
css: true,
|
||||
},
|
||||
})
|
||||
Loading…
Reference in New Issue
Block a user