You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.3 KiB
TypeScript
130 lines
3.3 KiB
TypeScript
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
import { render, waitFor, screen } from '@solidjs/testing-library';
|
|
import { Router, Route } from '@solidjs/router';
|
|
import { AuthProvider, useAuth } from '~/contexts/AuthContext';
|
|
import { I18nProvider } from '~/i18n';
|
|
import { ToastProvider } from '~/components/ui/Toast';
|
|
import { authApi } from '~/api/auth';
|
|
import type { User } from '~/types';
|
|
|
|
vi.mock('~/api/auth', () => ({
|
|
authApi: {
|
|
me: vi.fn(),
|
|
logout: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
const mockedMe = vi.mocked(authApi.me);
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
const adminUser: User = {
|
|
id: '1',
|
|
email: 'admin@example.com',
|
|
display_name: 'Admin',
|
|
role: 'admin',
|
|
created_at: '2026-01-01T00:00:00Z',
|
|
};
|
|
|
|
const regularUser: User = {
|
|
id: '2',
|
|
email: 'user@example.com',
|
|
display_name: 'User',
|
|
role: 'user',
|
|
created_at: '2026-01-01T00:00:00Z',
|
|
};
|
|
|
|
describe('Admin Route Guard', () => {
|
|
it('should expose isAdmin as true for admin users', async () => {
|
|
mockedMe.mockResolvedValue(adminUser);
|
|
|
|
const TestComponent = () => {
|
|
const { isAdmin, loading } = useAuth();
|
|
return (
|
|
<div>
|
|
<span data-testid="loading">{loading() ? 'true' : 'false'}</span>
|
|
<span data-testid="isAdmin">{isAdmin() ? 'true' : 'false'}</span>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
render(() => (
|
|
<I18nProvider locale="fr">
|
|
<ToastProvider>
|
|
<AuthProvider>
|
|
<TestComponent />
|
|
</AuthProvider>
|
|
</ToastProvider>
|
|
</I18nProvider>
|
|
));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId('loading').textContent).toBe('false');
|
|
});
|
|
|
|
expect(screen.getByTestId('isAdmin').textContent).toBe('true');
|
|
});
|
|
|
|
it('should expose isAdmin as false for non-admin users', async () => {
|
|
mockedMe.mockResolvedValue(regularUser);
|
|
|
|
const TestComponent = () => {
|
|
const { isAdmin, loading } = useAuth();
|
|
return (
|
|
<div>
|
|
<span data-testid="loading">{loading() ? 'true' : 'false'}</span>
|
|
<span data-testid="isAdmin">{isAdmin() ? 'true' : 'false'}</span>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
render(() => (
|
|
<I18nProvider locale="fr">
|
|
<ToastProvider>
|
|
<AuthProvider>
|
|
<TestComponent />
|
|
</AuthProvider>
|
|
</ToastProvider>
|
|
</I18nProvider>
|
|
));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId('loading').textContent).toBe('false');
|
|
});
|
|
|
|
expect(screen.getByTestId('isAdmin').textContent).toBe('false');
|
|
});
|
|
|
|
it('should expose isAdmin as false when user is null', async () => {
|
|
mockedMe.mockRejectedValue(new Error('Unauthorized'));
|
|
|
|
const TestComponent = () => {
|
|
const { isAdmin, loading } = useAuth();
|
|
return (
|
|
<div>
|
|
<span data-testid="loading">{loading() ? 'true' : 'false'}</span>
|
|
<span data-testid="isAdmin">{isAdmin() ? 'true' : 'false'}</span>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
render(() => (
|
|
<I18nProvider locale="fr">
|
|
<ToastProvider>
|
|
<AuthProvider>
|
|
<TestComponent />
|
|
</AuthProvider>
|
|
</ToastProvider>
|
|
</I18nProvider>
|
|
));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId('loading').textContent).toBe('false');
|
|
});
|
|
|
|
expect(screen.getByTestId('isAdmin').textContent).toBe('false');
|
|
});
|
|
});
|