mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 06:18:42 +02:00
JEST: Enable restoreMocks option and fix lint errors (#2333)
* JEST: Enable restoreMocks option and fix lint errors * Fix test\jest\Save.test.ts
This commit is contained in:
@@ -21,4 +21,5 @@ module.exports = {
|
||||
"/utils/Protections$": "<rootDir>/test/__mocks__/NullMock.js",
|
||||
"@swc/wasm-web": "@swc/core",
|
||||
},
|
||||
restoreMocks: true,
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import { PlayerObject } from "../../../src/PersonObjects/Player/PlayerObject";
|
||||
import { Player, setPlayer } from "@player";
|
||||
import { BlackOperation, Contract, GeneralAction, Operation } from "../../../src/Bladeburner/Actions";
|
||||
import {
|
||||
AugmentationName,
|
||||
BladeburnerActionType,
|
||||
BladeburnerContractName,
|
||||
BladeburnerGeneralActionName,
|
||||
@@ -15,6 +16,8 @@ import { CrimeWork } from "../../../src/Work/CrimeWork";
|
||||
import type { Action, ActionIdentifier } from "../../../src/Bladeburner/Types";
|
||||
import type { Skills } from "@nsdefs";
|
||||
import { BlackOperations } from "../../../src/Bladeburner/data/BlackOperations";
|
||||
import { applyAugmentation } from "../../../src/Augmentation/AugmentationHelpers";
|
||||
import { PlayerOwnedAugmentation } from "../../../src/Augmentation/PlayerOwnedAugmentation";
|
||||
|
||||
describe("Bladeburner Actions", () => {
|
||||
const SampleContract = Contract.createId(BladeburnerContractName.Tracking);
|
||||
@@ -24,6 +27,7 @@ describe("Bladeburner Actions", () => {
|
||||
|
||||
const ENOUGH_TIME_TO_FINISH_ACTION = 1e5;
|
||||
const BASE_STAT_EXP = 1e6;
|
||||
const HIGH_CHAOS = 1e12;
|
||||
|
||||
let bb: Bladeburner;
|
||||
|
||||
@@ -83,26 +87,30 @@ describe("Bladeburner Actions", () => {
|
||||
|
||||
it("mildly reduces chaos in the current city", () => {
|
||||
allCitiesHighChaos();
|
||||
let { chaos } = bb.getCurrentCity();
|
||||
const { chaos } = bb.getCurrentCity();
|
||||
complete(diplomacy);
|
||||
expect(bb.getCurrentCity().chaos).toBeGreaterThan(chaos * 0.9);
|
||||
expect(bb.getCurrentCity().chaos).toBeLessThan(chaos);
|
||||
});
|
||||
|
||||
it("effect scales significantly with player charisma", () => {
|
||||
Player.gainCharismaExp(1e500);
|
||||
gainHighCharismaLevel();
|
||||
allCitiesHighChaos();
|
||||
complete(diplomacy);
|
||||
expect(bb.getCurrentCity().chaos).toBe(0);
|
||||
expect(bb.getCurrentCity().chaos).toStrictEqual(0);
|
||||
});
|
||||
|
||||
it("does NOT affect chaos in other cities", () => {
|
||||
const otherCity = <CityName>cities.find((c) => c !== bb.getCurrentCity().name);
|
||||
const otherCity = cities.find((c) => c !== bb.getCurrentCity().name);
|
||||
if (!otherCity) {
|
||||
throw new Error("Invalid otherCity");
|
||||
}
|
||||
/** Testing against a guaranteed 0-chaos level of charisma */
|
||||
Player.gainCharismaExp(1e500);
|
||||
gainHighCharismaLevel();
|
||||
allCitiesHighChaos();
|
||||
complete(diplomacy);
|
||||
expect(bb.cities[otherCity].chaos).toBeGreaterThan(0);
|
||||
expect(bb.getCurrentCity().chaos).toStrictEqual(0);
|
||||
expect(bb.cities[otherCity].chaos).toStrictEqual(HIGH_CHAOS);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -284,6 +292,15 @@ describe("Bladeburner Actions", () => {
|
||||
resetCity();
|
||||
}
|
||||
|
||||
function gainHighCharismaLevel() {
|
||||
for (let i = 1; i <= 1000; ++i) {
|
||||
const aug = new PlayerOwnedAugmentation(AugmentationName.NeuroFluxGovernor);
|
||||
aug.level = i;
|
||||
applyAugmentation(aug);
|
||||
}
|
||||
Player.gainCharismaExp(1e6);
|
||||
}
|
||||
|
||||
function resetCity() {
|
||||
bb.cities[bb.city].chaos = 0;
|
||||
bb.cities[bb.city].comms = 100;
|
||||
@@ -295,7 +312,7 @@ describe("Bladeburner Actions", () => {
|
||||
|
||||
function allCitiesHighChaos() {
|
||||
for (const city of Object.values(bb.cities)) {
|
||||
city.chaos = 1e12;
|
||||
city.chaos = HIGH_CHAOS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ describe("MessageHelpers tests", () => {
|
||||
it("Should not repeatedly send the Icarus message after the player's first bitnode completion", () => {
|
||||
initSourceFiles();
|
||||
Player.sourceFiles.set(1, 1);
|
||||
jest.spyOn(console, "warn").mockImplementation(() => {}); // Prevent test spam
|
||||
Player.queueAugmentation(AugmentationName.TheRedPill);
|
||||
installAugmentations();
|
||||
Player.gainHackingExp(2 ** 200);
|
||||
|
||||
@@ -25,6 +25,9 @@ test("Edge cases of disableLog", function () {
|
||||
const ws = new WorkerScript(runningScript, 1, NetscriptFunctions);
|
||||
|
||||
const ns = ws.env.vars;
|
||||
if (!ns) {
|
||||
throw new Error("Invalid ws.env.vars");
|
||||
}
|
||||
|
||||
// Generate logs in a specific pattern that checks edge cases in
|
||||
// disableLog. We want to check various combinations of things that
|
||||
@@ -82,6 +85,8 @@ test("Edge cases of disableLog", function () {
|
||||
"end",
|
||||
]);
|
||||
} finally {
|
||||
DeleteServer(server.hostname);
|
||||
if (server) {
|
||||
DeleteServer(server.hostname);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { Player } from "../../../src/Player";
|
||||
import { NetscriptFunctions } from "../../../src/NetscriptFunctions";
|
||||
import { RamCosts, getRamCost, RamCostConstants, RamCostTree } from "../../../src/Netscript/RamCostGenerator";
|
||||
import { RamCosts, getRamCost, RamCostConstants, type RamCostTree } from "../../../src/Netscript/RamCostGenerator";
|
||||
import { Environment } from "../../../src/Netscript/Environment";
|
||||
import { RunningScript } from "../../../src/Script/RunningScript";
|
||||
import { Script } from "../../../src/Script/Script";
|
||||
import { WorkerScript } from "../../../src/Netscript/WorkerScript";
|
||||
import type { WorkerScript } from "../../../src/Netscript/WorkerScript";
|
||||
import { calculateRamUsage } from "../../../src/Script/RamCalculations";
|
||||
import { ns } from "../../../src/NetscriptFunctions";
|
||||
import { InternalAPI } from "src/Netscript/APIWrapper";
|
||||
import { Singularity } from "@nsdefs";
|
||||
import { ScriptFilePath } from "src/Paths/ScriptFilePath";
|
||||
import type { InternalAPI } from "../../../src/Netscript/APIWrapper";
|
||||
import type { Singularity } from "@nsdefs";
|
||||
import type { ScriptFilePath } from "../../../src/Paths/ScriptFilePath";
|
||||
|
||||
type PotentiallyAsyncFunction = (arg?: unknown) => { catch?: PotentiallyAsyncFunction };
|
||||
|
||||
@@ -21,12 +21,10 @@ function getFunction(fn: unknown) {
|
||||
function grabCost<API>(ramEntry: RamCostTree<API>[keyof API]) {
|
||||
if (typeof ramEntry === "function") return ramEntry();
|
||||
if (typeof ramEntry === "number") return ramEntry;
|
||||
throw new Error("Invalid ramcost: " + ramEntry);
|
||||
throw new Error("Invalid ramcost: " + String(ramEntry));
|
||||
}
|
||||
|
||||
describe("Netscript RAM Calculation/Generation Tests", function () {
|
||||
jest.spyOn(console, "warn").mockImplementation(() => {});
|
||||
jest.spyOn(console, "error").mockImplementation(() => {});
|
||||
Player.sourceFiles.set(4, 3);
|
||||
// For simulating costs of singularity functions.
|
||||
const baseCost = RamCostConstants.Base;
|
||||
@@ -96,12 +94,23 @@ describe("Netscript RAM Calculation/Generation Tests", function () {
|
||||
workerScript.env.vars = nsExternal;
|
||||
|
||||
// Run the function through the workerscript's args
|
||||
const fnPathAsString = fnPath.join(".");
|
||||
if (typeof fn === "function") {
|
||||
let consoleError;
|
||||
let consoleWarning;
|
||||
if (fnPathAsString === "ui.setTheme" || fnPathAsString === "ui.setStyles") {
|
||||
consoleError = jest.spyOn(console, "error").mockImplementation(jest.fn());
|
||||
}
|
||||
if (fnPathAsString === "alterReality") {
|
||||
consoleWarning = jest.spyOn(console, "warn").mockImplementation(jest.fn());
|
||||
}
|
||||
tryFunction(fn);
|
||||
tryFunction(fn);
|
||||
tryFunction(fn);
|
||||
consoleError?.mockRestore();
|
||||
consoleWarning?.mockRestore();
|
||||
} else {
|
||||
throw new Error(`Invalid function specified: [${fnPath.toString()}]`);
|
||||
throw new Error(`Invalid function specified: [${fnPathAsString}]`);
|
||||
}
|
||||
|
||||
if (expectedRamCost !== 0) {
|
||||
@@ -180,7 +189,7 @@ describe("Netscript RAM Calculation/Generation Tests", function () {
|
||||
])("%s", (code, expected) => {
|
||||
const fullCode = `export function main(ns) { ${code} }`;
|
||||
|
||||
const result = calculateRamUsage(fullCode, "testfile.js", new Map(), "testserver");
|
||||
const result = calculateRamUsage(fullCode, "testfile.js" as ScriptFilePath, "testserver", new Map());
|
||||
expect(result.errorMessage).toBe(undefined);
|
||||
expect(result.cost).toBe(expected);
|
||||
});
|
||||
|
||||
@@ -2,12 +2,11 @@ import type { Script } from "../../../src/Script/Script";
|
||||
import type { ScriptFilePath } from "../../../src/Paths/ScriptFilePath";
|
||||
import { runScriptFromScript, startWorkerScript } from "../../../src/NetscriptWorker";
|
||||
import { workerScripts } from "../../../src/Netscript/WorkerScripts";
|
||||
import { config as EvaluatorConfig } from "../../../src/NetscriptJSEvaluator";
|
||||
import { Server } from "../../../src/Server/Server";
|
||||
import { RunningScript } from "../../../src/Script/RunningScript";
|
||||
import { AddToAllServers, DeleteServer, GetServerOrThrow } from "../../../src/Server/AllServers";
|
||||
import { AlertEvents } from "../../../src/ui/React/AlertManager";
|
||||
import { initGameEnvironment, setupBasicTestingEnvironment } from "./Utilities";
|
||||
import { fixDoImportIssue, initGameEnvironment, setupBasicTestingEnvironment } from "../Utilities";
|
||||
import { Terminal } from "../../../src/Terminal";
|
||||
import { runScript } from "../../../src/Terminal/commands/runScript";
|
||||
import { Player } from "@player";
|
||||
@@ -18,25 +17,7 @@ import { NetscriptFunctions } from "../../../src/NetscriptFunctions";
|
||||
import type { PositiveInteger } from "../../../src/types";
|
||||
import { ErrorState } from "../../../src/ErrorHandling/ErrorState";
|
||||
|
||||
declare const importActual: (typeof EvaluatorConfig)["doImport"];
|
||||
|
||||
// Replace Blob/ObjectURL functions, because they don't work natively in Jest
|
||||
global.Blob = class extends Blob {
|
||||
code: string;
|
||||
constructor(blobParts?: BlobPart[], __options?: BlobPropertyBag) {
|
||||
super();
|
||||
this.code = String((blobParts ?? [])[0]);
|
||||
}
|
||||
};
|
||||
global.URL.revokeObjectURL = function () {};
|
||||
// Critical: We have to overwrite this, otherwise we get Jest's hooked
|
||||
// implementation, which will not work without passing special flags to Node,
|
||||
// and tends to crash even if you do.
|
||||
EvaluatorConfig.doImport = importActual;
|
||||
|
||||
global.URL.createObjectURL = function (blob) {
|
||||
return "data:text/javascript," + encodeURIComponent((blob as unknown as { code: string }).code);
|
||||
};
|
||||
fixDoImportIssue();
|
||||
|
||||
initGameEnvironment();
|
||||
|
||||
@@ -122,11 +103,6 @@ async function expectErrorWhenRunningScript(
|
||||
errorShown: Promise<unknown>,
|
||||
errorMessage: string,
|
||||
): Promise<void> {
|
||||
/**
|
||||
* Suppress console.error(). When there is a thrown error in the player's script, we print it to the console. In
|
||||
* this test, we intentionally throw an error, so we can ignore it.
|
||||
*/
|
||||
jest.spyOn(console, "error").mockImplementation(jest.fn());
|
||||
for (const script of scripts) {
|
||||
Player.getHomeComputer().writeToScriptFile(script.filePath, script.code);
|
||||
}
|
||||
@@ -135,10 +111,16 @@ async function expectErrorWhenRunningScript(
|
||||
if (!workerScript) {
|
||||
throw new Error(`Invalid worker script`);
|
||||
}
|
||||
/**
|
||||
* Suppress console.error(). When there is a thrown error in the player's script, we print it to the console. In
|
||||
* this test, we intentionally throw an error, so we can ignore it.
|
||||
*/
|
||||
const consoleError = jest.spyOn(console, "error").mockImplementation(jest.fn());
|
||||
const result = await Promise.race([
|
||||
errorShown,
|
||||
new Promise<void>((resolve) => (workerScript.atExit = new Map([["default", resolve]]))),
|
||||
]);
|
||||
consoleError.mockRestore();
|
||||
expect(result).toBeDefined();
|
||||
expect(workerScript.scriptRef.logs[0]).toContain(errorMessage);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { GetServerOrThrow } from "../../../src/Server/AllServers";
|
||||
import { SpecialServers } from "../../../src/Server/data/SpecialServers";
|
||||
import { Factions } from "../../../src/Faction/Factions";
|
||||
import { PlayerOwnedAugmentation } from "../../../src/Augmentation/PlayerOwnedAugmentation";
|
||||
import { getNS, initGameEnvironment, setupBasicTestingEnvironment } from "./Utilities";
|
||||
import { getNS, initGameEnvironment, setupBasicTestingEnvironment } from "../Utilities";
|
||||
import { Terminal } from "../../../src/Terminal";
|
||||
import type { NSFull } from "../../../src/NetscriptFunctions";
|
||||
import { Companies } from "../../../src/Company/Companies";
|
||||
|
||||
@@ -3,6 +3,8 @@ import type { ScriptFilePath } from "../../../src/Paths/ScriptFilePath";
|
||||
import { calculateRamUsage } from "../../../src/Script/RamCalculations";
|
||||
import { RamCosts } from "../../../src/Netscript/RamCostGenerator";
|
||||
import { Script } from "../../../src/Script/Script";
|
||||
import { setPlayer } from "@player";
|
||||
import { PlayerObject } from "../../../src/PersonObjects/Player/PlayerObject";
|
||||
|
||||
const BaseCost = 1.6;
|
||||
const HackCost = 0.1;
|
||||
@@ -14,8 +16,14 @@ const MaxCost = 1024;
|
||||
const filename = "testfile.js" as ScriptFilePath;
|
||||
const folderFilename = "test/testfile.js" as ScriptFilePath;
|
||||
const server = "testserver";
|
||||
|
||||
/**
|
||||
* Init the player object. When calculating the RAM usage of singularity APIs, RamCostGenerator.ts needs to access some
|
||||
* properties and functions of the player object.
|
||||
*/
|
||||
setPlayer(new PlayerObject());
|
||||
|
||||
describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
jest.spyOn(console, "error").mockImplementation(() => {});
|
||||
/** Tests numeric equality, allowing for floating point imprecision - and includes script base cost */
|
||||
function expectCost(val: number | undefined, expected: number) {
|
||||
const expectedWithBase = Math.min(expected + BaseCost, MaxCost);
|
||||
@@ -24,7 +32,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
}
|
||||
|
||||
describe("Single files with basic NS functions", function () {
|
||||
it("Empty main function", async function () {
|
||||
it("Empty main function", function () {
|
||||
const code = `
|
||||
export async function main(ns) { }
|
||||
`;
|
||||
@@ -32,7 +40,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, 0);
|
||||
});
|
||||
|
||||
it("Free NS function directly in main", async function () {
|
||||
it("Free NS function directly in main", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
ns.print("Slum snakes r00l!");
|
||||
@@ -42,7 +50,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, 0);
|
||||
});
|
||||
|
||||
it("Single simple base NS function directly in main", async function () {
|
||||
it("Single simple base NS function directly in main", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
await ns.hack("joesguns");
|
||||
@@ -52,7 +60,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
|
||||
it("Single simple base NS function directly in main with differing arg name", async function () {
|
||||
it("Single simple base NS function directly in main with differing arg name", function () {
|
||||
const code = `
|
||||
export async function main(X) {
|
||||
await X.hack("joesguns");
|
||||
@@ -62,7 +70,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
|
||||
it("Repeated simple base NS function directly in main", async function () {
|
||||
it("Repeated simple base NS function directly in main", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
await ns.hack("joesguns");
|
||||
@@ -73,7 +81,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
|
||||
it("Multiple simple base NS functions directly in main", async function () {
|
||||
it("Multiple simple base NS functions directly in main", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
await ns.hack("joesguns");
|
||||
@@ -84,7 +92,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HackCost + GrowCost);
|
||||
});
|
||||
|
||||
it("Simple base NS functions in a referenced function", async function () {
|
||||
it("Simple base NS functions in a referenced function", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
doHacking(ns);
|
||||
@@ -97,7 +105,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
|
||||
it("Simple base NS functions in a referenced class", async function () {
|
||||
it("Simple base NS functions in a referenced class", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
await new Hacker(ns).doHacking();
|
||||
@@ -112,7 +120,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
|
||||
it("Simple base NS functions in a referenced class", async function () {
|
||||
it("Simple base NS functions in a referenced class", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
await new Hacker(ns).doHacking();
|
||||
@@ -129,7 +137,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
});
|
||||
|
||||
describe("Functions that can be confused with NS functions", function () {
|
||||
it("Function 'get' that can be confused with Stanek.get", async function () {
|
||||
it("Function 'get' that can be confused with Stanek.get", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
get();
|
||||
@@ -140,7 +148,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, 0);
|
||||
});
|
||||
|
||||
it("Function 'purchaseNode' that can be confused with Hacknet.purchaseNode", async function () {
|
||||
it("Function 'purchaseNode' that can be confused with Hacknet.purchaseNode", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
purchaseNode();
|
||||
@@ -153,7 +161,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
});
|
||||
|
||||
// TODO: once we fix static parsing this should pass
|
||||
it.skip("Function 'getTask' that can be confused with Sleeve.getTask", async function () {
|
||||
it.skip("Function 'getTask' that can be confused with Sleeve.getTask", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
getTask();
|
||||
@@ -166,7 +174,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
});
|
||||
|
||||
describe("Single files with non-core NS functions", function () {
|
||||
it("Hacknet NS function with a cost from namespace", async function () {
|
||||
it("Hacknet NS function with a cost from namespace", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
ns.hacknet.purchaseNode(0);
|
||||
@@ -176,7 +184,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HacknetCost);
|
||||
});
|
||||
|
||||
it("Sleeve functions with an individual cost", async function () {
|
||||
it("Sleeve functions with an individual cost", function () {
|
||||
const code = `
|
||||
export async function main(ns) {
|
||||
ns.sleeve.getTask(3);
|
||||
@@ -188,7 +196,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
});
|
||||
|
||||
describe("Imported files", function () {
|
||||
it("Simple imported function with no cost", async function () {
|
||||
it("Simple imported function with no cost", function () {
|
||||
const libCode = `
|
||||
export function dummy() { return 0; }
|
||||
`;
|
||||
@@ -209,7 +217,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, 0);
|
||||
});
|
||||
|
||||
it("Imported ns function", async function () {
|
||||
it("Imported ns function", function () {
|
||||
const libCode = `
|
||||
export async function doHack(ns) { return await ns.hack("joesguns"); }
|
||||
`;
|
||||
@@ -230,7 +238,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
|
||||
it("Importing a single function from a library that exports multiple", async function () {
|
||||
it("Importing a single function from a library that exports multiple", function () {
|
||||
const libCode = `
|
||||
export async function doHack(ns) { return await ns.hack("joesguns"); }
|
||||
export async function doGrow(ns) { return await ns.grow("joesguns"); }
|
||||
@@ -252,7 +260,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
|
||||
it("Importing all functions from a library that exports multiple", async function () {
|
||||
it("Importing all functions from a library that exports multiple", function () {
|
||||
const libCode = `
|
||||
export async function doHack(ns) { return await ns.hack("joesguns"); }
|
||||
export async function doGrow(ns) { return await ns.grow("joesguns"); }
|
||||
@@ -296,7 +304,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
});
|
||||
|
||||
// TODO: once we fix static parsing this should pass
|
||||
it.skip("Importing a function from a library that contains a class", async function () {
|
||||
it.skip("Importing a function from a library that contains a class", function () {
|
||||
const libCode = `
|
||||
export async function doHack(ns) { return await ns.hack("joesguns"); }
|
||||
class Grower {
|
||||
@@ -322,7 +330,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
|
||||
it("Importing a function from a library that creates a class in a function", async function () {
|
||||
it("Importing a function from a library that creates a class in a function", function () {
|
||||
const libCode = `
|
||||
export function createClass() {
|
||||
class Grower {
|
||||
@@ -353,7 +361,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
expectCost(calculated, GrowCost);
|
||||
});
|
||||
|
||||
it("Importing with a relative path - One Layer Deep", async function () {
|
||||
it("Importing with a relative path - One Layer Deep", function () {
|
||||
const libCode = `
|
||||
export async function testRelative(ns) {
|
||||
await ns.hack("n00dles")
|
||||
@@ -375,7 +383,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
).cost;
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
it("Importing with a relative path - Two Layer Deep", async function () {
|
||||
it("Importing with a relative path - Two Layer Deep", function () {
|
||||
const libNameOne = "test/libTestOne.js" as ScriptFilePath;
|
||||
const libNameTwo = "test/libTestTwo.js" as ScriptFilePath;
|
||||
|
||||
@@ -412,7 +420,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () {
|
||||
).cost;
|
||||
expectCost(calculated, HackCost);
|
||||
});
|
||||
it("Importing with a relative path - possible path conflict", async function () {
|
||||
it("Importing with a relative path - possible path conflict", function () {
|
||||
const libNameOne = "foo/libTestOne.js" as ScriptFilePath;
|
||||
const libNameTwo = "foo/libTestTwo.js" as ScriptFilePath;
|
||||
const incorrect_libNameTwo = "test/libTestTwo.js" as ScriptFilePath;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { IStyleSettings, UserInterfaceTheme } from "../../../src/ScriptEditor/Ne
|
||||
import { Settings } from "../../../src/Settings/Settings";
|
||||
import { defaultStyles } from "../../../src/Themes/Styles";
|
||||
import { defaultTheme } from "../../../src/Themes/Themes";
|
||||
import { getNS, initGameEnvironment, setupBasicTestingEnvironment } from "./Utilities";
|
||||
import { getNS, initGameEnvironment, setupBasicTestingEnvironment } from "../Utilities";
|
||||
|
||||
const themeHexColor = "#abc";
|
||||
const fontFamily = "monospace";
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
import { WorkerScript } from "../../../src/Netscript/WorkerScript";
|
||||
import { NetscriptFunctions, type NSFull } from "../../../src/NetscriptFunctions";
|
||||
import type { ScriptFilePath } from "../../../src/Paths/ScriptFilePath";
|
||||
import { PlayerObject } from "../../../src/PersonObjects/Player/PlayerObject";
|
||||
import { Player, setPlayer } from "../../../src/Player";
|
||||
import { RunningScript } from "../../../src/Script/RunningScript";
|
||||
import { GetServerOrThrow, initForeignServers, prestigeAllServers } from "../../../src/Server/AllServers";
|
||||
import { SpecialServers } from "../../../src/Server/data/SpecialServers";
|
||||
import { initSourceFiles } from "../../../src/SourceFile/SourceFiles";
|
||||
import { FormatsNeedToChange } from "../../../src/ui/formatNumber";
|
||||
import { Router } from "../../../src/ui/GameRoot";
|
||||
|
||||
export function initGameEnvironment() {
|
||||
// We need to patch this function. Some APIs call it, but it only works properly after the main UI is loaded.
|
||||
Router.toPage = () => {};
|
||||
|
||||
/**
|
||||
* In src\ui\formatNumber.ts, there are some variables that need to be initialized before other functions can be
|
||||
* called. We have to call FormatsNeedToChange.emit() to initialize those variables.
|
||||
*/
|
||||
FormatsNeedToChange.emit();
|
||||
|
||||
initSourceFiles();
|
||||
}
|
||||
|
||||
export function setupBasicTestingEnvironment(): void {
|
||||
prestigeAllServers();
|
||||
setPlayer(new PlayerObject());
|
||||
Player.init();
|
||||
Player.sourceFiles.set(4, 3);
|
||||
initForeignServers(Player.getHomeComputer());
|
||||
}
|
||||
|
||||
export function getNS(): NSFull {
|
||||
const home = GetServerOrThrow(SpecialServers.Home);
|
||||
home.maxRam = 1024;
|
||||
const filePath = "test.js" as ScriptFilePath;
|
||||
home.writeToScriptFile(filePath, "");
|
||||
const script = home.scripts.get(filePath);
|
||||
if (!script) {
|
||||
throw new Error("Invalid script");
|
||||
}
|
||||
const runningScript = new RunningScript(script, 1024);
|
||||
const workerScript = new WorkerScript(runningScript, 1, NetscriptFunctions);
|
||||
const ns = workerScript.env.vars;
|
||||
if (!ns) {
|
||||
throw new Error("Invalid NS instance");
|
||||
}
|
||||
return ns;
|
||||
}
|
||||
@@ -6,8 +6,12 @@ import { Settings } from "../../src/Settings/Settings";
|
||||
import { Player, setPlayer } from "../../src/Player";
|
||||
import { PlayerObject } from "../../src/PersonObjects/Player/PlayerObject";
|
||||
import { UIEventEmitter, UIEventType } from "../../src/ui/UIEventEmitter";
|
||||
import { fixDoImportIssue } from "./Utilities";
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
fixDoImportIssue();
|
||||
|
||||
// Direct tests of loading and saving.
|
||||
// Tests here should try to be comprehensive (cover as much stuff as possible)
|
||||
// without requiring burdensome levels of maintenance when legitimate changes
|
||||
@@ -98,7 +102,7 @@ function loadStandardServers() {
|
||||
{
|
||||
"ctor": "Script",
|
||||
"data": {
|
||||
"code": "/** @param {NS} ns */\\nexport async function main(ns) {\\n return ns.asleep(1000000);\\n}",
|
||||
"code": "/** @param {NS} ns */\nexport async function main(ns) {\n return ns.asleep(1000000);\n}",
|
||||
"filename": "script.js",
|
||||
"module": {},
|
||||
"dependencies": [
|
||||
|
||||
@@ -33,10 +33,6 @@ import {
|
||||
} from "../../src/StockMarket/StockMarketHelpers";
|
||||
import { CompanyName, LocationName, OrderType, PositionType } from "../../src/Enums";
|
||||
|
||||
// jest.mock("../src/ui/React/createPopup.tsx", () => ({
|
||||
// createPopup: jest.fn(),
|
||||
// }));
|
||||
|
||||
describe("Stock Market Tests", function () {
|
||||
const commission = StockMarketConstants.StockMarketCommission;
|
||||
|
||||
@@ -451,7 +447,7 @@ describe("Stock Market Tests", function () {
|
||||
|
||||
it("should trigger a price update when it has enough cycles", function () {
|
||||
// Get the initial prices
|
||||
const initialValues: Record<string, any> = {};
|
||||
const initialValues: Record<string, { price: number; otlkMag: number; b: boolean }> = {};
|
||||
for (const stockName in StockMarket) {
|
||||
const stock = StockMarket[stockName];
|
||||
if (!(stock instanceof Stock)) {
|
||||
|
||||
73
test/jest/Utilities.ts
Normal file
73
test/jest/Utilities.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { WorkerScript } from "../../src/Netscript/WorkerScript";
|
||||
import { NetscriptFunctions, type NSFull } from "../../src/NetscriptFunctions";
|
||||
import type { ScriptFilePath } from "../../src/Paths/ScriptFilePath";
|
||||
import { PlayerObject } from "../../src/PersonObjects/Player/PlayerObject";
|
||||
import { Player, setPlayer } from "../../src/Player";
|
||||
import { RunningScript } from "../../src/Script/RunningScript";
|
||||
import { GetServerOrThrow, initForeignServers, prestigeAllServers } from "../../src/Server/AllServers";
|
||||
import { SpecialServers } from "../../src/Server/data/SpecialServers";
|
||||
import { initSourceFiles } from "../../src/SourceFile/SourceFiles";
|
||||
import { FormatsNeedToChange } from "../../src/ui/formatNumber";
|
||||
import { Router } from "../../src/ui/GameRoot";
|
||||
import { config } from "../../src/NetscriptJSEvaluator";
|
||||
|
||||
declare const importActual: (typeof config)["doImport"];
|
||||
|
||||
export function fixDoImportIssue() {
|
||||
// Replace Blob/ObjectURL functions, because they don't work natively in Jest
|
||||
global.Blob = class extends Blob {
|
||||
code: string;
|
||||
constructor(blobParts?: BlobPart[], __options?: BlobPropertyBag) {
|
||||
super();
|
||||
this.code = String((blobParts ?? [])[0]);
|
||||
}
|
||||
};
|
||||
global.URL.revokeObjectURL = function () {};
|
||||
// Critical: We have to overwrite this, otherwise we get Jest's hooked
|
||||
// implementation, which will not work without passing special flags to Node,
|
||||
// and tends to crash even if you do.
|
||||
config.doImport = importActual;
|
||||
|
||||
global.URL.createObjectURL = function (blob) {
|
||||
return "data:text/javascript," + encodeURIComponent((blob as unknown as { code: string }).code);
|
||||
};
|
||||
}
|
||||
|
||||
export function initGameEnvironment() {
|
||||
// We need to patch this function. Some APIs call it, but it only works properly after the main UI is loaded.
|
||||
Router.toPage = () => {};
|
||||
|
||||
/**
|
||||
* In src\ui\formatNumber.ts, there are some variables that need to be initialized before other functions can be
|
||||
* called. We have to call FormatsNeedToChange.emit() to initialize those variables.
|
||||
*/
|
||||
FormatsNeedToChange.emit();
|
||||
|
||||
initSourceFiles();
|
||||
}
|
||||
|
||||
export function setupBasicTestingEnvironment(): void {
|
||||
prestigeAllServers();
|
||||
setPlayer(new PlayerObject());
|
||||
Player.init();
|
||||
Player.sourceFiles.set(4, 3);
|
||||
initForeignServers(Player.getHomeComputer());
|
||||
}
|
||||
|
||||
export function getNS(): NSFull {
|
||||
const home = GetServerOrThrow(SpecialServers.Home);
|
||||
home.maxRam = 1024;
|
||||
const filePath = "test.js" as ScriptFilePath;
|
||||
home.writeToScriptFile(filePath, "");
|
||||
const script = home.scripts.get(filePath);
|
||||
if (!script) {
|
||||
throw new Error("Invalid script");
|
||||
}
|
||||
const runningScript = new RunningScript(script, 1024);
|
||||
const workerScript = new WorkerScript(runningScript, 1, NetscriptFunctions);
|
||||
const ns = workerScript.env.vars;
|
||||
if (!ns) {
|
||||
throw new Error("Invalid NS instance");
|
||||
}
|
||||
return ns;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ exports[`load/saveAllServers 1`] = `
|
||||
{
|
||||
"ctor": "Script",
|
||||
"data": {
|
||||
"code": "/** @param {NS} ns */\\\\nexport async function main(ns) {\\\\n return ns.asleep(1000000);\\\\n}",
|
||||
"code": "/** @param {NS} ns */\\nexport async function main(ns) {\\n return ns.asleep(1000000);\\n}",
|
||||
"filename": "script.js",
|
||||
"server": "home",
|
||||
"metadata": {
|
||||
@@ -165,7 +165,7 @@ exports[`load/saveAllServers pruning RunningScripts 1`] = `
|
||||
{
|
||||
"ctor": "Script",
|
||||
"data": {
|
||||
"code": "/** @param {NS} ns */\\\\nexport async function main(ns) {\\\\n return ns.asleep(1000000);\\\\n}",
|
||||
"code": "/** @param {NS} ns */\\nexport async function main(ns) {\\n return ns.asleep(1000000);\\n}",
|
||||
"filename": "script.js",
|
||||
"server": "home",
|
||||
"metadata": {
|
||||
|
||||
Reference in New Issue
Block a user