Files
Wand-Enhancer-luanslimadev-1/web-panel/src/remote-session/remote-session.reducer.test.ts
T
kitbyte a0b3968d33 refactor(web-panel): update architecture + cheat i18n
Reorganize the panel around product capabilities and integrate the
remote i18n feature from origin/master into the new structure.

- Restructure src into capability features (app, trainer, library,
  remote-session, appearance, shared); move the bridge to bridge/src.
- Add lingui-based UI localization and wrap remaining user-facing
  strings (Trans / msg macros); fix the 'END В·' mojibake.
- Port WeMod cheat-metadata i18n: capture the access token from the
  snapshot's renderer in the bridge and fetch localized trainer_meta
  in remote-session.i18n; guarantee snapshot sync on token failure.
- Wire vitest to the app's lingui/preact pipeline (mergeConfig).
2026-06-15 00:10:49 +03:00

105 lines
4.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { PROTOCOL_VERSION, type HelloAckMessage } from '../../protocol/messages';
import { protocolAction } from './remote-session.protocol';
import {
createInitialRemoteSessionState,
EConnectionStatus,
remoteSessionReducer,
type RemoteSessionState,
} from './remote-session.reducer';
describe('remote session protocol', () => {
it('connects only after an accepted compatible hello acknowledgement', () => {
const action = protocolAction(helloAck(PROTOCOL_VERSION));
expect(action).toEqual({ type: 'connected' });
});
it('rejects a protocol version mismatch', () => {
const action = protocolAction(helloAck(PROTOCOL_VERSION + 1));
expect(action).toEqual({
type: 'error',
message: `Protocol mismatch: bridge=${PROTOCOL_VERSION + 1}, panel=${PROTOCOL_VERSION}.`,
});
});
});
describe('remote session reducer', () => {
it('enters reconnecting state after an unexpected close', () => {
const state = { ...initialState(), connectionStatus: EConnectionStatus.Connected };
const next = remoteSessionReducer(state, { type: 'connectionClosed', message: 'closed' });
expect(next.connectionStatus).toBe(EConnectionStatus.Reconnecting);
expect(next.lastError).toBe('closed');
});
it('applies snapshots and clears trainer data on trainer switch', () => {
let state = remoteSessionReducer(initialState(), { type: 'trainerValues', payload: { speed: 2 } });
state = remoteSessionReducer(state, { type: 'valueChanged', target: 'speed', value: 3 });
expect(state.values.speed).toBe(3);
state = remoteSessionReducer(state, { type: 'trainerChanged' });
expect(state.values).toEqual({});
expect(state.pendingWrites).toEqual({});
});
it('keeps a write pending until result and commits a successful result', () => {
let state = withConfirmedValue(1);
state = remoteSessionReducer(state, { type: 'writeStarted', target: 'speed', value: 2, requestId: 'new' });
expect(state.values.speed).toBe(2);
expect(state.pendingWrites.speed?.requestId).toBe('new');
state = remoteSessionReducer(state, { type: 'writeResult', target: 'speed', requestId: 'new', ok: true });
expect(state.confirmedValues.speed).toBe(2);
expect(state.pendingWrites.speed).toBeUndefined();
});
it('clears a write after a matching value delta', () => {
let state = withConfirmedValue(false);
state = remoteSessionReducer(state, { type: 'writeStarted', target: 'speed', value: true, requestId: 'new' });
state = remoteSessionReducer(state, { type: 'valueChanged', target: 'speed', value: true });
expect(state.pendingWrites.speed).toBeUndefined();
expect(state.confirmedValues.speed).toBe(true);
});
it('rolls back only the current rejected request', () => {
let state = withConfirmedValue(1);
state = remoteSessionReducer(state, { type: 'writeStarted', target: 'speed', value: 2, requestId: 'old' });
state = remoteSessionReducer(state, { type: 'writeStarted', target: 'speed', value: 3, requestId: 'new' });
state = remoteSessionReducer(state, { type: 'writeResult', target: 'speed', requestId: 'old', ok: false });
expect(state.values.speed).toBe(3);
expect(state.pendingWrites.speed?.requestId).toBe('new');
state = remoteSessionReducer(state, { type: 'writeResult', target: 'speed', requestId: 'new', ok: false });
expect(state.values.speed).toBe(1);
expect(state.pendingWrites.speed).toBeUndefined();
});
});
function helloAck(protocolVersion: number): HelloAckMessage {
return {
type: 'hello_ack',
version: PROTOCOL_VERSION,
requestId: 'hello',
payload: {
sessionId: 'session',
accepted: true,
serverVersion: 'test',
protocolVersion,
},
};
}
function initialState(): RemoteSessionState {
return { ...createInitialRemoteSessionState(), wsUrl: 'ws://test' };
}
function withConfirmedValue(value: unknown): RemoteSessionState {
return {
...initialState(),
values: { speed: value },
confirmedValues: { speed: value },
};
}