mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-02 08:15:55 +00:00
90 lines
4.1 KiB
TypeScript
90 lines
4.1 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const auth = vi.hoisted(() => ({
|
|
clients: new Map<string, { getBasicPassword: () => string | null }>(),
|
|
signIn: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('@/stores/auth-store', () => ({
|
|
useAuthStore: {
|
|
getState: () => ({
|
|
getClientForAccount: (id: string) => auth.clients.get(id),
|
|
signInRestoredAccount: auth.signIn,
|
|
}),
|
|
},
|
|
}));
|
|
|
|
import { collectAccounts, restoreArchive } from '@/lib/account-archive-client';
|
|
import { generateAccountId } from '@/lib/account-utils';
|
|
import { useAccountStore } from '@/stores/account-store';
|
|
|
|
const server = 'https://mail.example.com';
|
|
const add = (username: string, authMode: 'basic' | 'oauth') => useAccountStore.getState().addAccount({
|
|
username, serverUrl: server, authMode, rememberMe: true, label: username, displayName: username, email: username,
|
|
lastLoginAt: 1, isConnected: true, hasError: false, isDefault: false,
|
|
});
|
|
|
|
beforeEach(() => {
|
|
useAccountStore.setState({ accounts: [], defaultAccountId: null });
|
|
auth.clients.clear();
|
|
auth.signIn.mockReset();
|
|
});
|
|
|
|
describe('collectAccounts', () => {
|
|
it('leaves passwords out unless asked', () => {
|
|
const id = add('a@example.com', 'basic');
|
|
auth.clients.set(id, { getBasicPassword: () => 'secret-a' });
|
|
expect(collectAccounts()[0]).not.toHaveProperty('password');
|
|
expect(collectAccounts(true)[0].password).toBe('secret-a');
|
|
});
|
|
|
|
it('takes a password only from a signed-in Basic account', () => {
|
|
const basic = add('a@example.com', 'basic');
|
|
const oauth = add('b@example.com', 'oauth');
|
|
add('c@example.com', 'basic'); // not signed in here
|
|
auth.clients.set(basic, { getBasicPassword: () => null }); // TOTP or bearer
|
|
auth.clients.set(oauth, { getBasicPassword: () => 'never-read' });
|
|
expect(collectAccounts(true).map(a => a.password)).toEqual([undefined, undefined, undefined]);
|
|
});
|
|
});
|
|
|
|
describe('restoreArchive', () => {
|
|
const entry = (username: string, password?: string) => ({ username, serverUrl: server, label: username, avatarColor: '#2563eb', password });
|
|
|
|
it('signs in to the accounts saved with a password and leaves the others waiting', async () => {
|
|
auth.signIn.mockImplementation(async (id: string, password: string) => {
|
|
if (password !== 'right') return false;
|
|
useAccountStore.getState().updateAccount(id, { awaitingSignIn: false });
|
|
return true;
|
|
});
|
|
const result = await restoreArchive([entry('a@example.com', 'right'), entry('b@example.com', 'stale'), entry('c@example.com')], true);
|
|
expect(auth.signIn).toHaveBeenCalledTimes(2);
|
|
expect(auth.signIn).toHaveBeenCalledWith(generateAccountId('a@example.com', server), 'right', false);
|
|
expect(result).toMatchObject({ added: 3, signedIn: 1, signInFailed: 1, waiting: 2 });
|
|
});
|
|
|
|
it('remembers the restored sign-ins only when the restoring account is remembered', async () => {
|
|
auth.signIn.mockResolvedValue(true);
|
|
const owner = add('owner@example.com', 'basic');
|
|
useAccountStore.getState().updateAccount(owner, { rememberMe: false });
|
|
useAccountStore.setState({ activeAccountId: owner });
|
|
await restoreArchive([entry('a@example.com', 'right')], true);
|
|
expect(auth.signIn).toHaveBeenLastCalledWith(generateAccountId('a@example.com', server), 'right', false);
|
|
|
|
useAccountStore.getState().updateAccount(owner, { rememberMe: true });
|
|
await restoreArchive([entry('b@example.com', 'right')], true);
|
|
expect(auth.signIn).toHaveBeenLastCalledWith(generateAccountId('b@example.com', server), 'right', true);
|
|
|
|
await restoreArchive([entry('c@example.com', 'right')], false);
|
|
expect(auth.signIn).toHaveBeenLastCalledWith(generateAccountId('c@example.com', server), 'right', false);
|
|
});
|
|
|
|
it('does not sign in again to an account already connected here', async () => {
|
|
const id = add('a@example.com', 'basic');
|
|
auth.clients.set(id, { getBasicPassword: () => 'right' });
|
|
const result = await restoreArchive([entry('a@example.com', 'right')], true);
|
|
expect(auth.signIn).not.toHaveBeenCalled();
|
|
expect(result).toMatchObject({ updated: 1, signedIn: 0, waiting: 0 });
|
|
});
|
|
});
|