initial
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { tokenStorage } from '@/api/tokenStorage';
|
||||
import { authApi } from '@/features/auth/api/authApi';
|
||||
import { useAuthStore } from '@/features/auth/store/authStore';
|
||||
|
||||
vi.mock('@/features/auth/api/authApi', () => ({
|
||||
authApi: {
|
||||
login: vi.fn(),
|
||||
logout: vi.fn(),
|
||||
refresh: vi.fn(),
|
||||
getMe: vi.fn(),
|
||||
listUsers: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockedAuthApi = vi.mocked(authApi);
|
||||
|
||||
describe('authStore', () => {
|
||||
beforeEach(() => {
|
||||
tokenStorage.clear();
|
||||
useAuthStore.setState({ user: null, isInitializing: true });
|
||||
vi.clearAllMocks();
|
||||
mockedAuthApi.login.mockResolvedValue({
|
||||
accessToken: 'access-123',
|
||||
user: { id: 'u1', email: 'learner@aplp.io', name: 'Learner' },
|
||||
});
|
||||
mockedAuthApi.refresh.mockResolvedValue({
|
||||
accessToken: 'access-refreshed',
|
||||
user: { id: 'u1', email: 'learner@aplp.io', name: 'Learner' },
|
||||
});
|
||||
});
|
||||
|
||||
it('login stores token and user', async () => {
|
||||
await useAuthStore.getState().login('learner@aplp.io', 'secret');
|
||||
|
||||
expect(mockedAuthApi.login).toHaveBeenCalledWith({
|
||||
email: 'learner@aplp.io',
|
||||
password: 'secret',
|
||||
});
|
||||
expect(tokenStorage.get()).toBe('access-123');
|
||||
expect(useAuthStore.getState().user?.email).toBe('learner@aplp.io');
|
||||
expect(useAuthStore.getState().isInitializing).toBe(false);
|
||||
});
|
||||
|
||||
it('login failure leaves user signed out', async () => {
|
||||
mockedAuthApi.login.mockRejectedValue(new Error('invalid credentials'));
|
||||
|
||||
await expect(useAuthStore.getState().login('learner@aplp.io', 'wrong')).rejects.toThrow(
|
||||
'invalid credentials',
|
||||
);
|
||||
expect(tokenStorage.get()).toBeNull();
|
||||
expect(useAuthStore.getState().user).toBeNull();
|
||||
});
|
||||
|
||||
it('logout clears token and user even when API call fails', async () => {
|
||||
await useAuthStore.getState().login('learner@aplp.io', 'secret');
|
||||
mockedAuthApi.logout.mockRejectedValue(new Error('network'));
|
||||
|
||||
await useAuthStore.getState().logout();
|
||||
|
||||
expect(tokenStorage.get()).toBeNull();
|
||||
expect(useAuthStore.getState().user).toBeNull();
|
||||
});
|
||||
|
||||
it('init restores session from refresh token', async () => {
|
||||
await useAuthStore.getState().init();
|
||||
|
||||
expect(mockedAuthApi.refresh).toHaveBeenCalledOnce();
|
||||
expect(tokenStorage.get()).toBe('access-refreshed');
|
||||
expect(useAuthStore.getState().user?.id).toBe('u1');
|
||||
expect(useAuthStore.getState().isInitializing).toBe(false);
|
||||
});
|
||||
|
||||
it('init handles expired refresh token gracefully', async () => {
|
||||
mockedAuthApi.refresh.mockRejectedValue(new Error('401'));
|
||||
|
||||
await useAuthStore.getState().init();
|
||||
|
||||
expect(tokenStorage.get()).toBeNull();
|
||||
expect(useAuthStore.getState().user).toBeNull();
|
||||
expect(useAuthStore.getState().isInitializing).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user