diff --git a/FixJSDOMEnvironment.ts b/FixJSDOMEnvironment.ts index e68ccdea3..a257593c4 100644 --- a/FixJSDOMEnvironment.ts +++ b/FixJSDOMEnvironment.ts @@ -14,5 +14,17 @@ export default class FixJSDOMEnvironment extends JSDOMEnvironment { // Wrap the construction of the function in eval, so that transpilers // don't touch the import() call. this.global.importActual = eval("url => import(url)"); + + /** + * By default, Jest only passes a limited number of global objects to the test environment. We need these global + * objects when testing code that loads save data. + */ + this.global.Uint8Array = Uint8Array; + this.global.Blob = Blob; + this.global.CompressionStream = CompressionStream; + this.global.DecompressionStream = DecompressionStream; + this.global.TextDecoderStream = TextDecoderStream; + this.global.URL = URL; + this.global.Response = Response; } } diff --git a/test/jest/Migration/Migration.test.ts b/test/jest/Migration/Migration.test.ts new file mode 100644 index 000000000..78c97155d --- /dev/null +++ b/test/jest/Migration/Migration.test.ts @@ -0,0 +1,40 @@ +import { Player } from "@player"; +import fs from "node:fs"; +import type { ScriptFilePath } from "../../../src/Paths/ScriptFilePath"; +import { loadGame } from "../../../src/SaveObject"; +import * as db from "../../../src/db"; +import * as FileUtils from "../../../src/utils/FileUtils"; + +describe("v3", () => { + test("v2.8.1 to v3.0.0", async () => { + const saveData = new Uint8Array(fs.readFileSync("test/jest/Migration/save-files/v2.8.1.gz")); + + // Simulate loading the data in IndexedDB + const mockedLoad = jest.spyOn(db, "load"); + /** + * We must use structuredClone(saveData) instead of saveData; otherwise, the check of mockedDownload won't catch + * wrong changes in evaluateVersionCompatibility (e.g., unexpectedly mutating saveData before passing it to + * downloadContentAsFile). + */ + mockedLoad.mockReturnValue(Promise.resolve(structuredClone(saveData))); + + const mockedDownload = jest.spyOn(FileUtils, "downloadContentAsFile"); + + await loadGame(await db.load()); + + // Check if auto-migration works + expect( + Player.getHomeComputer() + .scripts.get("a.js" as ScriptFilePath) + ?.code.includes("ns.ui.openTail()"), + ).toStrictEqual(true); + if (!Player.corporation) { + throw new Error("The save file does not have corporation data"); + } + expect(Object.keys(Player.corporation.upgrades).includes("DreamSense")).toStrictEqual(false); + expect(Player.corporation.funds).toStrictEqual(110e9); + + // Check if evaluateVersionCompatibility correctly loads the data in IndexedDB and passes it to downloadContentAsFile + expect(mockedDownload).toHaveBeenCalledWith(saveData, "bitburnerSave_backup_2.8.1_1756913326.json.gz"); + }); +}); diff --git a/test/jest/Migration/save-files/v2.8.1.gz b/test/jest/Migration/save-files/v2.8.1.gz new file mode 100644 index 000000000..70101abb7 Binary files /dev/null and b/test/jest/Migration/save-files/v2.8.1.gz differ