mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
Add near 100% unit test coverage for webclient websocket layer
This commit is contained in:
parent
8cc65b8967
commit
35be723ebf
26 changed files with 3932 additions and 0 deletions
119
webclient/src/websocket/services/BackendService.spec.ts
Normal file
119
webclient/src/websocket/services/BackendService.spec.ts
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
import { makeMockProtoRoot } from '../__mocks__/helpers';
|
||||
|
||||
jest.mock('./ProtoController', () => ({
|
||||
ProtoController: { root: null },
|
||||
}));
|
||||
|
||||
jest.mock('../WebClient', () => {
|
||||
const mockProtobuf = {
|
||||
sendSessionCommand: jest.fn(),
|
||||
sendRoomCommand: jest.fn(),
|
||||
sendModeratorCommand: jest.fn(),
|
||||
sendAdminCommand: jest.fn(),
|
||||
};
|
||||
return { __esModule: true, default: { protobuf: mockProtobuf } };
|
||||
});
|
||||
|
||||
import { BackendService } from './BackendService';
|
||||
import { ProtoController } from './ProtoController';
|
||||
import webClient from '../WebClient';
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
ProtoController.root = makeMockProtoRoot();
|
||||
ProtoController.root['Command_Test'] = { create: jest.fn(p => ({ ...p })) };
|
||||
ProtoController.root['Command_Room'] = { create: jest.fn(p => ({ ...p })) };
|
||||
ProtoController.root['Command_Mod'] = { create: jest.fn(p => ({ ...p })) };
|
||||
ProtoController.root['Command_Admin'] = { create: jest.fn(p => ({ ...p })) };
|
||||
ProtoController.root['Response_Test'] = {};
|
||||
});
|
||||
|
||||
function captureCallback(sendFn: jest.Mock) {
|
||||
return sendFn.mock.calls[0][sendFn === (webClient.protobuf as any).sendRoomCommand ? 2 : 1];
|
||||
}
|
||||
|
||||
describe('BackendService', () => {
|
||||
describe('send commands', () => {
|
||||
it.each<[string, () => void]>([
|
||||
['sendSessionCommand', () => BackendService.sendSessionCommand('Command_Test', { x: 1 }, {})],
|
||||
['sendRoomCommand', () => BackendService.sendRoomCommand(5, 'Command_Room', { y: 2 }, {})],
|
||||
['sendModeratorCommand', () => BackendService.sendModeratorCommand('Command_Mod', { z: 3 }, {})],
|
||||
['sendAdminCommand', () => BackendService.sendAdminCommand('Command_Admin', {}, {})],
|
||||
])('%s creates the command and delegates to protobuf', (methodName, invoke) => {
|
||||
invoke();
|
||||
expect((webClient.protobuf as any)[methodName]).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleResponse via non-session command callbacks', () => {
|
||||
it('sendRoomCommand callback invokes handleResponse', () => {
|
||||
const onSuccess = jest.fn();
|
||||
BackendService.sendRoomCommand(5, 'Command_Room', {}, { onSuccess });
|
||||
captureCallback((webClient.protobuf as any).sendRoomCommand)({ responseCode: 0 });
|
||||
expect(onSuccess).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sendModeratorCommand callback invokes handleResponse', () => {
|
||||
const onSuccess = jest.fn();
|
||||
BackendService.sendModeratorCommand('Command_Mod', {}, { onSuccess });
|
||||
captureCallback((webClient.protobuf as any).sendModeratorCommand)({ responseCode: 0 });
|
||||
expect(onSuccess).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sendAdminCommand callback invokes handleResponse', () => {
|
||||
const onSuccess = jest.fn();
|
||||
BackendService.sendAdminCommand('Command_Admin', {}, { onSuccess });
|
||||
captureCallback((webClient.protobuf as any).sendAdminCommand)({ responseCode: 0 });
|
||||
expect(onSuccess).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleResponse (via sendSessionCommand callback)', () => {
|
||||
function invokeCallback(options: any, raw: any) {
|
||||
BackendService.sendSessionCommand('Command_Test', {}, options);
|
||||
const cb = (webClient.protobuf as any).sendSessionCommand.mock.calls[0][1];
|
||||
cb(raw);
|
||||
}
|
||||
|
||||
it('calls onResponse and returns early when provided', () => {
|
||||
const onResponse = jest.fn();
|
||||
const onSuccess = jest.fn();
|
||||
invokeCallback({ onResponse, onSuccess }, { responseCode: 99 });
|
||||
expect(onResponse).toHaveBeenCalled();
|
||||
expect(onSuccess).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls onSuccess with raw when responseCode is RespOk and no responseName', () => {
|
||||
const onSuccess = jest.fn();
|
||||
const raw = { responseCode: 0 };
|
||||
invokeCallback({ onSuccess }, raw);
|
||||
expect(onSuccess).toHaveBeenCalledWith(raw, raw);
|
||||
});
|
||||
|
||||
it('calls onSuccess with nested response when responseName is set', () => {
|
||||
const onSuccess = jest.fn();
|
||||
const raw = { responseCode: 0, '.Response_Test.ext': { nested: true } };
|
||||
invokeCallback({ onSuccess, responseName: 'Response_Test' }, raw);
|
||||
expect(onSuccess).toHaveBeenCalledWith({ nested: true }, raw);
|
||||
});
|
||||
|
||||
it('calls onResponseCode handler when code matches', () => {
|
||||
const specificHandler = jest.fn();
|
||||
invokeCallback({ onResponseCode: { 5: specificHandler } }, { responseCode: 5 });
|
||||
expect(specificHandler).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls onError when responseCode is not RespOk and no specific handler', () => {
|
||||
const onError = jest.fn();
|
||||
invokeCallback({ onError }, { responseCode: 99 });
|
||||
expect(onError).toHaveBeenCalledWith(99, { responseCode: 99 });
|
||||
});
|
||||
|
||||
it('logs error to console when no callbacks for non-RespOk response', () => {
|
||||
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
invokeCallback({}, { responseCode: 42 });
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue