mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-10 00:04:48 -07:00
cleanup testing utilities, documentation, and AI commentary
This commit is contained in:
parent
bd2382c94e
commit
ef6cea6f6c
150 changed files with 891 additions and 1233 deletions
|
|
@ -25,14 +25,14 @@ const flushStoresAndEffects = async (): Promise<void> => {
|
|||
});
|
||||
};
|
||||
|
||||
import { autoLoginSession } from '../../../src/hooks/useAutoLogin';
|
||||
import { autoLoginGate } from '../../../src/hooks/useAutoLogin';
|
||||
import { settingsStore } from '../../../src/hooks/useSettings';
|
||||
import { knownHostsStore } from '../../../src/hooks/useKnownHosts';
|
||||
import Login from '../../../src/containers/Login/Login';
|
||||
import { HostDTO, SettingDTO } from '@app/services';
|
||||
import { App } from '@app/types';
|
||||
import { ServerSelectors, ServerDispatch } from '@app/store';
|
||||
import { StatusEnum } from '@app/websocket';
|
||||
import { WebsocketTypes } from '@app/websocket/types';
|
||||
|
||||
import { resetDexie } from '../services/dexie/resetDexie';
|
||||
import { renderAppScreen, store } from './helpers';
|
||||
|
|
@ -41,7 +41,7 @@ import { renderAppScreen, store } from './helpers';
|
|||
// dispatching updateStatus(DISCONNECTED) is what the real reducer uses to
|
||||
// clear connectionAttemptMade (clearStore intentionally preserves status).
|
||||
const simulateLogout = () => {
|
||||
ServerDispatch.updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
ServerDispatch.updateStatus(WebsocketTypes.StatusEnum.DISCONNECTED, null);
|
||||
};
|
||||
|
||||
const seedAutoConnect = async () => {
|
||||
|
|
@ -86,7 +86,7 @@ beforeEach(async () => {
|
|||
// cached values).
|
||||
settingsStore.reset();
|
||||
knownHostsStore.reset();
|
||||
autoLoginSession.startupCheckRan = false;
|
||||
autoLoginGate.hasChecked = false;
|
||||
});
|
||||
|
||||
describe('autoconnect — cold start', () => {
|
||||
|
|
@ -182,7 +182,7 @@ describe('autoconnect — refresh', () => {
|
|||
// Simulate a browser refresh: the session gate naturally resets on a
|
||||
// fresh JS context, and the real connection flag resets too.
|
||||
simulateLogout();
|
||||
autoLoginSession.startupCheckRan = false;
|
||||
autoLoginGate.hasChecked = false;
|
||||
|
||||
renderAppScreen(<Login />);
|
||||
await waitFor(() => {
|
||||
|
|
|
|||
|
|
@ -19,13 +19,8 @@ import { afterEach, beforeEach, vi } from 'vitest';
|
|||
|
||||
import { ServerDispatch, RoomsDispatch, GameDispatch } from '@app/store';
|
||||
import { Data } from '@app/types';
|
||||
import {
|
||||
WebClient,
|
||||
StatusEnum,
|
||||
WebSocketConnectReason,
|
||||
setPendingOptions,
|
||||
} from '@app/websocket';
|
||||
import type { WebSocketConnectOptions } from '@app/websocket';
|
||||
import { WebClient, setPendingOptions } from '@app/websocket';
|
||||
import { WebsocketTypes } from '@app/websocket/types';
|
||||
import { PROTOCOL_VERSION } from '../../../src/websocket/config';
|
||||
import { createWebClientRequest, createWebClientResponse } from '@app/api';
|
||||
|
||||
|
|
@ -109,7 +104,7 @@ function resetAll(): void {
|
|||
}
|
||||
|
||||
client.protobuf.resetCommands();
|
||||
client.status = StatusEnum.DISCONNECTED;
|
||||
client.status = WebsocketTypes.StatusEnum.DISCONNECTED;
|
||||
|
||||
ServerDispatch.clearStore();
|
||||
RoomsDispatch.clearStore();
|
||||
|
|
@ -128,8 +123,8 @@ function resetAll(): void {
|
|||
|
||||
// ── Shared connect helpers ──────────────────────────────────────────────────
|
||||
|
||||
const DEFAULT_LOGIN_OPTIONS: WebSocketConnectOptions = {
|
||||
reason: WebSocketConnectReason.LOGIN,
|
||||
const DEFAULT_LOGIN_OPTIONS: WebsocketTypes.WebSocketConnectOptions = {
|
||||
reason: WebsocketTypes.WebSocketConnectReason.LOGIN,
|
||||
host: 'localhost',
|
||||
port: '4748',
|
||||
userName: 'alice',
|
||||
|
|
@ -137,16 +132,16 @@ const DEFAULT_LOGIN_OPTIONS: WebSocketConnectOptions = {
|
|||
};
|
||||
|
||||
export function connectRaw(
|
||||
overrides: Partial<WebSocketConnectOptions> = {}
|
||||
overrides: Partial<WebsocketTypes.WebSocketConnectOptions> = {}
|
||||
): void {
|
||||
const opts = { ...DEFAULT_LOGIN_OPTIONS, ...overrides };
|
||||
setPendingOptions(opts as WebSocketConnectOptions);
|
||||
setPendingOptions(opts as WebsocketTypes.WebSocketConnectOptions);
|
||||
getWebClient().connect({ host: opts.host, port: opts.port });
|
||||
openMockWebSocket();
|
||||
}
|
||||
|
||||
export function connectAndHandshake(
|
||||
overrides: Partial<WebSocketConnectOptions> = {}
|
||||
overrides: Partial<WebsocketTypes.WebSocketConnectOptions> = {}
|
||||
): void {
|
||||
connectRaw(overrides);
|
||||
deliverMessage(buildSessionEventMessage(
|
||||
|
|
@ -160,7 +155,7 @@ export function connectAndHandshake(
|
|||
}
|
||||
|
||||
export function connectAndHandshakeWithSalt(
|
||||
overrides: Partial<WebSocketConnectOptions> = {}
|
||||
overrides: Partial<WebsocketTypes.WebSocketConnectOptions> = {}
|
||||
): void {
|
||||
connectRaw(overrides);
|
||||
deliverMessage(buildSessionEventMessage(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { describe, expect, it } from 'vitest';
|
|||
|
||||
import { Data } from '@app/types';
|
||||
import { store } from '@app/store';
|
||||
import { StatusEnum, WebSocketConnectReason } from '@app/websocket';
|
||||
import { WebsocketTypes } from '@app/websocket/types';
|
||||
|
||||
import { connectAndHandshake, connectAndHandshakeWithSalt } from '../helpers/setup';
|
||||
import {
|
||||
|
|
@ -44,7 +44,7 @@ describe('authentication', () => {
|
|||
})));
|
||||
|
||||
const state = store.getState().server;
|
||||
expect(state.status.state).toBe(StatusEnum.LOGGED_IN);
|
||||
expect(state.status.state).toBe(WebsocketTypes.StatusEnum.LOGGED_IN);
|
||||
expect(state.status.description).toBe('Logged in.');
|
||||
expect(state.user?.name).toBe('alice');
|
||||
expect(Object.keys(state.buddyList)).toEqual(['bob']);
|
||||
|
|
@ -64,7 +64,7 @@ describe('authentication', () => {
|
|||
})));
|
||||
|
||||
const state = store.getState().server;
|
||||
expect(state.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(state.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
expect(state.user).toBeNull();
|
||||
expect(state.buddyList).toEqual({});
|
||||
});
|
||||
|
|
@ -72,7 +72,7 @@ describe('authentication', () => {
|
|||
|
||||
describe('register', () => {
|
||||
const registerOptions = {
|
||||
reason: WebSocketConnectReason.REGISTER as const,
|
||||
reason: WebsocketTypes.WebSocketConnectReason.REGISTER as const,
|
||||
host: 'localhost',
|
||||
port: '4748',
|
||||
userName: 'newbie',
|
||||
|
|
@ -107,7 +107,7 @@ describe('authentication', () => {
|
|||
responseCode: Data.Response_ResponseCode.RespRegistrationAcceptedNeedsActivation,
|
||||
})));
|
||||
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
expect(() => findLastSessionCommand(Data.Command_Login_ext)).toThrow();
|
||||
});
|
||||
});
|
||||
|
|
@ -115,7 +115,7 @@ describe('authentication', () => {
|
|||
describe('activate', () => {
|
||||
it('auto-logs-in on RespActivationAccepted', () => {
|
||||
connectAndHandshake({
|
||||
reason: WebSocketConnectReason.ACTIVATE_ACCOUNT as const,
|
||||
reason: WebsocketTypes.WebSocketConnectReason.ACTIVATE_ACCOUNT as const,
|
||||
host: 'localhost',
|
||||
port: '4748',
|
||||
userName: 'alice',
|
||||
|
|
@ -171,7 +171,7 @@ describe('authentication', () => {
|
|||
}),
|
||||
})));
|
||||
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.LOGGED_IN);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.LOGGED_IN);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { describe, expect, it } from 'vitest';
|
|||
|
||||
import { Data } from '@app/types';
|
||||
import { store } from '@app/store';
|
||||
import { StatusEnum } from '@app/websocket';
|
||||
import { WebsocketTypes } from '@app/websocket/types';
|
||||
|
||||
import { PROTOCOL_VERSION } from '../../../src/websocket/config';
|
||||
|
||||
|
|
@ -18,17 +18,15 @@ import {
|
|||
setPendingOptions,
|
||||
connectAndHandshake,
|
||||
} from '../helpers/setup';
|
||||
import type { WebSocketConnectOptions } from '@app/websocket';
|
||||
import { WebSocketConnectReason } from '@app/websocket';
|
||||
import {
|
||||
buildSessionEventMessage,
|
||||
deliverMessage,
|
||||
} from '../helpers/protobuf-builders';
|
||||
import { findLastSessionCommand } from '../helpers/command-capture';
|
||||
|
||||
function loginOptions(overrides: Partial<{ userName: string; password: string }> = {}): WebSocketConnectOptions {
|
||||
function loginOptions(overrides: Partial<{ userName: string; password: string }> = {}): WebsocketTypes.WebSocketConnectOptions {
|
||||
return {
|
||||
reason: WebSocketConnectReason.LOGIN,
|
||||
reason: WebsocketTypes.WebSocketConnectReason.LOGIN,
|
||||
host: 'localhost',
|
||||
port: '4748',
|
||||
userName: overrides.userName ?? 'alice',
|
||||
|
|
@ -36,7 +34,7 @@ function loginOptions(overrides: Partial<{ userName: string; password: string }>
|
|||
};
|
||||
}
|
||||
|
||||
function connectWithOptions(opts: WebSocketConnectOptions): void {
|
||||
function connectWithOptions(opts: WebsocketTypes.WebSocketConnectOptions): void {
|
||||
setPendingOptions(opts);
|
||||
getWebClient().connect({ host: opts.host, port: opts.port });
|
||||
}
|
||||
|
|
@ -63,7 +61,7 @@ describe('connection lifecycle', () => {
|
|||
|
||||
openMockWebSocket();
|
||||
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.CONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.CONNECTED);
|
||||
expect(store.getState().server.status.description).toBe('Connected');
|
||||
});
|
||||
|
||||
|
|
@ -73,7 +71,7 @@ describe('connection lifecycle', () => {
|
|||
|
||||
deliverMessage(serverIdentification());
|
||||
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.LOGGING_IN);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.LOGGING_IN);
|
||||
expect(store.getState().server.info.name).toBe('TestServer');
|
||||
expect(store.getState().server.info.version).toBe('2.8.0');
|
||||
|
||||
|
|
@ -90,7 +88,7 @@ describe('connection lifecycle', () => {
|
|||
|
||||
const mock = getMockWebSocket();
|
||||
expect(mock.close).toHaveBeenCalled();
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
expect(() => findLastSessionCommand(Data.Command_Login_ext)).toThrow();
|
||||
});
|
||||
|
||||
|
|
@ -103,7 +101,7 @@ describe('connection lifecycle', () => {
|
|||
vi.advanceTimersByTime(5000);
|
||||
|
||||
expect(mock.close).toHaveBeenCalled();
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
});
|
||||
|
||||
it('releases keep-alive ping loop on explicit disconnect', () => {
|
||||
|
|
@ -115,7 +113,7 @@ describe('connection lifecycle', () => {
|
|||
getWebClient().disconnect();
|
||||
|
||||
expect(mock.close).toHaveBeenCalled();
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
});
|
||||
|
||||
it('drops pending commands and clears state on unexpected socket close', () => {
|
||||
|
|
@ -129,6 +127,6 @@ describe('connection lifecycle', () => {
|
|||
mock.readyState = 3;
|
||||
mock.onclose?.({ code: 1006, reason: '', wasClean: false } as CloseEvent);
|
||||
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
});
|
||||
});
|
||||
|
|
@ -4,7 +4,7 @@ import { describe, expect, it } from 'vitest';
|
|||
|
||||
import { Data } from '@app/types';
|
||||
import { store } from '@app/store';
|
||||
import { StatusEnum } from '@app/websocket';
|
||||
import { WebsocketTypes } from '@app/websocket/types';
|
||||
|
||||
import { connectRaw, getMockWebSocket } from '../helpers/setup';
|
||||
import {
|
||||
|
|
@ -32,7 +32,7 @@ describe('keep-alive', () => {
|
|||
vi.advanceTimersByTime(5000);
|
||||
const second = findLastSessionCommand(Data.Command_Ping_ext);
|
||||
expect(second.cmdId).toBeGreaterThan(first.cmdId);
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.CONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.CONNECTED);
|
||||
});
|
||||
|
||||
it('stays CONNECTED while pongs arrive before the next tick', () => {
|
||||
|
|
@ -47,7 +47,7 @@ describe('keep-alive', () => {
|
|||
})));
|
||||
}
|
||||
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.CONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.CONNECTED);
|
||||
expect(getMockWebSocket().close).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
|
@ -56,11 +56,11 @@ describe('keep-alive', () => {
|
|||
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(() => findLastSessionCommand(Data.Command_Ping_ext)).not.toThrow();
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.CONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.CONNECTED);
|
||||
|
||||
vi.advanceTimersByTime(5000);
|
||||
|
||||
expect(getMockWebSocket().close).toHaveBeenCalled();
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { describe, expect, it } from 'vitest';
|
|||
|
||||
import { Data } from '@app/types';
|
||||
import { store } from '@app/store';
|
||||
import { StatusEnum, WebSocketConnectReason } from '@app/websocket';
|
||||
import { WebsocketTypes } from '@app/websocket/types';
|
||||
|
||||
import { connectAndHandshake } from '../helpers/setup';
|
||||
import {
|
||||
|
|
@ -19,7 +19,7 @@ import { findLastSessionCommand } from '../helpers/command-capture';
|
|||
describe('password reset', () => {
|
||||
it('forgotPasswordRequest sends command and disconnects on success', () => {
|
||||
connectAndHandshake({
|
||||
reason: WebSocketConnectReason.PASSWORD_RESET_REQUEST as const,
|
||||
reason: WebsocketTypes.WebSocketConnectReason.PASSWORD_RESET_REQUEST as const,
|
||||
host: 'localhost',
|
||||
port: '4748',
|
||||
userName: 'alice',
|
||||
|
|
@ -37,12 +37,12 @@ describe('password reset', () => {
|
|||
}),
|
||||
})));
|
||||
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
});
|
||||
|
||||
it('forgotPasswordChallenge sends command with userName and email', () => {
|
||||
connectAndHandshake({
|
||||
reason: WebSocketConnectReason.PASSWORD_RESET_CHALLENGE as const,
|
||||
reason: WebsocketTypes.WebSocketConnectReason.PASSWORD_RESET_CHALLENGE as const,
|
||||
host: 'localhost',
|
||||
port: '4748',
|
||||
userName: 'alice',
|
||||
|
|
@ -58,12 +58,12 @@ describe('password reset', () => {
|
|||
responseCode: Data.Response_ResponseCode.RespOk,
|
||||
})));
|
||||
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
});
|
||||
|
||||
it('forgotPasswordReset sends command with userName, token, and newPassword', () => {
|
||||
connectAndHandshake({
|
||||
reason: WebSocketConnectReason.PASSWORD_RESET as const,
|
||||
reason: WebsocketTypes.WebSocketConnectReason.PASSWORD_RESET as const,
|
||||
host: 'localhost',
|
||||
port: '4748',
|
||||
userName: 'alice',
|
||||
|
|
@ -81,6 +81,6 @@ describe('password reset', () => {
|
|||
responseCode: Data.Response_ResponseCode.RespOk,
|
||||
})));
|
||||
|
||||
expect(store.getState().server.status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(store.getState().server.status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
});
|
||||
});
|
||||
|
|
@ -6,7 +6,7 @@ import { describe, expect, it } from 'vitest';
|
|||
|
||||
import { Data } from '@app/types';
|
||||
import { store } from '@app/store';
|
||||
import { StatusEnum } from '@app/websocket';
|
||||
import { WebsocketTypes } from '@app/websocket/types';
|
||||
|
||||
import { connectAndHandshake } from '../helpers/setup';
|
||||
import {
|
||||
|
|
@ -73,7 +73,7 @@ describe('server events', () => {
|
|||
));
|
||||
|
||||
const status = store.getState().server.status;
|
||||
expect(status.state).toBe(StatusEnum.DISCONNECTED);
|
||||
expect(status.state).toBe(WebsocketTypes.StatusEnum.DISCONNECTED);
|
||||
expect(status.description).toBe('kicked by admin');
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue