Files
webmail/stores/__tests__/auth-store-plugin-hooks.test.ts
T

73 lines
2.8 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
import { authHooks, clearAllHooks } from '@/lib/plugin-hooks';
import { useAuthStore } from '../auth-store';
import { useAccountStore } from '../account-store';
function listen(bus: { register: (id: string, fn: (...a: unknown[]) => unknown) => unknown }) {
const fn = vi.fn();
bus.register('test', fn);
return fn;
}
const ACCOUNT = {
label: 'Alice', serverUrl: 'https://mail.example.org', username: 'alice@example.org', authMode: 'basic' as const,
rememberMe: false, displayName: 'Alice', email: 'alice@example.org', lastLoginAt: 0,
isConnected: true, hasError: false, isDefault: true,
};
beforeEach(() => {
vi.restoreAllMocks();
clearAllHooks();
useAccountStore.setState({ accounts: [], activeAccountId: null, defaultAccountId: null });
useAuthStore.setState({ isAuthenticated: false, client: null, activeAccountId: null, username: null });
});
describe('auth hooks', () => {
it('reports accounts that are added and removed, once each', () => {
const added = listen(authHooks.onAccountAdd);
const removed = listen(authHooks.onAccountRemove);
const id = useAccountStore.getState().addAccount(ACCOUNT);
useAccountStore.getState().addAccount(ACCOUNT); // already there: an update
useAccountStore.getState().removeAccount(id);
useAccountStore.getState().removeAccount(id); // already gone
expect(added.mock.calls).toEqual([[{ accountId: id }]]);
expect(removed.mock.calls).toEqual([[{ accountId: id }]]);
});
it('says when the session is ready, and when another account becomes active', () => {
const ready = listen(authHooks.onAuthReady);
const switched = listen(authHooks.onAccountSwitch);
const client = {} as never;
useAuthStore.setState({ isAuthenticated: true, client, activeAccountId: 'a' });
useAuthStore.setState({ activeAccountId: 'b' });
expect(ready.mock.calls).toEqual([[{ accountId: 'a' }]]);
expect(switched).toHaveBeenCalledWith({ accountId: 'b', previousAccountId: 'a' });
});
it('reports a renewed access token', async () => {
const refreshed = listen(authHooks.onTokenRefresh);
vi.stubGlobal('fetch', vi.fn(async () => ({
ok: true, status: 200, json: async () => ({ access_token: 'new', expires_in: 3600 }),
})));
useAuthStore.setState({ activeAccountId: 'acc', authMode: 'oauth' });
await expect(useAuthStore.getState().refreshAccessToken()).resolves.toBe('new');
expect(refreshed).toHaveBeenCalledWith({ accountId: 'acc' });
});
it('reports a sign-in', async () => {
const signedIn = listen(authHooks.onLogin);
const ok = await useAuthStore.getState().loginDemo();
expect(ok).toBe(true);
const { activeAccountId, username } = useAuthStore.getState();
expect(signedIn).toHaveBeenCalledWith({ accountId: activeAccountId, username });
});
});