diff --git a/frontend/src/components/__tests__/auth-guard.test.tsx b/frontend/src/components/__tests__/auth-guard.test.tsx
index 5e64318..9de0101 100644
--- a/frontend/src/components/__tests__/auth-guard.test.tsx
+++ b/frontend/src/components/__tests__/auth-guard.test.tsx
@@ -22,28 +22,28 @@ describe('AuthGuard', () => {
beforeEach(() => {
vi.clearAllMocks();
- vi.mocked(useRouter).mockReturnValue({ push: mockPush } as any);
+ (useRouter as any).mockReturnValue({ push: mockPush } as any);
});
it('renders loading state when session is loading', () => {
- vi.mocked(useSession).mockReturnValue({ data: null, status: 'loading' } as any);
- vi.mocked(useTenant).mockReturnValue({ activeClubId: null, clubs: [], setActiveClub: vi.fn(), userRole: null });
+ (useSession as any).mockReturnValue({ data: null, status: 'loading' } as any);
+ (useTenant as any).mockReturnValue({ activeClubId: null, clubs: [], setActiveClub: vi.fn(), userRole: null });
render(Protected
);
expect(screen.getByText('Loading...')).toBeInTheDocument();
});
it('redirects to /login when unauthenticated', () => {
- vi.mocked(useSession).mockReturnValue({ data: null, status: 'unauthenticated' } as any);
- vi.mocked(useTenant).mockReturnValue({ activeClubId: null, clubs: [], setActiveClub: vi.fn(), userRole: null });
+ (useSession as any).mockReturnValue({ data: null, status: 'unauthenticated' } as any);
+ (useTenant as any).mockReturnValue({ activeClubId: null, clubs: [], setActiveClub: vi.fn(), userRole: null });
render(Protected
);
expect(mockPush).toHaveBeenCalledWith('/login');
});
it('shows Contact admin when 0 clubs', () => {
- vi.mocked(useSession).mockReturnValue({ data: { user: {} }, status: 'authenticated' } as any);
- vi.mocked(useTenant).mockReturnValue({ activeClubId: null, clubs: [], setActiveClub: vi.fn(), userRole: null });
+ (useSession as any).mockReturnValue({ data: { user: {} }, status: 'authenticated' } as any);
+ (useTenant as any).mockReturnValue({ activeClubId: null, clubs: [], setActiveClub: vi.fn(), userRole: null });
render(Protected
);
expect(screen.getByText('Contact admin to get access to a club')).toBeInTheDocument();
@@ -51,8 +51,8 @@ describe('AuthGuard', () => {
it('auto-selects when 1 club and no active club', () => {
const mockSetActiveClub = vi.fn();
- vi.mocked(useSession).mockReturnValue({ data: { user: {} }, status: 'authenticated' } as any);
- vi.mocked(useTenant).mockReturnValue({
+ (useSession as any).mockReturnValue({ data: { user: {} }, status: 'authenticated' } as any);
+ (useTenant as any).mockReturnValue({
activeClubId: null,
clubs: [{ id: 'club-1', name: 'Club 1' }],
setActiveClub: mockSetActiveClub,
@@ -64,8 +64,8 @@ describe('AuthGuard', () => {
});
it('redirects to /select-club when multiple clubs and no active club', () => {
- vi.mocked(useSession).mockReturnValue({ data: { user: {} }, status: 'authenticated' } as any);
- vi.mocked(useTenant).mockReturnValue({
+ (useSession as any).mockReturnValue({ data: { user: {} }, status: 'authenticated' } as any);
+ (useTenant as any).mockReturnValue({
activeClubId: null,
clubs: [{ id: 'club-1', name: 'Club 1' }, { id: 'club-2', name: 'Club 2' }],
setActiveClub: vi.fn(),
@@ -77,8 +77,8 @@ describe('AuthGuard', () => {
});
it('renders children when authenticated and active club is set', () => {
- vi.mocked(useSession).mockReturnValue({ data: { user: {} }, status: 'authenticated' } as any);
- vi.mocked(useTenant).mockReturnValue({
+ (useSession as any).mockReturnValue({ data: { user: {} }, status: 'authenticated' } as any);
+ (useTenant as any).mockReturnValue({
activeClubId: 'club-1',
clubs: [{ id: 'club-1', name: 'Club 1' }],
setActiveClub: vi.fn(),
diff --git a/frontend/src/components/__tests__/club-switcher.test.tsx b/frontend/src/components/__tests__/club-switcher.test.tsx
index a1a85bf..2ae02bf 100644
--- a/frontend/src/components/__tests__/club-switcher.test.tsx
+++ b/frontend/src/components/__tests__/club-switcher.test.tsx
@@ -22,7 +22,7 @@ describe('ClubSwitcher', () => {
});
it('renders loading state when clubs is empty', () => {
- vi.mocked(useTenant).mockReturnValue({
+ (useTenant as any).mockReturnValue({
activeClubId: null,
clubs: [],
setActiveClub: vi.fn(),
@@ -34,7 +34,7 @@ describe('ClubSwitcher', () => {
});
it('renders current club name and sport type badge', () => {
- vi.mocked(useTenant).mockReturnValue({
+ (useTenant as any).mockReturnValue({
activeClubId: 'club-1',
clubs: [
{ id: 'club-1', name: 'Tennis Club', sportType: 'Tennis' },
@@ -50,7 +50,7 @@ describe('ClubSwitcher', () => {
it('calls setActiveClub when club is selected', () => {
const mockSetActiveClub = vi.fn();
- vi.mocked(useTenant).mockReturnValue({
+ (useTenant as any).mockReturnValue({
activeClubId: 'club-1',
clubs: [
{ id: 'club-1', name: 'Tennis Club', sportType: 'Tennis' },
diff --git a/frontend/src/components/__tests__/task-detail.test.tsx b/frontend/src/components/__tests__/task-detail.test.tsx
index 6f2c7ba..fc74fa5 100644
--- a/frontend/src/components/__tests__/task-detail.test.tsx
+++ b/frontend/src/components/__tests__/task-detail.test.tsx
@@ -20,14 +20,14 @@ describe('TaskDetailPage', () => {
const mockMutate = vi.fn();
beforeEach(() => {
- vi.mocked(useUpdateTask).mockReturnValue({
+ (useUpdateTask as any).mockReturnValue({
mutate: mockMutate,
isPending: false,
} as any);
});
it('shows valid transitions for Open status', async () => {
- vi.mocked(useTask).mockReturnValue({
+ (useTask as any).mockReturnValue({
data: { id: '1', title: 'Task 1', status: 'Open', description: 'Desc', createdAt: '2024-01-01', updatedAt: '2024-01-01' },
isLoading: false,
error: null,
@@ -44,7 +44,7 @@ describe('TaskDetailPage', () => {
});
it('shows valid transitions for InProgress status', async () => {
- vi.mocked(useTask).mockReturnValue({
+ (useTask as any).mockReturnValue({
data: { id: '1', title: 'Task 1', status: 'InProgress', description: 'Desc', createdAt: '2024-01-01', updatedAt: '2024-01-01' },
isLoading: false,
error: null,
@@ -60,7 +60,7 @@ describe('TaskDetailPage', () => {
});
it('shows valid transitions for Review status (including back transition)', async () => {
- vi.mocked(useTask).mockReturnValue({
+ (useTask as any).mockReturnValue({
data: { id: '1', title: 'Task 1', status: 'Review', description: 'Desc', createdAt: '2024-01-01', updatedAt: '2024-01-01' },
isLoading: false,
error: null,
diff --git a/frontend/src/components/__tests__/task-list.test.tsx b/frontend/src/components/__tests__/task-list.test.tsx
index 9d3891d..d168594 100644
--- a/frontend/src/components/__tests__/task-list.test.tsx
+++ b/frontend/src/components/__tests__/task-list.test.tsx
@@ -24,7 +24,7 @@ vi.mock('@/hooks/useTasks', () => ({
describe('TaskListPage', () => {
beforeEach(() => {
- vi.mocked(useTasks).mockReturnValue({
+ (useTasks as any).mockReturnValue({
data: {
items: [
{ id: '1', title: 'Test Task 1', status: 'Open', assigneeId: null, createdAt: '2024-01-01' },
diff --git a/frontend/src/hooks/__tests__/useActiveClub.test.ts b/frontend/src/hooks/__tests__/useActiveClub.test.ts
index 1fb967c..13899f3 100644
--- a/frontend/src/hooks/__tests__/useActiveClub.test.ts
+++ b/frontend/src/hooks/__tests__/useActiveClub.test.ts
@@ -33,15 +33,15 @@ describe('useActiveClub', () => {
status: 'authenticated',
});
- vi.mocked(localStorage.getItem).mockImplementation((key: string) => {
+ (localStorage.getItem as any).mockImplementation((key: string) => {
return localStorageData[key] || null;
});
- vi.mocked(localStorage.setItem).mockImplementation((key: string, value: string) => {
+ (localStorage.setItem as any).mockImplementation((key: string, value: string) => {
localStorageData[key] = value;
});
- vi.mocked(localStorage.clear).mockImplementation(() => {
+ (localStorage.clear as any).mockImplementation(() => {
localStorageData = {};
});
});
diff --git a/frontend/vitest.config.ts b/frontend/vitest.config.ts
index e36d729..a785757 100644
--- a/frontend/vitest.config.ts
+++ b/frontend/vitest.config.ts
@@ -5,9 +5,10 @@ import path from 'path';
export default defineConfig({
plugins: [react()],
test: {
- environment: 'happy-dom',
+ environment: 'jsdom',
globals: true,
setupFiles: ['./src/test/setup.ts'],
+ exclude: ['node_modules', 'dist', '.idea', '.git', '.cache', 'e2e'],
},
resolve: {
alias: {