diff --git a/resources/js/admin/mobile/components/UserMenuSheet.tsx b/resources/js/admin/mobile/components/UserMenuSheet.tsx index 4c69f79b..dd9761bb 100644 --- a/resources/js/admin/mobile/components/UserMenuSheet.tsx +++ b/resources/js/admin/mobile/components/UserMenuSheet.tsx @@ -1,13 +1,8 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { ChevronRight, CreditCard, FileText, HelpCircle, User, X } from 'lucide-react'; -import { XStack, YStack } from '@tamagui/stacks'; -import { SizableText as Text } from '@tamagui/text'; +import { XStack, YStack, SizableText as Text, ListItem, YGroup, Switch, Separator } from 'tamagui'; import { Pressable } from '@tamagui/react-native-web-lite'; -import { ListItem } from '@tamagui/list-item'; -import { YGroup } from '@tamagui/group'; -import { Switch } from '@tamagui/switch'; -import { Separator } from 'tamagui'; import { useAppearance } from '@/hooks/use-appearance'; import { ADMIN_BILLING_PATH, ADMIN_DATA_EXPORTS_PATH, ADMIN_FAQ_PATH, ADMIN_PROFILE_ACCOUNT_PATH, adminPath } from '../../constants'; @@ -23,6 +18,7 @@ type UserMenuSheetProps = { }; const MENU_WIDTH = 320; +const MENU_CLOSED_OFFSET = MENU_WIDTH + 32; export function UserMenuSheet({ open, onClose, user, isMember, navigate }: UserMenuSheetProps) { const { t, i18n } = useTranslation('management'); @@ -84,18 +80,18 @@ export function UserMenuSheet({ open, onClose, user, isMember, navigate }: UserM zIndex={100000} pointerEvents={open ? 'auto' : 'none'} > - diff --git a/resources/js/admin/mobile/components/__tests__/UserMenuSheet.test.tsx b/resources/js/admin/mobile/components/__tests__/UserMenuSheet.test.tsx new file mode 100644 index 00000000..c1fa6114 --- /dev/null +++ b/resources/js/admin/mobile/components/__tests__/UserMenuSheet.test.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { describe, expect, it, vi } from 'vitest'; +import { render } from '@testing-library/react'; + +vi.mock('react-i18next', () => ({ + useTranslation: () => ({ t: (key: string, fallback?: string) => fallback ?? key, i18n: { language: 'en-GB' } }), +})); + +vi.mock('@tamagui/react-native-web-lite', () => ({ + Pressable: ({ children, onPress, ...props }: { children: React.ReactNode; onPress?: () => void }) => ( + + ), +})); + +vi.mock('tamagui', () => { + const Stack = ({ children, ...props }: { children: React.ReactNode }) =>
{children}
; + const Text = ({ children, ...props }: { children: React.ReactNode }) => {children}; + const Switch = ({ children }: { children?: React.ReactNode }) =>
{children}
; + Switch.Thumb = () =>
; + + const ListItem = ({ title, iconAfter, ...props }: { title?: React.ReactNode; iconAfter?: React.ReactNode }) => ( +
+ {title} + {iconAfter} +
+ ); + + const YGroup: any = ({ children }: { children: React.ReactNode }) =>
{children}
; + YGroup.Item = ({ children }: { children: React.ReactNode }) =>
{children}
; + + return { + XStack: Stack, + YStack: Stack, + SizableText: Text, + ListItem, + YGroup, + Switch, + Separator: ({ children }: { children?: React.ReactNode }) =>
{children}
, + }; +}); + +vi.mock('../FormControls', () => ({ + MobileSelect: ({ children }: { children: React.ReactNode }) => , +})); + +vi.mock('@/hooks/use-appearance', () => ({ + useAppearance: () => ({ + appearance: 'system', + resolved: 'light', + updateAppearance: vi.fn(), + }), +})); + +vi.mock('../../theme', () => ({ + useAdminTheme: () => ({ + overlay: 'rgba(0,0,0,0.3)', + surface: '#ffffff', + border: '#e5e7eb', + textStrong: '#111827', + muted: '#6b7280', + surfaceMuted: '#f3f4f6', + accentSoft: '#fef2f2', + primary: '#FF5A5F', + glassShadow: 'rgba(15,23,42,0.14)', + shadow: 'rgba(0,0,0,0.12)', + }), +})); + +import { UserMenuSheet } from '../UserMenuSheet'; + +const baseProps = { + onClose: vi.fn(), + user: { name: 'Ada Lovelace', email: 'ada@example.com' }, + isMember: false, + navigate: vi.fn(), +}; + +describe('UserMenuSheet', () => { + it('slides in when open', () => { + const { getByTestId } = render(); + + expect(getByTestId('user-menu-sheet-panel').style.transform).toBe('translateX(0px)'); + }); + + it('slides out when closed', () => { + const { getByTestId } = render(); + + expect(getByTestId('user-menu-sheet-panel').style.transform).toMatch(/translateX\(\d+px\)/); + }); +});