mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-09 15:54:47 -07:00
177 lines
5.5 KiB
TypeScript
177 lines
5.5 KiB
TypeScript
import { act, waitFor } from '@testing-library/react';
|
|
|
|
import { renderWithProviders, createMockWebClient, disconnectedState } from '../../__test-utils__';
|
|
|
|
const flushEffects = async (): Promise<void> => {
|
|
await act(async () => {
|
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
});
|
|
};
|
|
import { makeSettings, makeSettingsHook } from '../../hooks/__mocks__/useSettings';
|
|
import { makeHost, makeKnownHostsHook } from '../../hooks/__mocks__/useKnownHosts';
|
|
import { autoLoginGate } from '../../hooks/useAutoLogin';
|
|
import { LoadingState } from '@app/hooks';
|
|
import Login from './Login';
|
|
|
|
const hoisted = vi.hoisted(() => ({
|
|
mockWebClient: undefined as any,
|
|
getSettings: vi.fn(),
|
|
getKnownHosts: vi.fn(),
|
|
useSettings: vi.fn(),
|
|
useKnownHosts: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('../../hooks/useSettings', () => ({
|
|
useSettings: hoisted.useSettings,
|
|
getSettings: hoisted.getSettings,
|
|
}));
|
|
vi.mock('../../hooks/useKnownHosts', () => ({
|
|
useKnownHosts: hoisted.useKnownHosts,
|
|
getKnownHosts: hoisted.getKnownHosts,
|
|
}));
|
|
vi.mock('../../hooks/useWebClient', () => ({
|
|
useWebClient: () => hoisted.mockWebClient,
|
|
WebClientProvider: ({ children }: { children: any }) => children,
|
|
}));
|
|
|
|
beforeAll(() => {
|
|
const client = createMockWebClient();
|
|
(client.request.authentication as any).testConnection = vi.fn();
|
|
hoisted.mockWebClient = client;
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await flushEffects();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
autoLoginGate.hasChecked = false;
|
|
|
|
hoisted.getSettings.mockReset();
|
|
hoisted.getKnownHosts.mockReset();
|
|
hoisted.useSettings.mockReset();
|
|
hoisted.useKnownHosts.mockReset();
|
|
|
|
const defaultHost = makeHost({
|
|
id: 1,
|
|
remember: true,
|
|
userName: 'alice',
|
|
hashedPassword: 'stored-hash',
|
|
lastSelected: true,
|
|
});
|
|
|
|
hoisted.useSettings.mockReturnValue(
|
|
makeSettingsHook({
|
|
status: LoadingState.READY,
|
|
value: makeSettings({ autoConnect: false }),
|
|
update: vi.fn().mockResolvedValue(undefined),
|
|
})
|
|
);
|
|
hoisted.useKnownHosts.mockReturnValue(
|
|
makeKnownHostsHook({
|
|
status: LoadingState.READY,
|
|
value: { hosts: [defaultHost], selectedHost: defaultHost },
|
|
})
|
|
);
|
|
hoisted.getSettings.mockResolvedValue(makeSettings({ autoConnect: false }));
|
|
hoisted.getKnownHosts.mockResolvedValue({
|
|
hosts: [defaultHost],
|
|
selectedHost: defaultHost,
|
|
});
|
|
});
|
|
|
|
const armAutoConnect = () => {
|
|
const host = makeHost({
|
|
id: 1,
|
|
remember: true,
|
|
userName: 'alice',
|
|
hashedPassword: 'stored-hash',
|
|
lastSelected: true,
|
|
});
|
|
hoisted.getSettings.mockResolvedValue(makeSettings({ autoConnect: true }));
|
|
hoisted.getKnownHosts.mockResolvedValue({ hosts: [host], selectedHost: host });
|
|
};
|
|
|
|
describe('Login — auto-connect cold start', () => {
|
|
test('fires login when settings + host say go', async () => {
|
|
armAutoConnect();
|
|
|
|
renderWithProviders(<Login />, { preloadedState: disconnectedState });
|
|
|
|
await waitFor(() => {
|
|
expect(hoisted.mockWebClient.request.authentication.login).toHaveBeenCalledTimes(1);
|
|
});
|
|
expect(hoisted.mockWebClient.request.authentication.login.mock.calls[0][0]).toMatchObject({
|
|
userName: 'alice',
|
|
hashedPassword: 'stored-hash',
|
|
});
|
|
});
|
|
|
|
test('does not fire when autoConnect setting is off', async () => {
|
|
renderWithProviders(<Login />, { preloadedState: disconnectedState });
|
|
|
|
await flushEffects();
|
|
expect(hoisted.mockWebClient.request.authentication.login).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('does not fire when selected host has no stored credentials', async () => {
|
|
const host = makeHost({
|
|
id: 1,
|
|
remember: false,
|
|
userName: undefined,
|
|
hashedPassword: undefined,
|
|
lastSelected: true,
|
|
});
|
|
hoisted.getSettings.mockResolvedValue(makeSettings({ autoConnect: true }));
|
|
hoisted.getKnownHosts.mockResolvedValue({ hosts: [host], selectedHost: host });
|
|
|
|
renderWithProviders(<Login />, { preloadedState: disconnectedState });
|
|
|
|
await flushEffects();
|
|
expect(hoisted.mockWebClient.request.authentication.login).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('Login — logout cycle (same JS session)', () => {
|
|
test('does not re-auto-connect after first auto-login + logout', async () => {
|
|
armAutoConnect();
|
|
|
|
const first = renderWithProviders(<Login />, { preloadedState: disconnectedState });
|
|
await waitFor(() => {
|
|
expect(hoisted.mockWebClient.request.authentication.login).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
first.unmount();
|
|
renderWithProviders(<Login />, { preloadedState: disconnectedState });
|
|
|
|
await flushEffects();
|
|
|
|
expect(hoisted.mockWebClient.request.authentication.login).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
test('does not auto-connect when user enabled autoConnect mid-session and then logged out', async () => {
|
|
const first = renderWithProviders(<Login />, { preloadedState: disconnectedState });
|
|
await flushEffects();
|
|
expect(hoisted.mockWebClient.request.authentication.login).not.toHaveBeenCalled();
|
|
|
|
first.unmount();
|
|
|
|
hoisted.getSettings.mockResolvedValue(makeSettings({ autoConnect: true }));
|
|
|
|
renderWithProviders(<Login />, { preloadedState: disconnectedState });
|
|
await flushEffects();
|
|
expect(hoisted.mockWebClient.request.authentication.login).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('Login — refresh cycle', () => {
|
|
test('a fresh session gate re-fires auto-login when conditions still hold', async () => {
|
|
armAutoConnect();
|
|
|
|
renderWithProviders(<Login />, { preloadedState: disconnectedState });
|
|
|
|
await waitFor(() => {
|
|
expect(hoisted.mockWebClient.request.authentication.login).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
});
|