mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
migrate to Protobuf ES
This commit is contained in:
parent
68e22d22bf
commit
fd55f4fb7f
133 changed files with 1745 additions and 1621 deletions
|
|
@ -1,8 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_AccountEdit_ext, Command_AccountEditSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function accountEdit(passwordCheck: string, realName?: string, email?: string, country?: string): void {
|
||||
BackendService.sendSessionCommand('Command_AccountEdit', { passwordCheck, realName, email, country }, {
|
||||
const cmd = create(Command_AccountEditSchema, { passwordCheck, realName, email, country });
|
||||
BackendService.sendSessionCommand(Command_AccountEdit_ext, cmd, {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.accountEditChanged(realName, email, country);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_AccountImage_ext, Command_AccountImageSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function accountImage(image: Uint8Array): void {
|
||||
BackendService.sendSessionCommand('Command_AccountImage', { image }, {
|
||||
BackendService.sendSessionCommand(Command_AccountImage_ext, create(Command_AccountImageSchema, { image }), {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.accountImageChanged(image);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_AccountPassword_ext, Command_AccountPasswordSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function accountPassword(oldPassword: string, newPassword: string, hashedNewPassword: string): void {
|
||||
BackendService.sendSessionCommand('Command_AccountPassword', { oldPassword, newPassword, hashedNewPassword }, {
|
||||
const cmd = create(Command_AccountPasswordSchema, { oldPassword, newPassword, hashedNewPassword });
|
||||
BackendService.sendSessionCommand(Command_AccountPassword_ext, cmd, {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.accountPasswordChange();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,23 +1,25 @@
|
|||
import { AccountActivationParams } from 'store';
|
||||
import { StatusEnum, WebSocketConnectOptions } from 'types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import webClient from '../../WebClient';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { ProtoController } from '../../services/ProtoController';
|
||||
import { Command_Activate_ext, Command_ActivateSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_ResponseCode } from 'generated/proto/response_pb';
|
||||
|
||||
import { disconnect, login, updateStatus } from './';
|
||||
|
||||
export function activate(options: WebSocketConnectOptions, password?: string, passwordSalt?: string): void {
|
||||
const { userName, token } = options as unknown as AccountActivationParams;
|
||||
|
||||
BackendService.sendSessionCommand('Command_Activate', {
|
||||
BackendService.sendSessionCommand(Command_Activate_ext, create(Command_ActivateSchema, {
|
||||
...webClient.clientConfig,
|
||||
userName,
|
||||
token,
|
||||
}, {
|
||||
}), {
|
||||
onResponseCode: {
|
||||
[ProtoController.root.Response.ResponseCode.RespActivationAccepted]: () => {
|
||||
[Response_ResponseCode.RespActivationAccepted]: () => {
|
||||
SessionPersistence.accountActivationSuccess();
|
||||
login(options, password, passwordSalt);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_AddToList_ext, Command_AddToListSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function addToBuddyList(userName: string): void {
|
||||
|
|
@ -10,7 +12,7 @@ export function addToIgnoreList(userName: string): void {
|
|||
}
|
||||
|
||||
export function addToList(list: string, userName: string): void {
|
||||
BackendService.sendSessionCommand('Command_AddToList', { list, userName }, {
|
||||
BackendService.sendSessionCommand(Command_AddToList_ext, create(Command_AddToListSchema, { list, userName }), {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.addToList(list, userName);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_DeckDelSchema, Command_DeckDel_ext } from 'generated/proto/command_deck_del_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function deckDel(deckId: number): void {
|
||||
BackendService.sendSessionCommand('Command_DeckDel', { deckId }, {
|
||||
BackendService.sendSessionCommand(Command_DeckDel_ext, create(Command_DeckDelSchema, { deckId }), {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.deleteServerDeck(deckId);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_DeckDelDirSchema, Command_DeckDelDir_ext } from 'generated/proto/command_deck_del_dir_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function deckDelDir(path: string): void {
|
||||
BackendService.sendSessionCommand('Command_DeckDelDir', { path }, {
|
||||
BackendService.sendSessionCommand(Command_DeckDelDir_ext, create(Command_DeckDelDirSchema, { path }), {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.deleteServerDeckDir(path);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_DeckListSchema, Command_DeckList_ext } from 'generated/proto/command_deck_list_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_DeckList_ext } from 'generated/proto/response_deck_list_pb';
|
||||
|
||||
export function deckList(): void {
|
||||
BackendService.sendSessionCommand('Command_DeckList', {}, {
|
||||
responseName: 'Response_DeckList',
|
||||
BackendService.sendSessionCommand(Command_DeckList_ext, create(Command_DeckListSchema), {
|
||||
responseExt: Response_DeckList_ext,
|
||||
onSuccess: (response) => {
|
||||
SessionPersistence.updateServerDecks(response);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_DeckNewDirSchema, Command_DeckNewDir_ext } from 'generated/proto/command_deck_new_dir_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function deckNewDir(path: string, dirName: string): void {
|
||||
BackendService.sendSessionCommand('Command_DeckNewDir', { path, dirName }, {
|
||||
BackendService.sendSessionCommand(Command_DeckNewDir_ext, create(Command_DeckNewDirSchema, { path, dirName }), {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.createServerDeckDir(path, dirName);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_DeckUploadSchema, Command_DeckUpload_ext } from 'generated/proto/command_deck_upload_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_DeckUpload_ext } from 'generated/proto/response_deck_upload_pb';
|
||||
|
||||
export function deckUpload(path: string, deckId: number, deckList: string): void {
|
||||
BackendService.sendSessionCommand('Command_DeckUpload', { path, deckId, deckList }, {
|
||||
responseName: 'Response_DeckUpload',
|
||||
BackendService.sendSessionCommand(Command_DeckUpload_ext, create(Command_DeckUploadSchema, { path, deckId, deckList }), {
|
||||
responseExt: Response_DeckUpload_ext,
|
||||
onSuccess: (response) => {
|
||||
SessionPersistence.uploadServerDeck(path, response.newFile);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,19 +1,23 @@
|
|||
import { ForgotPasswordChallengeParams } from 'store';
|
||||
import { StatusEnum, WebSocketConnectOptions } from 'types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import webClient from '../../WebClient';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import {
|
||||
Command_ForgotPasswordChallenge_ext, Command_ForgotPasswordChallengeSchema,
|
||||
} from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { disconnect, updateStatus } from './';
|
||||
|
||||
export function forgotPasswordChallenge(options: WebSocketConnectOptions): void {
|
||||
const { userName, email } = options as unknown as ForgotPasswordChallengeParams;
|
||||
|
||||
BackendService.sendSessionCommand('Command_ForgotPasswordChallenge', {
|
||||
BackendService.sendSessionCommand(Command_ForgotPasswordChallenge_ext, create(Command_ForgotPasswordChallengeSchema, {
|
||||
...webClient.clientConfig,
|
||||
userName,
|
||||
email,
|
||||
}, {
|
||||
}), {
|
||||
onSuccess: () => {
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
SessionPersistence.resetPassword();
|
||||
|
|
|
|||
|
|
@ -1,20 +1,25 @@
|
|||
import { ForgotPasswordParams } from 'store';
|
||||
import { StatusEnum, WebSocketConnectOptions } from 'types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import webClient from '../../WebClient';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import {
|
||||
Command_ForgotPasswordRequest_ext, Command_ForgotPasswordRequestSchema,
|
||||
} from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_ForgotPasswordRequest_ext } from 'generated/proto/response_forgotpasswordrequest_pb';
|
||||
|
||||
import { disconnect, updateStatus } from './';
|
||||
|
||||
export function forgotPasswordRequest(options: WebSocketConnectOptions): void {
|
||||
const { userName } = options as unknown as ForgotPasswordParams;
|
||||
|
||||
BackendService.sendSessionCommand('Command_ForgotPasswordRequest', {
|
||||
BackendService.sendSessionCommand(Command_ForgotPasswordRequest_ext, create(Command_ForgotPasswordRequestSchema, {
|
||||
...webClient.clientConfig,
|
||||
userName,
|
||||
}, {
|
||||
responseName: 'Response_ForgotPasswordRequest',
|
||||
}), {
|
||||
responseExt: Response_ForgotPasswordRequest_ext,
|
||||
onSuccess: (resp) => {
|
||||
if (resp?.challengeEmail) {
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,13 @@
|
|||
import { ForgotPasswordResetParams } from 'store';
|
||||
import { StatusEnum, WebSocketConnectOptions } from 'types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import type { MessageInitShape } from '@bufbuild/protobuf';
|
||||
import webClient from '../../WebClient';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import {
|
||||
Command_ForgotPasswordReset_ext, Command_ForgotPasswordResetSchema,
|
||||
} from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { hashPassword } from '../../utils';
|
||||
|
||||
|
|
@ -11,19 +16,16 @@ import { disconnect, updateStatus } from '.';
|
|||
export function forgotPasswordReset(options: WebSocketConnectOptions, newPassword?: string, passwordSalt?: string): void {
|
||||
const { userName, token } = options as unknown as ForgotPasswordResetParams;
|
||||
|
||||
const params: any = {
|
||||
const params: MessageInitShape<typeof Command_ForgotPasswordResetSchema> = {
|
||||
...webClient.clientConfig,
|
||||
userName,
|
||||
token,
|
||||
...(passwordSalt
|
||||
? { hashedNewPassword: hashPassword(passwordSalt, newPassword) }
|
||||
: { newPassword }),
|
||||
};
|
||||
|
||||
if (passwordSalt) {
|
||||
params.hashedNewPassword = hashPassword(passwordSalt, newPassword);
|
||||
} else {
|
||||
params.newPassword = newPassword;
|
||||
}
|
||||
|
||||
BackendService.sendSessionCommand('Command_ForgotPasswordReset', params, {
|
||||
BackendService.sendSessionCommand(Command_ForgotPasswordReset_ext, create(Command_ForgotPasswordResetSchema, params), {
|
||||
onSuccess: () => {
|
||||
updateStatus(StatusEnum.DISCONNECTED, null);
|
||||
SessionPersistence.resetPasswordSuccess();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_GetGamesOfUser_ext, Command_GetGamesOfUserSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_GetGamesOfUser_ext } from 'generated/proto/response_get_games_of_user_pb';
|
||||
|
||||
export function getGamesOfUser(userName: string): void {
|
||||
BackendService.sendSessionCommand('Command_GetGamesOfUser', { userName }, {
|
||||
responseName: 'Response_GetGamesOfUser',
|
||||
BackendService.sendSessionCommand(Command_GetGamesOfUser_ext, create(Command_GetGamesOfUserSchema, { userName }), {
|
||||
responseExt: Response_GetGamesOfUser_ext,
|
||||
onSuccess: (response) => {
|
||||
SessionPersistence.getGamesOfUser(userName, response);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_GetUserInfo_ext, Command_GetUserInfoSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_GetUserInfo_ext } from 'generated/proto/response_get_user_info_pb';
|
||||
|
||||
export function getUserInfo(userName: string): void {
|
||||
BackendService.sendSessionCommand('Command_GetUserInfo', { userName }, {
|
||||
responseName: 'Response_GetUserInfo',
|
||||
BackendService.sendSessionCommand(Command_GetUserInfo_ext, create(Command_GetUserInfoSchema, { userName }), {
|
||||
responseExt: Response_GetUserInfo_ext,
|
||||
onSuccess: (response) => {
|
||||
SessionPersistence.getUserInfo(response.userInfo);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_JoinRoom_ext, Command_JoinRoomSchema } from 'generated/proto/session_commands_pb';
|
||||
import { RoomPersistence } from '../../persistence';
|
||||
import { Response_JoinRoom_ext } from 'generated/proto/response_join_room_pb';
|
||||
|
||||
export function joinRoom(roomId: number): void {
|
||||
BackendService.sendSessionCommand('Command_JoinRoom', { roomId }, {
|
||||
responseName: 'Response_JoinRoom',
|
||||
BackendService.sendSessionCommand(Command_JoinRoom_ext, create(Command_JoinRoomSchema, { roomId }), {
|
||||
responseExt: Response_JoinRoom_ext,
|
||||
onSuccess: (response) => {
|
||||
RoomPersistence.joinRoom(response.roomInfo);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_ListRooms_ext, Command_ListRoomsSchema } from 'generated/proto/session_commands_pb';
|
||||
|
||||
export function listRooms(): void {
|
||||
BackendService.sendSessionCommand('Command_ListRooms', {}, {});
|
||||
BackendService.sendSessionCommand(Command_ListRooms_ext, create(Command_ListRoomsSchema));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_ListUsers_ext, Command_ListUsersSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_ListUsers_ext } from 'generated/proto/response_list_users_pb';
|
||||
|
||||
export function listUsers(): void {
|
||||
BackendService.sendSessionCommand('Command_ListUsers', {}, {
|
||||
responseName: 'Response_ListUsers',
|
||||
BackendService.sendSessionCommand(Command_ListUsers_ext, create(Command_ListUsersSchema), {
|
||||
responseExt: Response_ListUsers_ext,
|
||||
onSuccess: (response) => {
|
||||
SessionPersistence.updateUsers(response.userList);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
import { StatusEnum, WebSocketConnectOptions } from 'types';
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import type { MessageInitShape } from '@bufbuild/protobuf';
|
||||
import webClient from '../../WebClient';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { ProtoController } from '../../services/ProtoController';
|
||||
import { Command_Login_ext, Command_LoginSchema } from 'generated/proto/session_commands_pb';
|
||||
import { hashPassword } from '../../utils';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_Login_ext } from 'generated/proto/response_login_pb';
|
||||
import { Response_ResponseCode } from 'generated/proto/response_pb';
|
||||
|
||||
import {
|
||||
disconnect,
|
||||
|
|
@ -15,20 +19,15 @@ import {
|
|||
export function login(options: WebSocketConnectOptions, password?: string, passwordSalt?: string): void {
|
||||
const { userName, hashedPassword } = options;
|
||||
|
||||
const loginConfig: any = {
|
||||
const loginConfig: MessageInitShape<typeof Command_LoginSchema> = {
|
||||
...webClient.clientConfig,
|
||||
clientid: 'webatrice',
|
||||
userName,
|
||||
...(passwordSalt
|
||||
? { hashedPassword: hashedPassword || hashPassword(passwordSalt, password) }
|
||||
: { password }),
|
||||
};
|
||||
|
||||
if (passwordSalt) {
|
||||
loginConfig.hashedPassword = hashedPassword || hashPassword(passwordSalt, password);
|
||||
} else {
|
||||
loginConfig.password = password;
|
||||
}
|
||||
|
||||
const { ResponseCode } = ProtoController.root.Response;
|
||||
|
||||
const onLoginError = (message: string, extra?: () => void) => {
|
||||
updateStatus(StatusEnum.DISCONNECTED, message);
|
||||
extra?.();
|
||||
|
|
@ -36,8 +35,8 @@ export function login(options: WebSocketConnectOptions, password?: string, passw
|
|||
disconnect();
|
||||
};
|
||||
|
||||
BackendService.sendSessionCommand('Command_Login', loginConfig, {
|
||||
responseName: 'Response_Login',
|
||||
BackendService.sendSessionCommand(Command_Login_ext, create(Command_LoginSchema, loginConfig), {
|
||||
responseExt: Response_Login_ext,
|
||||
onSuccess: (resp) => {
|
||||
const { buddyList, ignoreList, userInfo } = resp;
|
||||
|
||||
|
|
@ -53,23 +52,23 @@ export function login(options: WebSocketConnectOptions, password?: string, passw
|
|||
updateStatus(StatusEnum.LOGGED_IN, 'Logged in.');
|
||||
},
|
||||
onResponseCode: {
|
||||
[ResponseCode.RespClientUpdateRequired]: () =>
|
||||
[Response_ResponseCode.RespClientUpdateRequired]: () =>
|
||||
onLoginError('Login failed: missing features'),
|
||||
[ResponseCode.RespWrongPassword]: () =>
|
||||
[Response_ResponseCode.RespWrongPassword]: () =>
|
||||
onLoginError('Login failed: incorrect username or password'),
|
||||
[ResponseCode.RespUsernameInvalid]: () =>
|
||||
[Response_ResponseCode.RespUsernameInvalid]: () =>
|
||||
onLoginError('Login failed: incorrect username or password'),
|
||||
[ResponseCode.RespWouldOverwriteOldSession]: () =>
|
||||
[Response_ResponseCode.RespWouldOverwriteOldSession]: () =>
|
||||
onLoginError('Login failed: duplicated user session'),
|
||||
[ResponseCode.RespUserIsBanned]: () =>
|
||||
[Response_ResponseCode.RespUserIsBanned]: () =>
|
||||
onLoginError('Login failed: banned user'),
|
||||
[ResponseCode.RespRegistrationRequired]: () =>
|
||||
[Response_ResponseCode.RespRegistrationRequired]: () =>
|
||||
onLoginError('Login failed: registration required'),
|
||||
[ResponseCode.RespClientIdRequired]: () =>
|
||||
[Response_ResponseCode.RespClientIdRequired]: () =>
|
||||
onLoginError('Login failed: missing client ID'),
|
||||
[ResponseCode.RespContextError]: () =>
|
||||
[Response_ResponseCode.RespContextError]: () =>
|
||||
onLoginError('Login failed: server error'),
|
||||
[ResponseCode.RespAccountNotActivated]: () =>
|
||||
[Response_ResponseCode.RespAccountNotActivated]: () =>
|
||||
onLoginError('Login failed: account not activated',
|
||||
() => {
|
||||
const { password: _p, newPassword: _np, ...safeOptions } = options;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_Message_ext, Command_MessageSchema } from 'generated/proto/session_commands_pb';
|
||||
|
||||
export function message(userName: string, message: string): void {
|
||||
BackendService.sendSessionCommand('Command_Message', { userName, message }, {});
|
||||
BackendService.sendSessionCommand(Command_Message_ext, create(Command_MessageSchema, { userName, message }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_Ping_ext, Command_PingSchema } from 'generated/proto/session_commands_pb';
|
||||
|
||||
export function ping(pingReceived: Function): void {
|
||||
BackendService.sendSessionCommand('Command_Ping', {}, {
|
||||
BackendService.sendSessionCommand(Command_Ping_ext, create(Command_PingSchema), {
|
||||
onResponse: (raw) => pingReceived(raw),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,73 +1,71 @@
|
|||
import { ServerRegisterParams } from 'store';
|
||||
import { StatusEnum, WebSocketConnectOptions } from 'types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import type { MessageInitShape } from '@bufbuild/protobuf';
|
||||
import webClient from '../../WebClient';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { ProtoController } from '../../services/ProtoController';
|
||||
import { Command_Register_ext, Command_RegisterSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { hashPassword } from '../../utils';
|
||||
import { Response_ResponseCode } from 'generated/proto/response_pb';
|
||||
|
||||
import { login, disconnect, updateStatus } from './';
|
||||
|
||||
export function register(options: WebSocketConnectOptions, password?: string, passwordSalt?: string): void {
|
||||
const { userName, email, country, realName } = options as ServerRegisterParams;
|
||||
|
||||
const params: any = {
|
||||
const params: MessageInitShape<typeof Command_RegisterSchema> = {
|
||||
...webClient.clientConfig,
|
||||
userName,
|
||||
email,
|
||||
country,
|
||||
realName,
|
||||
...(passwordSalt
|
||||
? { hashedPassword: hashPassword(passwordSalt, password) }
|
||||
: { password }),
|
||||
};
|
||||
|
||||
if (passwordSalt) {
|
||||
params.hashedPassword = hashPassword(passwordSalt, password);
|
||||
} else {
|
||||
params.password = password;
|
||||
}
|
||||
|
||||
const { ResponseCode } = ProtoController.root.Response;
|
||||
|
||||
const onRegistrationError = (action: () => void) => {
|
||||
action();
|
||||
updateStatus(StatusEnum.DISCONNECTED, 'Registration failed');
|
||||
disconnect();
|
||||
};
|
||||
|
||||
BackendService.sendSessionCommand('Command_Register', params, {
|
||||
BackendService.sendSessionCommand(Command_Register_ext, create(Command_RegisterSchema, params), {
|
||||
onResponseCode: {
|
||||
[ResponseCode.RespRegistrationAccepted]: () => {
|
||||
[Response_ResponseCode.RespRegistrationAccepted]: () => {
|
||||
login(options, password, passwordSalt);
|
||||
SessionPersistence.registrationSuccess();
|
||||
},
|
||||
[ResponseCode.RespRegistrationAcceptedNeedsActivation]: () => {
|
||||
[Response_ResponseCode.RespRegistrationAcceptedNeedsActivation]: () => {
|
||||
updateStatus(StatusEnum.DISCONNECTED, 'Registration accepted, awaiting activation');
|
||||
const { password: _p, newPassword: _np, ...safeOptions } = options;
|
||||
SessionPersistence.accountAwaitingActivation(safeOptions);
|
||||
disconnect();
|
||||
},
|
||||
[ResponseCode.RespUserAlreadyExists]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespUserAlreadyExists]: () => onRegistrationError(
|
||||
() => SessionPersistence.registrationUserNameError('Username is taken')
|
||||
),
|
||||
[ResponseCode.RespUsernameInvalid]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespUsernameInvalid]: () => onRegistrationError(
|
||||
() => SessionPersistence.registrationUserNameError('Invalid username')
|
||||
),
|
||||
[ResponseCode.RespPasswordTooShort]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespPasswordTooShort]: () => onRegistrationError(
|
||||
() => SessionPersistence.registrationPasswordError('Your password was too short')
|
||||
),
|
||||
[ResponseCode.RespEmailRequiredToRegister]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespEmailRequiredToRegister]: () => onRegistrationError(
|
||||
() => SessionPersistence.registrationRequiresEmail()
|
||||
),
|
||||
[ResponseCode.RespEmailBlackListed]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespEmailBlackListed]: () => onRegistrationError(
|
||||
() => SessionPersistence.registrationEmailError('This email provider has been blocked')
|
||||
),
|
||||
[ResponseCode.RespTooManyRequests]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespTooManyRequests]: () => onRegistrationError(
|
||||
() => SessionPersistence.registrationEmailError('Max accounts reached for this email')
|
||||
),
|
||||
[ResponseCode.RespRegistrationDisabled]: () => onRegistrationError(
|
||||
[Response_ResponseCode.RespRegistrationDisabled]: () => onRegistrationError(
|
||||
() => SessionPersistence.registrationFailed('Registration is currently disabled')
|
||||
),
|
||||
[ResponseCode.RespUserIsBanned]: (raw) => onRegistrationError(
|
||||
[Response_ResponseCode.RespUserIsBanned]: (raw) => onRegistrationError(
|
||||
() => SessionPersistence.registrationFailed(raw.reasonStr, raw.endTime)
|
||||
),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_RemoveFromList_ext, Command_RemoveFromListSchema } from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function removeFromBuddyList(userName: string): void {
|
||||
|
|
@ -10,7 +12,7 @@ export function removeFromIgnoreList(userName: string): void {
|
|||
}
|
||||
|
||||
export function removeFromList(list: string, userName: string): void {
|
||||
BackendService.sendSessionCommand('Command_RemoveFromList', { list, userName }, {
|
||||
BackendService.sendSessionCommand(Command_RemoveFromList_ext, create(Command_RemoveFromListSchema, { list, userName }), {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.removeFromList(list, userName);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_ReplayDeleteMatchSchema, Command_ReplayDeleteMatch_ext } from 'generated/proto/command_replay_delete_match_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function replayDeleteMatch(gameId: number): void {
|
||||
BackendService.sendSessionCommand('Command_ReplayDeleteMatch', { gameId }, {
|
||||
BackendService.sendSessionCommand(Command_ReplayDeleteMatch_ext, create(Command_ReplayDeleteMatchSchema, { gameId }), {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.replayDeleteMatch(gameId);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_ReplayGetCodeSchema, Command_ReplayGetCode_ext } from 'generated/proto/command_replay_get_code_pb';
|
||||
import { Response_ReplayGetCode_ext } from 'generated/proto/response_replay_get_code_pb';
|
||||
|
||||
export function replayGetCode(gameId: number, onCodeReceived: (code: string) => void): void {
|
||||
BackendService.sendSessionCommand('Command_ReplayGetCode', { gameId }, {
|
||||
responseName: 'Response_ReplayGetCode',
|
||||
BackendService.sendSessionCommand(Command_ReplayGetCode_ext, create(Command_ReplayGetCodeSchema, { gameId }), {
|
||||
responseExt: Response_ReplayGetCode_ext,
|
||||
onSuccess: (response) => {
|
||||
onCodeReceived(response.replayCode);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_ReplayListSchema, Command_ReplayList_ext } from 'generated/proto/command_replay_list_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_ReplayList_ext } from 'generated/proto/response_replay_list_pb';
|
||||
|
||||
export function replayList(): void {
|
||||
BackendService.sendSessionCommand('Command_ReplayList', {}, {
|
||||
responseName: 'Response_ReplayList',
|
||||
BackendService.sendSessionCommand(Command_ReplayList_ext, create(Command_ReplayListSchema), {
|
||||
responseExt: Response_ReplayList_ext,
|
||||
onSuccess: (response) => {
|
||||
SessionPersistence.replayList(response.matchList);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_ReplayModifyMatchSchema, Command_ReplayModifyMatch_ext } from 'generated/proto/command_replay_modify_match_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
|
||||
export function replayModifyMatch(gameId: number, doNotHide: boolean): void {
|
||||
BackendService.sendSessionCommand('Command_ReplayModifyMatch', { gameId, doNotHide }, {
|
||||
BackendService.sendSessionCommand(Command_ReplayModifyMatch_ext, create(Command_ReplayModifyMatchSchema, { gameId, doNotHide }), {
|
||||
onSuccess: () => {
|
||||
SessionPersistence.replayModifyMatch(gameId, doNotHide);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import { create } from '@bufbuild/protobuf';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { Command_ReplaySubmitCodeSchema, Command_ReplaySubmitCode_ext } from 'generated/proto/command_replay_submit_code_pb';
|
||||
|
||||
export function replaySubmitCode(
|
||||
replayCode: string,
|
||||
onSuccess?: () => void,
|
||||
onError?: (responseCode: number) => void,
|
||||
): void {
|
||||
BackendService.sendSessionCommand('Command_ReplaySubmitCode', { replayCode }, {
|
||||
BackendService.sendSessionCommand(Command_ReplaySubmitCode_ext, create(Command_ReplaySubmitCodeSchema, { replayCode }), {
|
||||
onSuccess,
|
||||
onError,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
import { RequestPasswordSaltParams } from 'store';
|
||||
import { StatusEnum, WebSocketConnectOptions, WebSocketConnectReason } from 'types';
|
||||
|
||||
import { create } from '@bufbuild/protobuf';
|
||||
import webClient from '../../WebClient';
|
||||
import { BackendService } from '../../services/BackendService';
|
||||
import { ProtoController } from '../../services/ProtoController';
|
||||
import {
|
||||
Command_RequestPasswordSalt_ext, Command_RequestPasswordSaltSchema,
|
||||
} from 'generated/proto/session_commands_pb';
|
||||
import { SessionPersistence } from '../../persistence';
|
||||
import { Response_PasswordSalt_ext } from 'generated/proto/response_password_salt_pb';
|
||||
import { Response_ResponseCode } from 'generated/proto/response_pb';
|
||||
|
||||
import {
|
||||
activate,
|
||||
|
|
@ -31,11 +36,11 @@ export function requestPasswordSalt(options: WebSocketConnectOptions, password?:
|
|||
disconnect();
|
||||
};
|
||||
|
||||
BackendService.sendSessionCommand('Command_RequestPasswordSalt', {
|
||||
BackendService.sendSessionCommand(Command_RequestPasswordSalt_ext, create(Command_RequestPasswordSaltSchema, {
|
||||
...webClient.clientConfig,
|
||||
userName,
|
||||
}, {
|
||||
responseName: 'Response_PasswordSalt',
|
||||
}), {
|
||||
responseExt: Response_PasswordSalt_ext,
|
||||
onSuccess: (resp) => {
|
||||
const passwordSalt = resp?.passwordSalt;
|
||||
|
||||
|
|
@ -51,7 +56,7 @@ export function requestPasswordSalt(options: WebSocketConnectOptions, password?:
|
|||
}
|
||||
},
|
||||
onResponseCode: {
|
||||
[ProtoController.root.Response.ResponseCode.RespRegistrationRequired]: () => {
|
||||
[Response_ResponseCode.RespRegistrationRequired]: () => {
|
||||
updateStatus(StatusEnum.DISCONNECTED, 'Login failed: registration required');
|
||||
onFailure();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,11 +20,6 @@ vi.mock('../../WebClient', async () => {
|
|||
return { __esModule: true, default: makeWebClientMock() };
|
||||
});
|
||||
|
||||
vi.mock('../../services/ProtoController', async () => {
|
||||
const { makeProtoControllerRootMock } = await import('../../__mocks__/sessionCommandMocks');
|
||||
return { ProtoController: { root: makeProtoControllerRootMock() } };
|
||||
});
|
||||
|
||||
vi.mock('../../utils', async () => {
|
||||
const { makeUtilsMock } = await import('../../__mocks__/sessionCommandMocks');
|
||||
return makeUtilsMock();
|
||||
|
|
@ -43,6 +38,19 @@ import webClient from '../../WebClient';
|
|||
import * as SessionIndexMocks from './';
|
||||
import { StatusEnum, WebSocketConnectReason } from 'types';
|
||||
import { hashPassword, generateSalt, passwordSaltSupported } from '../../utils';
|
||||
import { Response_ResponseCode } from 'generated/proto/response_pb';
|
||||
import {
|
||||
Command_Activate_ext,
|
||||
Command_ForgotPasswordChallenge_ext,
|
||||
Command_ForgotPasswordRequest_ext,
|
||||
Command_ForgotPasswordReset_ext,
|
||||
Command_Login_ext,
|
||||
Command_Register_ext,
|
||||
Command_RequestPasswordSalt_ext,
|
||||
} from 'generated/proto/session_commands_pb';
|
||||
import { Response_ForgotPasswordRequest_ext } from 'generated/proto/response_forgotpasswordrequest_pb';
|
||||
import { Response_Login_ext } from 'generated/proto/response_login_pb';
|
||||
import { Response_PasswordSalt_ext } from 'generated/proto/response_password_salt_pb';
|
||||
import { connect } from './connect';
|
||||
import { updateStatus } from './updateStatus';
|
||||
import { login } from './login';
|
||||
|
|
@ -54,7 +62,8 @@ import { forgotPasswordReset } from './forgotPasswordReset';
|
|||
import { requestPasswordSalt } from './requestPasswordSalt';
|
||||
|
||||
const { getLastSendOpts, invokeOnSuccess, invokeResponseCode, invokeOnError } = makeCallbackHelpers(
|
||||
BackendService.sendSessionCommand as vi.Mock
|
||||
BackendService.sendSessionCommand as vi.Mock,
|
||||
2
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -132,34 +141,34 @@ describe('login', () => {
|
|||
it('sends Command_Login with plain password when no salt', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_Login',
|
||||
expect.objectContaining({ userName: 'alice', password: 'pw' }),
|
||||
expect.any(Object)
|
||||
Command_Login_ext,
|
||||
expect.objectContaining({ password: 'pw' }),
|
||||
expect.objectContaining({ responseExt: Response_Login_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('sends Command_Login with hashedPassword when salt is given', () => {
|
||||
login({ userName: 'alice' } as any, 'pw', 'salt');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_Login',
|
||||
Command_Login_ext,
|
||||
expect.objectContaining({ hashedPassword: 'hashed_pw' }),
|
||||
expect.any(Object)
|
||||
expect.objectContaining({ responseExt: Response_Login_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('uses options.hashedPassword if provided', () => {
|
||||
login({ userName: 'alice', hashedPassword: 'pre_hashed' } as any, 'pw', 'salt');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_Login',
|
||||
Command_Login_ext,
|
||||
expect.objectContaining({ hashedPassword: 'pre_hashed' }),
|
||||
expect.any(Object)
|
||||
expect.objectContaining({ responseExt: Response_Login_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('onSuccess dispatches buddy/ignore/user and calls listUsers/listRooms', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
const loginResp = { buddyList: [], ignoreList: [], userInfo: { name: 'alice' } };
|
||||
invokeOnSuccess(loginResp, { responseCode: 0, '.Response_Login.ext': loginResp });
|
||||
invokeOnSuccess(loginResp, { responseCode: 0 });
|
||||
expect(SessionPersistence.updateBuddyList).toHaveBeenCalledWith([]);
|
||||
expect(SessionPersistence.updateIgnoreList).toHaveBeenCalledWith([]);
|
||||
expect(SessionPersistence.updateUser).toHaveBeenCalledWith({ name: 'alice' });
|
||||
|
|
@ -172,7 +181,7 @@ describe('login', () => {
|
|||
it('onSuccess does NOT pass plaintext password to loginSuccessful', () => {
|
||||
login({ userName: 'alice' } as any, 'secret');
|
||||
const loginResp = { buddyList: [], ignoreList: [], userInfo: { name: 'alice' } };
|
||||
invokeOnSuccess(loginResp, { responseCode: 0, '.Response_Login.ext': loginResp });
|
||||
invokeOnSuccess(loginResp, { responseCode: 0 });
|
||||
const calledWith = (SessionPersistence.loginSuccessful as vi.Mock).mock.calls[0][0];
|
||||
expect(calledWith).not.toHaveProperty('password');
|
||||
});
|
||||
|
|
@ -180,63 +189,63 @@ describe('login', () => {
|
|||
it('onSuccess passes hashedPassword to loginSuccessful when salt is used', () => {
|
||||
login({ userName: 'alice' } as any, 'pw', 'salt');
|
||||
const loginResp = { buddyList: [], ignoreList: [], userInfo: { name: 'alice' } };
|
||||
invokeOnSuccess(loginResp, { responseCode: 0, '.Response_Login.ext': loginResp });
|
||||
invokeOnSuccess(loginResp, { responseCode: 0 });
|
||||
const calledWith = (SessionPersistence.loginSuccessful as vi.Mock).mock.calls[0][0];
|
||||
expect(calledWith).toHaveProperty('hashedPassword', 'hashed_pw');
|
||||
});
|
||||
|
||||
it('onResponseCode RespClientUpdateRequired calls onLoginError', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(1);
|
||||
invokeResponseCode(Response_ResponseCode.RespClientUpdateRequired);
|
||||
expect(SessionPersistence.loginFailed).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.disconnect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespWrongPassword', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(2);
|
||||
invokeResponseCode(Response_ResponseCode.RespWrongPassword);
|
||||
expect(SessionPersistence.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespUsernameInvalid', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(3);
|
||||
invokeResponseCode(Response_ResponseCode.RespUsernameInvalid);
|
||||
expect(SessionPersistence.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespWouldOverwriteOldSession', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(4);
|
||||
invokeResponseCode(Response_ResponseCode.RespWouldOverwriteOldSession);
|
||||
expect(SessionPersistence.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespUserIsBanned', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(5);
|
||||
invokeResponseCode(Response_ResponseCode.RespUserIsBanned);
|
||||
expect(SessionPersistence.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespRegistrationRequired', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(6);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationRequired);
|
||||
expect(SessionPersistence.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespClientIdRequired', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(7);
|
||||
invokeResponseCode(Response_ResponseCode.RespClientIdRequired);
|
||||
expect(SessionPersistence.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespContextError', () => {
|
||||
login({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(8);
|
||||
invokeResponseCode(Response_ResponseCode.RespContextError);
|
||||
expect(SessionPersistence.loginFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespAccountNotActivated calls accountAwaitingActivation without password in options', () => {
|
||||
login({ userName: 'alice', password: 'leaked' } as any, 'pw');
|
||||
invokeResponseCode(9);
|
||||
invokeResponseCode(Response_ResponseCode.RespAccountNotActivated);
|
||||
expect(SessionPersistence.accountAwaitingActivation).toHaveBeenCalledWith(
|
||||
expect.not.objectContaining({ password: expect.anything() })
|
||||
);
|
||||
|
|
@ -258,8 +267,8 @@ describe('register', () => {
|
|||
it('sends Command_Register with plain password when no salt', () => {
|
||||
register({ userName: 'alice', email: 'a@b.com', country: 'US', realName: 'Al' } as any, 'pw');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_Register',
|
||||
expect.objectContaining({ userName: 'alice', password: 'pw' }),
|
||||
Command_Register_ext,
|
||||
expect.objectContaining({ password: 'pw' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
|
@ -267,7 +276,7 @@ describe('register', () => {
|
|||
it('uses hashedPassword when salt is provided', () => {
|
||||
register({ userName: 'alice' } as any, 'pw', 'salt');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_Register',
|
||||
Command_Register_ext,
|
||||
expect.objectContaining({ hashedPassword: 'hashed_pw' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -275,21 +284,21 @@ describe('register', () => {
|
|||
|
||||
it('RespRegistrationAccepted calls login without salt and registrationSuccess', () => {
|
||||
register({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(10);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationAccepted);
|
||||
expect(SessionIndexMocks.login).toHaveBeenCalledWith(expect.any(Object), 'pw', undefined);
|
||||
expect(SessionPersistence.registrationSuccess).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespRegistrationAccepted forwards salt to login', () => {
|
||||
register({ userName: 'alice' } as any, 'pw', 'mySalt');
|
||||
invokeResponseCode(10);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationAccepted);
|
||||
expect(SessionIndexMocks.login).toHaveBeenCalledWith(expect.any(Object), 'pw', 'mySalt');
|
||||
expect(SessionPersistence.registrationSuccess).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespRegistrationAcceptedNeedsActivation calls accountAwaitingActivation without password in options', () => {
|
||||
register({ userName: 'alice', password: 'leaked' } as any, 'pw');
|
||||
invokeResponseCode(11);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationAcceptedNeedsActivation);
|
||||
expect(SessionPersistence.accountAwaitingActivation).toHaveBeenCalledWith(
|
||||
expect.not.objectContaining({ password: expect.anything() })
|
||||
);
|
||||
|
|
@ -298,49 +307,49 @@ describe('register', () => {
|
|||
|
||||
it('RespUserAlreadyExists calls registrationUserNameError', () => {
|
||||
register({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(12);
|
||||
invokeResponseCode(Response_ResponseCode.RespUserAlreadyExists);
|
||||
expect(SessionPersistence.registrationUserNameError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespUsernameInvalid calls registrationUserNameError', () => {
|
||||
register({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(3);
|
||||
invokeResponseCode(Response_ResponseCode.RespUsernameInvalid);
|
||||
expect(SessionPersistence.registrationUserNameError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespPasswordTooShort calls registrationPasswordError', () => {
|
||||
register({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(13);
|
||||
invokeResponseCode(Response_ResponseCode.RespPasswordTooShort);
|
||||
expect(SessionPersistence.registrationPasswordError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespEmailRequiredToRegister calls registrationRequiresEmail', () => {
|
||||
register({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(14);
|
||||
invokeResponseCode(Response_ResponseCode.RespEmailRequiredToRegister);
|
||||
expect(SessionPersistence.registrationRequiresEmail).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespEmailBlackListed calls registrationEmailError', () => {
|
||||
register({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(15);
|
||||
invokeResponseCode(Response_ResponseCode.RespEmailBlackListed);
|
||||
expect(SessionPersistence.registrationEmailError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespTooManyRequests calls registrationEmailError', () => {
|
||||
register({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(16);
|
||||
invokeResponseCode(Response_ResponseCode.RespTooManyRequests);
|
||||
expect(SessionPersistence.registrationEmailError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespRegistrationDisabled calls registrationFailed', () => {
|
||||
register({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(17);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationDisabled);
|
||||
expect(SessionPersistence.registrationFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('RespUserIsBanned calls registrationFailed with raw.reasonStr and raw.endTime', () => {
|
||||
register({ userName: 'alice' } as any, 'pw');
|
||||
invokeResponseCode(5, { reasonStr: 'bad user', endTime: 9999 });
|
||||
invokeResponseCode(Response_ResponseCode.RespUserIsBanned, { reasonStr: 'bad user', endTime: 9999 });
|
||||
expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith('bad user', 9999);
|
||||
});
|
||||
|
||||
|
|
@ -359,12 +368,12 @@ describe('activate', () => {
|
|||
it('sends Command_Activate with userName and token, not password', () => {
|
||||
activate({ userName: 'alice', token: 'tok' } as any, 'pw');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_Activate',
|
||||
Command_Activate_ext,
|
||||
expect.objectContaining({ userName: 'alice', token: 'tok' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_Activate',
|
||||
Command_Activate_ext,
|
||||
expect.not.objectContaining({ password: expect.anything() }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -372,7 +381,7 @@ describe('activate', () => {
|
|||
|
||||
it('RespActivationAccepted calls accountActivationSuccess and forwards password+salt to login', () => {
|
||||
activate({ userName: 'alice', token: 'tok' } as any, 'pw', 'salt');
|
||||
invokeResponseCode(18);
|
||||
invokeResponseCode(Response_ResponseCode.RespActivationAccepted);
|
||||
expect(SessionPersistence.accountActivationSuccess).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.login).toHaveBeenCalledWith(expect.any(Object), 'pw', 'salt');
|
||||
});
|
||||
|
|
@ -393,7 +402,7 @@ describe('forgotPasswordChallenge', () => {
|
|||
it('sends Command_ForgotPasswordChallenge', () => {
|
||||
forgotPasswordChallenge({ userName: 'alice', email: 'a@b.com' } as any);
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_ForgotPasswordChallenge', expect.any(Object), expect.any(Object)
|
||||
Command_ForgotPasswordChallenge_ext, expect.any(Object), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -419,13 +428,17 @@ describe('forgotPasswordRequest', () => {
|
|||
|
||||
it('sends Command_ForgotPasswordRequest', () => {
|
||||
forgotPasswordRequest({ userName: 'alice' } as any);
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_ForgotPasswordRequest', expect.any(Object), expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_ForgotPasswordRequest_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Response_ForgotPasswordRequest_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('onSuccess with challengeEmail calls resetPasswordChallenge', () => {
|
||||
forgotPasswordRequest({ userName: 'alice' } as any);
|
||||
const resp = { challengeEmail: true };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_ForgotPasswordRequest.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionPersistence.resetPasswordChallenge).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.disconnect).toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -433,7 +446,7 @@ describe('forgotPasswordRequest', () => {
|
|||
it('onSuccess without challengeEmail calls resetPassword', () => {
|
||||
forgotPasswordRequest({ userName: 'alice' } as any);
|
||||
const resp = { challengeEmail: false };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_ForgotPasswordRequest.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionPersistence.resetPassword).toHaveBeenCalled();
|
||||
expect(SessionIndexMocks.disconnect).toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -454,7 +467,7 @@ describe('forgotPasswordReset', () => {
|
|||
it('sends Command_ForgotPasswordReset with plain newPassword when no salt', () => {
|
||||
forgotPasswordReset({ userName: 'alice', token: 'tok' } as any, 'newpw');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_ForgotPasswordReset',
|
||||
Command_ForgotPasswordReset_ext,
|
||||
expect.objectContaining({ newPassword: 'newpw' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -463,7 +476,7 @@ describe('forgotPasswordReset', () => {
|
|||
it('sends hashed new password when salt provided', () => {
|
||||
forgotPasswordReset({ userName: 'alice', token: 'tok' } as any, 'newpw', 'salt');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_ForgotPasswordReset',
|
||||
Command_ForgotPasswordReset_ext,
|
||||
expect.objectContaining({ hashedNewPassword: 'hashed_pw' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
|
|
@ -491,40 +504,44 @@ describe('requestPasswordSalt', () => {
|
|||
|
||||
it('sends Command_RequestPasswordSalt', () => {
|
||||
requestPasswordSalt({ userName: 'alice', reason: WebSocketConnectReason.LOGIN } as any, 'pw');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_RequestPasswordSalt', expect.any(Object), expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_RequestPasswordSalt_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Response_PasswordSalt_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('onSuccess with LOGIN reason forwards password+salt to login', () => {
|
||||
requestPasswordSalt({ userName: 'alice', reason: WebSocketConnectReason.LOGIN } as any, 'pw');
|
||||
const resp = { passwordSalt: 'salt123' };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_PasswordSalt.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionIndexMocks.login).toHaveBeenCalledWith(expect.any(Object), 'pw', 'salt123');
|
||||
});
|
||||
|
||||
it('onSuccess with ACTIVATE_ACCOUNT reason forwards password+salt to activate', () => {
|
||||
requestPasswordSalt({ userName: 'alice', reason: WebSocketConnectReason.ACTIVATE_ACCOUNT } as any, 'pw');
|
||||
const resp = { passwordSalt: 'salt123' };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_PasswordSalt.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionIndexMocks.activate).toHaveBeenCalledWith(expect.any(Object), 'pw', 'salt123');
|
||||
});
|
||||
|
||||
it('onSuccess with PASSWORD_RESET reason forwards newPassword+salt to forgotPasswordReset', () => {
|
||||
requestPasswordSalt({ userName: 'alice', reason: WebSocketConnectReason.PASSWORD_RESET } as any, undefined, 'newpw');
|
||||
const resp = { passwordSalt: 'salt123' };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_PasswordSalt.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionIndexMocks.forgotPasswordReset).toHaveBeenCalledWith(expect.any(Object), 'newpw', 'salt123');
|
||||
});
|
||||
|
||||
it('onResponseCode RespRegistrationRequired calls updateStatus and disconnect', () => {
|
||||
requestPasswordSalt({ userName: 'alice', reason: WebSocketConnectReason.LOGIN } as any, 'pw');
|
||||
invokeResponseCode(6);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationRequired);
|
||||
expect(SessionIndexMocks.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, expect.any(String));
|
||||
expect(SessionIndexMocks.disconnect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onResponseCode RespRegistrationRequired with ACTIVATE_ACCOUNT calls accountActivationFailed', () => {
|
||||
requestPasswordSalt({ userName: 'alice', reason: WebSocketConnectReason.ACTIVATE_ACCOUNT } as any, 'pw');
|
||||
invokeResponseCode(6);
|
||||
invokeResponseCode(Response_ResponseCode.RespRegistrationRequired);
|
||||
expect(SessionPersistence.accountActivationFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,6 @@ vi.mock('../../WebClient', async () => {
|
|||
return { __esModule: true, default: makeWebClientMock() };
|
||||
});
|
||||
|
||||
vi.mock('../../services/ProtoController', async () => {
|
||||
const { makeProtoControllerRootMock } = await import('../../__mocks__/sessionCommandMocks');
|
||||
return { ProtoController: { root: makeProtoControllerRootMock() } };
|
||||
});
|
||||
|
||||
vi.mock('../../utils', async () => {
|
||||
const { makeUtilsMock } = await import('../../__mocks__/sessionCommandMocks');
|
||||
return makeUtilsMock();
|
||||
|
|
@ -43,6 +38,38 @@ import { RoomPersistence } from '../../persistence';
|
|||
import webClient from '../../WebClient';
|
||||
import * as SessionCommands from './';
|
||||
import { hashPassword, generateSalt, passwordSaltSupported } from '../../utils';
|
||||
import {
|
||||
Command_AccountEdit_ext,
|
||||
Command_AccountImage_ext,
|
||||
Command_AccountPassword_ext,
|
||||
Command_AddToList_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,
|
||||
} from 'generated/proto/session_commands_pb';
|
||||
import { Command_DeckDel_ext } from 'generated/proto/command_deck_del_pb';
|
||||
import { Command_DeckDelDir_ext } from 'generated/proto/command_deck_del_dir_pb';
|
||||
import { Command_DeckList_ext } from 'generated/proto/command_deck_list_pb';
|
||||
import { Command_DeckNewDir_ext } from 'generated/proto/command_deck_new_dir_pb';
|
||||
import { Command_DeckUpload_ext } from 'generated/proto/command_deck_upload_pb';
|
||||
import { Command_ReplayDeleteMatch_ext } from 'generated/proto/command_replay_delete_match_pb';
|
||||
import { Command_ReplayGetCode_ext } from 'generated/proto/command_replay_get_code_pb';
|
||||
import { Command_ReplayList_ext } from 'generated/proto/command_replay_list_pb';
|
||||
import { Command_ReplayModifyMatch_ext } from 'generated/proto/command_replay_modify_match_pb';
|
||||
import { Command_ReplaySubmitCode_ext } from 'generated/proto/command_replay_submit_code_pb';
|
||||
import { Response_DeckList_ext } from 'generated/proto/response_deck_list_pb';
|
||||
import { Response_DeckUpload_ext } from 'generated/proto/response_deck_upload_pb';
|
||||
import { Response_GetGamesOfUser_ext } from 'generated/proto/response_get_games_of_user_pb';
|
||||
import { Response_GetUserInfo_ext } from 'generated/proto/response_get_user_info_pb';
|
||||
import { Response_JoinRoom_ext } from 'generated/proto/response_join_room_pb';
|
||||
import { Response_ListUsers_ext } from 'generated/proto/response_list_users_pb';
|
||||
import { Response_ReplayGetCode_ext } from 'generated/proto/response_replay_get_code_pb';
|
||||
import { Response_ReplayList_ext } from 'generated/proto/response_replay_list_pb';
|
||||
import { accountEdit } from './accountEdit';
|
||||
import { accountImage } from './accountImage';
|
||||
import { accountPassword } from './accountPassword';
|
||||
|
|
@ -68,7 +95,8 @@ import { replayGetCode } from './replayGetCode';
|
|||
import { replaySubmitCode } from './replaySubmitCode';
|
||||
|
||||
const { invokeOnSuccess, invokeCallback } = makeCallbackHelpers(
|
||||
BackendService.sendSessionCommand as vi.Mock
|
||||
BackendService.sendSessionCommand as vi.Mock,
|
||||
2
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -86,8 +114,8 @@ describe('accountEdit', () => {
|
|||
it('sends Command_AccountEdit with correct params', () => {
|
||||
accountEdit('pw', 'Alice', 'a@b.com', 'US');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_AccountEdit',
|
||||
{ passwordCheck: 'pw', realName: 'Alice', email: 'a@b.com', country: 'US' },
|
||||
Command_AccountEdit_ext,
|
||||
expect.objectContaining({ passwordCheck: 'pw', realName: 'Alice', email: 'a@b.com', country: 'US' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
|
@ -105,7 +133,9 @@ describe('accountImage', () => {
|
|||
it('sends Command_AccountImage', () => {
|
||||
const img = new Uint8Array([1, 2]);
|
||||
accountImage(img);
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_AccountImage', { image: img }, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_AccountImage_ext, expect.objectContaining({ image: img }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
it('calls SessionPersistence.accountImageChanged on success', () => {
|
||||
|
|
@ -122,8 +152,8 @@ describe('accountPassword', () => {
|
|||
it('sends Command_AccountPassword', () => {
|
||||
accountPassword('old', 'new', 'hashed');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_AccountPassword',
|
||||
{ oldPassword: 'old', newPassword: 'new', hashedNewPassword: 'hashed' },
|
||||
Command_AccountPassword_ext,
|
||||
expect.objectContaining({ oldPassword: 'old', newPassword: 'new', hashedNewPassword: 'hashed' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
|
@ -140,7 +170,11 @@ describe('deckDel', () => {
|
|||
|
||||
it('sends Command_DeckDel', () => {
|
||||
deckDel(42);
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_DeckDel', { deckId: 42 }, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_DeckDel_ext,
|
||||
expect.objectContaining({ deckId: 42 }),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
it('calls deleteServerDeck on success', () => {
|
||||
|
|
@ -155,7 +189,9 @@ describe('deckDelDir', () => {
|
|||
|
||||
it('sends Command_DeckDelDir', () => {
|
||||
deckDelDir('/path');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_DeckDelDir', { path: '/path' }, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_DeckDelDir_ext, expect.objectContaining({ path: '/path' }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
it('calls deleteServerDeckDir on success', () => {
|
||||
|
|
@ -170,13 +206,17 @@ describe('deckList', () => {
|
|||
|
||||
it('sends Command_DeckList', () => {
|
||||
deckList();
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_DeckList', {}, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_DeckList_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Response_DeckList_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('calls updateServerDecks on success', () => {
|
||||
deckList();
|
||||
const resp = { folders: [] };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_DeckList.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionPersistence.updateServerDecks).toHaveBeenCalledWith(resp);
|
||||
});
|
||||
});
|
||||
|
|
@ -187,7 +227,7 @@ describe('deckNewDir', () => {
|
|||
it('sends Command_DeckNewDir', () => {
|
||||
deckNewDir('/path', 'dir');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_DeckNewDir', { path: '/path', dirName: 'dir' }, expect.any(Object)
|
||||
Command_DeckNewDir_ext, expect.objectContaining({ path: '/path', dirName: 'dir' }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -204,16 +244,16 @@ describe('deckUpload', () => {
|
|||
it('sends Command_DeckUpload', () => {
|
||||
deckUpload('/path', 1, 'content');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_DeckUpload',
|
||||
{ path: '/path', deckId: 1, deckList: 'content' },
|
||||
expect.any(Object)
|
||||
Command_DeckUpload_ext,
|
||||
expect.objectContaining({ path: '/path', deckId: 1, deckList: 'content' }),
|
||||
expect.objectContaining({ responseExt: Response_DeckUpload_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('calls uploadServerDeck on success', () => {
|
||||
deckUpload('/path', 1, 'content');
|
||||
const resp = { newFile: { id: 1 } };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_DeckUpload.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionPersistence.uploadServerDeck).toHaveBeenCalledWith('/path', resp.newFile);
|
||||
});
|
||||
});
|
||||
|
|
@ -232,13 +272,17 @@ describe('getGamesOfUser', () => {
|
|||
|
||||
it('sends Command_GetGamesOfUser', () => {
|
||||
getGamesOfUser('alice');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_GetGamesOfUser', { userName: 'alice' }, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_GetGamesOfUser_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Response_GetGamesOfUser_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('calls getGamesOfUser on success', () => {
|
||||
getGamesOfUser('alice');
|
||||
const resp = { gameList: [] };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_GetGamesOfUser.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionPersistence.getGamesOfUser).toHaveBeenCalledWith('alice', resp);
|
||||
});
|
||||
});
|
||||
|
|
@ -248,13 +292,17 @@ describe('getUserInfo', () => {
|
|||
|
||||
it('sends Command_GetUserInfo', () => {
|
||||
getUserInfo('alice');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_GetUserInfo', { userName: 'alice' }, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_GetUserInfo_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Response_GetUserInfo_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('calls getUserInfo on success', () => {
|
||||
getUserInfo('alice');
|
||||
const resp = { userInfo: { name: 'alice' } };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_GetUserInfo.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionPersistence.getUserInfo).toHaveBeenCalledWith(resp.userInfo);
|
||||
});
|
||||
});
|
||||
|
|
@ -264,13 +312,17 @@ describe('joinRoom', () => {
|
|||
|
||||
it('sends Command_JoinRoom', () => {
|
||||
joinRoom(5);
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_JoinRoom', { roomId: 5 }, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_JoinRoom_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Response_JoinRoom_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('calls RoomPersistence.joinRoom on success', () => {
|
||||
joinRoom(5);
|
||||
const resp = { roomInfo: { roomId: 5 } };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_JoinRoom.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(RoomPersistence.joinRoom).toHaveBeenCalledWith(resp.roomInfo);
|
||||
});
|
||||
});
|
||||
|
|
@ -280,7 +332,7 @@ describe('listRooms (command)', () => {
|
|||
|
||||
it('sends Command_ListRooms', () => {
|
||||
listRooms();
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_ListRooms', {}, {});
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(Command_ListRooms_ext, expect.any(Object));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -289,13 +341,17 @@ describe('listUsers', () => {
|
|||
|
||||
it('sends Command_ListUsers', () => {
|
||||
listUsers();
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_ListUsers', {}, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_ListUsers_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Response_ListUsers_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('calls SessionPersistence.updateUsers with the user list on success', () => {
|
||||
listUsers();
|
||||
const resp = { userList: [{ name: 'Alice' }] };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_ListUsers.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionPersistence.updateUsers).toHaveBeenCalledWith([{ name: 'Alice' }]);
|
||||
});
|
||||
});
|
||||
|
|
@ -306,7 +362,7 @@ describe('message', () => {
|
|||
it('sends Command_Message', () => {
|
||||
message('bob', 'hi');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_Message', { userName: 'bob', message: 'hi' }, expect.any(Object)
|
||||
Command_Message_ext, expect.objectContaining({ userName: 'bob', message: 'hi' })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -318,7 +374,7 @@ describe('ping', () => {
|
|||
it('sends Command_Ping', () => {
|
||||
const pingReceived = vi.fn();
|
||||
ping(pingReceived);
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_Ping', {}, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(Command_Ping_ext, expect.any(Object), expect.any(Object));
|
||||
});
|
||||
|
||||
it('calls pingReceived via onResponse', () => {
|
||||
|
|
@ -335,7 +391,11 @@ describe('replayDeleteMatch', () => {
|
|||
|
||||
it('sends Command_ReplayDeleteMatch', () => {
|
||||
replayDeleteMatch(7);
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_ReplayDeleteMatch', { gameId: 7 }, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_ReplayDeleteMatch_ext,
|
||||
expect.objectContaining({ gameId: 7 }),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
it('calls replayDeleteMatch on success', () => {
|
||||
|
|
@ -350,13 +410,17 @@ describe('replayList', () => {
|
|||
|
||||
it('sends Command_ReplayList', () => {
|
||||
replayList();
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith('Command_ReplayList', {}, expect.any(Object));
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
Command_ReplayList_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Response_ReplayList_ext })
|
||||
);
|
||||
});
|
||||
|
||||
it('calls replayList on success', () => {
|
||||
replayList();
|
||||
const resp = { matchList: [] };
|
||||
invokeOnSuccess(resp, { responseCode: 0, '.Response_ReplayList.ext': resp });
|
||||
invokeOnSuccess(resp, { responseCode: 0 });
|
||||
expect(SessionPersistence.replayList).toHaveBeenCalledWith([]);
|
||||
});
|
||||
});
|
||||
|
|
@ -367,7 +431,7 @@ describe('replayModifyMatch', () => {
|
|||
it('sends Command_ReplayModifyMatch', () => {
|
||||
replayModifyMatch(7, true);
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_ReplayModifyMatch', { gameId: 7, doNotHide: true }, expect.any(Object)
|
||||
Command_ReplayModifyMatch_ext, expect.objectContaining({ gameId: 7, doNotHide: true }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -384,14 +448,18 @@ describe('addToList / addToBuddyList / addToIgnoreList', () => {
|
|||
it('addToBuddyList sends Command_AddToList with list=buddy', () => {
|
||||
addToBuddyList('alice');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_AddToList', { list: 'buddy', userName: 'alice' }, expect.any(Object)
|
||||
Command_AddToList_ext,
|
||||
expect.objectContaining({ list: 'buddy' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
it('addToIgnoreList sends Command_AddToList with list=ignore', () => {
|
||||
addToIgnoreList('bob');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_AddToList', { list: 'ignore', userName: 'bob' }, expect.any(Object)
|
||||
Command_AddToList_ext,
|
||||
expect.objectContaining({ list: 'ignore' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -408,14 +476,18 @@ describe('removeFromList / removeFromBuddyList / removeFromIgnoreList', () => {
|
|||
it('removeFromBuddyList sends Command_RemoveFromList with list=buddy', () => {
|
||||
removeFromBuddyList('alice');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_RemoveFromList', { list: 'buddy', userName: 'alice' }, expect.any(Object)
|
||||
Command_RemoveFromList_ext,
|
||||
expect.objectContaining({ list: 'buddy' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
it('removeFromIgnoreList sends Command_RemoveFromList with list=ignore', () => {
|
||||
removeFromIgnoreList('bob');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_RemoveFromList', { list: 'ignore', userName: 'bob' }, expect.any(Object)
|
||||
Command_RemoveFromList_ext,
|
||||
expect.objectContaining({ list: 'ignore' }),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -429,12 +501,12 @@ describe('removeFromList / removeFromBuddyList / removeFromIgnoreList', () => {
|
|||
describe('replayGetCode', () => {
|
||||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it('sends Command_ReplayGetCode with gameId and responseName', () => {
|
||||
it('sends Command_ReplayGetCode with gameId and responseExt', () => {
|
||||
replayGetCode(42, vi.fn());
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_ReplayGetCode',
|
||||
{ gameId: 42 },
|
||||
expect.objectContaining({ responseName: 'Response_ReplayGetCode' })
|
||||
Command_ReplayGetCode_ext,
|
||||
expect.any(Object),
|
||||
expect.objectContaining({ responseExt: Response_ReplayGetCode_ext })
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -452,9 +524,7 @@ describe('replaySubmitCode', () => {
|
|||
it('sends Command_ReplaySubmitCode with replayCode', () => {
|
||||
replaySubmitCode('42-abc123');
|
||||
expect(BackendService.sendSessionCommand).toHaveBeenCalledWith(
|
||||
'Command_ReplaySubmitCode',
|
||||
{ replayCode: '42-abc123' },
|
||||
expect.any(Object)
|
||||
Command_ReplaySubmitCode_ext, expect.objectContaining({ replayCode: '42-abc123' }), expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue