Server-side save states via js-dos fsChanges hooks
This commit is contained in:
@@ -7,6 +7,9 @@ vi.mock("../../lib/api.js", () => ({
|
||||
getGame: vi.fn(),
|
||||
bundleUrl: vi.fn(),
|
||||
setupBundleUrl: vi.fn(),
|
||||
pullSaves: vi.fn(),
|
||||
pushSaves: vi.fn(),
|
||||
deleteSaves: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock router
|
||||
@@ -74,4 +77,49 @@ describe("Play", () => {
|
||||
expect(screen.getByText("Starting emulator...")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it("starts js-dos with server-backed save hooks", async () => {
|
||||
api.getGame.mockResolvedValue(makeGame());
|
||||
api.bundleUrl.mockReturnValue("/games/game-1.jsdos");
|
||||
|
||||
const dosMock = vi.fn().mockReturnValue({
|
||||
save: vi.fn().mockResolvedValue(true),
|
||||
stop: vi.fn().mockResolvedValue(undefined),
|
||||
});
|
||||
window.Dos = dosMock;
|
||||
|
||||
try {
|
||||
render(Play, { props: { id: "game-1" } });
|
||||
await vi.waitFor(() => {
|
||||
expect(dosMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const opts = dosMock.mock.calls[0][1];
|
||||
expect(opts.url).toBe("/games/game-1.jsdos");
|
||||
expect(opts.autoSave).toBe(true);
|
||||
|
||||
// Both normal and setup bundles map to the same per-game save key
|
||||
await expect(opts.fsChanges.urlToKey("/games/game-1.jsdos")).resolves.toBe("game-1");
|
||||
|
||||
// pull() forwards to the API and returns null when there is no save
|
||||
api.pullSaves.mockResolvedValue(null);
|
||||
await expect(opts.fsChanges.pull("game-1")).resolves.toBeNull();
|
||||
expect(api.pullSaves).toHaveBeenCalledWith("game-1");
|
||||
|
||||
// push()/delete() forward to the API
|
||||
api.pushSaves.mockResolvedValue({ status: "saved" });
|
||||
await opts.fsChanges.push("game-1", new Uint8Array([1]));
|
||||
expect(api.pushSaves).toHaveBeenCalledWith("game-1", expect.any(Uint8Array));
|
||||
|
||||
api.deleteSaves.mockResolvedValue({ status: "deleted" });
|
||||
await opts.fsChanges.delete("game-1");
|
||||
expect(api.deleteSaves).toHaveBeenCalledWith("game-1");
|
||||
|
||||
// pull() survives API errors so the game still boots
|
||||
api.pullSaves.mockRejectedValue(new Error("offline"));
|
||||
await expect(opts.fsChanges.pull("game-1")).resolves.toBeNull();
|
||||
} finally {
|
||||
delete window.Dos;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user