complete unit testing of redux and api layers

This commit is contained in:
seavor 2026-04-12 12:53:51 -05:00
parent 367852866f
commit 3001925430
19 changed files with 2808 additions and 5 deletions

View file

@ -0,0 +1,48 @@
jest.mock('websocket', () => ({
AdminCommands: {
adjustMod: jest.fn(),
reloadConfig: jest.fn(),
shutdownServer: jest.fn(),
updateServerMessage: jest.fn(),
},
}));
import { AdminService } from './AdminService';
import { AdminCommands } from 'websocket';
beforeEach(() => jest.clearAllMocks());
describe('AdminService', () => {
describe('adjustMod', () => {
it('delegates to AdminCommands.adjustMod with all arguments', () => {
AdminService.adjustMod('alice', true, false);
expect(AdminCommands.adjustMod).toHaveBeenCalledWith('alice', true, false);
});
it('delegates with optional arguments omitted', () => {
AdminService.adjustMod('alice');
expect(AdminCommands.adjustMod).toHaveBeenCalledWith('alice', undefined, undefined);
});
});
describe('reloadConfig', () => {
it('delegates to AdminCommands.reloadConfig', () => {
AdminService.reloadConfig();
expect(AdminCommands.reloadConfig).toHaveBeenCalled();
});
});
describe('shutdownServer', () => {
it('delegates to AdminCommands.shutdownServer', () => {
AdminService.shutdownServer('maintenance', 10);
expect(AdminCommands.shutdownServer).toHaveBeenCalledWith('maintenance', 10);
});
});
describe('updateServerMessage', () => {
it('delegates to AdminCommands.updateServerMessage', () => {
AdminService.updateServerMessage();
expect(AdminCommands.updateServerMessage).toHaveBeenCalled();
});
});
});

View file

@ -0,0 +1,145 @@
jest.mock('websocket', () => ({
SessionCommands: {
connect: jest.fn(),
disconnect: jest.fn(),
},
webClient: {
connectionAttemptMade: false,
},
}));
jest.mock('websocket/services/ProtoController', () => ({
ProtoController: {
root: {
ServerInfo_User: {
UserLevelFlag: {
IsModerator: 4,
},
},
},
},
}));
import { AuthenticationService } from './AuthenticationService';
import { SessionCommands, webClient } from 'websocket';
import { StatusEnum, WebSocketConnectOptions, WebSocketConnectReason } from 'types';
const testOptions: WebSocketConnectOptions = { host: 'localhost', port: '4748', userName: 'user', password: 'pw' };
beforeEach(() => jest.clearAllMocks());
describe('AuthenticationService', () => {
describe('login', () => {
it('calls SessionCommands.connect with LOGIN reason', () => {
AuthenticationService.login(testOptions);
expect(SessionCommands.connect).toHaveBeenCalledWith(testOptions, WebSocketConnectReason.LOGIN);
});
});
describe('testConnection', () => {
it('calls SessionCommands.connect with TEST_CONNECTION reason', () => {
AuthenticationService.testConnection(testOptions);
expect(SessionCommands.connect).toHaveBeenCalledWith(testOptions, WebSocketConnectReason.TEST_CONNECTION);
});
});
describe('register', () => {
it('calls SessionCommands.connect with REGISTER reason', () => {
AuthenticationService.register(testOptions);
expect(SessionCommands.connect).toHaveBeenCalledWith(testOptions, WebSocketConnectReason.REGISTER);
});
});
describe('activateAccount', () => {
it('calls SessionCommands.connect with ACTIVATE_ACCOUNT reason', () => {
AuthenticationService.activateAccount(testOptions);
expect(SessionCommands.connect).toHaveBeenCalledWith(testOptions, WebSocketConnectReason.ACTIVATE_ACCOUNT);
});
});
describe('resetPasswordRequest', () => {
it('calls SessionCommands.connect with PASSWORD_RESET_REQUEST reason', () => {
AuthenticationService.resetPasswordRequest(testOptions);
expect(SessionCommands.connect).toHaveBeenCalledWith(testOptions, WebSocketConnectReason.PASSWORD_RESET_REQUEST);
});
});
describe('resetPasswordChallenge', () => {
it('calls SessionCommands.connect with PASSWORD_RESET_CHALLENGE reason', () => {
AuthenticationService.resetPasswordChallenge(testOptions);
expect(SessionCommands.connect).toHaveBeenCalledWith(testOptions, WebSocketConnectReason.PASSWORD_RESET_CHALLENGE);
});
});
describe('resetPassword', () => {
it('calls SessionCommands.connect with PASSWORD_RESET reason', () => {
AuthenticationService.resetPassword(testOptions);
expect(SessionCommands.connect).toHaveBeenCalledWith(testOptions, WebSocketConnectReason.PASSWORD_RESET);
});
});
describe('disconnect', () => {
it('delegates to SessionCommands.disconnect', () => {
AuthenticationService.disconnect();
expect(SessionCommands.disconnect).toHaveBeenCalled();
});
});
describe('isConnected', () => {
it('returns true when state is LOGGED_IN', () => {
expect(AuthenticationService.isConnected(StatusEnum.LOGGED_IN)).toBe(true);
});
it('returns false when state is DISCONNECTED', () => {
expect(AuthenticationService.isConnected(StatusEnum.DISCONNECTED)).toBe(false);
});
it('returns false when state is CONNECTING', () => {
expect(AuthenticationService.isConnected(StatusEnum.CONNECTING)).toBe(false);
});
it('returns false when state is CONNECTED', () => {
expect(AuthenticationService.isConnected(StatusEnum.CONNECTED)).toBe(false);
});
it('returns false when state is LOGGING_IN', () => {
expect(AuthenticationService.isConnected(StatusEnum.LOGGING_IN)).toBe(false);
});
});
describe('isModerator', () => {
it('returns true when userLevel has the IsModerator bit set', () => {
expect(AuthenticationService.isModerator({ userLevel: 4 } as any)).toBe(true);
});
it('returns true when userLevel has IsModerator and other bits set', () => {
expect(AuthenticationService.isModerator({ userLevel: 7 } as any)).toBe(true);
});
it('returns false when userLevel does not have the IsModerator bit', () => {
expect(AuthenticationService.isModerator({ userLevel: 1 } as any)).toBe(false);
});
it('returns false for admin-only userLevel without moderator bit', () => {
expect(AuthenticationService.isModerator({ userLevel: 8 } as any)).toBe(false);
});
});
describe('isAdmin', () => {
it('returns undefined (not yet implemented)', () => {
expect(AuthenticationService.isAdmin()).toBeUndefined();
});
});
describe('connectionAttemptMade', () => {
it('returns webClient.connectionAttemptMade when false', () => {
(webClient as any).connectionAttemptMade = false;
expect(AuthenticationService.connectionAttemptMade()).toBe(false);
});
it('returns webClient.connectionAttemptMade when true', () => {
(webClient as any).connectionAttemptMade = true;
expect(AuthenticationService.connectionAttemptMade()).toBe(true);
});
});
});

View file

@ -0,0 +1,75 @@
jest.mock('websocket', () => ({
ModeratorCommands: {
banFromServer: jest.fn(),
getBanHistory: jest.fn(),
getWarnHistory: jest.fn(),
getWarnList: jest.fn(),
viewLogHistory: jest.fn(),
warnUser: jest.fn(),
},
}));
import { ModeratorService } from './ModeratorService';
import { ModeratorCommands } from 'websocket';
import { LogFilters } from 'types';
beforeEach(() => jest.clearAllMocks());
describe('ModeratorService', () => {
describe('banFromServer', () => {
it('delegates to ModeratorCommands.banFromServer with all arguments', () => {
ModeratorService.banFromServer(30, 'alice', '1.2.3.4', 'reason', 'visible reason', 'cid', 1);
expect(ModeratorCommands.banFromServer).toHaveBeenCalledWith(
30, 'alice', '1.2.3.4', 'reason', 'visible reason', 'cid', 1
);
});
it('delegates with only required argument', () => {
ModeratorService.banFromServer(60);
expect(ModeratorCommands.banFromServer).toHaveBeenCalledWith(
60, undefined, undefined, undefined, undefined, undefined, undefined
);
});
});
describe('getBanHistory', () => {
it('delegates to ModeratorCommands.getBanHistory', () => {
ModeratorService.getBanHistory('alice');
expect(ModeratorCommands.getBanHistory).toHaveBeenCalledWith('alice');
});
});
describe('getWarnHistory', () => {
it('delegates to ModeratorCommands.getWarnHistory', () => {
ModeratorService.getWarnHistory('alice');
expect(ModeratorCommands.getWarnHistory).toHaveBeenCalledWith('alice');
});
});
describe('getWarnList', () => {
it('delegates to ModeratorCommands.getWarnList', () => {
ModeratorService.getWarnList('mod1', 'alice', 'cid123');
expect(ModeratorCommands.getWarnList).toHaveBeenCalledWith('mod1', 'alice', 'cid123');
});
});
describe('viewLogHistory', () => {
it('delegates to ModeratorCommands.viewLogHistory', () => {
const filters: LogFilters = { dateRange: 7, userName: 'alice' };
ModeratorService.viewLogHistory(filters);
expect(ModeratorCommands.viewLogHistory).toHaveBeenCalledWith(filters);
});
});
describe('warnUser', () => {
it('delegates to ModeratorCommands.warnUser with all arguments', () => {
ModeratorService.warnUser('alice', 'spamming', 'cid', 5);
expect(ModeratorCommands.warnUser).toHaveBeenCalledWith('alice', 'spamming', 'cid', 5);
});
it('delegates with only required arguments', () => {
ModeratorService.warnUser('alice', 'spamming');
expect(ModeratorCommands.warnUser).toHaveBeenCalledWith('alice', 'spamming', undefined, undefined);
});
});
});

View file

@ -0,0 +1,37 @@
jest.mock('websocket', () => ({
SessionCommands: {
joinRoom: jest.fn(),
},
RoomCommands: {
leaveRoom: jest.fn(),
roomSay: jest.fn(),
},
}));
import { RoomsService } from './RoomsService';
import { RoomCommands, SessionCommands } from 'websocket';
beforeEach(() => jest.clearAllMocks());
describe('RoomsService', () => {
describe('joinRoom', () => {
it('delegates to SessionCommands.joinRoom', () => {
RoomsService.joinRoom(42);
expect(SessionCommands.joinRoom).toHaveBeenCalledWith(42);
});
});
describe('leaveRoom', () => {
it('delegates to RoomCommands.leaveRoom', () => {
RoomsService.leaveRoom(42);
expect(RoomCommands.leaveRoom).toHaveBeenCalledWith(42);
});
});
describe('roomSay', () => {
it('delegates to RoomCommands.roomSay', () => {
RoomsService.roomSay(42, 'hello room');
expect(RoomCommands.roomSay).toHaveBeenCalledWith(42, 'hello room');
});
});
});

View file

@ -0,0 +1,102 @@
jest.mock('websocket', () => ({
SessionCommands: {
addToBuddyList: jest.fn(),
removeFromBuddyList: jest.fn(),
addToIgnoreList: jest.fn(),
removeFromIgnoreList: jest.fn(),
accountPassword: jest.fn(),
accountEdit: jest.fn(),
accountImage: jest.fn(),
message: jest.fn(),
getUserInfo: jest.fn(),
getGamesOfUser: jest.fn(),
},
}));
import { SessionService } from './SessionService';
import { SessionCommands } from 'websocket';
beforeEach(() => jest.clearAllMocks());
describe('SessionService', () => {
describe('addToBuddyList', () => {
it('delegates to SessionCommands.addToBuddyList', () => {
SessionService.addToBuddyList('alice');
expect(SessionCommands.addToBuddyList).toHaveBeenCalledWith('alice');
});
});
describe('removeFromBuddyList', () => {
it('delegates to SessionCommands.removeFromBuddyList', () => {
SessionService.removeFromBuddyList('alice');
expect(SessionCommands.removeFromBuddyList).toHaveBeenCalledWith('alice');
});
});
describe('addToIgnoreList', () => {
it('delegates to SessionCommands.addToIgnoreList', () => {
SessionService.addToIgnoreList('bob');
expect(SessionCommands.addToIgnoreList).toHaveBeenCalledWith('bob');
});
});
describe('removeFromIgnoreList', () => {
it('delegates to SessionCommands.removeFromIgnoreList', () => {
SessionService.removeFromIgnoreList('bob');
expect(SessionCommands.removeFromIgnoreList).toHaveBeenCalledWith('bob');
});
});
describe('changeAccountPassword', () => {
it('delegates to SessionCommands.accountPassword with all arguments', () => {
SessionService.changeAccountPassword('oldPw', 'newPw', 'hashedPw');
expect(SessionCommands.accountPassword).toHaveBeenCalledWith('oldPw', 'newPw', 'hashedPw');
});
it('delegates without hashedNewPassword when omitted', () => {
SessionService.changeAccountPassword('oldPw', 'newPw');
expect(SessionCommands.accountPassword).toHaveBeenCalledWith('oldPw', 'newPw', undefined);
});
});
describe('changeAccountDetails', () => {
it('delegates to SessionCommands.accountEdit with all arguments', () => {
SessionService.changeAccountDetails('pw', 'Alice', 'alice@example.com', 'US');
expect(SessionCommands.accountEdit).toHaveBeenCalledWith('pw', 'Alice', 'alice@example.com', 'US');
});
it('delegates with only required argument', () => {
SessionService.changeAccountDetails('pw');
expect(SessionCommands.accountEdit).toHaveBeenCalledWith('pw', undefined, undefined, undefined);
});
});
describe('changeAccountImage', () => {
it('delegates to SessionCommands.accountImage', () => {
const image = new Uint8Array([1, 2, 3]);
SessionService.changeAccountImage(image);
expect(SessionCommands.accountImage).toHaveBeenCalledWith(image);
});
});
describe('sendDirectMessage', () => {
it('delegates to SessionCommands.message', () => {
SessionService.sendDirectMessage('alice', 'hello');
expect(SessionCommands.message).toHaveBeenCalledWith('alice', 'hello');
});
});
describe('getUserInfo', () => {
it('delegates to SessionCommands.getUserInfo', () => {
SessionService.getUserInfo('alice');
expect(SessionCommands.getUserInfo).toHaveBeenCalledWith('alice');
});
});
describe('getUserGames', () => {
it('delegates to SessionCommands.getGamesOfUser', () => {
SessionService.getUserGames('alice');
expect(SessionCommands.getGamesOfUser).toHaveBeenCalledWith('alice');
});
});
});