From a703e8753b5cbb3de3be2478c9187ef35632f179 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Wed, 22 Oct 2025 07:57:14 +0700 Subject: [PATCH] JEST: Refactor tests that add home server manually (#2358) --- test/jest/Go/NetscriptGo.test.ts | 27 ++---- test/jest/Messages/MessageHelper.test.ts | 111 ++++++++++++++++------- 2 files changed, 85 insertions(+), 53 deletions(-) diff --git a/test/jest/Go/NetscriptGo.test.ts b/test/jest/Go/NetscriptGo.test.ts index 700a2f6fc..53c97911b 100644 --- a/test/jest/Go/NetscriptGo.test.ts +++ b/test/jest/Go/NetscriptGo.test.ts @@ -1,4 +1,4 @@ -import { Player, setPlayer } from "@player"; +import { Player } from "@player"; import { AugmentationName, GoColor, GoOpponent, GoPlayType } from "@enums"; import { Go } from "../../../src/Go/Go"; import { @@ -22,33 +22,21 @@ import { resetBoardState, validateMove, } from "../../../src/Go/effects/netscriptGoImplementation"; -import { PlayerObject } from "../../../src/PersonObjects/Player/PlayerObject"; -import "../../../src/Faction/Factions"; import { getNewBoardState, getNewBoardStateFromSimpleBoard } from "../../../src/Go/boardState/boardState"; import { installAugmentations } from "../../../src/Augmentation/AugmentationHelpers"; -import { AddToAllServers } from "../../../src/Server/AllServers"; -import { Server } from "../../../src/Server/Server"; -import { initSourceFiles } from "../../../src/SourceFile/SourceFiles"; -import { getMockedNetscriptContext } from "../Utilities"; +import { getMockedNetscriptContext, initGameEnvironment, setupBasicTestingEnvironment } from "../Utilities"; -jest.mock("../../../src/Faction/Factions", () => ({ - Factions: {}, -})); +initGameEnvironment(); + +beforeEach(() => { + setupBasicTestingEnvironment(); +}); -jest.mock("../../../src/ui/GameRoot", () => ({ - Router: { - page: () => ({}), - toPage: () => ({}), - }, -})); const mockLogger: (s: string) => void = jest.fn(); const mockCtx = getMockedNetscriptContext((_: string, txt: () => string) => { mockLogger(txt()); }); -setPlayer(new PlayerObject()); -AddToAllServers(new Server({ hostname: "home" })); - describe("Netscript Go API unit tests", () => { describe("makeMove() tests", () => { it("should handle invalid moves", () => { @@ -365,7 +353,6 @@ describe("Netscript Go API unit tests", () => { it("should have a scaled chance based on layer cheat success level", () => { Player.setBitNodeNumber(13); - initSourceFiles(); Player.queueAugmentation(AugmentationName.BrachiBlades); Player.queueAugmentation(AugmentationName.GrapheneBrachiBlades); Player.queueAugmentation(AugmentationName.INFRARet); diff --git a/test/jest/Messages/MessageHelper.test.ts b/test/jest/Messages/MessageHelper.test.ts index 504aad58d..272fd631f 100644 --- a/test/jest/Messages/MessageHelper.test.ts +++ b/test/jest/Messages/MessageHelper.test.ts @@ -1,63 +1,108 @@ import { checkForMessagesToSend } from "../../../src/Message/MessageHelpers"; import * as dialogBoxCreate from "../../../src/ui/React/DialogBox"; import { Player } from "@player"; -import "../../../src/ui/GameRoot"; -import { AugmentationName } from "@enums"; -import { AddToAllServers } from "../../../src/Server/AllServers"; -import { Server } from "../../../src/Server/Server"; +import { Router } from "../../../src/ui/GameRoot"; +import { AugmentationName, MessageFilename } from "@enums"; import { installAugmentations } from "../../../src/Augmentation/AugmentationHelpers"; -import { initSourceFiles } from "../../../src/SourceFile/SourceFiles"; +import { initGameEnvironment, setupBasicTestingEnvironment } from "../Utilities"; +import prettyFormat from "pretty-format"; -jest.mock("../../../src/ui/GameRoot", () => ({ - Router: { - page: () => ({}), - toPage: () => ({}), - hidingMessages: () => false, - }, -})); +initGameEnvironment(); -jest.mock("../../../src/ui/React/DialogBox", () => ({ - dialogBoxCreate: jest.fn(), -})); +/** + * Router.hidingMessages returns true by default. It's only initialized after the first render of GameRoot, but it won't + * happen in Jest tests. If Router.hidingMessages returns true, checkForMessagesToSend will return immediately, so we + * need to override it. + */ +Router.hidingMessages = () => false; -AddToAllServers(new Server({ hostname: "home" })); +beforeEach(() => { + setupBasicTestingEnvironment(); +}); + +/** + * Ideally, we should spy on sendMessage/showMessage and check its string param (the message file's name). However, + * they are in the same module of checkForMessagesToSend, so expect().toHaveBeenCalledTimes() does not work as expected. + * For more information, please check https://github.com/jestjs/jest/issues/936. + */ +let spiedDialogBoxCreate: jest.Spied; + +function expectLastCallShowingMessageFile(name: MessageFilename): void { + /** + * showMessage passes a React element containing the message file's name. "prettyFormat" (a Jest's dependency) helps + * us convert this element to a string that can be checked by toContain. + */ + expect(prettyFormat(spiedDialogBoxCreate.mock.lastCall?.[0])).toContain(name); +} describe("MessageHelpers tests", () => { + beforeEach(() => { + spiedDialogBoxCreate = jest.spyOn(dialogBoxCreate, "dialogBoxCreate"); + }); afterEach(() => { - jest.clearAllMocks(); + spiedDialogBoxCreate.mockRestore(); }); - it("Should repeatedly send the Icarus message on the player's first bitnode", () => { + it("Should repeatedly send the Icarus message on the player's first BitNode", () => { + /** + * In the first BitNode, the player does not have any SF, but setupBasicTestingEnvironment adds SF4, so we need to + * clear Player.sourceFiles. + */ + Player.sourceFiles.clear(); + + // Queue and install TRP. + expect(Player.augmentations.length).toStrictEqual(0); Player.queueAugmentation(AugmentationName.TheRedPill); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(0); installAugmentations(); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(1); + expect(Player.augmentations[0].name).toStrictEqual(AugmentationName.TheRedPill); + // Get tons of hacking exp to make sure Player.skills.hacking is greater than worldDaemon.requiredHackingSkill Player.gainHackingExp(2 ** 200); - const showMessageSpy = jest.spyOn(dialogBoxCreate, "dialogBoxCreate"); - + // Receive the icarus message. checkForMessagesToSend(); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(2); + expectLastCallShowingMessageFile(MessageFilename.RedPill); + // Receive the icarus message again. checkForMessagesToSend(); - - // Called once for installing augmentations, and once for each - // checkForMessagesToSend() sending an Icarus message - expect(showMessageSpy).toHaveBeenCalledTimes(3); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(3); + expectLastCallShowingMessageFile(MessageFilename.RedPill); }); - it("Should not repeatedly send the Icarus message after the player's first bitnode completion", () => { - initSourceFiles(); + it("Should not repeatedly send the Icarus message after the player's first BitNode completion", () => { + /** + * After the player completes their first BitNode, they will have SF1.1. In theory, we don't have to do this because + * setupBasicTestingEnvironment already adds SF4. However, we still should set SF1, just in case we change how + * setupBasicTestingEnvironment works. + */ Player.sourceFiles.set(1, 1); + + // Queue and install TRP. + expect(Player.augmentations.length).toStrictEqual(0); Player.queueAugmentation(AugmentationName.TheRedPill); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(0); installAugmentations(); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(1); + expect(Player.augmentations[0].name).toStrictEqual(AugmentationName.TheRedPill); + // Get tons of hacking exp to make sure Player.skills.hacking is greater than worldDaemon.requiredHackingSkill Player.gainHackingExp(2 ** 200); - const showMessageSpy = jest.spyOn(dialogBoxCreate, "dialogBoxCreate"); + // Receive the icarus message. + checkForMessagesToSend(); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(2); + expectLastCallShowingMessageFile(MessageFilename.RedPill); + // Receive the truthgazer message. + checkForMessagesToSend(); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(3); + expectLastCallShowingMessageFile(MessageFilename.TruthGazer); + // Not receive any more messages. checkForMessagesToSend(); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(3); + expectLastCallShowingMessageFile(MessageFilename.TruthGazer); checkForMessagesToSend(); - checkForMessagesToSend(); - checkForMessagesToSend(); - - // Called once for installing augmentations, and only once for any number of - // checkForMessagesToSend() ( sending an Icarus message only the first time) - expect(showMessageSpy).toHaveBeenCalledTimes(2); + expect(spiedDialogBoxCreate).toHaveBeenCalledTimes(3); + expectLastCallShowingMessageFile(MessageFilename.TruthGazer); }); });