mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
more integration tests
This commit is contained in:
parent
4b5f66d497
commit
decebc25c7
192 changed files with 3090 additions and 1657 deletions
8
webclient/src/websocket/StatusEnum.ts
Normal file
8
webclient/src/websocket/StatusEnum.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export enum StatusEnum {
|
||||
DISCONNECTED,
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
LOGGING_IN,
|
||||
LOGGED_IN,
|
||||
DISCONNECTING = 99
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
const captured = vi.hoisted(() => ({
|
||||
wsOptions: null as WebSocketServiceConfig | null,
|
||||
pbOptions: null as SocketTransport | null,
|
||||
pbEvents: null as EventRegistries | null,
|
||||
}));
|
||||
|
||||
vi.mock('./services/WebSocketService', () => ({
|
||||
|
|
@ -17,8 +18,9 @@ vi.mock('./services/WebSocketService', () => ({
|
|||
}));
|
||||
|
||||
vi.mock('./services/ProtobufService', () => ({
|
||||
ProtobufService: vi.fn().mockImplementation(function ProtobufServiceImpl(options: SocketTransport) {
|
||||
captured.pbOptions = options;
|
||||
ProtobufService: vi.fn().mockImplementation(function ProtobufServiceImpl(transport: SocketTransport, events: EventRegistries) {
|
||||
captured.pbOptions = transport;
|
||||
captured.pbEvents = events;
|
||||
return {
|
||||
handleMessageEvent: vi.fn(),
|
||||
resetCommands: vi.fn(),
|
||||
|
|
@ -26,29 +28,28 @@ vi.mock('./services/ProtobufService', () => ({
|
|||
}),
|
||||
}));
|
||||
|
||||
vi.mock('./commands/session', () => ({
|
||||
ping: vi.fn(),
|
||||
}));
|
||||
|
||||
import { WebClient } from './WebClient';
|
||||
import { WebSocketService } from './services/WebSocketService';
|
||||
import { ProtobufService } from './services/ProtobufService';
|
||||
import { ping } from './commands/session';
|
||||
import { App, Enriched } from '@app/types';
|
||||
import { StatusEnum } from './StatusEnum';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Mock } from 'vitest';
|
||||
import { SocketTransport } from './services/ProtobufService';
|
||||
import { SocketTransport, EventRegistries } from './services/ProtobufService';
|
||||
import { WebSocketServiceConfig } from './services/WebSocketService';
|
||||
import type { IWebClientResponse, IWebClientRequest } from './interfaces';
|
||||
import { installMockWebSocket } from './__mocks__/helpers';
|
||||
import type { IWebClientResponse } from './interfaces';
|
||||
import type { WebClientConfig, ConnectTarget } from './WebClientConfig';
|
||||
import { installMockWebSocket, useWebClientCleanup } from './__mocks__/helpers';
|
||||
|
||||
function makeMockResponse(): IWebClientResponse {
|
||||
return {
|
||||
session: {
|
||||
initialized: vi.fn(),
|
||||
connectionAttempted: vi.fn(),
|
||||
connectionFailed: vi.fn(),
|
||||
clearStore: vi.fn(),
|
||||
updateStatus: vi.fn(),
|
||||
testConnectionSuccessful: vi.fn(),
|
||||
testConnectionFailed: vi.fn(),
|
||||
},
|
||||
room: { clearStore: vi.fn() },
|
||||
game: { clearStore: vi.fn() },
|
||||
|
|
@ -57,28 +58,35 @@ function makeMockResponse(): IWebClientResponse {
|
|||
} as unknown as IWebClientResponse;
|
||||
}
|
||||
|
||||
function makeMockRequest(): IWebClientRequest {
|
||||
function makeMockConfig(response: IWebClientResponse): WebClientConfig {
|
||||
return {
|
||||
authentication: {},
|
||||
session: {},
|
||||
rooms: {},
|
||||
admin: {},
|
||||
moderator: {},
|
||||
} as unknown as IWebClientRequest;
|
||||
response,
|
||||
onServerIdentified: vi.fn(),
|
||||
sessionEvents: [],
|
||||
roomEvents: [],
|
||||
gameEvents: [],
|
||||
keepAliveFn: vi.fn(),
|
||||
};
|
||||
}
|
||||
|
||||
useWebClientCleanup();
|
||||
|
||||
describe('WebClient', () => {
|
||||
let client: WebClient;
|
||||
let mockResponse: IWebClientResponse;
|
||||
let mockRequest: IWebClientRequest;
|
||||
let mockConfig: WebClientConfig;
|
||||
let messageSubject: Subject<MessageEvent>;
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset the singleton so each test starts fresh.
|
||||
// This direct reset is needed in addition to useWebClientCleanup() because
|
||||
// this file imports the real WebClient (not a mock), and with isolate:false
|
||||
// the helper's import may resolve to a different (mocked) module reference.
|
||||
(WebClient as unknown as { _instance: WebClient | null })._instance = null;
|
||||
|
||||
(ProtobufService as Mock).mockImplementation(function ProtobufServiceImpl(options: SocketTransport) {
|
||||
captured.pbOptions = options;
|
||||
(ProtobufService as Mock).mockImplementation(function ProtobufServiceImpl(transport: SocketTransport, events: EventRegistries) {
|
||||
captured.pbOptions = transport;
|
||||
captured.pbEvents = events;
|
||||
return {
|
||||
handleMessageEvent: vi.fn(),
|
||||
resetCommands: vi.fn(),
|
||||
|
|
@ -98,8 +106,8 @@ describe('WebClient', () => {
|
|||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
|
||||
mockResponse = makeMockResponse();
|
||||
mockRequest = makeMockRequest();
|
||||
client = new WebClient(mockResponse, mockRequest);
|
||||
mockConfig = makeMockConfig(mockResponse);
|
||||
client = new WebClient(mockConfig);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -108,9 +116,9 @@ describe('WebClient', () => {
|
|||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('stores the response and request on the instance', () => {
|
||||
it('stores the response and config on the instance', () => {
|
||||
expect(client.response).toBe(mockResponse);
|
||||
expect(client.request).toBe(mockRequest);
|
||||
expect(client.config).toBe(mockConfig);
|
||||
});
|
||||
|
||||
it('subscribes socket.message$ to protobuf.handleMessageEvent', () => {
|
||||
|
|
@ -128,7 +136,7 @@ describe('WebClient', () => {
|
|||
});
|
||||
|
||||
it('throws when instantiated more than once', () => {
|
||||
expect(() => new WebClient(makeMockResponse(), makeMockRequest())).toThrow(/singleton/);
|
||||
expect(() => new WebClient(makeMockConfig(makeMockResponse()))).toThrow(/singleton/);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -141,16 +149,15 @@ describe('WebClient', () => {
|
|||
|
||||
describe('connect', () => {
|
||||
it('calls response.session.connectionAttempted', () => {
|
||||
const opts: Enriched.WebSocketConnectOptions = { host: 'h', port: '1', reason: App.WebSocketConnectReason.LOGIN, userName: 'u' };
|
||||
client.connect(opts);
|
||||
const target: ConnectTarget = { host: 'h', port: '1' };
|
||||
client.connect(target);
|
||||
expect(mockResponse.session.connectionAttempted).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('stores options and calls socket.connect', () => {
|
||||
const opts: Enriched.WebSocketConnectOptions = { host: 'h', port: '1', reason: App.WebSocketConnectReason.LOGIN, userName: 'u' };
|
||||
client.connect(opts);
|
||||
expect(client.options).toBe(opts);
|
||||
expect(client.socket.connect).toHaveBeenCalledWith(opts);
|
||||
it('calls socket.connect with target', () => {
|
||||
const target: ConnectTarget = { host: 'h', port: '1' };
|
||||
client.connect(target);
|
||||
expect(client.socket.connect).toHaveBeenCalledWith(target);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -172,30 +179,28 @@ describe('WebClient', () => {
|
|||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
const opts: Enriched.WebSocketConnectOptions = { host: 'h', port: '1', reason: App.WebSocketConnectReason.LOGIN, userName: 'u' };
|
||||
const target: ConnectTarget = { host: 'h', port: '1' };
|
||||
|
||||
it('creates a WebSocket with the correct URL', () => {
|
||||
client.testConnect(opts);
|
||||
client.testConnect(target);
|
||||
expect(MockWS).toHaveBeenCalledWith(expect.stringContaining('://h:1'));
|
||||
});
|
||||
|
||||
it('calls testConnectionSuccessful and closes on open', () => {
|
||||
(mockResponse.session as any).testConnectionSuccessful = vi.fn();
|
||||
client.testConnect(opts);
|
||||
client.testConnect(target);
|
||||
wsMockInstance.onopen();
|
||||
expect((mockResponse.session as any).testConnectionSuccessful).toHaveBeenCalled();
|
||||
expect(mockResponse.session.testConnectionSuccessful).toHaveBeenCalled();
|
||||
expect(wsMockInstance.close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls testConnectionFailed on error', () => {
|
||||
(mockResponse.session as any).testConnectionFailed = vi.fn();
|
||||
client.testConnect(opts);
|
||||
client.testConnect(target);
|
||||
wsMockInstance.onerror();
|
||||
expect((mockResponse.session as any).testConnectionFailed).toHaveBeenCalled();
|
||||
expect(mockResponse.session.testConnectionFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('closes socket after keepalive timeout', () => {
|
||||
client.testConnect(opts);
|
||||
client.testConnect(target);
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(wsMockInstance.close).toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -210,32 +215,43 @@ describe('WebClient', () => {
|
|||
|
||||
describe('updateStatus', () => {
|
||||
it('sets the status', () => {
|
||||
client.updateStatus(App.StatusEnum.CONNECTED);
|
||||
expect(client.status).toBe(App.StatusEnum.CONNECTED);
|
||||
client.updateStatus(StatusEnum.CONNECTED);
|
||||
expect(client.status).toBe(StatusEnum.CONNECTED);
|
||||
});
|
||||
|
||||
it('calls protobuf.resetCommands on DISCONNECTED', () => {
|
||||
client.updateStatus(App.StatusEnum.DISCONNECTED);
|
||||
client.updateStatus(StatusEnum.DISCONNECTED);
|
||||
expect(client.protobuf.resetCommands).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not reset protobuf when status is not DISCONNECTED', () => {
|
||||
client.updateStatus(App.StatusEnum.CONNECTED);
|
||||
client.updateStatus(StatusEnum.CONNECTED);
|
||||
expect(client.protobuf.resetCommands).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('constructor closures', () => {
|
||||
it('keepAliveFn calls ping with the callback', () => {
|
||||
it('keepAliveFn forwards from config to WebSocketService', () => {
|
||||
const cb = vi.fn();
|
||||
captured.wsOptions!.keepAliveFn(cb);
|
||||
expect(ping).toHaveBeenCalledWith(cb);
|
||||
expect(mockConfig.keepAliveFn).toHaveBeenCalledWith(cb);
|
||||
});
|
||||
|
||||
it('onStatusChange routes to response.session.updateStatus and updates own status', () => {
|
||||
captured.wsOptions!.onStatusChange(App.StatusEnum.CONNECTED, 'Connected');
|
||||
expect(mockResponse.session.updateStatus).toHaveBeenCalledWith(App.StatusEnum.CONNECTED, 'Connected');
|
||||
expect(client.status).toBe(App.StatusEnum.CONNECTED);
|
||||
captured.wsOptions!.onStatusChange(StatusEnum.CONNECTED, 'Connected');
|
||||
expect(mockResponse.session.updateStatus).toHaveBeenCalledWith(StatusEnum.CONNECTED, 'Connected');
|
||||
expect(client.status).toBe(StatusEnum.CONNECTED);
|
||||
});
|
||||
|
||||
it('onConnectionFailed routes to response.session.connectionFailed', () => {
|
||||
captured.wsOptions!.onConnectionFailed();
|
||||
expect(mockResponse.session.connectionFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('passes event registries from config to ProtobufService', () => {
|
||||
expect(captured.pbEvents!.sessionEvents).toBe(mockConfig.sessionEvents);
|
||||
expect(captured.pbEvents!.roomEvents).toBe(mockConfig.roomEvents);
|
||||
expect(captured.pbEvents!.gameEvents).toBe(mockConfig.gameEvents);
|
||||
});
|
||||
|
||||
it('send closure delegates to socket.send', () => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { App, Enriched } from '@app/types';
|
||||
|
||||
import { StatusEnum } from './StatusEnum';
|
||||
import { ProtobufService } from './services/ProtobufService';
|
||||
import { WebSocketService } from './services/WebSocketService';
|
||||
import { ping } from './commands/session';
|
||||
import { CLIENT_OPTIONS } from './config';
|
||||
import { IWebClientResponse, IWebClientRequest } from './interfaces';
|
||||
import type { IWebClientResponse } from './interfaces';
|
||||
import type { WebClientConfig, ConnectTarget } from './WebClientConfig';
|
||||
|
||||
export class WebClient {
|
||||
private static _instance: WebClient | null = null;
|
||||
|
|
@ -12,7 +11,7 @@ export class WebClient {
|
|||
public static get instance(): WebClient {
|
||||
if (!WebClient._instance) {
|
||||
throw new Error(
|
||||
'WebClient has not been initialized. Instantiate it via `new WebClient(response, request)` before accessing `WebClient.instance`.'
|
||||
'WebClient has not been initialized. Instantiate it via `new WebClient(config)` before accessing `WebClient.instance`.'
|
||||
);
|
||||
}
|
||||
return WebClient._instance;
|
||||
|
|
@ -21,32 +20,40 @@ export class WebClient {
|
|||
public socket: WebSocketService;
|
||||
public protobuf: ProtobufService;
|
||||
public response: IWebClientResponse;
|
||||
public request: IWebClientRequest;
|
||||
public config: WebClientConfig;
|
||||
|
||||
public options: Enriched.WebSocketConnectOptions | null = null;
|
||||
public status: App.StatusEnum;
|
||||
public status: StatusEnum;
|
||||
|
||||
constructor(response: IWebClientResponse, request: IWebClientRequest) {
|
||||
constructor(config: WebClientConfig) {
|
||||
if (WebClient._instance) {
|
||||
throw new Error('WebClient is a singleton and has already been initialized.');
|
||||
}
|
||||
|
||||
this.response = response;
|
||||
this.request = request;
|
||||
this.config = config;
|
||||
this.response = config.response;
|
||||
|
||||
this.socket = new WebSocketService({
|
||||
keepAliveFn: (cb) => ping(cb),
|
||||
response,
|
||||
keepAliveFn: config.keepAliveFn,
|
||||
onStatusChange: (status, description) => {
|
||||
this.response.session.updateStatus(status, description);
|
||||
this.updateStatus(status);
|
||||
},
|
||||
onConnectionFailed: () => {
|
||||
this.response.session.connectionFailed();
|
||||
},
|
||||
});
|
||||
|
||||
this.protobuf = new ProtobufService({
|
||||
send: (data) => this.socket.send(data),
|
||||
isOpen: () => this.socket.checkReadyState(WebSocket.OPEN),
|
||||
});
|
||||
this.protobuf = new ProtobufService(
|
||||
{
|
||||
send: (data) => this.socket.send(data),
|
||||
isOpen: () => this.socket.checkReadyState(WebSocket.OPEN),
|
||||
},
|
||||
{
|
||||
sessionEvents: config.sessionEvents,
|
||||
roomEvents: config.roomEvents,
|
||||
gameEvents: config.gameEvents,
|
||||
},
|
||||
);
|
||||
|
||||
this.socket.message$.subscribe((message: MessageEvent) => {
|
||||
this.protobuf.handleMessageEvent(message);
|
||||
|
|
@ -57,15 +64,14 @@ export class WebClient {
|
|||
this.response.session.initialized();
|
||||
}
|
||||
|
||||
public connect(options: Enriched.WebSocketConnectOptions) {
|
||||
public connect(target: ConnectTarget) {
|
||||
this.response.session.connectionAttempted();
|
||||
this.options = options;
|
||||
this.socket.connect(options);
|
||||
this.socket.connect(target);
|
||||
}
|
||||
|
||||
public testConnect(options: Enriched.WebSocketConnectOptions) {
|
||||
public testConnect(target: ConnectTarget) {
|
||||
const protocol = window.location.hostname === 'localhost' ? 'ws' : 'wss';
|
||||
const { host, port } = options;
|
||||
const { host, port } = target;
|
||||
const socket = new WebSocket(`${protocol}://${host}:${port}`);
|
||||
socket.binaryType = 'arraybuffer';
|
||||
|
||||
|
|
@ -88,10 +94,10 @@ export class WebClient {
|
|||
this.socket.disconnect();
|
||||
}
|
||||
|
||||
public updateStatus(status: App.StatusEnum) {
|
||||
public updateStatus(status: StatusEnum) {
|
||||
this.status = status;
|
||||
|
||||
if (status === App.StatusEnum.DISCONNECTED) {
|
||||
if (status === StatusEnum.DISCONNECTED) {
|
||||
this.protobuf.resetCommands();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
27
webclient/src/websocket/WebClientConfig.ts
Normal file
27
webclient/src/websocket/WebClientConfig.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import type {
|
||||
RegistryEntry,
|
||||
SessionEvent,
|
||||
RoomEvent,
|
||||
GameEvent,
|
||||
Event_ServerIdentification,
|
||||
} from '@app/generated';
|
||||
|
||||
import type { GameEventMeta } from './types';
|
||||
import type { IWebClientResponse } from './interfaces';
|
||||
|
||||
export interface ConnectTarget {
|
||||
host: string;
|
||||
port: string;
|
||||
}
|
||||
|
||||
export interface WebClientConfig {
|
||||
response: IWebClientResponse;
|
||||
|
||||
onServerIdentified(info: Event_ServerIdentification): void;
|
||||
|
||||
sessionEvents: RegistryEntry<unknown, SessionEvent>[];
|
||||
roomEvents: RegistryEntry<unknown, RoomEvent, RoomEvent>[];
|
||||
gameEvents: RegistryEntry<unknown, GameEvent, GameEventMeta>[];
|
||||
|
||||
keepAliveFn(pingReceived: () => void): void;
|
||||
}
|
||||
|
|
@ -1,8 +1,27 @@
|
|||
/**
|
||||
* Shared mock factories for websocket layer unit tests.
|
||||
* Import the helpers you need in each spec file via:
|
||||
* import { makeMockWebSocket } from '../__mocks__/helpers';
|
||||
* import { makeMockWebSocket, useWebClientCleanup } from '../__mocks__/helpers';
|
||||
*/
|
||||
import { WebClient } from '../WebClient';
|
||||
|
||||
/**
|
||||
* Resets the WebClient singleton to null. Call directly, or use
|
||||
* `useWebClientCleanup()` to register automatic beforeEach/afterEach hooks.
|
||||
*/
|
||||
export function resetWebClientSingleton() {
|
||||
(WebClient as unknown as { _instance: WebClient | null })._instance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers beforeEach/afterEach hooks that reset the WebClient singleton.
|
||||
* Call at describe-level or file-level in any spec that mocks WebClient.
|
||||
* Prevents isolate:false singleton leakage between spec files.
|
||||
*/
|
||||
export function useWebClientCleanup() {
|
||||
beforeEach(() => resetWebClientSingleton());
|
||||
afterEach(() => resetWebClientSingleton());
|
||||
}
|
||||
|
||||
/** Builds a mock WebSocket instance */
|
||||
export function makeMockWebSocketInstance() {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export function makeWebClientMock() {
|
|||
testConnect: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
updateStatus: vi.fn(),
|
||||
options: {},
|
||||
config: { onServerIdentified: vi.fn() },
|
||||
status: 0,
|
||||
protobuf: {
|
||||
sendSessionCommand: vi.fn(),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_AdjustMod_ext, Command_AdjustModSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
export function adjustMod(userName: string, shouldBeMod?: boolean, shouldBeJudge?: boolean): void {
|
||||
WebClient.instance.protobuf.sendAdminCommand(
|
||||
Data.Command_AdjustMod_ext,
|
||||
create(Data.Command_AdjustModSchema, { userName, shouldBeMod, shouldBeJudge }),
|
||||
Command_AdjustMod_ext,
|
||||
create(Command_AdjustModSchema, { userName, shouldBeMod, shouldBeJudge }),
|
||||
{
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.admin.adjustMod(userName, shouldBeMod, shouldBeJudge);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ vi.mock('../../WebClient', () => ({
|
|||
}));
|
||||
|
||||
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
|
||||
import { useWebClientCleanup } from '../../__mocks__/helpers';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { adjustMod } from './adjustMod';
|
||||
import { reloadConfig } from './reloadConfig';
|
||||
|
|
@ -23,6 +24,8 @@ import { updateServerMessage } from './updateServerMessage';
|
|||
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
useWebClientCleanup();
|
||||
|
||||
const { invokeOnSuccess } = makeCallbackHelpers(
|
||||
WebClient.instance.protobuf.sendAdminCommand as Mock,
|
||||
2
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ReloadConfig_ext, Command_ReloadConfigSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
export function reloadConfig(): void {
|
||||
WebClient.instance.protobuf.sendAdminCommand(Data.Command_ReloadConfig_ext, create(Data.Command_ReloadConfigSchema), {
|
||||
WebClient.instance.protobuf.sendAdminCommand(Command_ReloadConfig_ext, create(Command_ReloadConfigSchema), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.admin.reloadConfig();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ShutdownServer_ext, Command_ShutdownServerSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
export function shutdownServer(reason: string, minutes: number): void {
|
||||
WebClient.instance.protobuf.sendAdminCommand(
|
||||
Data.Command_ShutdownServer_ext,
|
||||
create(Data.Command_ShutdownServerSchema, { reason, minutes }),
|
||||
Command_ShutdownServer_ext,
|
||||
create(Command_ShutdownServerSchema, { reason, minutes }),
|
||||
{
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.admin.shutdownServer();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_UpdateServerMessage_ext, Command_UpdateServerMessageSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
export function updateServerMessage(): void {
|
||||
WebClient.instance.protobuf.sendAdminCommand(Data.Command_UpdateServerMessage_ext, create(Data.Command_UpdateServerMessageSchema), {
|
||||
WebClient.instance.protobuf.sendAdminCommand(Command_UpdateServerMessage_ext, create(Command_UpdateServerMessageSchema), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.admin.updateServerMessage();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_AttachCard_ext, Command_AttachCardSchema, type AttachCardParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function attachCard(gameId: number, params: Data.AttachCardParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_AttachCard_ext, create(Data.Command_AttachCardSchema, params));
|
||||
export function attachCard(gameId: number, params: AttachCardParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_AttachCard_ext, create(Command_AttachCardSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_ChangeZoneProperties_ext, Command_ChangeZonePropertiesSchema, type ChangeZonePropertiesParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function changeZoneProperties(gameId: number, params: Data.ChangeZonePropertiesParams): void {
|
||||
export function changeZoneProperties(gameId: number, params: ChangeZonePropertiesParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(
|
||||
gameId,
|
||||
Data.Command_ChangeZoneProperties_ext,
|
||||
create(Data.Command_ChangeZonePropertiesSchema, params)
|
||||
Command_ChangeZoneProperties_ext,
|
||||
create(Command_ChangeZonePropertiesSchema, params)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_Concede_ext, Command_ConcedeSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function concede(gameId: number): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_Concede_ext, create(Data.Command_ConcedeSchema));
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_Concede_ext, create(Command_ConcedeSchema));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_CreateArrow_ext, Command_CreateArrowSchema, type CreateArrowParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function createArrow(gameId: number, params: Data.CreateArrowParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_CreateArrow_ext, create(Data.Command_CreateArrowSchema, params));
|
||||
export function createArrow(gameId: number, params: CreateArrowParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_CreateArrow_ext, create(Command_CreateArrowSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_CreateCounter_ext, Command_CreateCounterSchema, type CreateCounterParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function createCounter(gameId: number, params: Data.CreateCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_CreateCounter_ext, create(Data.Command_CreateCounterSchema, params));
|
||||
export function createCounter(gameId: number, params: CreateCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_CreateCounter_ext, create(Command_CreateCounterSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_CreateToken_ext, Command_CreateTokenSchema, type CreateTokenParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function createToken(gameId: number, params: Data.CreateTokenParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_CreateToken_ext, create(Data.Command_CreateTokenSchema, params));
|
||||
export function createToken(gameId: number, params: CreateTokenParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_CreateToken_ext, create(Command_CreateTokenSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_DeckSelect_ext, Command_DeckSelectSchema, type DeckSelectParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function deckSelect(gameId: number, params: Data.DeckSelectParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_DeckSelect_ext, create(Data.Command_DeckSelectSchema, params));
|
||||
export function deckSelect(gameId: number, params: DeckSelectParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_DeckSelect_ext, create(Command_DeckSelectSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_DelCounter_ext, Command_DelCounterSchema, type DelCounterParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function delCounter(gameId: number, params: Data.DelCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_DelCounter_ext, create(Data.Command_DelCounterSchema, params));
|
||||
export function delCounter(gameId: number, params: DelCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_DelCounter_ext, create(Command_DelCounterSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_DeleteArrow_ext, Command_DeleteArrowSchema, type DeleteArrowParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function deleteArrow(gameId: number, params: Data.DeleteArrowParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_DeleteArrow_ext, create(Data.Command_DeleteArrowSchema, params));
|
||||
export function deleteArrow(gameId: number, params: DeleteArrowParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_DeleteArrow_ext, create(Command_DeleteArrowSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_DrawCards_ext, Command_DrawCardsSchema, type DrawCardsParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function drawCards(gameId: number, params: Data.DrawCardsParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_DrawCards_ext, create(Data.Command_DrawCardsSchema, params));
|
||||
export function drawCards(gameId: number, params: DrawCardsParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_DrawCards_ext, create(Command_DrawCardsSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_DumpZone_ext, Command_DumpZoneSchema, type DumpZoneParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function dumpZone(gameId: number, params: Data.DumpZoneParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_DumpZone_ext, create(Data.Command_DumpZoneSchema, params));
|
||||
export function dumpZone(gameId: number, params: DumpZoneParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_DumpZone_ext, create(Command_DumpZoneSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_FlipCard_ext, Command_FlipCardSchema, type FlipCardParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function flipCard(gameId: number, params: Data.FlipCardParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_FlipCard_ext, create(Data.Command_FlipCardSchema, params));
|
||||
export function flipCard(gameId: number, params: FlipCardParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_FlipCard_ext, create(Command_FlipCardSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,48 @@ vi.mock('../../WebClient', () => ({
|
|||
}));
|
||||
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { useWebClientCleanup } from '../../__mocks__/helpers';
|
||||
|
||||
useWebClientCleanup();
|
||||
import { create, setExtension } from '@bufbuild/protobuf';
|
||||
import { Data } from '@app/types';
|
||||
import {
|
||||
Command_AttachCard_ext,
|
||||
Command_ChangeZoneProperties_ext,
|
||||
Command_Concede_ext,
|
||||
Command_CreateArrow_ext,
|
||||
Command_CreateCounter_ext,
|
||||
Command_CreateToken_ext,
|
||||
Command_DeckSelect_ext,
|
||||
Command_DelCounter_ext,
|
||||
Command_DeleteArrow_ext,
|
||||
Command_DrawCards_ext,
|
||||
Command_DrawCardsSchema,
|
||||
Command_DumpZone_ext,
|
||||
Command_FlipCard_ext,
|
||||
Command_GameSay_ext,
|
||||
Command_IncCardCounter_ext,
|
||||
Command_IncCounter_ext,
|
||||
Command_Judge_ext,
|
||||
Command_KickFromGame_ext,
|
||||
Command_LeaveGame_ext,
|
||||
Command_MoveCard_ext,
|
||||
Command_Mulligan_ext,
|
||||
Command_NextTurn_ext,
|
||||
Command_ReadyStart_ext,
|
||||
Command_RevealCards_ext,
|
||||
Command_ReverseTurn_ext,
|
||||
Command_RollDie_ext,
|
||||
Command_SetActivePhase_ext,
|
||||
Command_SetCardAttr_ext,
|
||||
Command_SetCardCounter_ext,
|
||||
Command_SetCounter_ext,
|
||||
Command_SetSideboardLock_ext,
|
||||
Command_SetSideboardPlan_ext,
|
||||
Command_Shuffle_ext,
|
||||
Command_UndoDraw_ext,
|
||||
Command_Unconcede_ext,
|
||||
GameCommandSchema,
|
||||
} from '@app/generated';
|
||||
|
||||
import { attachCard } from './attachCard';
|
||||
import { changeZoneProperties } from './changeZoneProperties';
|
||||
|
|
@ -52,122 +92,122 @@ describe('Game commands — delegate to WebClient.instance.protobuf.sendGameComm
|
|||
it('attachCard sends Command_AttachCard', () => {
|
||||
attachCard(gameId, { cardId: 10, startZone: 'hand' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_AttachCard_ext, expect.objectContaining({ cardId: 10, startZone: 'hand' })
|
||||
gameId, Command_AttachCard_ext, expect.objectContaining({ cardId: 10, startZone: 'hand' })
|
||||
);
|
||||
});
|
||||
|
||||
it('changeZoneProperties sends Command_ChangeZoneProperties', () => {
|
||||
changeZoneProperties(gameId, { zoneName: 'side' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_ChangeZoneProperties_ext, expect.objectContaining({ zoneName: 'side' })
|
||||
gameId, Command_ChangeZoneProperties_ext, expect.objectContaining({ zoneName: 'side' })
|
||||
);
|
||||
});
|
||||
|
||||
it('concede sends Command_Concede with empty object', () => {
|
||||
concede(gameId);
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Data.Command_Concede_ext, expect.any(Object));
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_Concede_ext, expect.any(Object));
|
||||
});
|
||||
|
||||
it('createArrow sends Command_CreateArrow', () => {
|
||||
createArrow(gameId, { startPlayerId: 1, startZone: 'hand' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_CreateArrow_ext, expect.objectContaining({ startPlayerId: 1, startZone: 'hand' })
|
||||
gameId, Command_CreateArrow_ext, expect.objectContaining({ startPlayerId: 1, startZone: 'hand' })
|
||||
);
|
||||
});
|
||||
|
||||
it('createCounter sends Command_CreateCounter', () => {
|
||||
createCounter(gameId, { counterName: 'life' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_CreateCounter_ext, expect.objectContaining({ counterName: 'life' })
|
||||
gameId, Command_CreateCounter_ext, expect.objectContaining({ counterName: 'life' })
|
||||
);
|
||||
});
|
||||
|
||||
it('createToken sends Command_CreateToken', () => {
|
||||
createToken(gameId, { cardName: 'Goblin', zone: 'play' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_CreateToken_ext, expect.objectContaining({ cardName: 'Goblin', zone: 'play' })
|
||||
gameId, Command_CreateToken_ext, expect.objectContaining({ cardName: 'Goblin', zone: 'play' })
|
||||
);
|
||||
});
|
||||
|
||||
it('deckSelect sends Command_DeckSelect', () => {
|
||||
deckSelect(gameId, { deckId: 5 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_DeckSelect_ext, expect.objectContaining({ deckId: 5 })
|
||||
gameId, Command_DeckSelect_ext, expect.objectContaining({ deckId: 5 })
|
||||
);
|
||||
});
|
||||
|
||||
it('delCounter sends Command_DelCounter', () => {
|
||||
delCounter(gameId, { counterId: 3 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_DelCounter_ext, expect.objectContaining({ counterId: 3 })
|
||||
gameId, Command_DelCounter_ext, expect.objectContaining({ counterId: 3 })
|
||||
);
|
||||
});
|
||||
|
||||
it('deleteArrow sends Command_DeleteArrow', () => {
|
||||
deleteArrow(gameId, { arrowId: 2 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_DeleteArrow_ext, expect.objectContaining({ arrowId: 2 })
|
||||
gameId, Command_DeleteArrow_ext, expect.objectContaining({ arrowId: 2 })
|
||||
);
|
||||
});
|
||||
|
||||
it('drawCards sends Command_DrawCards', () => {
|
||||
drawCards(gameId, { number: 3 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_DrawCards_ext, expect.objectContaining({ number: 3 })
|
||||
gameId, Command_DrawCards_ext, expect.objectContaining({ number: 3 })
|
||||
);
|
||||
});
|
||||
|
||||
it('dumpZone sends Command_DumpZone', () => {
|
||||
dumpZone(gameId, { playerId: 2, zoneName: 'library' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_DumpZone_ext, expect.objectContaining({ playerId: 2, zoneName: 'library' })
|
||||
gameId, Command_DumpZone_ext, expect.objectContaining({ playerId: 2, zoneName: 'library' })
|
||||
);
|
||||
});
|
||||
|
||||
it('flipCard sends Command_FlipCard', () => {
|
||||
flipCard(gameId, { cardId: 7, faceDown: false });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_FlipCard_ext, expect.objectContaining({ cardId: 7, faceDown: false })
|
||||
gameId, Command_FlipCard_ext, expect.objectContaining({ cardId: 7, faceDown: false })
|
||||
);
|
||||
});
|
||||
|
||||
it('gameSay sends Command_GameSay', () => {
|
||||
gameSay(gameId, { message: 'hello' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_GameSay_ext, expect.objectContaining({ message: 'hello' })
|
||||
gameId, Command_GameSay_ext, expect.objectContaining({ message: 'hello' })
|
||||
);
|
||||
});
|
||||
|
||||
it('incCardCounter sends Command_IncCardCounter', () => {
|
||||
incCardCounter(gameId, { cardId: 5, counterId: 1 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_IncCardCounter_ext, expect.objectContaining({ cardId: 5, counterId: 1 })
|
||||
gameId, Command_IncCardCounter_ext, expect.objectContaining({ cardId: 5, counterId: 1 })
|
||||
);
|
||||
});
|
||||
|
||||
it('incCounter sends Command_IncCounter', () => {
|
||||
incCounter(gameId, { counterId: 1, delta: 5 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_IncCounter_ext, expect.objectContaining({ counterId: 1, delta: 5 })
|
||||
gameId, Command_IncCounter_ext, expect.objectContaining({ counterId: 1, delta: 5 })
|
||||
);
|
||||
});
|
||||
|
||||
it('kickFromGame sends Command_KickFromGame', () => {
|
||||
kickFromGame(gameId, { playerId: 2 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_KickFromGame_ext, expect.objectContaining({ playerId: 2 })
|
||||
gameId, Command_KickFromGame_ext, expect.objectContaining({ playerId: 2 })
|
||||
);
|
||||
});
|
||||
|
||||
it('leaveGame sends Command_LeaveGame with empty object', () => {
|
||||
leaveGame(gameId);
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Data.Command_LeaveGame_ext, expect.any(Object));
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_LeaveGame_ext, expect.any(Object));
|
||||
});
|
||||
|
||||
it('moveCard sends Command_MoveCard', () => {
|
||||
moveCard(gameId, { startZone: 'hand', targetZone: 'graveyard' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_MoveCard_ext,
|
||||
gameId, Command_MoveCard_ext,
|
||||
expect.objectContaining({ startZone: 'hand', targetZone: 'graveyard' })
|
||||
);
|
||||
});
|
||||
|
|
@ -175,45 +215,45 @@ describe('Game commands — delegate to WebClient.instance.protobuf.sendGameComm
|
|||
it('mulligan sends Command_Mulligan', () => {
|
||||
mulligan(gameId, { number: 7 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_Mulligan_ext, expect.objectContaining({ number: 7 })
|
||||
gameId, Command_Mulligan_ext, expect.objectContaining({ number: 7 })
|
||||
);
|
||||
});
|
||||
|
||||
it('nextTurn sends Command_NextTurn with empty object', () => {
|
||||
nextTurn(gameId);
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Data.Command_NextTurn_ext, expect.any(Object));
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_NextTurn_ext, expect.any(Object));
|
||||
});
|
||||
|
||||
it('readyStart sends Command_ReadyStart', () => {
|
||||
readyStart(gameId, { ready: true });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_ReadyStart_ext, expect.objectContaining({ ready: true })
|
||||
gameId, Command_ReadyStart_ext, expect.objectContaining({ ready: true })
|
||||
);
|
||||
});
|
||||
|
||||
it('revealCards sends Command_RevealCards', () => {
|
||||
revealCards(gameId, { zoneName: 'hand', cardId: [1, 2] });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_RevealCards_ext, expect.objectContaining({ zoneName: 'hand', cardId: [1, 2] })
|
||||
gameId, Command_RevealCards_ext, expect.objectContaining({ zoneName: 'hand', cardId: [1, 2] })
|
||||
);
|
||||
});
|
||||
|
||||
it('reverseTurn sends Command_ReverseTurn with empty object', () => {
|
||||
reverseTurn(gameId);
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Data.Command_ReverseTurn_ext, expect.any(Object));
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_ReverseTurn_ext, expect.any(Object));
|
||||
});
|
||||
|
||||
it('setActivePhase sends Command_SetActivePhase', () => {
|
||||
setActivePhase(gameId, { phase: 2 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_SetActivePhase_ext, expect.objectContaining({ phase: 2 })
|
||||
gameId, Command_SetActivePhase_ext, expect.objectContaining({ phase: 2 })
|
||||
);
|
||||
});
|
||||
|
||||
it('setCardAttr sends Command_SetCardAttr', () => {
|
||||
setCardAttr(gameId, { zone: 'play', cardId: 5, attrValue: '2' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_SetCardAttr_ext,
|
||||
gameId, Command_SetCardAttr_ext,
|
||||
expect.objectContaining({ zone: 'play', cardId: 5, attrValue: '2' })
|
||||
);
|
||||
});
|
||||
|
|
@ -221,63 +261,63 @@ describe('Game commands — delegate to WebClient.instance.protobuf.sendGameComm
|
|||
it('setCardCounter sends Command_SetCardCounter', () => {
|
||||
setCardCounter(gameId, { cardId: 5, counterId: 1 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_SetCardCounter_ext, expect.objectContaining({ cardId: 5, counterId: 1 })
|
||||
gameId, Command_SetCardCounter_ext, expect.objectContaining({ cardId: 5, counterId: 1 })
|
||||
);
|
||||
});
|
||||
|
||||
it('setCounter sends Command_SetCounter', () => {
|
||||
setCounter(gameId, { counterId: 1, value: 10 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_SetCounter_ext, expect.objectContaining({ counterId: 1, value: 10 })
|
||||
gameId, Command_SetCounter_ext, expect.objectContaining({ counterId: 1, value: 10 })
|
||||
);
|
||||
});
|
||||
|
||||
it('setSideboardLock sends Command_SetSideboardLock', () => {
|
||||
setSideboardLock(gameId, { locked: true });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_SetSideboardLock_ext, expect.objectContaining({ locked: true })
|
||||
gameId, Command_SetSideboardLock_ext, expect.objectContaining({ locked: true })
|
||||
);
|
||||
});
|
||||
|
||||
it('setSideboardPlan sends Command_SetSideboardPlan', () => {
|
||||
setSideboardPlan(gameId, { moveList: [] });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_SetSideboardPlan_ext, expect.objectContaining({ moveList: expect.any(Array) })
|
||||
gameId, Command_SetSideboardPlan_ext, expect.objectContaining({ moveList: expect.any(Array) })
|
||||
);
|
||||
});
|
||||
|
||||
it('shuffle sends Command_Shuffle', () => {
|
||||
shuffle(gameId, { zoneName: 'hand' });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_Shuffle_ext, expect.objectContaining({ zoneName: 'hand' })
|
||||
gameId, Command_Shuffle_ext, expect.objectContaining({ zoneName: 'hand' })
|
||||
);
|
||||
});
|
||||
|
||||
it('undoDraw sends Command_UndoDraw with empty object', () => {
|
||||
undoDraw(gameId);
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Data.Command_UndoDraw_ext, expect.any(Object));
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_UndoDraw_ext, expect.any(Object));
|
||||
});
|
||||
|
||||
it('unconcede sends Command_Unconcede with empty object', () => {
|
||||
unconcede(gameId);
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Data.Command_Unconcede_ext, expect.any(Object));
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_Unconcede_ext, expect.any(Object));
|
||||
});
|
||||
|
||||
it('rollDie sends Command_RollDie', () => {
|
||||
rollDie(gameId, { sides: 6, count: 2 });
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId, Data.Command_RollDie_ext, expect.objectContaining({ sides: 6, count: 2 })
|
||||
gameId, Command_RollDie_ext, expect.objectContaining({ sides: 6, count: 2 })
|
||||
);
|
||||
});
|
||||
|
||||
it('judge sends Command_Judge with targetId and wrapped gameCommand array', () => {
|
||||
const targetId = 3;
|
||||
const innerCmd = create(Data.GameCommandSchema);
|
||||
setExtension(innerCmd, Data.Command_DrawCards_ext, create(Data.Command_DrawCardsSchema, { number: 2 }));
|
||||
const innerCmd = create(GameCommandSchema);
|
||||
setExtension(innerCmd, Command_DrawCards_ext, create(Command_DrawCardsSchema, { number: 2 }));
|
||||
judge(gameId, targetId, innerCmd);
|
||||
expect(WebClient.instance.protobuf.sendGameCommand).toHaveBeenCalledWith(
|
||||
gameId,
|
||||
Data.Command_Judge_ext,
|
||||
Command_Judge_ext,
|
||||
expect.objectContaining({ targetId: 3, gameCommand: expect.any(Array) })
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_GameSay_ext, Command_GameSaySchema, type GameSayParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function gameSay(gameId: number, params: Data.GameSayParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_GameSay_ext, create(Data.Command_GameSaySchema, params));
|
||||
export function gameSay(gameId: number, params: GameSayParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_GameSay_ext, create(Command_GameSaySchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_IncCardCounter_ext, Command_IncCardCounterSchema, type IncCardCounterParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function incCardCounter(gameId: number, params: Data.IncCardCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_IncCardCounter_ext, create(Data.Command_IncCardCounterSchema, params));
|
||||
export function incCardCounter(gameId: number, params: IncCardCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_IncCardCounter_ext, create(Command_IncCardCounterSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_IncCounter_ext, Command_IncCounterSchema, type IncCounterParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function incCounter(gameId: number, params: Data.IncCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_IncCounter_ext, create(Data.Command_IncCounterSchema, params));
|
||||
export function incCounter(gameId: number, params: IncCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_IncCounter_ext, create(Command_IncCounterSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_Judge_ext, Command_JudgeSchema, type GameCommand } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function judge(gameId: number, targetId: number, innerGameCommand: Data.GameCommand): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_Judge_ext, create(Data.Command_JudgeSchema, {
|
||||
export function judge(gameId: number, targetId: number, innerGameCommand: GameCommand): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_Judge_ext, create(Command_JudgeSchema, {
|
||||
targetId,
|
||||
gameCommand: [innerGameCommand],
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_KickFromGame_ext, Command_KickFromGameSchema, type KickFromGameParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function kickFromGame(gameId: number, params: Data.KickFromGameParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_KickFromGame_ext, create(Data.Command_KickFromGameSchema, params));
|
||||
export function kickFromGame(gameId: number, params: KickFromGameParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_KickFromGame_ext, create(Command_KickFromGameSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_LeaveGame_ext, Command_LeaveGameSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function leaveGame(gameId: number): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_LeaveGame_ext, create(Data.Command_LeaveGameSchema));
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_LeaveGame_ext, create(Command_LeaveGameSchema));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_MoveCard_ext, Command_MoveCardSchema, type MoveCardParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function moveCard(gameId: number, params: Data.MoveCardParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_MoveCard_ext, create(Data.Command_MoveCardSchema, params));
|
||||
export function moveCard(gameId: number, params: MoveCardParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_MoveCard_ext, create(Command_MoveCardSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_Mulligan_ext, Command_MulliganSchema, type MulliganParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function mulligan(gameId: number, params: Data.MulliganParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_Mulligan_ext, create(Data.Command_MulliganSchema, params));
|
||||
export function mulligan(gameId: number, params: MulliganParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_Mulligan_ext, create(Command_MulliganSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_NextTurn_ext, Command_NextTurnSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function nextTurn(gameId: number): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_NextTurn_ext, create(Data.Command_NextTurnSchema));
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_NextTurn_ext, create(Command_NextTurnSchema));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_ReadyStart_ext, Command_ReadyStartSchema, type ReadyStartParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function readyStart(gameId: number, params: Data.ReadyStartParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_ReadyStart_ext, create(Data.Command_ReadyStartSchema, params));
|
||||
export function readyStart(gameId: number, params: ReadyStartParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_ReadyStart_ext, create(Command_ReadyStartSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_RevealCards_ext, Command_RevealCardsSchema, type RevealCardsParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function revealCards(gameId: number, params: Data.RevealCardsParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_RevealCards_ext, create(Data.Command_RevealCardsSchema, params));
|
||||
export function revealCards(gameId: number, params: RevealCardsParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_RevealCards_ext, create(Command_RevealCardsSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_ReverseTurn_ext, Command_ReverseTurnSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function reverseTurn(gameId: number): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_ReverseTurn_ext, create(Data.Command_ReverseTurnSchema));
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_ReverseTurn_ext, create(Command_ReverseTurnSchema));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_RollDie_ext, Command_RollDieSchema, type RollDieParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function rollDie(gameId: number, params: Data.RollDieParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_RollDie_ext, create(Data.Command_RollDieSchema, params));
|
||||
export function rollDie(gameId: number, params: RollDieParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_RollDie_ext, create(Command_RollDieSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_SetActivePhase_ext, Command_SetActivePhaseSchema, type SetActivePhaseParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function setActivePhase(gameId: number, params: Data.SetActivePhaseParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_SetActivePhase_ext, create(Data.Command_SetActivePhaseSchema, params));
|
||||
export function setActivePhase(gameId: number, params: SetActivePhaseParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_SetActivePhase_ext, create(Command_SetActivePhaseSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_SetCardAttr_ext, Command_SetCardAttrSchema, type SetCardAttrParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function setCardAttr(gameId: number, params: Data.SetCardAttrParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_SetCardAttr_ext, create(Data.Command_SetCardAttrSchema, params));
|
||||
export function setCardAttr(gameId: number, params: SetCardAttrParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_SetCardAttr_ext, create(Command_SetCardAttrSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_SetCardCounter_ext, Command_SetCardCounterSchema, type SetCardCounterParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function setCardCounter(gameId: number, params: Data.SetCardCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_SetCardCounter_ext, create(Data.Command_SetCardCounterSchema, params));
|
||||
export function setCardCounter(gameId: number, params: SetCardCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_SetCardCounter_ext, create(Command_SetCardCounterSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_SetCounter_ext, Command_SetCounterSchema, type SetCounterParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function setCounter(gameId: number, params: Data.SetCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_SetCounter_ext, create(Data.Command_SetCounterSchema, params));
|
||||
export function setCounter(gameId: number, params: SetCounterParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_SetCounter_ext, create(Command_SetCounterSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_SetSideboardLock_ext, Command_SetSideboardLockSchema, type SetSideboardLockParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function setSideboardLock(gameId: number, params: Data.SetSideboardLockParams): void {
|
||||
export function setSideboardLock(gameId: number, params: SetSideboardLockParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(
|
||||
gameId,
|
||||
Data.Command_SetSideboardLock_ext,
|
||||
create(Data.Command_SetSideboardLockSchema, params)
|
||||
Command_SetSideboardLock_ext,
|
||||
create(Command_SetSideboardLockSchema, params)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_SetSideboardPlan_ext, Command_SetSideboardPlanSchema, type SetSideboardPlanParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function setSideboardPlan(gameId: number, params: Data.SetSideboardPlanParams): void {
|
||||
export function setSideboardPlan(gameId: number, params: SetSideboardPlanParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(
|
||||
gameId,
|
||||
Data.Command_SetSideboardPlan_ext,
|
||||
create(Data.Command_SetSideboardPlanSchema, params)
|
||||
Command_SetSideboardPlan_ext,
|
||||
create(Command_SetSideboardPlanSchema, params)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_Shuffle_ext, Command_ShuffleSchema, type ShuffleParams } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function shuffle(gameId: number, params: Data.ShuffleParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_Shuffle_ext, create(Data.Command_ShuffleSchema, params));
|
||||
export function shuffle(gameId: number, params: ShuffleParams): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_Shuffle_ext, create(Command_ShuffleSchema, params));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_Unconcede_ext, Command_UnconcedeSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function unconcede(gameId: number): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_Unconcede_ext, create(Data.Command_UnconcedeSchema));
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_Unconcede_ext, create(Command_UnconcedeSchema));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Command_UndoDraw_ext, Command_UndoDrawSchema } from '@app/generated';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
|
||||
export function undoDraw(gameId: number): void {
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Data.Command_UndoDraw_ext, create(Data.Command_UndoDrawSchema));
|
||||
WebClient.instance.protobuf.sendGameCommand(gameId, Command_UndoDraw_ext, create(Command_UndoDrawSchema));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_BanFromServer_ext, Command_BanFromServerSchema } from '@app/generated';
|
||||
|
||||
export function banFromServer(minutes: number, userName?: string, address?: string, reason?: string,
|
||||
visibleReason?: string, clientid?: string, removeMessages?: number): void {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Data.Command_BanFromServer_ext, create(Data.Command_BanFromServerSchema, {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Command_BanFromServer_ext, create(Command_BanFromServerSchema, {
|
||||
minutes, userName, address, reason, visibleReason, clientid, removeMessages
|
||||
}), {
|
||||
onSuccess: () => {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ForceActivateUser_ext, Command_ForceActivateUserSchema } from '@app/generated';
|
||||
|
||||
export function forceActivateUser(usernameToActivate: string, moderatorName: string): void {
|
||||
const cmd = create(Data.Command_ForceActivateUserSchema, { usernameToActivate, moderatorName });
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Data.Command_ForceActivateUser_ext, cmd, {
|
||||
const cmd = create(Command_ForceActivateUserSchema, { usernameToActivate, moderatorName });
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Command_ForceActivateUser_ext, cmd, {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.moderator.forceActivateUser(usernameToActivate, moderatorName);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_GetAdminNotes_ext, Command_GetAdminNotesSchema, Response_GetAdminNotes_ext } from '@app/generated';
|
||||
|
||||
export function getAdminNotes(userName: string): void {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Data.Command_GetAdminNotes_ext, create(Data.Command_GetAdminNotesSchema, { userName }), {
|
||||
responseExt: Data.Response_GetAdminNotes_ext,
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Command_GetAdminNotes_ext, create(Command_GetAdminNotesSchema, { userName }), {
|
||||
responseExt: Response_GetAdminNotes_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.moderator.getAdminNotes(userName, response.notes);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_GetBanHistory_ext, Command_GetBanHistorySchema, Response_BanHistory_ext } from '@app/generated';
|
||||
|
||||
export function getBanHistory(userName: string): void {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Data.Command_GetBanHistory_ext, create(Data.Command_GetBanHistorySchema, { userName }), {
|
||||
responseExt: Data.Response_BanHistory_ext,
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Command_GetBanHistory_ext, create(Command_GetBanHistorySchema, { userName }), {
|
||||
responseExt: Response_BanHistory_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.moderator.banHistory(userName, response.banList);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_GetWarnHistory_ext, Command_GetWarnHistorySchema, Response_WarnHistory_ext } from '@app/generated';
|
||||
|
||||
export function getWarnHistory(userName: string): void {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(
|
||||
Data.Command_GetWarnHistory_ext,
|
||||
create(Data.Command_GetWarnHistorySchema, { userName }),
|
||||
Command_GetWarnHistory_ext,
|
||||
create(Command_GetWarnHistorySchema, { userName }),
|
||||
{
|
||||
responseExt: Data.Response_WarnHistory_ext,
|
||||
responseExt: Response_WarnHistory_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.moderator.warnHistory(userName, response.warnList);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_GetWarnList_ext, Command_GetWarnListSchema, Response_WarnList_ext } from '@app/generated';
|
||||
|
||||
export function getWarnList(modName: string, userName: string, userClientid: string): void {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(
|
||||
Data.Command_GetWarnList_ext,
|
||||
create(Data.Command_GetWarnListSchema, { modName, userName, userClientid }),
|
||||
Command_GetWarnList_ext,
|
||||
create(Command_GetWarnListSchema, { modName, userName, userClientid }),
|
||||
{
|
||||
responseExt: Data.Response_WarnList_ext,
|
||||
responseExt: Response_WarnList_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.moderator.warnListOptions([response]);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_GrantReplayAccess_ext, Command_GrantReplayAccessSchema } from '@app/generated';
|
||||
|
||||
export function grantReplayAccess(replayId: number, moderatorName: string): void {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(
|
||||
Data.Command_GrantReplayAccess_ext,
|
||||
create(Data.Command_GrantReplayAccessSchema, { replayId, moderatorName }),
|
||||
Command_GrantReplayAccess_ext,
|
||||
create(Command_GrantReplayAccessSchema, { replayId, moderatorName }),
|
||||
{
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.moderator.grantReplayAccess(replayId, moderatorName);
|
||||
|
|
|
|||
|
|
@ -21,8 +21,26 @@ vi.mock('../../WebClient', () => ({
|
|||
}));
|
||||
|
||||
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
|
||||
import { useWebClientCleanup } from '../../__mocks__/helpers';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
import {
|
||||
Command_BanFromServer_ext,
|
||||
Command_ForceActivateUser_ext,
|
||||
Command_GetAdminNotes_ext,
|
||||
Command_GetBanHistory_ext,
|
||||
Command_GetWarnHistory_ext,
|
||||
Command_GetWarnList_ext,
|
||||
Command_GrantReplayAccess_ext,
|
||||
Command_UpdateAdminNotes_ext,
|
||||
Command_ViewLogHistory_ext,
|
||||
Command_ViewLogHistorySchema,
|
||||
Command_WarnUser_ext,
|
||||
Response_BanHistory_ext,
|
||||
Response_GetAdminNotes_ext,
|
||||
Response_ViewLogHistory_ext,
|
||||
Response_WarnHistory_ext,
|
||||
Response_WarnList_ext,
|
||||
} from '@app/generated';
|
||||
|
||||
import { banFromServer } from './banFromServer';
|
||||
import { forceActivateUser } from './forceActivateUser';
|
||||
|
|
@ -37,6 +55,8 @@ import { warnUser } from './warnUser';
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
useWebClientCleanup();
|
||||
|
||||
const { invokeOnSuccess } = makeCallbackHelpers(
|
||||
WebClient.instance.protobuf.sendModeratorCommand as Mock,
|
||||
2
|
||||
|
|
@ -50,7 +70,7 @@ describe('banFromServer', () => {
|
|||
it('calls sendModeratorCommand with Command_BanFromServer', () => {
|
||||
banFromServer(30, 'alice', '1.2.3.4', 'reason', 'visible', 'cid', 1);
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_BanFromServer_ext,
|
||||
Command_BanFromServer_ext,
|
||||
expect.objectContaining({ minutes: 30, userName: 'alice' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -71,7 +91,7 @@ describe('forceActivateUser', () => {
|
|||
it('calls sendModeratorCommand with Command_ForceActivateUser', () => {
|
||||
forceActivateUser('alice', 'mod1');
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ForceActivateUser_ext, expect.any(Object), expect.any(Object)
|
||||
Command_ForceActivateUser_ext, expect.any(Object), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -90,9 +110,9 @@ describe('getAdminNotes', () => {
|
|||
it('calls sendModeratorCommand with Command_GetAdminNotes', () => {
|
||||
getAdminNotes('alice');
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_GetAdminNotes_ext,
|
||||
Command_GetAdminNotes_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_GetAdminNotes_ext })
|
||||
expect.objectContaining({ responseExt: Response_GetAdminNotes_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -112,9 +132,9 @@ describe('getBanHistory', () => {
|
|||
it('calls sendModeratorCommand with Command_GetBanHistory', () => {
|
||||
getBanHistory('alice');
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_GetBanHistory_ext,
|
||||
Command_GetBanHistory_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_BanHistory_ext })
|
||||
expect.objectContaining({ responseExt: Response_BanHistory_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -134,9 +154,9 @@ describe('getWarnHistory', () => {
|
|||
it('calls sendModeratorCommand with Command_GetWarnHistory', () => {
|
||||
getWarnHistory('alice');
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_GetWarnHistory_ext,
|
||||
Command_GetWarnHistory_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_WarnHistory_ext })
|
||||
expect.objectContaining({ responseExt: Response_WarnHistory_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -156,9 +176,9 @@ describe('getWarnList', () => {
|
|||
it('calls sendModeratorCommand with Command_GetWarnList', () => {
|
||||
getWarnList('mod1', 'alice', 'US');
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_GetWarnList_ext,
|
||||
Command_GetWarnList_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_WarnList_ext })
|
||||
expect.objectContaining({ responseExt: Response_WarnList_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -178,7 +198,7 @@ describe('grantReplayAccess', () => {
|
|||
it('calls sendModeratorCommand with Command_GrantReplayAccess', () => {
|
||||
grantReplayAccess(10, 'mod1');
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_GrantReplayAccess_ext, expect.any(Object), expect.any(Object)
|
||||
Command_GrantReplayAccess_ext, expect.any(Object), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -197,7 +217,7 @@ describe('updateAdminNotes', () => {
|
|||
it('calls sendModeratorCommand with Command_UpdateAdminNotes', () => {
|
||||
updateAdminNotes('alice', 'new notes');
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_UpdateAdminNotes_ext, expect.any(Object), expect.any(Object)
|
||||
Command_UpdateAdminNotes_ext, expect.any(Object), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -214,17 +234,17 @@ describe('updateAdminNotes', () => {
|
|||
describe('viewLogHistory', () => {
|
||||
|
||||
it('calls sendModeratorCommand with Command_ViewLogHistory', () => {
|
||||
const filters = create(Data.Command_ViewLogHistorySchema, { dateRange: 7 });
|
||||
const filters = create(Command_ViewLogHistorySchema, { dateRange: 7 });
|
||||
viewLogHistory(filters);
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ViewLogHistory_ext,
|
||||
Command_ViewLogHistory_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_ViewLogHistory_ext })
|
||||
expect.objectContaining({ responseExt: Response_ViewLogHistory_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('onSuccess calls response.moderator.viewLogs with logMessage', () => {
|
||||
const filters = create(Data.Command_ViewLogHistorySchema, { dateRange: 7 });
|
||||
const filters = create(Command_ViewLogHistorySchema, { dateRange: 7 });
|
||||
viewLogHistory(filters);
|
||||
const resp = { logMessage: ['log1'] };
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
|
|
@ -240,7 +260,7 @@ describe('warnUser', () => {
|
|||
it('calls sendModeratorCommand with Command_WarnUser', () => {
|
||||
warnUser('alice', 'bad behavior', 'cid');
|
||||
expect(WebClient.instance.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
|
||||
Data.Command_WarnUser_ext, expect.any(Object), expect.any(Object)
|
||||
Command_WarnUser_ext, expect.any(Object), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_UpdateAdminNotes_ext, Command_UpdateAdminNotesSchema } from '@app/generated';
|
||||
|
||||
export function updateAdminNotes(userName: string, notes: string): void {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(
|
||||
Data.Command_UpdateAdminNotes_ext,
|
||||
create(Data.Command_UpdateAdminNotesSchema, { userName, notes }),
|
||||
Command_UpdateAdminNotes_ext,
|
||||
create(Command_UpdateAdminNotesSchema, { userName, notes }),
|
||||
{
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.moderator.updateAdminNotes(userName, notes);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ViewLogHistory_ext, Command_ViewLogHistorySchema, Response_ViewLogHistory_ext } from '@app/generated';
|
||||
import type { ViewLogHistoryParams } from '@app/generated';
|
||||
|
||||
export function viewLogHistory(filters: Data.ViewLogHistoryParams): void {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Data.Command_ViewLogHistory_ext, create(Data.Command_ViewLogHistorySchema, filters), {
|
||||
responseExt: Data.Response_ViewLogHistory_ext,
|
||||
export function viewLogHistory(filters: ViewLogHistoryParams): void {
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Command_ViewLogHistory_ext, create(Command_ViewLogHistorySchema, filters), {
|
||||
responseExt: Response_ViewLogHistory_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.moderator.viewLogs(response.logMessage);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_WarnUser_ext, Command_WarnUserSchema } from '@app/generated';
|
||||
|
||||
export function warnUser(userName: string, reason: string, clientid?: string, removeMessages?: number): void {
|
||||
const cmd = create(Data.Command_WarnUserSchema, { userName, reason, clientid, removeMessages });
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Data.Command_WarnUser_ext, cmd, {
|
||||
const cmd = create(Command_WarnUserSchema, { userName, reason, clientid, removeMessages });
|
||||
WebClient.instance.protobuf.sendModeratorCommand(Command_WarnUser_ext, cmd, {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.moderator.warnUser(userName);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_CreateGame_ext, Command_CreateGameSchema } from '@app/generated';
|
||||
import type { CreateGameParams } from '@app/generated';
|
||||
|
||||
export function createGame(roomId: number, gameConfig: Data.CreateGameParams): void {
|
||||
WebClient.instance.protobuf.sendRoomCommand(roomId, Data.Command_CreateGame_ext, create(Data.Command_CreateGameSchema, gameConfig), {
|
||||
export function createGame(roomId: number, gameConfig: CreateGameParams): void {
|
||||
WebClient.instance.protobuf.sendRoomCommand(roomId, Command_CreateGame_ext, create(Command_CreateGameSchema, gameConfig), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.room.gameCreated(roomId);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_JoinGame_ext, Command_JoinGameSchema } from '@app/generated';
|
||||
import type { JoinGameParams } from '@app/generated';
|
||||
|
||||
export function joinGame(roomId: number, joinGameParams: Data.JoinGameParams): void {
|
||||
WebClient.instance.protobuf.sendRoomCommand(roomId, Data.Command_JoinGame_ext, create(Data.Command_JoinGameSchema, joinGameParams), {
|
||||
export function joinGame(roomId: number, joinGameParams: JoinGameParams): void {
|
||||
WebClient.instance.protobuf.sendRoomCommand(roomId, Command_JoinGame_ext, create(Command_JoinGameSchema, joinGameParams), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.room.joinedGame(roomId, joinGameParams.gameId);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_LeaveRoom_ext, Command_LeaveRoomSchema } from '@app/generated';
|
||||
|
||||
export function leaveRoom(roomId: number): void {
|
||||
WebClient.instance.protobuf.sendRoomCommand(roomId, Data.Command_LeaveRoom_ext, create(Data.Command_LeaveRoomSchema), {
|
||||
WebClient.instance.protobuf.sendRoomCommand(roomId, Command_LeaveRoom_ext, create(Command_LeaveRoomSchema), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.room.leaveRoom(roomId);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,8 +14,16 @@ vi.mock('../../WebClient', () => ({
|
|||
}));
|
||||
|
||||
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
|
||||
import { useWebClientCleanup } from '../../__mocks__/helpers';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
import {
|
||||
Command_CreateGame_ext,
|
||||
Command_CreateGameSchema,
|
||||
Command_JoinGame_ext,
|
||||
Command_JoinGameSchema,
|
||||
Command_LeaveRoom_ext,
|
||||
Command_RoomSay_ext,
|
||||
} from '@app/generated';
|
||||
|
||||
import { createGame } from './createGame';
|
||||
import { joinGame } from './joinGame';
|
||||
|
|
@ -24,6 +32,8 @@ import { roomSay } from './roomSay';
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
useWebClientCleanup();
|
||||
|
||||
const { invokeOnSuccess } = makeCallbackHelpers(
|
||||
WebClient.instance.protobuf.sendRoomCommand as Mock,
|
||||
// sendRoomCommand(roomId, ext, value, options) — options at index 3
|
||||
|
|
@ -36,14 +46,14 @@ const { invokeOnSuccess } = makeCallbackHelpers(
|
|||
describe('createGame', () => {
|
||||
|
||||
it('calls sendRoomCommand with Command_CreateGame', () => {
|
||||
createGame(5, create(Data.Command_CreateGameSchema, { maxPlayers: 4 }));
|
||||
createGame(5, create(Command_CreateGameSchema, { maxPlayers: 4 }));
|
||||
expect(WebClient.instance.protobuf.sendRoomCommand).toHaveBeenCalledWith(
|
||||
5, Data.Command_CreateGame_ext, expect.objectContaining({ maxPlayers: 4 }), expect.any(Object)
|
||||
5, Command_CreateGame_ext, expect.objectContaining({ maxPlayers: 4 }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
it('onSuccess calls response.room.gameCreated with roomId', () => {
|
||||
createGame(5, create(Data.Command_CreateGameSchema, {}));
|
||||
createGame(5, create(Command_CreateGameSchema, {}));
|
||||
invokeOnSuccess();
|
||||
expect(WebClient.instance.response.room.gameCreated).toHaveBeenCalledWith(5);
|
||||
});
|
||||
|
|
@ -55,14 +65,14 @@ describe('createGame', () => {
|
|||
describe('joinGame', () => {
|
||||
|
||||
it('calls sendRoomCommand with Command_JoinGame', () => {
|
||||
joinGame(7, create(Data.Command_JoinGameSchema, { gameId: 42, password: '' }));
|
||||
joinGame(7, create(Command_JoinGameSchema, { gameId: 42, password: '' }));
|
||||
expect(WebClient.instance.protobuf.sendRoomCommand).toHaveBeenCalledWith(
|
||||
7, Data.Command_JoinGame_ext, expect.objectContaining({ gameId: 42, password: '' }), expect.any(Object)
|
||||
7, Command_JoinGame_ext, expect.objectContaining({ gameId: 42, password: '' }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
it('onSuccess calls response.room.joinedGame with roomId and gameId', () => {
|
||||
joinGame(7, create(Data.Command_JoinGameSchema, { gameId: 42 }));
|
||||
joinGame(7, create(Command_JoinGameSchema, { gameId: 42 }));
|
||||
invokeOnSuccess();
|
||||
expect(WebClient.instance.response.room.joinedGame).toHaveBeenCalledWith(7, 42);
|
||||
});
|
||||
|
|
@ -76,7 +86,7 @@ describe('leaveRoom', () => {
|
|||
it('calls sendRoomCommand with Command_LeaveRoom', () => {
|
||||
leaveRoom(3);
|
||||
expect(WebClient.instance.protobuf.sendRoomCommand).toHaveBeenCalledWith(
|
||||
3, Data.Command_LeaveRoom_ext, expect.any(Object), expect.any(Object)
|
||||
3, Command_LeaveRoom_ext, expect.any(Object), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -96,7 +106,7 @@ describe('roomSay', () => {
|
|||
roomSay(2, ' hello ');
|
||||
expect(WebClient.instance.protobuf.sendRoomCommand).toHaveBeenCalledWith(
|
||||
2,
|
||||
Data.Command_RoomSay_ext,
|
||||
Command_RoomSay_ext,
|
||||
expect.objectContaining({ message: 'hello' })
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_RoomSay_ext, Command_RoomSaySchema } from '@app/generated';
|
||||
|
||||
export function roomSay(roomId: number, message: string): void {
|
||||
const trimmed = message.trim();
|
||||
|
|
@ -9,5 +9,5 @@ export function roomSay(roomId: number, message: string): void {
|
|||
return;
|
||||
}
|
||||
|
||||
WebClient.instance.protobuf.sendRoomCommand(roomId, Data.Command_RoomSay_ext, create(Data.Command_RoomSaySchema, { message: trimmed }));
|
||||
WebClient.instance.protobuf.sendRoomCommand(roomId, Command_RoomSay_ext, create(Command_RoomSaySchema, { message: trimmed }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_AccountEdit_ext, Command_AccountEditSchema } from '@app/generated';
|
||||
|
||||
export function accountEdit(passwordCheck: string, realName?: string, email?: string, country?: string): void {
|
||||
const cmd = create(Data.Command_AccountEditSchema, { passwordCheck, realName, email, country });
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_AccountEdit_ext, cmd, {
|
||||
const cmd = create(Command_AccountEditSchema, { passwordCheck, realName, email, country });
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_AccountEdit_ext, cmd, {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.accountEditChanged(realName, email, country);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_AccountImage_ext, Command_AccountImageSchema } from '@app/generated';
|
||||
|
||||
export function accountImage(image: Uint8Array): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_AccountImage_ext, create(Data.Command_AccountImageSchema, { image }), {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_AccountImage_ext, create(Command_AccountImageSchema, { image }), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.accountImageChanged(image);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_AccountPassword_ext, Command_AccountPasswordSchema } from '@app/generated';
|
||||
|
||||
export function accountPassword(oldPassword: string, newPassword: string, hashedNewPassword: string): void {
|
||||
const cmd = create(Data.Command_AccountPasswordSchema, { oldPassword, newPassword, hashedNewPassword });
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_AccountPassword_ext, cmd, {
|
||||
const cmd = create(Command_AccountPasswordSchema, { oldPassword, newPassword, hashedNewPassword });
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_AccountPassword_ext, cmd, {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.accountPasswordChange();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,32 +1,37 @@
|
|||
import { App, Enriched, Data } from '@app/types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import {
|
||||
Command_Activate_ext,
|
||||
Command_ActivateSchema,
|
||||
Response_ResponseCode,
|
||||
type ActivateParams,
|
||||
} from '@app/generated';
|
||||
|
||||
import { StatusEnum } from '../../StatusEnum';
|
||||
import { CLIENT_CONFIG } from '../../config';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import type { ConnectTarget } from '../../WebClientConfig';
|
||||
import { disconnect, login, updateStatus } from './';
|
||||
|
||||
export function activate(options: Omit<Enriched.ActivateConnectOptions, 'password'>, password?: string, passwordSalt?: string): void {
|
||||
export function activate(options: ConnectTarget & ActivateParams, password?: string, passwordSalt?: string): void {
|
||||
const { userName, token } = options;
|
||||
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_Activate_ext, create(Data.Command_ActivateSchema, {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_Activate_ext, create(Command_ActivateSchema, {
|
||||
...CLIENT_CONFIG,
|
||||
userName,
|
||||
token,
|
||||
}), {
|
||||
onResponseCode: {
|
||||
[Data.Response_ResponseCode.RespActivationAccepted]: () => {
|
||||
[Response_ResponseCode.RespActivationAccepted]: () => {
|
||||
WebClient.instance.response.session.accountActivationSuccess();
|
||||
login({
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
userName: options.userName,
|
||||
reason: App.WebSocketConnectReason.LOGIN,
|
||||
}, password, passwordSalt);
|
||||
},
|
||||
},
|
||||
onError: () => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, 'Account Activation Failed');
|
||||
updateStatus(StatusEnum.DISCONNECTED, 'Account Activation Failed');
|
||||
disconnect();
|
||||
WebClient.instance.response.session.accountActivationFailed();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_AddToList_ext, Command_AddToListSchema } from '@app/generated';
|
||||
|
||||
export function addToBuddyList(userName: string): void {
|
||||
addToList('buddy', userName);
|
||||
|
|
@ -12,7 +12,7 @@ export function addToIgnoreList(userName: string): void {
|
|||
}
|
||||
|
||||
export function addToList(list: string, userName: string): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_AddToList_ext, create(Data.Command_AddToListSchema, { list, userName }), {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_AddToList_ext, create(Command_AddToListSchema, { list, userName }), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.addToList(list, userName);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,25 +1,10 @@
|
|||
import { App, Enriched } from '@app/types';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { updateStatus } from './';
|
||||
import type { ConnectTarget } from '../../WebClientConfig';
|
||||
|
||||
export function connect(options: Enriched.WebSocketConnectOptions): void {
|
||||
switch (options.reason) {
|
||||
case App.WebSocketConnectReason.LOGIN:
|
||||
case App.WebSocketConnectReason.REGISTER:
|
||||
case App.WebSocketConnectReason.ACTIVATE_ACCOUNT:
|
||||
case App.WebSocketConnectReason.PASSWORD_RESET_REQUEST:
|
||||
case App.WebSocketConnectReason.PASSWORD_RESET_CHALLENGE:
|
||||
case App.WebSocketConnectReason.PASSWORD_RESET:
|
||||
updateStatus(App.StatusEnum.CONNECTING, 'Connecting...');
|
||||
WebClient.instance.connect(options);
|
||||
return;
|
||||
case App.WebSocketConnectReason.TEST_CONNECTION:
|
||||
WebClient.instance.testConnect(options);
|
||||
return;
|
||||
default: {
|
||||
const { reason } = options as Enriched.WebSocketConnectOptions;
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, `Unknown Connection Attempt: ${reason}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
export function connect(target: ConnectTarget): void {
|
||||
WebClient.instance.connect(target);
|
||||
}
|
||||
|
||||
export function testConnect(target: ConnectTarget): void {
|
||||
WebClient.instance.testConnect(target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_DeckDel_ext, Command_DeckDelSchema } from '@app/generated';
|
||||
|
||||
export function deckDel(deckId: number): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_DeckDel_ext, create(Data.Command_DeckDelSchema, { deckId }), {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_DeckDel_ext, create(Command_DeckDelSchema, { deckId }), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.deleteServerDeck(deckId);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_DeckDelDir_ext, Command_DeckDelDirSchema } from '@app/generated';
|
||||
|
||||
export function deckDelDir(path: string): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_DeckDelDir_ext, create(Data.Command_DeckDelDirSchema, { path }), {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_DeckDelDir_ext, create(Command_DeckDelDirSchema, { path }), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.deleteServerDeckDir(path);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_DeckDownload_ext, Command_DeckDownloadSchema, Response_DeckDownload_ext } from '@app/generated';
|
||||
|
||||
export function deckDownload(deckId: number): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(
|
||||
Data.Command_DeckDownload_ext,
|
||||
create(Data.Command_DeckDownloadSchema, { deckId }),
|
||||
Command_DeckDownload_ext,
|
||||
create(Command_DeckDownloadSchema, { deckId }),
|
||||
{
|
||||
responseExt: Data.Response_DeckDownload_ext,
|
||||
responseExt: Response_DeckDownload_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.session.downloadServerDeck(deckId, response);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_DeckList_ext, Command_DeckListSchema, Response_DeckList_ext } from '@app/generated';
|
||||
|
||||
export function deckList(): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_DeckList_ext, create(Data.Command_DeckListSchema), {
|
||||
responseExt: Data.Response_DeckList_ext,
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_DeckList_ext, create(Command_DeckListSchema), {
|
||||
responseExt: Response_DeckList_ext,
|
||||
onSuccess: (response) => {
|
||||
if (response.root) {
|
||||
WebClient.instance.response.session.updateServerDecks(response);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_DeckNewDir_ext, Command_DeckNewDirSchema } from '@app/generated';
|
||||
|
||||
export function deckNewDir(path: string, dirName: string): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_DeckNewDir_ext, create(Data.Command_DeckNewDirSchema, { path, dirName }), {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_DeckNewDir_ext, create(Command_DeckNewDirSchema, { path, dirName }), {
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.createServerDeckDir(path, dirName);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_DeckUpload_ext, Command_DeckUploadSchema, Response_DeckUpload_ext } from '@app/generated';
|
||||
|
||||
export function deckUpload(path: string, deckId: number, deckList: string): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(
|
||||
Data.Command_DeckUpload_ext,
|
||||
create(Data.Command_DeckUploadSchema, { path, deckId, deckList }),
|
||||
Command_DeckUpload_ext,
|
||||
create(Command_DeckUploadSchema, { path, deckId, deckList }),
|
||||
{
|
||||
responseExt: Data.Response_DeckUpload_ext,
|
||||
responseExt: Response_DeckUpload_ext,
|
||||
onSuccess: (response) => {
|
||||
if (response.newFile) {
|
||||
WebClient.instance.response.session.uploadServerDeck(path, response.newFile);
|
||||
|
|
|
|||
|
|
@ -1,29 +1,34 @@
|
|||
import { App, Enriched, Data } from '@app/types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import {
|
||||
Command_ForgotPasswordChallenge_ext,
|
||||
Command_ForgotPasswordChallengeSchema,
|
||||
type ForgotPasswordChallengeParams,
|
||||
} from '@app/generated';
|
||||
|
||||
import { StatusEnum } from '../../StatusEnum';
|
||||
import { CLIENT_CONFIG } from '../../config';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import type { ConnectTarget } from '../../WebClientConfig';
|
||||
import { disconnect, updateStatus } from './';
|
||||
|
||||
export function forgotPasswordChallenge(options: Enriched.PasswordResetChallengeConnectOptions): void {
|
||||
export function forgotPasswordChallenge(options: ConnectTarget & ForgotPasswordChallengeParams): void {
|
||||
const { userName, email } = options;
|
||||
|
||||
WebClient.instance.protobuf.sendSessionCommand(
|
||||
Data.Command_ForgotPasswordChallenge_ext,
|
||||
create(Data.Command_ForgotPasswordChallengeSchema, {
|
||||
Command_ForgotPasswordChallenge_ext,
|
||||
create(Command_ForgotPasswordChallengeSchema, {
|
||||
...CLIENT_CONFIG,
|
||||
userName,
|
||||
email,
|
||||
}),
|
||||
{
|
||||
onSuccess: () => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, null);
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
WebClient.instance.response.session.resetPassword();
|
||||
disconnect();
|
||||
},
|
||||
onError: () => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, null);
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
WebClient.instance.response.session.resetPasswordFailed();
|
||||
disconnect();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,31 +1,37 @@
|
|||
import { App, Enriched, Data } from '@app/types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import {
|
||||
Command_ForgotPasswordRequest_ext,
|
||||
Command_ForgotPasswordRequestSchema,
|
||||
Response_ForgotPasswordRequest_ext,
|
||||
type ForgotPasswordRequestParams,
|
||||
} from '@app/generated';
|
||||
|
||||
import { StatusEnum } from '../../StatusEnum';
|
||||
import { CLIENT_CONFIG } from '../../config';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import type { ConnectTarget } from '../../WebClientConfig';
|
||||
import { disconnect, updateStatus } from './';
|
||||
|
||||
export function forgotPasswordRequest(options: Enriched.PasswordResetRequestConnectOptions): void {
|
||||
export function forgotPasswordRequest(options: ConnectTarget & ForgotPasswordRequestParams): void {
|
||||
const { userName } = options;
|
||||
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_ForgotPasswordRequest_ext, create(Data.Command_ForgotPasswordRequestSchema, {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_ForgotPasswordRequest_ext, create(Command_ForgotPasswordRequestSchema, {
|
||||
...CLIENT_CONFIG,
|
||||
userName,
|
||||
}), {
|
||||
responseExt: Data.Response_ForgotPasswordRequest_ext,
|
||||
responseExt: Response_ForgotPasswordRequest_ext,
|
||||
onSuccess: (resp) => {
|
||||
if (resp?.challengeEmail) {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, null);
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
WebClient.instance.response.session.resetPasswordChallenge();
|
||||
} else {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, null);
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
WebClient.instance.response.session.resetPassword();
|
||||
}
|
||||
disconnect();
|
||||
},
|
||||
onError: () => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, null);
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
WebClient.instance.response.session.resetPasswordFailed();
|
||||
disconnect();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,22 +1,26 @@
|
|||
import { App, Enriched, Data } from '@app/types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import type { MessageInitShape } from '@bufbuild/protobuf';
|
||||
import {
|
||||
Command_ForgotPasswordReset_ext,
|
||||
Command_ForgotPasswordResetSchema,
|
||||
type ForgotPasswordResetParams,
|
||||
} from '@app/generated';
|
||||
|
||||
import { StatusEnum } from '../../StatusEnum';
|
||||
import { CLIENT_CONFIG } from '../../config';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import type { ConnectTarget } from '../../WebClientConfig';
|
||||
import { hashPassword } from '../../utils';
|
||||
|
||||
import { disconnect, updateStatus } from '.';
|
||||
|
||||
export function forgotPasswordReset(
|
||||
options: Omit<Enriched.PasswordResetConnectOptions, 'newPassword'>,
|
||||
options: ConnectTarget & ForgotPasswordResetParams,
|
||||
newPassword?: string,
|
||||
passwordSalt?: string
|
||||
): void {
|
||||
const { userName, token } = options;
|
||||
|
||||
const params: MessageInitShape<typeof Data.Command_ForgotPasswordResetSchema> = {
|
||||
const params: MessageInitShape<typeof Command_ForgotPasswordResetSchema> = {
|
||||
...CLIENT_CONFIG,
|
||||
userName,
|
||||
token,
|
||||
|
|
@ -26,16 +30,16 @@ export function forgotPasswordReset(
|
|||
};
|
||||
|
||||
WebClient.instance.protobuf.sendSessionCommand(
|
||||
Data.Command_ForgotPasswordReset_ext,
|
||||
create(Data.Command_ForgotPasswordResetSchema, params),
|
||||
Command_ForgotPasswordReset_ext,
|
||||
create(Command_ForgotPasswordResetSchema, params),
|
||||
{
|
||||
onSuccess: () => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, null);
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
WebClient.instance.response.session.resetPasswordSuccess();
|
||||
disconnect();
|
||||
},
|
||||
onError: () => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, null);
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
WebClient.instance.response.session.resetPasswordFailed();
|
||||
disconnect();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_GetGamesOfUser_ext, Command_GetGamesOfUserSchema, Response_GetGamesOfUser_ext } from '@app/generated';
|
||||
|
||||
export function getGamesOfUser(userName: string): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_GetGamesOfUser_ext, create(Data.Command_GetGamesOfUserSchema, { userName }), {
|
||||
responseExt: Data.Response_GetGamesOfUser_ext,
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_GetGamesOfUser_ext, create(Command_GetGamesOfUserSchema, { userName }), {
|
||||
responseExt: Response_GetGamesOfUser_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.session.getGamesOfUser(userName, response);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_GetUserInfo_ext, Command_GetUserInfoSchema, Response_GetUserInfo_ext } from '@app/generated';
|
||||
|
||||
export function getUserInfo(userName: string): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_GetUserInfo_ext, create(Data.Command_GetUserInfoSchema, { userName }), {
|
||||
responseExt: Data.Response_GetUserInfo_ext,
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_GetUserInfo_ext, create(Command_GetUserInfoSchema, { userName }), {
|
||||
responseExt: Response_GetUserInfo_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.session.getUserInfo(response.userInfo);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_JoinRoom_ext, Command_JoinRoomSchema, Response_JoinRoom_ext } from '@app/generated';
|
||||
|
||||
export function joinRoom(roomId: number): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_JoinRoom_ext, create(Data.Command_JoinRoomSchema, { roomId }), {
|
||||
responseExt: Data.Response_JoinRoom_ext,
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_JoinRoom_ext, create(Command_JoinRoomSchema, { roomId }), {
|
||||
responseExt: Response_JoinRoom_ext,
|
||||
onSuccess: (response) => {
|
||||
if (response.roomInfo) {
|
||||
WebClient.instance.response.room.joinRoom(response.roomInfo);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ListRooms_ext, Command_ListRoomsSchema } from '@app/generated';
|
||||
|
||||
export function listRooms(): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_ListRooms_ext, create(Data.Command_ListRoomsSchema));
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_ListRooms_ext, create(Command_ListRoomsSchema));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ListUsers_ext, Command_ListUsersSchema, Response_ListUsers_ext } from '@app/generated';
|
||||
|
||||
export function listUsers(): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_ListUsers_ext, create(Data.Command_ListUsersSchema), {
|
||||
responseExt: Data.Response_ListUsers_ext,
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_ListUsers_ext, create(Command_ListUsersSchema), {
|
||||
responseExt: Response_ListUsers_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.session.updateUsers(response.userList);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
import { App, Enriched, Data } from '@app/types';
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import type { MessageInitShape } from '@bufbuild/protobuf';
|
||||
import {
|
||||
Command_Login_ext,
|
||||
Command_LoginSchema,
|
||||
Response_Login_ext,
|
||||
Response_ResponseCode,
|
||||
type LoginParams,
|
||||
} from '@app/generated';
|
||||
|
||||
import { StatusEnum } from '../../StatusEnum';
|
||||
import { CLIENT_CONFIG } from '../../config';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import type { ConnectTarget } from '../../WebClientConfig';
|
||||
import { hashPassword } from '../../utils';
|
||||
import {
|
||||
disconnect,
|
||||
|
|
@ -12,7 +20,7 @@ import {
|
|||
updateStatus,
|
||||
} from './';
|
||||
|
||||
export function login(options: Omit<Enriched.LoginConnectOptions, 'password'>, password?: string, passwordSalt?: string): void {
|
||||
export function login(options: ConnectTarget & LoginParams, password?: string, passwordSalt?: string): void {
|
||||
const { userName, hashedPassword } = options;
|
||||
|
||||
const loginConfig = {
|
||||
|
|
@ -22,51 +30,52 @@ export function login(options: Omit<Enriched.LoginConnectOptions, 'password'>, p
|
|||
...(passwordSalt
|
||||
? { hashedPassword: hashedPassword || hashPassword(passwordSalt, password) }
|
||||
: { password }),
|
||||
} satisfies MessageInitShape<typeof Data.Command_LoginSchema>;
|
||||
} satisfies MessageInitShape<typeof Command_LoginSchema>;
|
||||
|
||||
const onLoginError = (message: string, extra?: () => void) => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, message);
|
||||
updateStatus(StatusEnum.DISCONNECTED, message);
|
||||
extra?.();
|
||||
WebClient.instance.response.session.loginFailed();
|
||||
disconnect();
|
||||
};
|
||||
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_Login_ext, create(Data.Command_LoginSchema, loginConfig), {
|
||||
responseExt: Data.Response_Login_ext,
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_Login_ext, create(Command_LoginSchema, loginConfig), {
|
||||
responseExt: Response_Login_ext,
|
||||
onSuccess: (resp) => {
|
||||
const { buddyList, ignoreList, userInfo } = resp;
|
||||
|
||||
WebClient.instance.response.session.updateBuddyList(buddyList);
|
||||
WebClient.instance.response.session.updateIgnoreList(ignoreList);
|
||||
WebClient.instance.response.session.updateUser(userInfo);
|
||||
WebClient.instance.response.session.loginSuccessful({ hashedPassword: loginConfig.hashedPassword });
|
||||
WebClient.instance.response.session.loginSuccessful({ ...resp, hashedPassword: loginConfig.hashedPassword });
|
||||
|
||||
listUsers();
|
||||
listRooms();
|
||||
|
||||
updateStatus(App.StatusEnum.LOGGED_IN, 'Logged in.');
|
||||
updateStatus(StatusEnum.LOGGED_IN, 'Logged in.');
|
||||
},
|
||||
onResponseCode: {
|
||||
[Data.Response_ResponseCode.RespClientUpdateRequired]: () =>
|
||||
[Response_ResponseCode.RespClientUpdateRequired]: () =>
|
||||
onLoginError('Login failed: missing features'),
|
||||
[Data.Response_ResponseCode.RespWrongPassword]: () =>
|
||||
[Response_ResponseCode.RespWrongPassword]: () =>
|
||||
onLoginError('Login failed: incorrect username or password'),
|
||||
[Data.Response_ResponseCode.RespUsernameInvalid]: () =>
|
||||
[Response_ResponseCode.RespUsernameInvalid]: () =>
|
||||
onLoginError('Login failed: incorrect username or password'),
|
||||
[Data.Response_ResponseCode.RespWouldOverwriteOldSession]: () =>
|
||||
[Response_ResponseCode.RespWouldOverwriteOldSession]: () =>
|
||||
onLoginError('Login failed: duplicated user session'),
|
||||
[Data.Response_ResponseCode.RespUserIsBanned]: () =>
|
||||
[Response_ResponseCode.RespUserIsBanned]: () =>
|
||||
onLoginError('Login failed: banned user'),
|
||||
[Data.Response_ResponseCode.RespRegistrationRequired]: () =>
|
||||
[Response_ResponseCode.RespRegistrationRequired]: () =>
|
||||
onLoginError('Login failed: registration required'),
|
||||
[Data.Response_ResponseCode.RespClientIdRequired]: () =>
|
||||
[Response_ResponseCode.RespClientIdRequired]: () =>
|
||||
onLoginError('Login failed: missing client ID'),
|
||||
[Data.Response_ResponseCode.RespContextError]: () =>
|
||||
[Response_ResponseCode.RespContextError]: () =>
|
||||
onLoginError('Login failed: server error'),
|
||||
[Data.Response_ResponseCode.RespAccountNotActivated]: () =>
|
||||
[Response_ResponseCode.RespAccountNotActivated]: (raw) =>
|
||||
onLoginError('Login failed: account not activated',
|
||||
() => {
|
||||
WebClient.instance.response.session.accountAwaitingActivation({
|
||||
...raw,
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
userName: options.userName,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_Message_ext, Command_MessageSchema } from '@app/generated';
|
||||
|
||||
export function message(userName: string, message: string): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_Message_ext, create(Data.Command_MessageSchema, { userName, message }));
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_Message_ext, create(Command_MessageSchema, { userName, message }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_Ping_ext, Command_PingSchema } from '@app/generated';
|
||||
|
||||
export function ping(pingReceived: () => void): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_Ping_ext, create(Data.Command_PingSchema), {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_Ping_ext, create(Command_PingSchema), {
|
||||
onResponse: () => pingReceived(),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,24 @@
|
|||
import { App, Enriched, Data } from '@app/types';
|
||||
|
||||
import { create, getExtension } from '@bufbuild/protobuf';
|
||||
import type { MessageInitShape } from '@bufbuild/protobuf';
|
||||
import {
|
||||
Command_Register_ext,
|
||||
Command_RegisterSchema,
|
||||
Response_Register_ext,
|
||||
Response_ResponseCode,
|
||||
type RegisterParams,
|
||||
} from '@app/generated';
|
||||
|
||||
import { StatusEnum } from '../../StatusEnum';
|
||||
import { CLIENT_CONFIG } from '../../config';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import type { ConnectTarget } from '../../WebClientConfig';
|
||||
import { hashPassword } from '../../utils';
|
||||
|
||||
import { login, disconnect, updateStatus } from './';
|
||||
|
||||
export function register(options: Omit<Enriched.RegisterConnectOptions, 'password'>, password?: string, passwordSalt?: string): void {
|
||||
export function register(options: ConnectTarget & RegisterParams, password?: string, passwordSalt?: string): void {
|
||||
const { userName, email, country, realName } = options;
|
||||
|
||||
const params: MessageInitShape<typeof Data.Command_RegisterSchema> = {
|
||||
const params: MessageInitShape<typeof Command_RegisterSchema> = {
|
||||
...CLIENT_CONFIG,
|
||||
userName,
|
||||
email,
|
||||
|
|
@ -25,53 +31,53 @@ export function register(options: Omit<Enriched.RegisterConnectOptions, 'passwor
|
|||
|
||||
const onRegistrationError = (action: () => void) => {
|
||||
action();
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, 'Registration failed');
|
||||
updateStatus(StatusEnum.DISCONNECTED, 'Registration failed');
|
||||
disconnect();
|
||||
};
|
||||
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_Register_ext, create(Data.Command_RegisterSchema, params), {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_Register_ext, create(Command_RegisterSchema, params), {
|
||||
onResponseCode: {
|
||||
[Data.Response_ResponseCode.RespRegistrationAccepted]: () => {
|
||||
[Response_ResponseCode.RespRegistrationAccepted]: () => {
|
||||
login({
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
userName: options.userName,
|
||||
reason: App.WebSocketConnectReason.LOGIN,
|
||||
}, password, passwordSalt);
|
||||
WebClient.instance.response.session.registrationSuccess();
|
||||
},
|
||||
[Data.Response_ResponseCode.RespRegistrationAcceptedNeedsActivation]: () => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, 'Registration accepted, awaiting activation');
|
||||
[Response_ResponseCode.RespRegistrationAcceptedNeedsActivation]: (raw) => {
|
||||
updateStatus(StatusEnum.DISCONNECTED, 'Registration accepted, awaiting activation');
|
||||
WebClient.instance.response.session.accountAwaitingActivation({
|
||||
...raw,
|
||||
host: options.host,
|
||||
port: options.port,
|
||||
userName: options.userName,
|
||||
});
|
||||
disconnect();
|
||||
},
|
||||
[Data.Response_ResponseCode.RespUserAlreadyExists]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespUserAlreadyExists]: () => onRegistrationError(
|
||||
() => WebClient.instance.response.session.registrationUserNameError('Username is taken')
|
||||
),
|
||||
[Data.Response_ResponseCode.RespUsernameInvalid]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespUsernameInvalid]: () => onRegistrationError(
|
||||
() => WebClient.instance.response.session.registrationUserNameError('Invalid username')
|
||||
),
|
||||
[Data.Response_ResponseCode.RespPasswordTooShort]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespPasswordTooShort]: () => onRegistrationError(
|
||||
() => WebClient.instance.response.session.registrationPasswordError('Your password was too short')
|
||||
),
|
||||
[Data.Response_ResponseCode.RespEmailRequiredToRegister]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespEmailRequiredToRegister]: () => onRegistrationError(
|
||||
() => WebClient.instance.response.session.registrationRequiresEmail()
|
||||
),
|
||||
[Data.Response_ResponseCode.RespEmailBlackListed]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespEmailBlackListed]: () => onRegistrationError(
|
||||
() => WebClient.instance.response.session.registrationEmailError('This email provider has been blocked')
|
||||
),
|
||||
[Data.Response_ResponseCode.RespTooManyRequests]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespTooManyRequests]: () => onRegistrationError(
|
||||
() => WebClient.instance.response.session.registrationEmailError('Max accounts reached for this email')
|
||||
),
|
||||
[Data.Response_ResponseCode.RespRegistrationDisabled]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespRegistrationDisabled]: () => onRegistrationError(
|
||||
() => WebClient.instance.response.session.registrationFailed('Registration is currently disabled')
|
||||
),
|
||||
[Data.Response_ResponseCode.RespUserIsBanned]: (raw) => {
|
||||
const register = getExtension(raw, Data.Response_Register_ext);
|
||||
[Response_ResponseCode.RespUserIsBanned]: (raw) => {
|
||||
const register = getExtension(raw, Response_Register_ext);
|
||||
onRegistrationError(
|
||||
() => WebClient.instance.response.session.registrationFailed(register.deniedReasonStr, Number(register.deniedEndTime))
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_RemoveFromList_ext, Command_RemoveFromListSchema } from '@app/generated';
|
||||
|
||||
export function removeFromBuddyList(userName: string): void {
|
||||
removeFromList('buddy', userName);
|
||||
|
|
@ -13,8 +13,8 @@ export function removeFromIgnoreList(userName: string): void {
|
|||
|
||||
export function removeFromList(list: string, userName: string): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(
|
||||
Data.Command_RemoveFromList_ext,
|
||||
create(Data.Command_RemoveFromListSchema, { list, userName }),
|
||||
Command_RemoveFromList_ext,
|
||||
create(Command_RemoveFromListSchema, { list, userName }),
|
||||
{
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.removeFromList(list, userName);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ReplayDeleteMatch_ext, Command_ReplayDeleteMatchSchema } from '@app/generated';
|
||||
|
||||
export function replayDeleteMatch(gameId: number): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(
|
||||
Data.Command_ReplayDeleteMatch_ext,
|
||||
create(Data.Command_ReplayDeleteMatchSchema, { gameId }),
|
||||
Command_ReplayDeleteMatch_ext,
|
||||
create(Command_ReplayDeleteMatchSchema, { gameId }),
|
||||
{
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.replayDeleteMatch(gameId);
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ReplayDownload_ext, Command_ReplayDownloadSchema, Response_ReplayDownload_ext } from '@app/generated';
|
||||
|
||||
export function replayDownload(replayId: number): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(
|
||||
Data.Command_ReplayDownload_ext,
|
||||
create(Data.Command_ReplayDownloadSchema, { replayId }),
|
||||
Command_ReplayDownload_ext,
|
||||
create(Command_ReplayDownloadSchema, { replayId }),
|
||||
{
|
||||
responseExt: Data.Response_ReplayDownload_ext,
|
||||
responseExt: Response_ReplayDownload_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.session.replayDownloaded(replayId, response);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ReplayGetCode_ext, Command_ReplayGetCodeSchema, Response_ReplayGetCode_ext } from '@app/generated';
|
||||
|
||||
export function replayGetCode(gameId: number, onCodeReceived: (code: string) => void): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_ReplayGetCode_ext, create(Data.Command_ReplayGetCodeSchema, { gameId }), {
|
||||
responseExt: Data.Response_ReplayGetCode_ext,
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_ReplayGetCode_ext, create(Command_ReplayGetCodeSchema, { gameId }), {
|
||||
responseExt: Response_ReplayGetCode_ext,
|
||||
onSuccess: (response) => {
|
||||
onCodeReceived(response.replayCode);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ReplayList_ext, Command_ReplayListSchema, Response_ReplayList_ext } from '@app/generated';
|
||||
|
||||
export function replayList(): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_ReplayList_ext, create(Data.Command_ReplayListSchema), {
|
||||
responseExt: Data.Response_ReplayList_ext,
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_ReplayList_ext, create(Command_ReplayListSchema), {
|
||||
responseExt: Response_ReplayList_ext,
|
||||
onSuccess: (response) => {
|
||||
WebClient.instance.response.session.replayList(response.matchList);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ReplayModifyMatch_ext, Command_ReplayModifyMatchSchema } from '@app/generated';
|
||||
|
||||
export function replayModifyMatch(gameId: number, doNotHide: boolean): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(
|
||||
Data.Command_ReplayModifyMatch_ext,
|
||||
create(Data.Command_ReplayModifyMatchSchema, { gameId, doNotHide }),
|
||||
Command_ReplayModifyMatch_ext,
|
||||
create(Command_ReplayModifyMatchSchema, { gameId, doNotHide }),
|
||||
{
|
||||
onSuccess: () => {
|
||||
WebClient.instance.response.session.replayModifyMatch(gameId, doNotHide);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { Data } from '@app/types';
|
||||
import { Command_ReplaySubmitCode_ext, Command_ReplaySubmitCodeSchema } from '@app/generated';
|
||||
|
||||
export function replaySubmitCode(
|
||||
replayCode: string,
|
||||
|
|
@ -8,8 +8,8 @@ export function replaySubmitCode(
|
|||
onError?: (responseCode: number) => void,
|
||||
): void {
|
||||
WebClient.instance.protobuf.sendSessionCommand(
|
||||
Data.Command_ReplaySubmitCode_ext,
|
||||
create(Data.Command_ReplaySubmitCodeSchema, { replayCode }),
|
||||
Command_ReplaySubmitCode_ext,
|
||||
create(Command_ReplaySubmitCodeSchema, { replayCode }),
|
||||
{
|
||||
onSuccess,
|
||||
onError,
|
||||
|
|
|
|||
|
|
@ -1,66 +1,41 @@
|
|||
import { App, Enriched, Data } from '@app/types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import {
|
||||
Command_RequestPasswordSalt_ext,
|
||||
Command_RequestPasswordSaltSchema,
|
||||
Response_PasswordSalt_ext,
|
||||
Response_ResponseCode,
|
||||
type RequestPasswordSaltParams,
|
||||
} from '@app/generated';
|
||||
|
||||
import { StatusEnum } from '../../StatusEnum';
|
||||
import { CLIENT_CONFIG } from '../../config';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import type { ConnectTarget } from '../../WebClientConfig';
|
||||
import { updateStatus } from './';
|
||||
|
||||
import {
|
||||
activate,
|
||||
disconnect,
|
||||
login,
|
||||
forgotPasswordReset,
|
||||
updateStatus
|
||||
} from './';
|
||||
|
||||
type PasswordSaltOptions =
|
||||
| Omit<Enriched.LoginConnectOptions, 'password'>
|
||||
| Omit<Enriched.ActivateConnectOptions, 'password'>
|
||||
| Omit<Enriched.PasswordResetConnectOptions, 'newPassword'>;
|
||||
|
||||
export function requestPasswordSalt(options: PasswordSaltOptions, password?: string, newPassword?: string): void {
|
||||
export function requestPasswordSalt(
|
||||
options: ConnectTarget & RequestPasswordSaltParams,
|
||||
onSaltReceived: (passwordSalt: string) => void,
|
||||
onFailure: () => void,
|
||||
): void {
|
||||
const { userName } = options;
|
||||
|
||||
const onFailure = () => {
|
||||
switch (options.reason) {
|
||||
case App.WebSocketConnectReason.ACTIVATE_ACCOUNT:
|
||||
WebClient.instance.response.session.accountActivationFailed();
|
||||
break;
|
||||
case App.WebSocketConnectReason.PASSWORD_RESET:
|
||||
WebClient.instance.response.session.resetPasswordFailed();
|
||||
break;
|
||||
default:
|
||||
WebClient.instance.response.session.loginFailed();
|
||||
}
|
||||
disconnect();
|
||||
};
|
||||
|
||||
WebClient.instance.protobuf.sendSessionCommand(Data.Command_RequestPasswordSalt_ext, create(Data.Command_RequestPasswordSaltSchema, {
|
||||
WebClient.instance.protobuf.sendSessionCommand(Command_RequestPasswordSalt_ext, create(Command_RequestPasswordSaltSchema, {
|
||||
...CLIENT_CONFIG,
|
||||
userName,
|
||||
}), {
|
||||
responseExt: Data.Response_PasswordSalt_ext,
|
||||
responseExt: Response_PasswordSalt_ext,
|
||||
onSuccess: (resp) => {
|
||||
const passwordSalt = resp?.passwordSalt;
|
||||
|
||||
switch (options.reason) {
|
||||
case App.WebSocketConnectReason.ACTIVATE_ACCOUNT:
|
||||
activate(options, password, passwordSalt);
|
||||
break;
|
||||
case App.WebSocketConnectReason.PASSWORD_RESET:
|
||||
forgotPasswordReset(options, newPassword, passwordSalt);
|
||||
break;
|
||||
default:
|
||||
login(options, password, passwordSalt);
|
||||
}
|
||||
onSaltReceived(resp?.passwordSalt);
|
||||
},
|
||||
onResponseCode: {
|
||||
[Data.Response_ResponseCode.RespRegistrationRequired]: () => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, 'Login failed: registration required');
|
||||
[Response_ResponseCode.RespRegistrationRequired]: () => {
|
||||
updateStatus(StatusEnum.DISCONNECTED, 'Login failed: registration required');
|
||||
onFailure();
|
||||
},
|
||||
},
|
||||
onError: () => {
|
||||
updateStatus(App.StatusEnum.DISCONNECTED, 'Login failed: Unknown Reason');
|
||||
updateStatus(StatusEnum.DISCONNECTED, 'Login failed: Unknown Reason');
|
||||
onFailure();
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,14 +19,32 @@ vi.mock('./', async () => {
|
|||
|
||||
import { Mock } from 'vitest';
|
||||
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
|
||||
import { useWebClientCleanup } from '../../__mocks__/helpers';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import * as SessionIndexMocks from './';
|
||||
import { App, Enriched, Data } from '@app/types';
|
||||
import { App, Enriched } from '@app/types';
|
||||
import { StatusEnum } from '../../StatusEnum';
|
||||
import {
|
||||
Command_Activate_ext,
|
||||
Command_ForgotPasswordChallenge_ext,
|
||||
Command_ForgotPasswordRequest_ext,
|
||||
Command_ForgotPasswordReset_ext,
|
||||
Command_Login_ext,
|
||||
Command_Register_ext,
|
||||
Command_RequestPasswordSalt_ext,
|
||||
Response_ForgotPasswordRequest_ext,
|
||||
Response_Login_ext,
|
||||
Response_PasswordSalt_ext,
|
||||
Response_Register_ext,
|
||||
Response_RegisterSchema,
|
||||
Response_ResponseCode,
|
||||
ResponseSchema,
|
||||
} from '@app/generated';
|
||||
import { hashPassword, generateSalt, passwordSaltSupported } from '../../utils';
|
||||
|
||||
import { create, setExtension } from '@bufbuild/protobuf';
|
||||
|
||||
import { connect } from './connect';
|
||||
import { connect, testConnect } from './connect';
|
||||
import { updateStatus } from './updateStatus';
|
||||
import { login } from './login';
|
||||
import { register } from './register';
|
||||
|
|
@ -36,6 +54,7 @@ import { forgotPasswordRequest } from './forgotPasswordRequest';
|
|||
import { forgotPasswordReset } from './forgotPasswordReset';
|
||||
import { requestPasswordSalt } from './requestPasswordSalt';
|
||||
|
||||
useWebClientCleanup();
|
||||
|
||||
const { invokeOnSuccess, invokeResponseCode, invokeOnError } = makeCallbackHelpers(
|
||||
WebClient.instance.protobuf.sendSessionCommand as Mock,
|
||||
|
|
@ -88,13 +107,7 @@ const makeForgotResetOpts = (): Enriched.PasswordResetConnectOptions => ({
|
|||
newPassword: 'newpw',
|
||||
reason: App.WebSocketConnectReason.PASSWORD_RESET,
|
||||
});
|
||||
const makeSaltOpts = (
|
||||
reason: App.WebSocketConnectReason,
|
||||
extras: Record<string, unknown> = {}
|
||||
) => ({ ...baseTransport, userName: 'alice', reason, ...extras } as
|
||||
| Enriched.LoginConnectOptions
|
||||
| Enriched.ActivateConnectOptions
|
||||
| Enriched.PasswordResetConnectOptions);
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
(hashPassword as Mock).mockReturnValue('hashed_pw');
|
||||
|
|
@ -107,47 +120,17 @@ beforeEach(() => {
|
|||
// ----------------------------------------------------------------
|
||||
describe('connect', () => {
|
||||
|
||||
it('calls updateStatus CONNECTING for LOGIN reason', () => {
|
||||
connect({ host: 'h', port: '1', userName: 'u', reason: App.WebSocketConnectReason.LOGIN });
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(App.StatusEnum.CONNECTING, 'Connecting...');
|
||||
expect(WebClient.instance.connect).toHaveBeenCalled();
|
||||
it('calls WebClient.instance.connect with the target', () => {
|
||||
connect({ host: 'h', port: '1' });
|
||||
expect(WebClient.instance.connect).toHaveBeenCalledWith({ host: 'h', port: '1' });
|
||||
});
|
||||
});
|
||||
|
||||
it('calls updateStatus CONNECTING for REGISTER reason', () => {
|
||||
connect(makeRegisterOpts({ userName: 'u', realName: 'U' }));
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(App.StatusEnum.CONNECTING, 'Connecting...');
|
||||
});
|
||||
describe('testConnect', () => {
|
||||
|
||||
it('calls updateStatus CONNECTING for ACTIVATE_ACCOUNT reason', () => {
|
||||
connect({ host: 'h', port: '1', userName: 'u', token: 'tok', reason: App.WebSocketConnectReason.ACTIVATE_ACCOUNT });
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(App.StatusEnum.CONNECTING, 'Connecting...');
|
||||
});
|
||||
|
||||
it('calls updateStatus CONNECTING for PASSWORD_RESET_REQUEST reason', () => {
|
||||
connect({ host: 'h', port: '1', userName: 'u', reason: App.WebSocketConnectReason.PASSWORD_RESET_REQUEST });
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(App.StatusEnum.CONNECTING, 'Connecting...');
|
||||
});
|
||||
|
||||
it('calls updateStatus CONNECTING for PASSWORD_RESET_CHALLENGE reason', () => {
|
||||
connect({ host: 'h', port: '1', userName: 'u', email: 'a@b.com', reason: App.WebSocketConnectReason.PASSWORD_RESET_CHALLENGE });
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(App.StatusEnum.CONNECTING, 'Connecting...');
|
||||
});
|
||||
|
||||
it('calls updateStatus CONNECTING for PASSWORD_RESET reason', () => {
|
||||
connect({ host: 'h', port: '1', userName: 'u', token: 'tok', newPassword: 'newpw', reason: App.WebSocketConnectReason.PASSWORD_RESET });
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(App.StatusEnum.CONNECTING, 'Connecting...');
|
||||
});
|
||||
|
||||
it('calls testConnect for TEST_CONNECTION reason', () => {
|
||||
connect({ host: 'h', port: '1', reason: App.WebSocketConnectReason.TEST_CONNECTION });
|
||||
expect(WebClient.instance.testConnect).toHaveBeenCalled();
|
||||
expect(WebClient.instance.connect).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls updateStatus DISCONNECTED for unknown reason', () => {
|
||||
const bogus = { host: 'h', port: '1', reason: 999 as App.WebSocketConnectReason };
|
||||
connect(bogus as Enriched.WebSocketConnectOptions);
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(App.StatusEnum.DISCONNECTED, expect.stringContaining('Unknown'));
|
||||
it('calls WebClient.instance.testConnect with the target', () => {
|
||||
testConnect({ host: 'h', port: '1' });
|
||||
expect(WebClient.instance.testConnect).toHaveBeenCalledWith({ host: 'h', port: '1' });
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -157,9 +140,9 @@ describe('connect', () => {
|
|||
describe('updateStatus', () => {
|
||||
|
||||
it('calls WebClient.instance.response.session.updateStatus and WebClient.instance.updateStatus', () => {
|
||||
updateStatus(App.StatusEnum.CONNECTED, 'OK');
|
||||
expect(WebClient.instance.response.session.updateStatus).toHaveBeenCalledWith(App.StatusEnum.CONNECTED, 'OK');
|
||||
expect(WebClient.instance.updateStatus).toHaveBeenCalledWith(App.StatusEnum.CONNECTED);
|
||||
updateStatus(StatusEnum.CONNECTED, 'OK');
|
||||
expect(WebClient.instance.response.session.updateStatus).toHaveBeenCalledWith(StatusEnum.CONNECTED, 'OK');
|
||||
expect(WebClient.instance.updateStatus).toHaveBeenCalledWith(StatusEnum.CONNECTED);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -171,27 +154,27 @@ describe('login', () => {
|
|||
it('sends Command_Login with plain password when no salt', () => {
|
||||
login(makeLoginOpts(), 'pw');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_Login_ext,
|
||||
Command_Login_ext,
|
||||
expect.objectContaining({ password: 'pw' }),
|
||||
expect.objectContaining({ responseExt: Data.Response_Login_ext })
|
||||
expect.objectContaining({ responseExt: Response_Login_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('sends Command_Login with hashedPassword when salt is given', () => {
|
||||
login(makeLoginOpts(), 'pw', 'salt');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_Login_ext,
|
||||
Command_Login_ext,
|
||||
expect.objectContaining({ hashedPassword: 'hashed_pw' }),
|
||||
expect.objectContaining({ responseExt: Data.Response_Login_ext })
|
||||
expect.objectContaining({ responseExt: Response_Login_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('uses options.hashedPassword if provided', () => {
|
||||
login(makeLoginOpts({ hashedPassword: 'pre_hashed' }), 'pw', 'salt');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_Login_ext,
|
||||
Command_Login_ext,
|
||||
expect.objectContaining({ hashedPassword: 'pre_hashed' }),
|
||||
expect.objectContaining({ responseExt: Data.Response_Login_ext })
|
||||
expect.objectContaining({ responseExt: Response_Login_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -205,7 +188,7 @@ describe('login', () => {
|
|||
expect(WebClient.instance.response.session.loginSuccessful).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.listUsers).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.listRooms).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(App.StatusEnum.LOGGED_IN, 'Logged in.');
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(StatusEnum.LOGGED_IN, 'Logged in.');
|
||||
});
|
||||
|
||||
it('onSuccess does NOT pass plaintext password to loginSuccessful', () => {
|
||||
|
|
@ -226,56 +209,56 @@ describe('login', () => {
|
|||
|
||||
it('onResponseCode RespClientUpdateRequired calls onLoginError', () => {
|
||||
login(makeLoginOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespClientUpdateRequired);
|
||||
invokeResponseCode(Response_ResponseCode.RespClientUpdateRequired);
|
||||
expect(WebClient.instance.response.session.loginFailed).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.disconnect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespWrongPassword', () => {
|
||||
login(makeLoginOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespWrongPassword);
|
||||
invokeResponseCode(Response_ResponseCode.RespWrongPassword);
|
||||
expect(WebClient.instance.response.session.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespUsernameInvalid', () => {
|
||||
login(makeLoginOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespUsernameInvalid);
|
||||
invokeResponseCode(Response_ResponseCode.RespUsernameInvalid);
|
||||
expect(WebClient.instance.response.session.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespWouldOverwriteOldSession', () => {
|
||||
login(makeLoginOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespWouldOverwriteOldSession);
|
||||
invokeResponseCode(Response_ResponseCode.RespWouldOverwriteOldSession);
|
||||
expect(WebClient.instance.response.session.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespUserIsBanned', () => {
|
||||
login(makeLoginOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespUserIsBanned);
|
||||
invokeResponseCode(Response_ResponseCode.RespUserIsBanned);
|
||||
expect(WebClient.instance.response.session.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespRegistrationRequired', () => {
|
||||
login(makeLoginOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespRegistrationRequired);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationRequired);
|
||||
expect(WebClient.instance.response.session.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespClientIdRequired', () => {
|
||||
login(makeLoginOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespClientIdRequired);
|
||||
invokeResponseCode(Response_ResponseCode.RespClientIdRequired);
|
||||
expect(WebClient.instance.response.session.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespContextError', () => {
|
||||
login(makeLoginOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespContextError);
|
||||
invokeResponseCode(Response_ResponseCode.RespContextError);
|
||||
expect(WebClient.instance.response.session.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespAccountNotActivated calls accountAwaitingActivation without password in options', () => {
|
||||
login(makeLoginOpts({ password: 'leaked' }), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespAccountNotActivated);
|
||||
invokeResponseCode(Response_ResponseCode.RespAccountNotActivated);
|
||||
expect(WebClient.instance.response.session.accountAwaitingActivation).toHaveBeenCalledWith(
|
||||
expect.not.objectContaining({ password: expect.anything() })
|
||||
);
|
||||
|
|
@ -297,7 +280,7 @@ describe('register', () => {
|
|||
it('sends Command_Register with plain password when no salt', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_Register_ext,
|
||||
Command_Register_ext,
|
||||
expect.objectContaining({ password: 'pw' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -306,7 +289,7 @@ describe('register', () => {
|
|||
it('uses hashedPassword when salt is provided', () => {
|
||||
register(makeRegisterOpts(), 'pw', 'salt');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_Register_ext,
|
||||
Command_Register_ext,
|
||||
expect.objectContaining({ hashedPassword: 'hashed_pw' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -314,21 +297,21 @@ describe('register', () => {
|
|||
|
||||
it('RespRegistrationAccepted calls login without salt and registrationSuccess', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespRegistrationAccepted);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationAccepted);
|
||||
expect(SessionIndexMocks.login).toHaveBeenCalledWith(expect.any(Object), 'pw', undefined);
|
||||
expect(WebClient.instance.response.session.registrationSuccess).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespRegistrationAccepted forwards salt to login', () => {
|
||||
register(makeRegisterOpts(), 'pw', 'mySalt');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespRegistrationAccepted);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationAccepted);
|
||||
expect(SessionIndexMocks.login).toHaveBeenCalledWith(expect.any(Object), 'pw', 'mySalt');
|
||||
expect(WebClient.instance.response.session.registrationSuccess).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespRegistrationAcceptedNeedsActivation calls accountAwaitingActivation without password in options', () => {
|
||||
register(makeRegisterOpts({ password: 'leaked' }), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespRegistrationAcceptedNeedsActivation);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationAcceptedNeedsActivation);
|
||||
expect(WebClient.instance.response.session.accountAwaitingActivation).toHaveBeenCalledWith(
|
||||
expect.not.objectContaining({ password: expect.anything() })
|
||||
);
|
||||
|
|
@ -337,53 +320,53 @@ describe('register', () => {
|
|||
|
||||
it('RespUserAlreadyExists calls registrationUserNameError', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespUserAlreadyExists);
|
||||
invokeResponseCode(Response_ResponseCode.RespUserAlreadyExists);
|
||||
expect(WebClient.instance.response.session.registrationUserNameError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespUsernameInvalid calls registrationUserNameError', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespUsernameInvalid);
|
||||
invokeResponseCode(Response_ResponseCode.RespUsernameInvalid);
|
||||
expect(WebClient.instance.response.session.registrationUserNameError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespPasswordTooShort calls registrationPasswordError', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespPasswordTooShort);
|
||||
invokeResponseCode(Response_ResponseCode.RespPasswordTooShort);
|
||||
expect(WebClient.instance.response.session.registrationPasswordError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespEmailRequiredToRegister calls registrationRequiresEmail', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespEmailRequiredToRegister);
|
||||
invokeResponseCode(Response_ResponseCode.RespEmailRequiredToRegister);
|
||||
expect(WebClient.instance.response.session.registrationRequiresEmail).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespEmailBlackListed calls registrationEmailError', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespEmailBlackListed);
|
||||
invokeResponseCode(Response_ResponseCode.RespEmailBlackListed);
|
||||
expect(WebClient.instance.response.session.registrationEmailError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespTooManyRequests calls registrationEmailError', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespTooManyRequests);
|
||||
invokeResponseCode(Response_ResponseCode.RespTooManyRequests);
|
||||
expect(WebClient.instance.response.session.registrationEmailError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespRegistrationDisabled calls registrationFailed', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespRegistrationDisabled);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationDisabled);
|
||||
expect(WebClient.instance.response.session.registrationFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespUserIsBanned calls registrationFailed with deniedReasonStr and deniedEndTime', () => {
|
||||
register(makeRegisterOpts(), 'pw');
|
||||
const raw = create(Data.ResponseSchema, { responseCode: Data.Response_ResponseCode.RespUserIsBanned });
|
||||
setExtension(raw, Data.Response_Register_ext, create(Data.Response_RegisterSchema, {
|
||||
const raw = create(ResponseSchema, { responseCode: Response_ResponseCode.RespUserIsBanned });
|
||||
setExtension(raw, Response_Register_ext, create(Response_RegisterSchema, {
|
||||
deniedReasonStr: 'bad user', deniedEndTime: 9999n,
|
||||
}));
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespUserIsBanned, raw);
|
||||
invokeResponseCode(Response_ResponseCode.RespUserIsBanned, raw);
|
||||
expect(WebClient.instance.response.session.registrationFailed).toHaveBeenCalledWith('bad user', 9999);
|
||||
});
|
||||
|
||||
|
|
@ -402,12 +385,12 @@ describe('activate', () => {
|
|||
it('sends Command_Activate with userName and token, not password', () => {
|
||||
activate(makeActivateOpts(), 'pw');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_Activate_ext,
|
||||
Command_Activate_ext,
|
||||
expect.objectContaining({ userName: 'alice', token: 'tok' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_Activate_ext,
|
||||
Command_Activate_ext,
|
||||
expect.not.objectContaining({ password: expect.anything() }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -415,7 +398,7 @@ describe('activate', () => {
|
|||
|
||||
it('RespActivationAccepted calls accountActivationSuccess and forwards password+salt to login', () => {
|
||||
activate(makeActivateOpts(), 'pw', 'salt');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespActivationAccepted);
|
||||
invokeResponseCode(Response_ResponseCode.RespActivationAccepted);
|
||||
expect(WebClient.instance.response.session.accountActivationSuccess).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.login).toHaveBeenCalledWith(expect.any(Object), 'pw', 'salt');
|
||||
});
|
||||
|
|
@ -436,7 +419,7 @@ describe('forgotPasswordChallenge', () => {
|
|||
it('sends Command_ForgotPasswordChallenge', () => {
|
||||
forgotPasswordChallenge(makeForgotChallengeOpts());
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ForgotPasswordChallenge_ext, expect.any(Object), expect.any(Object)
|
||||
Command_ForgotPasswordChallenge_ext, expect.any(Object), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -463,9 +446,9 @@ describe('forgotPasswordRequest', () => {
|
|||
it('sends Command_ForgotPasswordRequest', () => {
|
||||
forgotPasswordRequest(makeForgotRequestOpts());
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ForgotPasswordRequest_ext,
|
||||
Command_ForgotPasswordRequest_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_ForgotPasswordRequest_ext })
|
||||
expect.objectContaining({ responseExt: Response_ForgotPasswordRequest_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -501,7 +484,7 @@ describe('forgotPasswordReset', () => {
|
|||
it('sends Command_ForgotPasswordReset with plain newPassword when no salt', () => {
|
||||
forgotPasswordReset(makeForgotResetOpts(), 'newpw');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ForgotPasswordReset_ext,
|
||||
Command_ForgotPasswordReset_ext,
|
||||
expect.objectContaining({ newPassword: 'newpw' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -510,7 +493,7 @@ describe('forgotPasswordReset', () => {
|
|||
it('sends hashed new password when salt provided', () => {
|
||||
forgotPasswordReset(makeForgotResetOpts(), 'newpw', 'salt');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ForgotPasswordReset_ext,
|
||||
Command_ForgotPasswordReset_ext,
|
||||
expect.objectContaining({ hashedNewPassword: 'hashed_pw' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -537,66 +520,40 @@ describe('forgotPasswordReset', () => {
|
|||
describe('requestPasswordSalt', () => {
|
||||
|
||||
it('sends Command_RequestPasswordSalt', () => {
|
||||
requestPasswordSalt(makeSaltOpts(App.WebSocketConnectReason.LOGIN), 'pw');
|
||||
const onSaltReceived = vi.fn();
|
||||
const onFailure = vi.fn();
|
||||
requestPasswordSalt({ host: 'h', port: '1', userName: 'alice' }, onSaltReceived, onFailure);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_RequestPasswordSalt_ext,
|
||||
Command_RequestPasswordSalt_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_PasswordSalt_ext })
|
||||
expect.objectContaining({ responseExt: Response_PasswordSalt_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('onSuccess with LOGIN reason forwards password+salt to login', () => {
|
||||
requestPasswordSalt(makeSaltOpts(App.WebSocketConnectReason.LOGIN), 'pw');
|
||||
it('onSuccess calls onSaltReceived with the salt', () => {
|
||||
const onSaltReceived = vi.fn();
|
||||
const onFailure = vi.fn();
|
||||
requestPasswordSalt({ host: 'h', port: '1', userName: 'alice' }, onSaltReceived, onFailure);
|
||||
const resp = { passwordSalt: 'salt123' };
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionIndexMocks.login).toHaveBeenCalledWith(expect.any(Object), 'pw', 'salt123');
|
||||
expect(onSaltReceived).toHaveBeenCalledWith('salt123');
|
||||
});
|
||||
|
||||
it('onSuccess with ACTIVATE_ACCOUNT reason forwards password+salt to activate', () => {
|
||||
requestPasswordSalt(makeSaltOpts(App.WebSocketConnectReason.ACTIVATE_ACCOUNT, { token: 'tok' }), 'pw');
|
||||
const resp = { passwordSalt: 'salt123' };
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionIndexMocks.activate).toHaveBeenCalledWith(expect.any(Object), 'pw', 'salt123');
|
||||
it('onResponseCode RespRegistrationRequired calls updateStatus and onFailure', () => {
|
||||
const onSaltReceived = vi.fn();
|
||||
const onFailure = vi.fn();
|
||||
requestPasswordSalt({ host: 'h', port: '1', userName: 'alice' }, onSaltReceived, onFailure);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationRequired);
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, expect.any(String));
|
||||
expect(onFailure).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onSuccess with PASSWORD_RESET reason forwards newPassword+salt to forgotPasswordReset', () => {
|
||||
requestPasswordSalt(
|
||||
makeSaltOpts(App.WebSocketConnectReason.PASSWORD_RESET, { token: 'tok', newPassword: 'newpw' }),
|
||||
undefined,
|
||||
'newpw'
|
||||
);
|
||||
const resp = { passwordSalt: 'salt123' };
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionIndexMocks.forgotPasswordReset).toHaveBeenCalledWith(expect.any(Object), 'newpw', 'salt123');
|
||||
});
|
||||
|
||||
it('onResponseCode RespRegistrationRequired calls updateStatus and disconnect', () => {
|
||||
requestPasswordSalt(makeSaltOpts(App.WebSocketConnectReason.LOGIN), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespRegistrationRequired);
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(App.StatusEnum.DISCONNECTED, expect.any(String));
|
||||
expect(SessionIndexMocks.disconnect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespRegistrationRequired with ACTIVATE_ACCOUNT calls accountActivationFailed', () => {
|
||||
requestPasswordSalt(makeSaltOpts(App.WebSocketConnectReason.ACTIVATE_ACCOUNT, { token: 'tok' }), 'pw');
|
||||
invokeResponseCode(Data.Response_ResponseCode.RespRegistrationRequired);
|
||||
expect(WebClient.instance.response.session.accountActivationFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onError calls updateStatus DISCONNECTED and disconnect', () => {
|
||||
requestPasswordSalt(makeSaltOpts(App.WebSocketConnectReason.LOGIN), 'pw');
|
||||
it('onError calls updateStatus DISCONNECTED and onFailure', () => {
|
||||
const onSaltReceived = vi.fn();
|
||||
const onFailure = vi.fn();
|
||||
requestPasswordSalt({ host: 'h', port: '1', userName: 'alice' }, onSaltReceived, onFailure);
|
||||
invokeOnError();
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.disconnect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onError with PASSWORD_RESET reason calls resetPasswordFailed', () => {
|
||||
requestPasswordSalt(
|
||||
makeSaltOpts(App.WebSocketConnectReason.PASSWORD_RESET, { token: 'tok', newPassword: 'newpw' }),
|
||||
undefined,
|
||||
'newpw'
|
||||
);
|
||||
invokeOnError();
|
||||
expect(WebClient.instance.response.session.resetPasswordFailed).toHaveBeenCalled();
|
||||
expect(onFailure).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ vi.mock('./', async () => {
|
|||
|
||||
import { Mock } from 'vitest';
|
||||
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
|
||||
import { useWebClientCleanup } from '../../__mocks__/helpers';
|
||||
import { WebClient } from '../../WebClient';
|
||||
import { hashPassword, generateSalt, passwordSaltSupported } from '../../utils';
|
||||
|
||||
|
|
@ -47,8 +48,44 @@ import { addToList, addToBuddyList, addToIgnoreList } from './addToList';
|
|||
import { removeFromList, removeFromBuddyList, removeFromIgnoreList } from './removeFromList';
|
||||
import { replayGetCode } from './replayGetCode';
|
||||
import { replaySubmitCode } from './replaySubmitCode';
|
||||
import { Data } from '@app/types';
|
||||
import {
|
||||
Command_AccountEdit_ext,
|
||||
Command_AccountImage_ext,
|
||||
Command_AccountPassword_ext,
|
||||
Command_AddToList_ext,
|
||||
Command_DeckDel_ext,
|
||||
Command_DeckDelDir_ext,
|
||||
Command_DeckDownload_ext,
|
||||
Command_DeckList_ext,
|
||||
Command_DeckNewDir_ext,
|
||||
Command_DeckUpload_ext,
|
||||
Command_GetGamesOfUser_ext,
|
||||
Command_GetUserInfo_ext,
|
||||
Command_JoinRoom_ext,
|
||||
Command_ListRooms_ext,
|
||||
Command_ListUsers_ext,
|
||||
Command_Message_ext,
|
||||
Command_Ping_ext,
|
||||
Command_RemoveFromList_ext,
|
||||
Command_ReplayDeleteMatch_ext,
|
||||
Command_ReplayDownload_ext,
|
||||
Command_ReplayGetCode_ext,
|
||||
Command_ReplayList_ext,
|
||||
Command_ReplayModifyMatch_ext,
|
||||
Command_ReplaySubmitCode_ext,
|
||||
Response_DeckDownload_ext,
|
||||
Response_DeckList_ext,
|
||||
Response_DeckUpload_ext,
|
||||
Response_GetGamesOfUser_ext,
|
||||
Response_GetUserInfo_ext,
|
||||
Response_JoinRoom_ext,
|
||||
Response_ListUsers_ext,
|
||||
Response_ReplayDownload_ext,
|
||||
Response_ReplayGetCode_ext,
|
||||
Response_ReplayList_ext,
|
||||
} from '@app/generated';
|
||||
|
||||
useWebClientCleanup();
|
||||
|
||||
const { invokeOnSuccess, invokeCallback } = makeCallbackHelpers(
|
||||
WebClient.instance.protobuf.sendSessionCommand as Mock,
|
||||
|
|
@ -67,7 +104,7 @@ describe('accountEdit', () => {
|
|||
it('sends Command_AccountEdit with correct params', () => {
|
||||
accountEdit('pw', 'Alice', 'a@b.com', 'US');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_AccountEdit_ext,
|
||||
Command_AccountEdit_ext,
|
||||
expect.objectContaining({ passwordCheck: 'pw', realName: 'Alice', email: 'a@b.com', country: 'US' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -85,7 +122,7 @@ describe('accountImage', () => {
|
|||
const img = new Uint8Array([1, 2]);
|
||||
accountImage(img);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_AccountImage_ext, expect.objectContaining({ image: img }), expect.any(Object)
|
||||
Command_AccountImage_ext, expect.objectContaining({ image: img }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -101,7 +138,7 @@ describe('accountPassword', () => {
|
|||
it('sends Command_AccountPassword', () => {
|
||||
accountPassword('old', 'new', 'hashed');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_AccountPassword_ext,
|
||||
Command_AccountPassword_ext,
|
||||
expect.objectContaining({ oldPassword: 'old', newPassword: 'new', hashedNewPassword: 'hashed' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -118,7 +155,7 @@ describe('deckDel', () => {
|
|||
it('sends Command_DeckDel', () => {
|
||||
deckDel(42);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_DeckDel_ext,
|
||||
Command_DeckDel_ext,
|
||||
expect.objectContaining({ deckId: 42 }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -135,7 +172,7 @@ describe('deckDelDir', () => {
|
|||
it('sends Command_DeckDelDir', () => {
|
||||
deckDelDir('/path');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_DeckDelDir_ext, expect.objectContaining({ path: '/path' }), expect.any(Object)
|
||||
Command_DeckDelDir_ext, expect.objectContaining({ path: '/path' }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -150,9 +187,9 @@ describe('deckList', () => {
|
|||
it('sends Command_DeckList', () => {
|
||||
deckList();
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_DeckList_ext,
|
||||
Command_DeckList_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_DeckList_ext })
|
||||
expect.objectContaining({ responseExt: Response_DeckList_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -168,7 +205,7 @@ describe('deckNewDir', () => {
|
|||
it('sends Command_DeckNewDir', () => {
|
||||
deckNewDir('/path', 'dir');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_DeckNewDir_ext, expect.objectContaining({ path: '/path', dirName: 'dir' }), expect.any(Object)
|
||||
Command_DeckNewDir_ext, expect.objectContaining({ path: '/path', dirName: 'dir' }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -183,9 +220,9 @@ describe('deckUpload', () => {
|
|||
it('sends Command_DeckUpload', () => {
|
||||
deckUpload('/path', 1, 'content');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_DeckUpload_ext,
|
||||
Command_DeckUpload_ext,
|
||||
expect.objectContaining({ path: '/path', deckId: 1, deckList: 'content' }),
|
||||
expect.objectContaining({ responseExt: Data.Response_DeckUpload_ext })
|
||||
expect.objectContaining({ responseExt: Response_DeckUpload_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -208,9 +245,9 @@ describe('getGamesOfUser', () => {
|
|||
it('sends Command_GetGamesOfUser', () => {
|
||||
getGamesOfUser('alice');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_GetGamesOfUser_ext,
|
||||
Command_GetGamesOfUser_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_GetGamesOfUser_ext })
|
||||
expect.objectContaining({ responseExt: Response_GetGamesOfUser_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -226,9 +263,9 @@ describe('getUserInfo', () => {
|
|||
it('sends Command_GetUserInfo', () => {
|
||||
getUserInfo('alice');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_GetUserInfo_ext,
|
||||
Command_GetUserInfo_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_GetUserInfo_ext })
|
||||
expect.objectContaining({ responseExt: Response_GetUserInfo_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -244,9 +281,9 @@ describe('joinRoom', () => {
|
|||
it('sends Command_JoinRoom', () => {
|
||||
joinRoom(5);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_JoinRoom_ext,
|
||||
Command_JoinRoom_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_JoinRoom_ext })
|
||||
expect.objectContaining({ responseExt: Response_JoinRoom_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -261,7 +298,7 @@ describe('joinRoom', () => {
|
|||
describe('listRooms (command)', () => {
|
||||
it('sends Command_ListRooms', () => {
|
||||
listRooms();
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(Data.Command_ListRooms_ext, expect.any(Object));
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(Command_ListRooms_ext, expect.any(Object));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -269,9 +306,9 @@ describe('listUsers', () => {
|
|||
it('sends Command_ListUsers', () => {
|
||||
listUsers();
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ListUsers_ext,
|
||||
Command_ListUsers_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_ListUsers_ext })
|
||||
expect.objectContaining({ responseExt: Response_ListUsers_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -287,7 +324,7 @@ describe('message', () => {
|
|||
it('sends Command_Message', () => {
|
||||
message('bob', 'hi');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_Message_ext, expect.objectContaining({ userName: 'bob', message: 'hi' })
|
||||
Command_Message_ext, expect.objectContaining({ userName: 'bob', message: 'hi' })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -298,7 +335,7 @@ describe('ping', () => {
|
|||
const pingReceived = vi.fn();
|
||||
ping(pingReceived);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_Ping_ext, expect.any(Object), expect.any(Object)
|
||||
Command_Ping_ext, expect.any(Object), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -314,7 +351,7 @@ describe('replayDeleteMatch', () => {
|
|||
it('sends Command_ReplayDeleteMatch', () => {
|
||||
replayDeleteMatch(7);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ReplayDeleteMatch_ext,
|
||||
Command_ReplayDeleteMatch_ext,
|
||||
expect.objectContaining({ gameId: 7 }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -331,9 +368,9 @@ describe('replayList', () => {
|
|||
it('sends Command_ReplayList', () => {
|
||||
replayList();
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ReplayList_ext,
|
||||
Command_ReplayList_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_ReplayList_ext })
|
||||
expect.objectContaining({ responseExt: Response_ReplayList_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -349,7 +386,7 @@ describe('replayModifyMatch', () => {
|
|||
it('sends Command_ReplayModifyMatch', () => {
|
||||
replayModifyMatch(7, true);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ReplayModifyMatch_ext, expect.objectContaining({ gameId: 7, doNotHide: true }), expect.any(Object)
|
||||
Command_ReplayModifyMatch_ext, expect.objectContaining({ gameId: 7, doNotHide: true }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -364,7 +401,7 @@ describe('addToList / addToBuddyList / addToIgnoreList', () => {
|
|||
it('addToBuddyList sends Command_AddToList with list=buddy', () => {
|
||||
addToBuddyList('alice');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_AddToList_ext,
|
||||
Command_AddToList_ext,
|
||||
expect.objectContaining({ list: 'buddy' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -373,7 +410,7 @@ describe('addToList / addToBuddyList / addToIgnoreList', () => {
|
|||
it('addToIgnoreList sends Command_AddToList with list=ignore', () => {
|
||||
addToIgnoreList('bob');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_AddToList_ext,
|
||||
Command_AddToList_ext,
|
||||
expect.objectContaining({ list: 'ignore' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -390,7 +427,7 @@ describe('removeFromList / removeFromBuddyList / removeFromIgnoreList', () => {
|
|||
it('removeFromBuddyList sends Command_RemoveFromList with list=buddy', () => {
|
||||
removeFromBuddyList('alice');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_RemoveFromList_ext,
|
||||
Command_RemoveFromList_ext,
|
||||
expect.objectContaining({ list: 'buddy' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -399,7 +436,7 @@ describe('removeFromList / removeFromBuddyList / removeFromIgnoreList', () => {
|
|||
it('removeFromIgnoreList sends Command_RemoveFromList with list=ignore', () => {
|
||||
removeFromIgnoreList('bob');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_RemoveFromList_ext,
|
||||
Command_RemoveFromList_ext,
|
||||
expect.objectContaining({ list: 'ignore' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -416,9 +453,9 @@ describe('replayGetCode', () => {
|
|||
it('sends Command_ReplayGetCode with gameId and responseExt', () => {
|
||||
replayGetCode(42, vi.fn());
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ReplayGetCode_ext,
|
||||
Command_ReplayGetCode_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Data.Response_ReplayGetCode_ext })
|
||||
expect.objectContaining({ responseExt: Response_ReplayGetCode_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -434,7 +471,7 @@ describe('replaySubmitCode', () => {
|
|||
it('sends Command_ReplaySubmitCode with replayCode', () => {
|
||||
replaySubmitCode('42-abc123');
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ReplaySubmitCode_ext, expect.objectContaining({ replayCode: '42-abc123' }), expect.any(Object)
|
||||
Command_ReplaySubmitCode_ext, expect.objectContaining({ replayCode: '42-abc123' }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -457,9 +494,9 @@ describe('deckDownload', () => {
|
|||
it('sends Command_DeckDownload', () => {
|
||||
deckDownload(42);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_DeckDownload_ext,
|
||||
Command_DeckDownload_ext,
|
||||
expect.objectContaining({ deckId: 42 }),
|
||||
expect.objectContaining({ responseExt: Data.Response_DeckDownload_ext })
|
||||
expect.objectContaining({ responseExt: Response_DeckDownload_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -475,9 +512,9 @@ describe('replayDownload', () => {
|
|||
it('sends Command_ReplayDownload', () => {
|
||||
replayDownload(99);
|
||||
expect(WebClient.instance.protobuf.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Data.Command_ReplayDownload_ext,
|
||||
Command_ReplayDownload_ext,
|
||||
expect.objectContaining({ replayId: 99 }),
|
||||
expect.objectContaining({ responseExt: Data.Response_ReplayDownload_ext })
|
||||
expect.objectContaining({ responseExt: Response_ReplayDownload_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { App } from '@app/types';
|
||||
import { StatusEnum } from '../../StatusEnum';
|
||||
import { WebClient } from '../../WebClient';
|
||||
export function updateStatus(status: App.StatusEnum, description: string): void {
|
||||
WebClient.instance.response.session.updateStatus(status, description);
|
||||
|
||||
export function updateStatus(status: StatusEnum, description: string): void {
|
||||
WebClient.instance.response.session.updateStatus(status, description);
|
||||
WebClient.instance.updateStatus(status);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ export const CLIENT_CONFIG = {
|
|||
]
|
||||
} as const;
|
||||
|
||||
export const PROTOCOL_VERSION = 14;
|
||||
|
||||
export const CLIENT_OPTIONS = {
|
||||
autojoinrooms: true,
|
||||
keepalive: 5000
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { Data, Enriched } from '@app/types';
|
||||
import type { Event_AttachCard } from '@app/generated';
|
||||
import type { GameEventMeta } from '../../types';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
export function attachCard(data: Data.Event_AttachCard, meta: Enriched.GameEventMeta): void {
|
||||
export function attachCard(data: Event_AttachCard, meta: GameEventMeta): void {
|
||||
WebClient.instance.response.game.cardAttached(meta.gameId, meta.playerId, data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { Data, Enriched } from '@app/types';
|
||||
import type { Event_ChangeZoneProperties } from '@app/generated';
|
||||
import type { GameEventMeta } from '../../types';
|
||||
import { WebClient } from '../../WebClient';
|
||||
|
||||
export function changeZoneProperties(data: Data.Event_ChangeZoneProperties, meta: Enriched.GameEventMeta): void {
|
||||
export function changeZoneProperties(data: Event_ChangeZoneProperties, meta: GameEventMeta): void {
|
||||
WebClient.instance.response.game.zonePropertiesChanged(meta.gameId, meta.playerId, data);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue