A lot of refectoring
This commit is contained in:
@@ -1,19 +1,17 @@
|
||||
import { MantineProvider } from '@mantine/core'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { MantineBetterMenusProvider } from './MantineBetterMenu'
|
||||
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>
|
||||
}))
|
||||
MenuRenderer: () => <div data-testid="menu-renderer">Menu Renderer</div>,
|
||||
}));
|
||||
|
||||
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<MantineProvider>
|
||||
{children}
|
||||
</MantineProvider>
|
||||
)
|
||||
<MantineProvider>{children}</MantineProvider>
|
||||
);
|
||||
|
||||
describe('MantineBetterMenusProvider', () => {
|
||||
it('renders children correctly', () => {
|
||||
@@ -23,10 +21,10 @@ describe('MantineBetterMenusProvider', () => {
|
||||
<div data-testid="test-child">Test Child</div>
|
||||
</MantineBetterMenusProvider>
|
||||
</TestWrapper>
|
||||
)
|
||||
);
|
||||
|
||||
expect(screen.getByTestId('test-child')).toBeInTheDocument()
|
||||
})
|
||||
expect(screen.getByTestId('test-child')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders MenuRenderer component', () => {
|
||||
render(
|
||||
@@ -35,10 +33,10 @@ describe('MantineBetterMenusProvider', () => {
|
||||
<div>Test</div>
|
||||
</MantineBetterMenusProvider>
|
||||
</TestWrapper>
|
||||
)
|
||||
);
|
||||
|
||||
expect(screen.getByTestId('menu-renderer')).toBeInTheDocument()
|
||||
})
|
||||
expect(screen.getByTestId('menu-renderer')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('accepts providerID prop', () => {
|
||||
render(
|
||||
@@ -47,9 +45,9 @@ describe('MantineBetterMenusProvider', () => {
|
||||
<div>Test</div>
|
||||
</MantineBetterMenusProvider>
|
||||
</TestWrapper>
|
||||
)
|
||||
);
|
||||
|
||||
// Component should render without errors
|
||||
expect(screen.getByTestId('menu-renderer')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
expect(screen.getByTestId('menu-renderer')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { MenuRenderer } from './MenuRenderer';
|
||||
import { MantineBetterMenusStoreProvider, type MenuStoreProps } from './Store';
|
||||
import { MantineBetterMenusStoreProvider, type MantineBetterMenuStoreProps } from './Store';
|
||||
|
||||
export function MantineBetterMenusProvider(props: React.PropsWithChildren<MenuStoreProps>) {
|
||||
export function MantineBetterMenusProvider(
|
||||
props: React.PropsWithChildren<MantineBetterMenuStoreProps>
|
||||
) {
|
||||
return (
|
||||
<MantineBetterMenusStoreProvider {...props}>
|
||||
<MenuRenderer />
|
||||
|
||||
@@ -1,100 +1,98 @@
|
||||
import { act, renderHook } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it } from 'vitest'
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { MantineBetterMenusStoreProvider, useMantineBetterMenus } from './Store'
|
||||
import { MantineBetterMenusStoreProvider, useMantineBetterMenus } from './Store';
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('@warkypublic/artemis-kit', () => ({
|
||||
getUUID: () => 'test-uuid-123'
|
||||
}))
|
||||
getUUID: () => 'test-uuid-123',
|
||||
}));
|
||||
|
||||
const createWrapper = () => {
|
||||
return ({ children }: { children: React.ReactNode }) => (
|
||||
<MantineBetterMenusStoreProvider>
|
||||
{children}
|
||||
</MantineBetterMenusStoreProvider>
|
||||
)
|
||||
}
|
||||
<MantineBetterMenusStoreProvider>{children}</MantineBetterMenusStoreProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe('MantineBetterMenus Store', () => {
|
||||
let wrapper: ReturnType<typeof createWrapper>
|
||||
let wrapper: ReturnType<typeof createWrapper>;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = createWrapper()
|
||||
})
|
||||
wrapper = createWrapper();
|
||||
});
|
||||
|
||||
it('initializes with empty menus array', () => {
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper })
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper });
|
||||
|
||||
expect(result.current.menus).toEqual([])
|
||||
})
|
||||
expect(result.current.menus).toEqual([]);
|
||||
});
|
||||
|
||||
it('can show a menu', () => {
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper })
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper });
|
||||
|
||||
act(() => {
|
||||
result.current.show('test-menu', {
|
||||
items: [{ label: 'Test Item' }],
|
||||
x: 100,
|
||||
y: 200
|
||||
})
|
||||
})
|
||||
y: 200,
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.menus).toHaveLength(1)
|
||||
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
|
||||
})
|
||||
})
|
||||
y: 200,
|
||||
});
|
||||
});
|
||||
|
||||
it('can hide a menu', () => {
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper })
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper });
|
||||
|
||||
// First show a menu
|
||||
act(() => {
|
||||
result.current.show('test-menu', { x: 100, y: 200 })
|
||||
})
|
||||
result.current.show('test-menu', { x: 100, y: 200 });
|
||||
});
|
||||
|
||||
expect(result.current.menus[0].visible).toBe(true)
|
||||
expect(result.current.menus[0].visible).toBe(true);
|
||||
|
||||
// Then hide it
|
||||
act(() => {
|
||||
result.current.hide('test-menu')
|
||||
})
|
||||
result.current.hide('test-menu');
|
||||
});
|
||||
|
||||
expect(result.current.menus[0].visible).toBe(false)
|
||||
})
|
||||
expect(result.current.menus[0].visible).toBe(false);
|
||||
});
|
||||
|
||||
it('can update instance state', () => {
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper })
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper });
|
||||
|
||||
// Show a menu
|
||||
act(() => {
|
||||
result.current.show('test-menu', { x: 100, y: 200 })
|
||||
})
|
||||
result.current.show('test-menu', { x: 100, y: 200 });
|
||||
});
|
||||
|
||||
// Update its position
|
||||
act(() => {
|
||||
result.current.setInstanceState('test-menu', 'x', 300)
|
||||
})
|
||||
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
|
||||
})
|
||||
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 })
|
||||
const { result } = renderHook(() => useMantineBetterMenus(), { wrapper });
|
||||
|
||||
act(() => {
|
||||
result.current.show('menu-1', { x: 100, y: 200 })
|
||||
result.current.show('menu-2', { x: 300, y: 400 })
|
||||
})
|
||||
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()
|
||||
})
|
||||
})
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,15 +28,16 @@ export interface MantineBetterMenuInstanceItem extends Partial<MenuItemProps> {
|
||||
| ReactNode;
|
||||
}
|
||||
|
||||
export interface MenuStoreProps {
|
||||
export interface MantineBetterMenuStoreProps {
|
||||
menus?: Array<MantineBetterMenuInstance>;
|
||||
providerID?: string;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
export type MenuStoreState = MenuStoreProps & MenuStoreStateOnly;
|
||||
export type MantineBetterMenuStoreState = MantineBetterMenuStoreProps &
|
||||
MantineBetterMenuStoreStateOnly;
|
||||
|
||||
export interface MenuStoreStateOnly {
|
||||
export interface MantineBetterMenuStoreStateOnly {
|
||||
hide: (id: string) => void;
|
||||
menus: Array<MantineBetterMenuInstance>;
|
||||
setInstanceState: <K extends keyof MantineBetterMenuInstance>(
|
||||
@@ -44,12 +45,15 @@ export interface MenuStoreStateOnly {
|
||||
key: K,
|
||||
value: MantineBetterMenuInstance[K]
|
||||
) => void;
|
||||
setState: <K extends keyof MenuStoreState>(key: K, value: Partial<MenuStoreState[K]>) => void;
|
||||
setState: <K extends keyof MantineBetterMenuStoreState>(
|
||||
key: K,
|
||||
value: Partial<MantineBetterMenuStoreState[K]>
|
||||
) => void;
|
||||
show: (id: string, options?: Partial<MantineBetterMenuInstance>) => void;
|
||||
}
|
||||
|
||||
const { Provider: MantineBetterMenusStoreProvider, useStore: useMantineBetterMenus } =
|
||||
createSyncStore<MenuStoreState, MenuStoreProps>(
|
||||
createSyncStore<MantineBetterMenuStoreState, MantineBetterMenuStoreProps>(
|
||||
(set, get) => ({
|
||||
hide: (id: string) => {
|
||||
const s = get();
|
||||
@@ -59,7 +63,7 @@ const { Provider: MantineBetterMenusStoreProvider, useStore: useMantineBetterMen
|
||||
setInstanceState: (id, key, value) => {
|
||||
//@ts-expect-error Type instantiation is excessively deep and possibly infinite.
|
||||
set(
|
||||
produce((state: MenuStoreState) => {
|
||||
produce((state: MantineBetterMenuStoreState) => {
|
||||
const idx = state?.menus?.findIndex((m: MantineBetterMenuInstance) => m.id === id);
|
||||
if (idx >= 0) {
|
||||
state.menus[idx][key] = value;
|
||||
@@ -89,7 +93,7 @@ const { Provider: MantineBetterMenusStoreProvider, useStore: useMantineBetterMen
|
||||
s.setState('menus', [...s.menus, menu as MantineBetterMenuInstance]);
|
||||
} else {
|
||||
set(
|
||||
produce((state: MenuStoreState) => {
|
||||
produce((state: MantineBetterMenuStoreState) => {
|
||||
if (!state.menus) {
|
||||
state.menus = [];
|
||||
}
|
||||
|
||||
@@ -3,5 +3,5 @@ export { useMantineBetterMenus } from './Store';
|
||||
export type {
|
||||
MantineBetterMenuInstance,
|
||||
MantineBetterMenuInstanceItem,
|
||||
MenuStoreState
|
||||
MantineBetterMenuStoreState
|
||||
} from './Store';
|
||||
|
||||
Reference in New Issue
Block a user