mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-29 21:12:45 +02:00
Implement Rename Input Design and Tests for Name Run Feat
Created a test to verify Name Run Feature behaviour in the backend (rename_run.test.ts), checking possible errors and expected behaviours. Created a UiHandler RenameRunFormUiHandler (rename-run-ui-handler.ts), creating a frontend input overlay for the Name Run Feature. Signed-off-by: Matheus Alves <matheus.r.noya.alves@tecnico.ulisboa.pt> Co-authored-by: Inês Simões <ines.p.simoes@tecnico.ulisboa.pt>
This commit is contained in:
parent
5217acaf8b
commit
1e806fa6ff
@ -38,6 +38,7 @@ export enum UiMode {
|
|||||||
UNAVAILABLE,
|
UNAVAILABLE,
|
||||||
CHALLENGE_SELECT,
|
CHALLENGE_SELECT,
|
||||||
RENAME_POKEMON,
|
RENAME_POKEMON,
|
||||||
|
RENAME_RUN,
|
||||||
RUN_HISTORY,
|
RUN_HISTORY,
|
||||||
RUN_INFO,
|
RUN_INFO,
|
||||||
TEST_DIALOGUE,
|
TEST_DIALOGUE,
|
||||||
|
@ -979,7 +979,7 @@ export class GameData {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renameSession(slotId: number, newName: string): Promise<boolean> {
|
async renameSession(slotId: number, newName: string): Promise<boolean> {
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
if (slotId < 0) {
|
if (slotId < 0) {
|
||||||
return resolve(false);
|
return resolve(false);
|
||||||
@ -1010,7 +1010,8 @@ export class GameData {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
localStorage.setItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`, encrypted); // Keep local in sync
|
localStorage.setItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`, encrypted);
|
||||||
|
await updateUserInfo();
|
||||||
resolve(true);
|
resolve(true);
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to update session name:", error);
|
console.error("Failed to update session name:", error);
|
||||||
|
49
src/ui/rename-run-ui-handler.ts
Normal file
49
src/ui/rename-run-ui-handler.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import type { InputFieldConfig } from "./form-modal-ui-handler";
|
||||||
|
import { FormModalUiHandler } from "./form-modal-ui-handler";
|
||||||
|
import type { ModalConfig } from "./modal-ui-handler";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
export default class RenameRunFormUiHandler extends FormModalUiHandler {
|
||||||
|
getModalTitle(_config?: ModalConfig): string {
|
||||||
|
return i18next.t("menu:renamerun");
|
||||||
|
}
|
||||||
|
|
||||||
|
getWidth(_config?: ModalConfig): number {
|
||||||
|
return 160;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMargin(_config?: ModalConfig): [number, number, number, number] {
|
||||||
|
return [0, 0, 48, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
getButtonLabels(_config?: ModalConfig): string[] {
|
||||||
|
return [i18next.t("menu:rename"), i18next.t("menu:cancel")];
|
||||||
|
}
|
||||||
|
|
||||||
|
getReadableErrorMessage(error: string): string {
|
||||||
|
const colonIndex = error?.indexOf(":");
|
||||||
|
if (colonIndex > 0) {
|
||||||
|
error = error.slice(0, colonIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getReadableErrorMessage(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
override getInputFieldConfigs(): InputFieldConfig[] {
|
||||||
|
return [{ label: i18next.t("menu:runName") }];
|
||||||
|
}
|
||||||
|
|
||||||
|
show(args: any[]): boolean {
|
||||||
|
if (super.show(args)) {
|
||||||
|
const config = args[0] as ModalConfig;
|
||||||
|
this.submitAction = _ => {
|
||||||
|
this.sanitizeInputs();
|
||||||
|
const sanitizedName = btoa(encodeURIComponent(this.inputs[0].text));
|
||||||
|
config.buttonActions[0](sanitizedName);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -131,11 +131,11 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
|
|||||||
handler: () => {
|
handler: () => {
|
||||||
globalScene.ui.revertMode();
|
globalScene.ui.revertMode();
|
||||||
ui.setOverlayMode(
|
ui.setOverlayMode(
|
||||||
UiMode.RENAME_POKEMON,
|
UiMode.RENAME_RUN,
|
||||||
{
|
{
|
||||||
buttonActions: [
|
buttonActions: [
|
||||||
(sanitizedName: string) => {
|
(sanitizedName: string) => {
|
||||||
const name = decodeURIComponent((atob(sanitizedName)));
|
const name = decodeURIComponent(atob(sanitizedName));
|
||||||
globalScene.gameData.renameSession(cursor, name).then(response => {
|
globalScene.gameData.renameSession(cursor, name).then(response => {
|
||||||
if (response[0] === false) {
|
if (response[0] === false) {
|
||||||
globalScene.reset(true);
|
globalScene.reset(true);
|
||||||
|
@ -58,6 +58,7 @@ import PokedexScanUiHandler from "./pokedex-scan-ui-handler";
|
|||||||
import PokedexPageUiHandler from "./pokedex-page-ui-handler";
|
import PokedexPageUiHandler from "./pokedex-page-ui-handler";
|
||||||
import { NavigationManager } from "./settings/navigationMenu";
|
import { NavigationManager } from "./settings/navigationMenu";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
|
import RenameRunFormUiHandler from "./rename-run-ui-handler";
|
||||||
|
|
||||||
const transitionModes = [
|
const transitionModes = [
|
||||||
UiMode.SAVE_SLOT,
|
UiMode.SAVE_SLOT,
|
||||||
@ -96,6 +97,7 @@ const noTransitionModes = [
|
|||||||
UiMode.SESSION_RELOAD,
|
UiMode.SESSION_RELOAD,
|
||||||
UiMode.UNAVAILABLE,
|
UiMode.UNAVAILABLE,
|
||||||
UiMode.RENAME_POKEMON,
|
UiMode.RENAME_POKEMON,
|
||||||
|
UiMode.RENAME_RUN,
|
||||||
UiMode.TEST_DIALOGUE,
|
UiMode.TEST_DIALOGUE,
|
||||||
UiMode.AUTO_COMPLETE,
|
UiMode.AUTO_COMPLETE,
|
||||||
UiMode.ADMIN,
|
UiMode.ADMIN,
|
||||||
@ -165,6 +167,7 @@ export default class UI extends Phaser.GameObjects.Container {
|
|||||||
new UnavailableModalUiHandler(),
|
new UnavailableModalUiHandler(),
|
||||||
new GameChallengesUiHandler(),
|
new GameChallengesUiHandler(),
|
||||||
new RenameFormUiHandler(),
|
new RenameFormUiHandler(),
|
||||||
|
new RenameRunFormUiHandler(),
|
||||||
new RunHistoryUiHandler(),
|
new RunHistoryUiHandler(),
|
||||||
new RunInfoUiHandler(),
|
new RunInfoUiHandler(),
|
||||||
new TestDialogueUiHandler(UiMode.TEST_DIALOGUE),
|
new TestDialogueUiHandler(UiMode.TEST_DIALOGUE),
|
||||||
|
82
test/system/rename_run.test.ts
Normal file
82
test/system/rename_run.test.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import * as bypassLoginModule from "#app/global-vars/bypass-login";
|
||||||
|
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
|
||||||
|
import type { SessionSaveData } from "#app/system/game-data";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import * as account from "#app/account";
|
||||||
|
|
||||||
|
describe("System - Rename Run", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.override
|
||||||
|
.moveset([Moves.SPLASH])
|
||||||
|
.battleStyle("single")
|
||||||
|
.enemyAbility(Abilities.BALL_FETCH)
|
||||||
|
.enemyMoveset(Moves.SPLASH);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("renameSession", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.spyOn(bypassLoginModule, "bypassLogin", "get").mockReturnValue(false);
|
||||||
|
vi.spyOn(account, "updateUserInfo").mockImplementation(async () => [true, 1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return false if slotId < 0", async () => {
|
||||||
|
const result = await game.scene.gameData.renameSession(-1, "Named Run");
|
||||||
|
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return false if getSession returns null", async () => {
|
||||||
|
vi.spyOn(game.scene.gameData, "getSession").mockResolvedValue(null as unknown as SessionSaveData);
|
||||||
|
|
||||||
|
const result = await game.scene.gameData.renameSession(-1, "Named Run");
|
||||||
|
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true if bypassLogin is true", async () => {
|
||||||
|
vi.spyOn(bypassLoginModule, "bypassLogin", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(game.scene.gameData, "getSession").mockResolvedValue({} as SessionSaveData);
|
||||||
|
|
||||||
|
const result = await game.scene.gameData.renameSession(0, "Named Run");
|
||||||
|
|
||||||
|
expect(result).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return false if api returns error", async () => {
|
||||||
|
vi.spyOn(game.scene.gameData, "getSession").mockResolvedValue({} as SessionSaveData);
|
||||||
|
vi.spyOn(pokerogueApi.savedata.session, "update").mockResolvedValue("Unknown Error!");
|
||||||
|
|
||||||
|
const result = await game.scene.gameData.renameSession(0, "Named Run");
|
||||||
|
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true if api is succesfull", async () => {
|
||||||
|
vi.spyOn(game.scene.gameData, "getSession").mockResolvedValue({} as SessionSaveData);
|
||||||
|
vi.spyOn(pokerogueApi.savedata.session, "update").mockResolvedValue("");
|
||||||
|
|
||||||
|
const result = await game.scene.gameData.renameSession(0, "Named Run");
|
||||||
|
|
||||||
|
expect(result).toEqual(true);
|
||||||
|
expect(account.updateUserInfo).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user