mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
fix tests
This commit is contained in:
parent
a75abe1454
commit
88489ea2eb
9 changed files with 27 additions and 28 deletions
|
|
@ -30,8 +30,8 @@ export class SessionResponseImpl implements WebsocketTypes.ISessionResponse {
|
|||
ServerDispatch.connectionFailed();
|
||||
}
|
||||
|
||||
testConnectionSuccessful(serverOptions: number): void {
|
||||
ServerDispatch.testConnectionSuccessful(serverOptions);
|
||||
testConnectionSuccessful(supportsHashedPassword: boolean): void {
|
||||
ServerDispatch.testConnectionSuccessful(supportsHashedPassword);
|
||||
}
|
||||
|
||||
testConnectionFailed(): void {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { LoadingState, useKnownHosts, useReduxEffect, useWebClient } from '@app/
|
|||
import { getHostPort, HostDTO } from '@app/services';
|
||||
import { ServerDispatch, ServerSelectors, ServerTypes, useAppSelector } from '@app/store';
|
||||
import { App } from '@app/types';
|
||||
import { passwordSaltSupported } from '@app/websocket';
|
||||
|
||||
export enum TestConnection {
|
||||
TESTING = 'testing',
|
||||
|
|
@ -83,14 +82,13 @@ export function useKnownHostsComponent({
|
|||
testConnection(selectedHost);
|
||||
}, [selectedHost]);
|
||||
|
||||
useReduxEffect<{ serverOptions: number }>(({ payload: { serverOptions } }) => {
|
||||
useReduxEffect<{ supportsHashedPassword: boolean }>(({ payload: { supportsHashedPassword } }) => {
|
||||
const host = pendingTestRef.current;
|
||||
if (!host) {
|
||||
return;
|
||||
}
|
||||
pendingTestRef.current = null;
|
||||
|
||||
const supportsHashedPassword = passwordSaltSupported(serverOptions);
|
||||
if (host.id != null && host.supportsHashedPassword !== supportsHashedPassword) {
|
||||
void knownHosts.update(host.id, { supportsHashedPassword });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ describe('Actions', () => {
|
|||
});
|
||||
|
||||
it('testConnectionSuccessful', () => {
|
||||
expect(Actions.testConnectionSuccessful({ serverOptions: 1 })).toEqual({
|
||||
expect(Actions.testConnectionSuccessful({ supportsHashedPassword: true })).toEqual({
|
||||
type: Types.TEST_CONNECTION_SUCCESSFUL,
|
||||
payload: { serverOptions: 1 },
|
||||
payload: { supportsHashedPassword: true },
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ describe('Dispatch', () => {
|
|||
});
|
||||
|
||||
it('testConnectionSuccessful dispatches Actions.testConnectionSuccessful()', () => {
|
||||
Dispatch.testConnectionSuccessful(3);
|
||||
Dispatch.testConnectionSuccessful(true);
|
||||
expect(mockDispatch).toHaveBeenCalledWith(
|
||||
Actions.testConnectionSuccessful({ serverOptions: 3 }),
|
||||
Actions.testConnectionSuccessful({ supportsHashedPassword: true }),
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ export const Dispatch = {
|
|||
testConnectionStarted: () => {
|
||||
store.dispatch(Actions.testConnectionStarted());
|
||||
},
|
||||
testConnectionSuccessful: (serverOptions: number) => {
|
||||
store.dispatch(Actions.testConnectionSuccessful({ serverOptions }));
|
||||
testConnectionSuccessful: (supportsHashedPassword: boolean) => {
|
||||
store.dispatch(Actions.testConnectionSuccessful({ supportsHashedPassword }));
|
||||
},
|
||||
testConnectionFailed: () => {
|
||||
store.dispatch(Actions.testConnectionFailed());
|
||||
|
|
|
|||
|
|
@ -129,11 +129,11 @@ export const serverSlice = createSlice({
|
|||
state.testConnectionStatus = 'testing';
|
||||
},
|
||||
|
||||
// `serverOptions` is typed on the action so `useReduxEffect` subscribers
|
||||
// (see useKnownHostsComponent) can read it from the dispatched action —
|
||||
// it's deliberately not stored in state since only the lifecycle matters
|
||||
// here; the capability bitmask is persisted per-host to Dexie.
|
||||
testConnectionSuccessful: (state, _action: PayloadAction<{ serverOptions: number }>) => {
|
||||
// `supportsHashedPassword` is typed on the action so `useReduxEffect`
|
||||
// subscribers (see useKnownHostsComponent) can persist it to the host
|
||||
// record in Dexie. It's deliberately not stored in redux state since
|
||||
// only the lifecycle matters here; per-host capability lives in Dexie.
|
||||
testConnectionSuccessful: (state, _action: PayloadAction<{ supportsHashedPassword: boolean }>) => {
|
||||
state.testConnectionStatus = 'success';
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -205,23 +205,21 @@ describe('WebClient', () => {
|
|||
expect(MockWS).toHaveBeenCalledWith(expect.stringMatching(/:\/\/server\.example\.com\/servatrice$/));
|
||||
});
|
||||
|
||||
it('dispatches testConnectionSuccessful with serverOptions on ServerIdentification', () => {
|
||||
it('dispatches testConnectionSuccessful with supportsHashedPassword=true when the bit is set', () => {
|
||||
client.testConnect(target);
|
||||
const data = buildServerIdentificationMessage({
|
||||
serverOptions: Event_ServerIdentification_ServerOptions.SupportsPasswordHash,
|
||||
});
|
||||
wsMockInstance.onmessage({ data: data.buffer });
|
||||
expect(mockResponse.session.testConnectionSuccessful).toHaveBeenCalledWith(
|
||||
Event_ServerIdentification_ServerOptions.SupportsPasswordHash,
|
||||
);
|
||||
expect(mockResponse.session.testConnectionSuccessful).toHaveBeenCalledWith(true);
|
||||
expect(wsMockInstance.close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('reports success with serverOptions=0 for naked-password servers', () => {
|
||||
it('dispatches testConnectionSuccessful with supportsHashedPassword=false for naked-password servers', () => {
|
||||
client.testConnect(target);
|
||||
const data = buildServerIdentificationMessage({ serverOptions: 0 });
|
||||
wsMockInstance.onmessage({ data: data.buffer });
|
||||
expect(mockResponse.session.testConnectionSuccessful).toHaveBeenCalledWith(0);
|
||||
expect(mockResponse.session.testConnectionSuccessful).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('fails on protocol-version mismatch instead of reporting success', () => {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { StatusEnum } from './types/StatusEnum';
|
|||
import { ProtobufService } from './services/ProtobufService';
|
||||
import { WebSocketService } from './services/WebSocketService';
|
||||
import { buildWebSocketUrl } from './utils/buildWebSocketUrl';
|
||||
import { passwordSaltSupported } from './utils/passwordHasher';
|
||||
|
||||
export class WebClient {
|
||||
private static _instance: WebClient | null = null;
|
||||
|
|
@ -96,10 +97,12 @@ export class WebClient {
|
|||
this.testSocket = socket;
|
||||
|
||||
// "Green" means reachable AND speaking a compatible Cockatrice protocol.
|
||||
// Waiting for Event_ServerIdentification lets us carry serverOptions back
|
||||
// to the UI so naked-password hosts can be distinguished without a login.
|
||||
// Waiting for Event_ServerIdentification lets us read the hashed-password
|
||||
// capability before the user ever logs in. The bitmask is resolved here
|
||||
// (the websocket layer owns protocol details) so downstream consumers
|
||||
// receive a domain-level boolean instead of a raw integer.
|
||||
let resolved = false;
|
||||
const resolve = (ok: boolean, serverOptions = 0): void => {
|
||||
const resolve = (ok: boolean, supportsHashedPassword = false): void => {
|
||||
if (resolved) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -109,7 +112,7 @@ export class WebClient {
|
|||
// already taken over and we'd race a stale result into its pending-ref.
|
||||
if (this.testSocket === socket) {
|
||||
if (ok) {
|
||||
this.response.session.testConnectionSuccessful(serverOptions);
|
||||
this.response.session.testConnectionSuccessful(supportsHashedPassword);
|
||||
} else {
|
||||
this.response.session.testConnectionFailed();
|
||||
}
|
||||
|
|
@ -135,7 +138,7 @@ export class WebClient {
|
|||
resolve(false);
|
||||
return;
|
||||
}
|
||||
resolve(true, ident.serverOptions);
|
||||
resolve(true, passwordSaltSupported(ident.serverOptions));
|
||||
} catch {
|
||||
resolve(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export interface ISessionResponse {
|
|||
loginSuccessful(options: LoginSuccessContext): void;
|
||||
loginFailed(): void;
|
||||
connectionFailed(): void;
|
||||
testConnectionSuccessful(serverOptions: number): void;
|
||||
testConnectionSuccessful(supportsHashedPassword: boolean): void;
|
||||
testConnectionFailed(): void;
|
||||
updateBuddyList(buddyList: ServerInfo_User[]): void;
|
||||
addToBuddyList(user: ServerInfo_User): void;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue