mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-08-07 19:21:30 +00:00
build: migrate build system to Vite and test runner to Vitest & Remove depracated husky usage (#2703)
- Replace Webpack with Vite for faster client bundling and HMR. - Migrate tests from Jest to Vitest and update configuration. - Update Web Worker instantiation to standard ESM syntax. - Implement Env utility in `src/core` for safe, hybrid environment variable access (Vite vs Node). - Refactor configuration loaders to remove direct `process.env` dependencies in shared code. - Update TypeScript environment definitions and project scripts for the new toolchain. - Remove the [depracated usage of the husky](https://github.com/typicode/husky/releases/tag/v9.0.1). ## Description: migrate build system to Vite and test runner to Vitest & Remove depracated husky usage ## Please complete the following: - [X] I have added screenshots for all UI updates - [X] I process any text displayed to the user through translateText() and I've added it to the en.json file - [ ] I have added relevant tests to the test directory - [X] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: wraith4081 --------- Co-authored-by: evanpelle <evanpelle@gmail.com>
This commit is contained in:
@@ -35,9 +35,9 @@ describe("AllianceExtensionExecution", () => {
|
||||
});
|
||||
|
||||
test("Successfully extends existing alliance between Humans", () => {
|
||||
jest.spyOn(player1, "canSendAllianceRequest").mockReturnValue(true);
|
||||
jest.spyOn(player2, "isAlive").mockReturnValue(true);
|
||||
jest.spyOn(player1, "isAlive").mockReturnValue(true);
|
||||
vi.spyOn(player1, "canSendAllianceRequest").mockReturnValue(true);
|
||||
vi.spyOn(player2, "isAlive").mockReturnValue(true);
|
||||
vi.spyOn(player1, "isAlive").mockReturnValue(true);
|
||||
|
||||
game.addExecution(new AllianceRequestExecution(player1, player2.id()));
|
||||
game.executeNextTick();
|
||||
@@ -53,7 +53,7 @@ describe("AllianceExtensionExecution", () => {
|
||||
expect(player2.allianceWith(player1)).toBeTruthy();
|
||||
|
||||
const allianceBefore = player1.allianceWith(player2)!;
|
||||
const allianceSpy = jest.spyOn(allianceBefore, "extend");
|
||||
const allianceSpy = vi.spyOn(allianceBefore, "extend");
|
||||
|
||||
const expirationBefore = allianceBefore.expiresAt();
|
||||
|
||||
@@ -82,9 +82,9 @@ describe("AllianceExtensionExecution", () => {
|
||||
});
|
||||
|
||||
test("Successfully extends existing alliance between Human and non-Human", () => {
|
||||
jest.spyOn(player1, "canSendAllianceRequest").mockReturnValue(true);
|
||||
jest.spyOn(player3, "isAlive").mockReturnValue(true);
|
||||
jest.spyOn(player1, "isAlive").mockReturnValue(true);
|
||||
vi.spyOn(player1, "canSendAllianceRequest").mockReturnValue(true);
|
||||
vi.spyOn(player3, "isAlive").mockReturnValue(true);
|
||||
vi.spyOn(player1, "isAlive").mockReturnValue(true);
|
||||
|
||||
game.addExecution(new AllianceRequestExecution(player1, player3.id()));
|
||||
game.executeNextTick();
|
||||
@@ -100,7 +100,7 @@ describe("AllianceExtensionExecution", () => {
|
||||
expect(player3.allianceWith(player1)).toBeTruthy();
|
||||
|
||||
const allianceBefore = player1.allianceWith(player3)!;
|
||||
const allianceSpy = jest.spyOn(allianceBefore, "extend");
|
||||
const allianceSpy = vi.spyOn(allianceBefore, "extend");
|
||||
const expirationBefore = allianceBefore.expiresAt();
|
||||
|
||||
game.addExecution(new AllianceExtensionExecution(player1, player3.id()));
|
||||
@@ -120,9 +120,9 @@ describe("AllianceExtensionExecution", () => {
|
||||
});
|
||||
|
||||
test("Sends message to other player when one player requests renewal", () => {
|
||||
jest.spyOn(player1, "canSendAllianceRequest").mockReturnValue(true);
|
||||
jest.spyOn(player2, "isAlive").mockReturnValue(true);
|
||||
jest.spyOn(player1, "isAlive").mockReturnValue(true);
|
||||
vi.spyOn(player1, "canSendAllianceRequest").mockReturnValue(true);
|
||||
vi.spyOn(player2, "isAlive").mockReturnValue(true);
|
||||
vi.spyOn(player1, "isAlive").mockReturnValue(true);
|
||||
|
||||
// Create alliance between player1 and player2
|
||||
game.addExecution(new AllianceRequestExecution(player1, player2.id()));
|
||||
@@ -139,7 +139,7 @@ describe("AllianceExtensionExecution", () => {
|
||||
expect(player2.allianceWith(player1)).toBeTruthy();
|
||||
|
||||
// Spy on displayMessage to verify it's called
|
||||
const displayMessageSpy = jest.spyOn(game, "displayMessage");
|
||||
const displayMessageSpy = vi.spyOn(game, "displayMessage");
|
||||
|
||||
// Player1 requests renewal
|
||||
game.addExecution(new AllianceExtensionExecution(player1, player2.id()));
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import { AutoUpgradeEvent } from "../src/client/InputHandler";
|
||||
import { EventBus } from "../src/core/EventBus";
|
||||
|
||||
@@ -19,7 +16,7 @@ describe("AutoUpgrade Feature", () => {
|
||||
});
|
||||
|
||||
test("should emit AutoUpgradeEvent when created", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const event = new AutoUpgradeEvent(150, 250);
|
||||
eventBus.emit(event);
|
||||
@@ -36,7 +33,7 @@ describe("AutoUpgrade Feature", () => {
|
||||
|
||||
describe("AutoUpgradeEvent Integration", () => {
|
||||
test("should handle multiple AutoUpgradeEvents", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const event1 = new AutoUpgradeEvent(100, 200);
|
||||
const event2 = new AutoUpgradeEvent(300, 400);
|
||||
@@ -70,7 +67,7 @@ describe("AutoUpgrade Feature", () => {
|
||||
|
||||
describe("AutoUpgradeEvent Event Bus Integration", () => {
|
||||
test("should allow event listeners to subscribe to AutoUpgradeEvent", () => {
|
||||
const mockListener = jest.fn();
|
||||
const mockListener = vi.fn();
|
||||
const event = new AutoUpgradeEvent(100, 200);
|
||||
|
||||
eventBus.on(AutoUpgradeEvent, mockListener);
|
||||
@@ -80,8 +77,8 @@ describe("AutoUpgrade Feature", () => {
|
||||
});
|
||||
|
||||
test("should allow multiple listeners for AutoUpgradeEvent", () => {
|
||||
const mockListener1 = jest.fn();
|
||||
const mockListener2 = jest.fn();
|
||||
const mockListener1 = vi.fn();
|
||||
const mockListener2 = vi.fn();
|
||||
const event = new AutoUpgradeEvent(100, 200);
|
||||
|
||||
eventBus.on(AutoUpgradeEvent, mockListener1);
|
||||
@@ -93,7 +90,7 @@ describe("AutoUpgrade Feature", () => {
|
||||
});
|
||||
|
||||
test("should not call unsubscribed listeners", () => {
|
||||
const mockListener = jest.fn();
|
||||
const mockListener = vi.fn();
|
||||
const event = new AutoUpgradeEvent(100, 200);
|
||||
|
||||
eventBus.on(AutoUpgradeEvent, mockListener);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Mocking the obscenity library to control its behavior in tests.
|
||||
jest.mock("obscenity", () => {
|
||||
vi.mock("obscenity", () => {
|
||||
return {
|
||||
RegExpMatcher: class {
|
||||
private dummy: string[] = ["foo", "bar", "leet", "code"];
|
||||
@@ -26,7 +26,7 @@ jest.mock("obscenity", () => {
|
||||
});
|
||||
|
||||
// Mocks the output of translation functions to return predictable values.
|
||||
jest.mock("../src/client/Utils", () => ({
|
||||
vi.mock("../src/client/Utils", () => ({
|
||||
translateText: (key: string, vars?: any) =>
|
||||
vars ? `${key}:${JSON.stringify(vars)}` : key,
|
||||
}));
|
||||
|
||||
@@ -112,7 +112,7 @@ describe("DeleteUnitExecution Security Tests", () => {
|
||||
});
|
||||
|
||||
it("should prevent deleting units during spawn phase", () => {
|
||||
jest.spyOn(game, "inSpawnPhase").mockReturnValue(true);
|
||||
vi.spyOn(game, "inSpawnPhase").mockReturnValue(true);
|
||||
|
||||
const execution = new DeleteUnitExecution(player, unit.id());
|
||||
execution.init(game, 0);
|
||||
@@ -122,7 +122,7 @@ describe("DeleteUnitExecution Security Tests", () => {
|
||||
});
|
||||
|
||||
it("should allow deleting units when all conditions are met", () => {
|
||||
jest.spyOn(game, "inSpawnPhase").mockReturnValue(false);
|
||||
vi.spyOn(game, "inSpawnPhase").mockReturnValue(false);
|
||||
|
||||
const execution = new DeleteUnitExecution(player, unit.id());
|
||||
execution.init(game, 0);
|
||||
@@ -131,7 +131,7 @@ describe("DeleteUnitExecution Security Tests", () => {
|
||||
});
|
||||
|
||||
it("should delete after deletion delay", () => {
|
||||
jest.spyOn(game, "inSpawnPhase").mockReturnValue(false);
|
||||
vi.spyOn(game, "inSpawnPhase").mockReturnValue(false);
|
||||
|
||||
const execution = new DeleteUnitExecution(player, unit.id());
|
||||
game.addExecution(execution);
|
||||
@@ -144,7 +144,7 @@ describe("DeleteUnitExecution Security Tests", () => {
|
||||
});
|
||||
|
||||
it("should reset deletion if captured", () => {
|
||||
jest.spyOn(game, "inSpawnPhase").mockReturnValue(false);
|
||||
vi.spyOn(game, "inSpawnPhase").mockReturnValue(false);
|
||||
|
||||
const execution = new DeleteUnitExecution(player, unit.id());
|
||||
game.addExecution(execution);
|
||||
|
||||
+19
-22
@@ -1,6 +1,3 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import { AutoUpgradeEvent, InputHandler } from "../src/client/InputHandler";
|
||||
import { EventBus } from "../src/core/EventBus";
|
||||
|
||||
@@ -18,7 +15,7 @@ class MockPointerEvent {
|
||||
this.clientX = init.clientX;
|
||||
this.clientY = init.clientY;
|
||||
this.pointerId = init.pointerId;
|
||||
this.preventDefault = jest.fn();
|
||||
this.preventDefault = vi.fn();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +42,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
|
||||
describe("Middle Mouse Button Handling", () => {
|
||||
test("should emit AutoUpgradeEvent on middle mouse button press", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -65,7 +62,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should emit MouseDownEvent on left mouse button press instead of AutoUpgradeEvent", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 0,
|
||||
@@ -89,7 +86,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should not emit AutoUpgradeEvent on right mouse button press", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 2,
|
||||
@@ -109,7 +106,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should handle multiple middle mouse button presses", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent1 = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -145,7 +142,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should handle middle mouse button press with zero coordinates", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -165,7 +162,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should handle middle mouse button press with negative coordinates", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -185,7 +182,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should handle middle mouse button press with decimal coordinates", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -207,7 +204,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
|
||||
describe("Pointer Event Handling", () => {
|
||||
test("should handle pointer events with different pointer IDs", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent1 = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -229,7 +226,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should handle pointer events with same pointer ID", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent1 = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -253,7 +250,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
|
||||
describe("Edge Cases", () => {
|
||||
test("should handle very large coordinates", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -273,7 +270,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should handle very small coordinates", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -293,7 +290,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should handle NaN coordinates", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -313,7 +310,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should handle Infinity coordinates", () => {
|
||||
const mockEmit = jest.spyOn(eventBus, "emit");
|
||||
const mockEmit = vi.spyOn(eventBus, "emit");
|
||||
|
||||
const pointerEvent = new PointerEvent("pointerdown", {
|
||||
button: 1,
|
||||
@@ -335,7 +332,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
|
||||
describe("Integration with Event Bus", () => {
|
||||
test("should allow event listeners to receive AutoUpgradeEvents", () => {
|
||||
const mockListener = jest.fn();
|
||||
const mockListener = vi.fn();
|
||||
|
||||
eventBus.on(AutoUpgradeEvent, mockListener);
|
||||
|
||||
@@ -356,8 +353,8 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should allow multiple listeners for AutoUpgradeEvent", () => {
|
||||
const mockListener1 = jest.fn();
|
||||
const mockListener2 = jest.fn();
|
||||
const mockListener1 = vi.fn();
|
||||
const mockListener2 = vi.fn();
|
||||
|
||||
eventBus.on(AutoUpgradeEvent, mockListener1);
|
||||
eventBus.on(AutoUpgradeEvent, mockListener2);
|
||||
@@ -385,7 +382,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("should not call unsubscribed listeners", () => {
|
||||
const mockListener = jest.fn();
|
||||
const mockListener = vi.fn();
|
||||
|
||||
eventBus.on(AutoUpgradeEvent, mockListener);
|
||||
eventBus.off(AutoUpgradeEvent, mockListener);
|
||||
@@ -444,7 +441,7 @@ describe("InputHandler AutoUpgrade", () => {
|
||||
});
|
||||
|
||||
test("handles invalid JSON gracefully and warns", () => {
|
||||
const spy = jest.spyOn(console, "warn").mockImplementation(() => {});
|
||||
const spy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
localStorage.setItem("settings.keybinds", "not a json");
|
||||
|
||||
inputHandler.initialize();
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { vi, type MockInstance } from "vitest";
|
||||
import { getMessageTypeClasses, severityColors } from "../src/client/Utils";
|
||||
import { MessageType } from "../src/core/game/Game";
|
||||
|
||||
describe("getMessageTypeClasses", () => {
|
||||
// Spy on console.warn to track when the default case is hit
|
||||
let consoleSpy: jest.SpyInstance;
|
||||
let consoleSpy: MockInstance;
|
||||
|
||||
beforeEach(() => {
|
||||
consoleSpy = jest.spyOn(console, "warn").mockImplementation(() => {});
|
||||
consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -77,19 +77,17 @@ describe("AllianceBehavior.handleAllianceRequests", () => {
|
||||
}
|
||||
});
|
||||
|
||||
jest.spyOn(player, "alliances").mockReturnValue(new Array(alliancesCount));
|
||||
vi.spyOn(player, "alliances").mockReturnValue(new Array(alliancesCount));
|
||||
|
||||
const mockRequest = {
|
||||
requestor: () => requestor,
|
||||
recipient: () => player,
|
||||
createdAt: () => 0 as unknown as Tick,
|
||||
accept: jest.fn(),
|
||||
reject: jest.fn(),
|
||||
accept: vi.fn(),
|
||||
reject: vi.fn(),
|
||||
} as unknown as AllianceRequest;
|
||||
|
||||
jest
|
||||
.spyOn(player, "incomingAllianceRequests")
|
||||
.mockReturnValue([mockRequest]);
|
||||
vi.spyOn(player, "incomingAllianceRequests").mockReturnValue([mockRequest]);
|
||||
|
||||
return mockRequest;
|
||||
}
|
||||
@@ -151,19 +149,19 @@ describe("AllianceBehavior.handleAllianceExtensionRequests", () => {
|
||||
let allianceBehavior: NationAllianceBehavior;
|
||||
|
||||
beforeEach(() => {
|
||||
mockGame = { addExecution: jest.fn() };
|
||||
mockHuman = { id: jest.fn(() => "human_id") };
|
||||
mockGame = { addExecution: vi.fn() };
|
||||
mockHuman = { id: vi.fn(() => "human_id") };
|
||||
mockAlliance = {
|
||||
onlyOneAgreedToExtend: jest.fn(() => true),
|
||||
other: jest.fn(() => mockHuman),
|
||||
onlyOneAgreedToExtend: vi.fn(() => true),
|
||||
other: vi.fn(() => mockHuman),
|
||||
};
|
||||
mockRandom = { chance: jest.fn() };
|
||||
mockRandom = { chance: vi.fn() };
|
||||
|
||||
mockPlayer = {
|
||||
alliances: jest.fn(() => [mockAlliance]),
|
||||
relation: jest.fn(),
|
||||
id: jest.fn(() => "bot_id"),
|
||||
type: jest.fn(() => PlayerType.Nation),
|
||||
alliances: vi.fn(() => [mockAlliance]),
|
||||
relation: vi.fn(),
|
||||
id: vi.fn(() => "bot_id"),
|
||||
type: vi.fn(() => PlayerType.Nation),
|
||||
};
|
||||
|
||||
allianceBehavior = new NationAllianceBehavior(
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import { FluentSlider } from "../../../src/client/components/FluentSlider";
|
||||
|
||||
// Mock the translateText function
|
||||
jest.mock("../../../src/client/Utils", () => ({
|
||||
translateText: jest.fn((key: string) => key),
|
||||
vi.mock("../../../src/client/Utils", () => ({
|
||||
translateText: vi.fn((key: string) => key),
|
||||
}));
|
||||
|
||||
describe("FluentSlider", () => {
|
||||
@@ -84,7 +81,7 @@ describe("FluentSlider", () => {
|
||||
|
||||
describe("Value-Changed Event - CRITICAL FOR BUG FIX", () => {
|
||||
it("should dispatch CustomEvent with detail.value (not event.target.value)", async () => {
|
||||
const eventSpy = jest.fn();
|
||||
const eventSpy = vi.fn();
|
||||
slider.addEventListener("value-changed", eventSpy);
|
||||
|
||||
const rangeInput = slider.shadowRoot?.querySelector(
|
||||
@@ -107,7 +104,7 @@ describe("FluentSlider", () => {
|
||||
});
|
||||
|
||||
it("should not dispatch event on input, only on change", async () => {
|
||||
const eventSpy = jest.fn();
|
||||
const eventSpy = vi.fn();
|
||||
slider.addEventListener("value-changed", eventSpy);
|
||||
|
||||
const rangeInput = slider.shadowRoot?.querySelector(
|
||||
@@ -128,7 +125,7 @@ describe("FluentSlider", () => {
|
||||
|
||||
it("should work with the handler pattern used in HostLobbyModal", async () => {
|
||||
// This simulates the actual handler code in HostLobbyModal.ts:656-660
|
||||
const mockHandler = jest.fn((e: Event) => {
|
||||
const mockHandler = vi.fn((e: Event) => {
|
||||
const customEvent = e as CustomEvent<{ value: number }>;
|
||||
const value = customEvent.detail.value;
|
||||
if (isNaN(value) || value < 0 || value > 400) {
|
||||
@@ -154,7 +151,7 @@ describe("FluentSlider", () => {
|
||||
|
||||
it("should work with the handler pattern used in SinglePlayerModal", async () => {
|
||||
// This simulates the actual handler code in SinglePlayerModal.ts:444-451
|
||||
const mockHandler = jest.fn((e: Event) => {
|
||||
const mockHandler = vi.fn((e: Event) => {
|
||||
const customEvent = e as CustomEvent<{ value: number }>;
|
||||
const value = customEvent.detail.value;
|
||||
if (isNaN(value) || value < 0 || value > 400) {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import { ProgressBar } from "../../../src/client/graphics/ProgressBar";
|
||||
|
||||
describe("ProgressBar", () => {
|
||||
@@ -15,9 +12,9 @@ describe("ProgressBar", () => {
|
||||
});
|
||||
|
||||
it("should initialize and draw the background", () => {
|
||||
const spyClearRect = jest.spyOn(ctx, "clearRect");
|
||||
const spyFillRect = jest.spyOn(ctx, "fillRect");
|
||||
const spyFillStyle = jest.spyOn(ctx, "fillStyle", "set");
|
||||
const spyClearRect = vi.spyOn(ctx, "clearRect");
|
||||
const spyFillRect = vi.spyOn(ctx, "fillRect");
|
||||
const spyFillStyle = vi.spyOn(ctx, "fillStyle", "set");
|
||||
const bar = new ProgressBar(["#ff0000", "#00ff00"], ctx, 2, 2, 80, 10, 0.5);
|
||||
expect(spyClearRect).toHaveBeenCalledWith(0, 0, 82, 12);
|
||||
expect(spyFillRect).toHaveBeenCalledWith(1, 1, 80, 10);
|
||||
@@ -28,7 +25,7 @@ describe("ProgressBar", () => {
|
||||
|
||||
it("should set progress and draw the progress bar", () => {
|
||||
const bar = new ProgressBar(["#ff0000", "#00ff00"], ctx, 2, 2, 80, 10);
|
||||
const spyFillRect = jest.spyOn(ctx, "fillRect");
|
||||
const spyFillRect = vi.spyOn(ctx, "fillRect");
|
||||
bar.setProgress(0.5);
|
||||
expect(bar.getProgress()).toBe(0.5);
|
||||
expect(spyFillRect).toHaveBeenCalledWith(
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import { vi, type Mock } from "vitest";
|
||||
import {
|
||||
attackMenuElement,
|
||||
buildMenuElement,
|
||||
@@ -13,13 +11,15 @@ import { UnitType } from "../../../src/core/game/Game";
|
||||
import { TileRef } from "../../../src/core/game/GameMap";
|
||||
import { GameView, PlayerView } from "../../../src/core/game/GameView";
|
||||
|
||||
jest.mock("../../../src/client/Utils", () => ({
|
||||
translateText: jest.fn((key: string) => key),
|
||||
renderNumber: jest.fn((num: number) => num.toString()),
|
||||
vi.mock("../../../src/client/Utils", () => ({
|
||||
translateText: vi.fn((key: string) => key),
|
||||
renderNumber: vi.fn((num: number) => num.toString()),
|
||||
}));
|
||||
|
||||
jest.mock("../../../src/client/graphics/layers/BuildMenu", () => {
|
||||
const { UnitType } = jest.requireActual("../../../src/core/game/Game");
|
||||
vi.mock("../../../src/client/graphics/layers/BuildMenu", async () => {
|
||||
const { UnitType } = await vi.importActual<
|
||||
typeof import("../../../src/core/game/Game")
|
||||
>("../../../src/core/game/Game");
|
||||
return {
|
||||
flattenedBuildTable: [
|
||||
{
|
||||
@@ -68,14 +68,14 @@ jest.mock("../../../src/client/graphics/layers/BuildMenu", () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock("nanoid", () => ({
|
||||
customAlphabet: jest.fn(() => jest.fn(() => "mock-id")),
|
||||
vi.mock("nanoid", () => ({
|
||||
customAlphabet: vi.fn(() => vi.fn(() => "mock-id")),
|
||||
}));
|
||||
|
||||
jest.mock("dompurify", () => ({
|
||||
vi.mock("dompurify", () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
sanitize: jest.fn((str: string) => str),
|
||||
sanitize: vi.fn((str: string) => str),
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -90,29 +90,29 @@ describe("RadialMenuElements", () => {
|
||||
beforeEach(() => {
|
||||
mockPlayer = {
|
||||
id: () => 1,
|
||||
isAlliedWith: jest.fn(() => false),
|
||||
isPlayer: jest.fn(() => true),
|
||||
isAlliedWith: vi.fn(() => false),
|
||||
isPlayer: vi.fn(() => true),
|
||||
} as unknown as PlayerView;
|
||||
|
||||
mockGame = {
|
||||
inSpawnPhase: jest.fn(() => false),
|
||||
owner: jest.fn(() => mockPlayer),
|
||||
isLand: jest.fn(() => true),
|
||||
config: jest.fn(() => ({
|
||||
inSpawnPhase: vi.fn(() => false),
|
||||
owner: vi.fn(() => mockPlayer),
|
||||
isLand: vi.fn(() => true),
|
||||
config: vi.fn(() => ({
|
||||
theme: () => ({
|
||||
territoryColor: () => ({
|
||||
lighten: () => ({ alpha: () => ({ toRgbString: () => "#fff" }) }),
|
||||
}),
|
||||
}),
|
||||
isUnitDisabled: jest.fn(() => false),
|
||||
isUnitDisabled: vi.fn(() => false),
|
||||
})),
|
||||
} as unknown as GameView;
|
||||
|
||||
mockBuildMenu = {
|
||||
canBuildOrUpgrade: jest.fn(() => true),
|
||||
cost: jest.fn(() => 100),
|
||||
count: jest.fn(() => 5),
|
||||
sendBuildOrUpgrade: jest.fn(),
|
||||
canBuildOrUpgrade: vi.fn(() => true),
|
||||
cost: vi.fn(() => 100),
|
||||
count: vi.fn(() => 5),
|
||||
sendBuildOrUpgrade: vi.fn(),
|
||||
};
|
||||
|
||||
mockPlayerActions = {
|
||||
@@ -148,7 +148,7 @@ describe("RadialMenuElements", () => {
|
||||
playerPanel: {} as any,
|
||||
chatIntegration: {} as any,
|
||||
eventBus: {} as any,
|
||||
closeMenu: jest.fn(),
|
||||
closeMenu: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -161,19 +161,19 @@ describe("RadialMenuElements", () => {
|
||||
});
|
||||
|
||||
it("should be disabled during spawn phase", () => {
|
||||
mockGame.inSpawnPhase = jest.fn(() => true);
|
||||
mockGame.inSpawnPhase = vi.fn(() => true);
|
||||
expect(attackMenuElement.disabled(mockParams)).toBe(true);
|
||||
});
|
||||
|
||||
it("should be enabled when not in spawn phase", () => {
|
||||
mockGame.inSpawnPhase = jest.fn(() => false);
|
||||
mockGame.inSpawnPhase = vi.fn(() => false);
|
||||
expect(attackMenuElement.disabled(mockParams)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return attack submenu with attack units only", () => {
|
||||
const enemyPlayer = {
|
||||
id: () => 2,
|
||||
isPlayer: jest.fn(() => true),
|
||||
isPlayer: vi.fn(() => true),
|
||||
} as unknown as PlayerView;
|
||||
mockParams.selected = enemyPlayer;
|
||||
|
||||
@@ -203,7 +203,7 @@ describe("RadialMenuElements", () => {
|
||||
it("should not include construction units in attack menu", () => {
|
||||
const enemyPlayer = {
|
||||
id: () => 2,
|
||||
isPlayer: jest.fn(() => true),
|
||||
isPlayer: vi.fn(() => true),
|
||||
} as unknown as PlayerView;
|
||||
mockParams.selected = enemyPlayer;
|
||||
|
||||
@@ -237,12 +237,12 @@ describe("RadialMenuElements", () => {
|
||||
});
|
||||
|
||||
it("should be disabled during spawn phase", () => {
|
||||
mockGame.inSpawnPhase = jest.fn(() => true);
|
||||
mockGame.inSpawnPhase = vi.fn(() => true);
|
||||
expect(buildMenuElement.disabled(mockParams)).toBe(true);
|
||||
});
|
||||
|
||||
it("should be enabled when not in spawn phase", () => {
|
||||
mockGame.inSpawnPhase = jest.fn(() => false);
|
||||
mockGame.inSpawnPhase = vi.fn(() => false);
|
||||
expect(buildMenuElement.disabled(mockParams)).toBe(false);
|
||||
});
|
||||
|
||||
@@ -313,9 +313,9 @@ describe("RadialMenuElements", () => {
|
||||
it("should show attack and boat menu on enemy territory", () => {
|
||||
const enemyPlayer = {
|
||||
id: () => 2,
|
||||
isPlayer: jest.fn(() => true),
|
||||
isPlayer: vi.fn(() => true),
|
||||
} as unknown as PlayerView;
|
||||
mockGame.owner = jest.fn(() => enemyPlayer);
|
||||
mockGame.owner = vi.fn(() => enemyPlayer);
|
||||
|
||||
const subMenu = rootMenuElement.subMenu!(mockParams);
|
||||
const buildMenu = subMenu.find((item) => item.id === Slot.Build);
|
||||
@@ -337,8 +337,8 @@ describe("RadialMenuElements", () => {
|
||||
it("should handle ally menu correctly", () => {
|
||||
const allyPlayer = {
|
||||
id: () => 2,
|
||||
isAlliedWith: jest.fn(() => true),
|
||||
isPlayer: jest.fn(() => true),
|
||||
isAlliedWith: vi.fn(() => true),
|
||||
isPlayer: vi.fn(() => true),
|
||||
} as unknown as PlayerView;
|
||||
mockParams.selected = allyPlayer;
|
||||
|
||||
@@ -367,7 +367,7 @@ describe("RadialMenuElements", () => {
|
||||
it("should execute attack action correctly", () => {
|
||||
const enemyPlayer = {
|
||||
id: () => 2,
|
||||
isPlayer: jest.fn(() => true),
|
||||
isPlayer: vi.fn(() => true),
|
||||
} as unknown as PlayerView;
|
||||
mockParams.selected = enemyPlayer;
|
||||
|
||||
@@ -389,7 +389,7 @@ describe("RadialMenuElements", () => {
|
||||
|
||||
it("should not execute action when buildable unit is not found", () => {
|
||||
mockPlayerActions.buildableUnits = [];
|
||||
mockBuildMenu.canBuildOrUpgrade = jest.fn(() => false);
|
||||
mockBuildMenu.canBuildOrUpgrade = vi.fn(() => false);
|
||||
|
||||
const subMenu = buildMenuElement.subMenu!(mockParams);
|
||||
const cityElement = subMenu.find((item) => item.id === "build_City");
|
||||
@@ -420,7 +420,7 @@ describe("RadialMenuElements", () => {
|
||||
it("should generate correct tooltip items for attack elements", () => {
|
||||
const enemyPlayer = {
|
||||
id: () => 2,
|
||||
isPlayer: jest.fn(() => true),
|
||||
isPlayer: vi.fn(() => true),
|
||||
} as unknown as PlayerView;
|
||||
mockParams.selected = enemyPlayer;
|
||||
|
||||
@@ -452,7 +452,7 @@ describe("RadialMenuElements", () => {
|
||||
it("should use correct colors for attack elements", () => {
|
||||
const enemyPlayer = {
|
||||
id: () => 2,
|
||||
isPlayer: jest.fn(() => true),
|
||||
isPlayer: vi.fn(() => true),
|
||||
} as unknown as PlayerView;
|
||||
mockParams.selected = enemyPlayer;
|
||||
|
||||
@@ -465,7 +465,7 @@ describe("RadialMenuElements", () => {
|
||||
});
|
||||
|
||||
it("should not set color when element is disabled", () => {
|
||||
mockBuildMenu.canBuildOrUpgrade = jest.fn(() => false);
|
||||
mockBuildMenu.canBuildOrUpgrade = vi.fn(() => false);
|
||||
|
||||
const subMenu = buildMenuElement.subMenu!(mockParams);
|
||||
const cityElement = subMenu.find((item) => item.id === "build_City");
|
||||
@@ -475,10 +475,12 @@ describe("RadialMenuElements", () => {
|
||||
});
|
||||
|
||||
describe("Translation integration", () => {
|
||||
it("should use translateText for tooltip items in build menu", () => {
|
||||
const { translateText } = jest.requireMock("../../../src/client/Utils");
|
||||
it("should use translateText for tooltip items in build menu", async () => {
|
||||
const { translateText } = await vi.importMock<
|
||||
typeof import("../../../src/client/Utils")
|
||||
>("../../../src/client/Utils");
|
||||
|
||||
(translateText as jest.Mock).mockClear();
|
||||
(translateText as Mock).mockClear();
|
||||
|
||||
buildMenuElement.subMenu!(mockParams);
|
||||
|
||||
@@ -488,14 +490,16 @@ describe("RadialMenuElements", () => {
|
||||
expect(translateText).toHaveBeenCalledWith("unit_type.factory_desc");
|
||||
});
|
||||
|
||||
it("should use translateText for tooltip items in attack menu", () => {
|
||||
const { translateText } = jest.requireMock("../../../src/client/Utils");
|
||||
it("should use translateText for tooltip items in attack menu", async () => {
|
||||
const { translateText } = await vi.importMock<
|
||||
typeof import("../../../src/client/Utils")
|
||||
>("../../../src/client/Utils");
|
||||
|
||||
(translateText as jest.Mock).mockClear();
|
||||
(translateText as Mock).mockClear();
|
||||
|
||||
const enemyPlayer = {
|
||||
id: () => 2,
|
||||
isPlayer: jest.fn(() => true),
|
||||
isPlayer: vi.fn(() => true),
|
||||
} as unknown as PlayerView;
|
||||
mockParams.selected = enemyPlayer;
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import { UILayer } from "../../../src/client/graphics/layers/UILayer";
|
||||
import { UnitSelectionEvent } from "../../../src/client/InputHandler";
|
||||
import { UnitView } from "../../../src/core/game/GameView";
|
||||
@@ -28,7 +25,7 @@ describe("UILayer", () => {
|
||||
ticks: () => 1,
|
||||
updatesSinceLastTick: () => undefined,
|
||||
};
|
||||
eventBus = { on: jest.fn() };
|
||||
eventBus = { on: vi.fn() };
|
||||
transformHandler = {};
|
||||
});
|
||||
|
||||
@@ -50,7 +47,7 @@ describe("UILayer", () => {
|
||||
owner: () => ({}),
|
||||
};
|
||||
const event = { isSelected: true, unit };
|
||||
ui.drawSelectionBox = jest.fn();
|
||||
ui.drawSelectionBox = vi.fn();
|
||||
ui["onUnitSelection"](event as UnitSelectionEvent);
|
||||
expect(ui.drawSelectionBox).toHaveBeenCalledWith(unit);
|
||||
});
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
jest.mock("lit", () => ({
|
||||
vi.mock("lit", () => ({
|
||||
html: () => {},
|
||||
LitElement: class {},
|
||||
}));
|
||||
|
||||
jest.mock("lit/decorators.js", () => ({
|
||||
vi.mock("lit/decorators.js", () => ({
|
||||
customElement: () => (clazz: any) => clazz,
|
||||
query: () => () => {},
|
||||
state: () => () => {},
|
||||
property: () => () => {},
|
||||
}));
|
||||
|
||||
jest.mock("lit/directive.js", () => ({
|
||||
vi.mock("lit/directive.js", () => ({
|
||||
DirectiveResult: class {},
|
||||
}));
|
||||
|
||||
jest.mock("lit/directives/unsafe-html.js", () => ({
|
||||
vi.mock("lit/directives/unsafe-html.js", () => ({
|
||||
unsafeHTML: () => {},
|
||||
UnsafeHTMLDirective: class {},
|
||||
}));
|
||||
|
||||
@@ -28,11 +28,11 @@ describe("NukeExecution", () => {
|
||||
],
|
||||
);
|
||||
|
||||
(game.config() as TestConfig).nukeMagnitudes = jest.fn(() => ({
|
||||
(game.config() as TestConfig).nukeMagnitudes = vi.fn(() => ({
|
||||
inner: 10,
|
||||
outer: 10,
|
||||
}));
|
||||
(game.config() as TestConfig).nukeAllianceBreakThreshold = jest.fn(() => 5);
|
||||
(game.config() as TestConfig).nukeAllianceBreakThreshold = vi.fn(() => 5);
|
||||
|
||||
while (game.inSpawnPhase()) {
|
||||
game.executeNextTick();
|
||||
@@ -51,14 +51,14 @@ describe("NukeExecution", () => {
|
||||
player.buildUnit(UnitType.MissileSilo, game.ref(1, 10), {});
|
||||
// Build a SAM out of range
|
||||
const sam = player.buildUnit(UnitType.SAMLauncher, game.ref(1, 11), {});
|
||||
sam.touch = jest.fn();
|
||||
sam.touch = vi.fn();
|
||||
// Build a Defense post out of range AND out of redraw range
|
||||
const defensePost = player.buildUnit(
|
||||
UnitType.DefensePost,
|
||||
game.ref(1, 27),
|
||||
{},
|
||||
);
|
||||
defensePost.touch = jest.fn();
|
||||
defensePost.touch = vi.fn();
|
||||
// Add a nuke execution targeting the city
|
||||
const nukeExec = new NukeExecution(
|
||||
UnitType.AtomBomb,
|
||||
|
||||
@@ -20,70 +20,70 @@ describe("TradeShipExecution", () => {
|
||||
infiniteGold: true,
|
||||
instantBuild: true,
|
||||
});
|
||||
game.displayMessage = jest.fn();
|
||||
game.displayMessage = vi.fn();
|
||||
origOwner = {
|
||||
canBuild: jest.fn(() => true),
|
||||
buildUnit: jest.fn((type, spawn, opts) => tradeShip),
|
||||
displayName: jest.fn(() => "Origin"),
|
||||
addGold: jest.fn(),
|
||||
units: jest.fn(() => [dstPort]),
|
||||
unitCount: jest.fn(() => 1),
|
||||
id: jest.fn(() => 1),
|
||||
clientID: jest.fn(() => 1),
|
||||
canTrade: jest.fn(() => true),
|
||||
canBuild: vi.fn(() => true),
|
||||
buildUnit: vi.fn((type, spawn, opts) => tradeShip),
|
||||
displayName: vi.fn(() => "Origin"),
|
||||
addGold: vi.fn(),
|
||||
units: vi.fn(() => [dstPort]),
|
||||
unitCount: vi.fn(() => 1),
|
||||
id: vi.fn(() => 1),
|
||||
clientID: vi.fn(() => 1),
|
||||
canTrade: vi.fn(() => true),
|
||||
} as any;
|
||||
|
||||
dstOwner = {
|
||||
id: jest.fn(() => 2),
|
||||
addGold: jest.fn(),
|
||||
displayName: jest.fn(() => "Destination"),
|
||||
units: jest.fn(() => [dstPort]),
|
||||
unitCount: jest.fn(() => 1),
|
||||
clientID: jest.fn(() => 2),
|
||||
canTrade: jest.fn(() => true),
|
||||
id: vi.fn(() => 2),
|
||||
addGold: vi.fn(),
|
||||
displayName: vi.fn(() => "Destination"),
|
||||
units: vi.fn(() => [dstPort]),
|
||||
unitCount: vi.fn(() => 1),
|
||||
clientID: vi.fn(() => 2),
|
||||
canTrade: vi.fn(() => true),
|
||||
} as any;
|
||||
|
||||
pirate = {
|
||||
id: jest.fn(() => 3),
|
||||
addGold: jest.fn(),
|
||||
displayName: jest.fn(() => "Destination"),
|
||||
units: jest.fn(() => [piratePort]),
|
||||
unitCount: jest.fn(() => 1),
|
||||
canTrade: jest.fn(() => true),
|
||||
id: vi.fn(() => 3),
|
||||
addGold: vi.fn(),
|
||||
displayName: vi.fn(() => "Destination"),
|
||||
units: vi.fn(() => [piratePort]),
|
||||
unitCount: vi.fn(() => 1),
|
||||
canTrade: vi.fn(() => true),
|
||||
} as any;
|
||||
|
||||
piratePort = {
|
||||
tile: jest.fn(() => 40011),
|
||||
owner: jest.fn(() => pirate),
|
||||
isActive: jest.fn(() => true),
|
||||
tile: vi.fn(() => 40011),
|
||||
owner: vi.fn(() => pirate),
|
||||
isActive: vi.fn(() => true),
|
||||
} as any;
|
||||
|
||||
srcPort = {
|
||||
tile: jest.fn(() => 20011),
|
||||
owner: jest.fn(() => origOwner),
|
||||
isActive: jest.fn(() => true),
|
||||
tile: vi.fn(() => 20011),
|
||||
owner: vi.fn(() => origOwner),
|
||||
isActive: vi.fn(() => true),
|
||||
} as any;
|
||||
|
||||
dstPort = {
|
||||
tile: jest.fn(() => 30015), // 15x15
|
||||
owner: jest.fn(() => dstOwner),
|
||||
isActive: jest.fn(() => true),
|
||||
tile: vi.fn(() => 30015), // 15x15
|
||||
owner: vi.fn(() => dstOwner),
|
||||
isActive: vi.fn(() => true),
|
||||
} as any;
|
||||
|
||||
tradeShip = {
|
||||
isActive: jest.fn(() => true),
|
||||
owner: jest.fn(() => origOwner),
|
||||
move: jest.fn(),
|
||||
setTargetUnit: jest.fn(),
|
||||
setSafeFromPirates: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
tile: jest.fn(() => 2001),
|
||||
isActive: vi.fn(() => true),
|
||||
owner: vi.fn(() => origOwner),
|
||||
move: vi.fn(),
|
||||
setTargetUnit: vi.fn(),
|
||||
setSafeFromPirates: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
tile: vi.fn(() => 2001),
|
||||
} as any;
|
||||
|
||||
tradeShipExecution = new TradeShipExecution(origOwner, srcPort, dstPort);
|
||||
tradeShipExecution.init(game, 0);
|
||||
tradeShipExecution["pathFinder"] = {
|
||||
nextTile: jest.fn(() => ({ type: 0, node: 2001 })),
|
||||
nextTile: vi.fn(() => ({ type: 0, node: 2001 })),
|
||||
} as any;
|
||||
tradeShipExecution["tradeShip"] = tradeShip;
|
||||
});
|
||||
@@ -94,27 +94,27 @@ describe("TradeShipExecution", () => {
|
||||
});
|
||||
|
||||
it("should deactivate if tradeShip is not active", () => {
|
||||
tradeShip.isActive = jest.fn(() => false);
|
||||
tradeShip.isActive = vi.fn(() => false);
|
||||
tradeShipExecution.tick(1);
|
||||
expect(tradeShipExecution.isActive()).toBe(false);
|
||||
});
|
||||
|
||||
it("should delete ship if port owner changes to current owner", () => {
|
||||
dstPort.owner = jest.fn(() => origOwner);
|
||||
dstPort.owner = vi.fn(() => origOwner);
|
||||
tradeShipExecution.tick(1);
|
||||
expect(tradeShip.delete).toHaveBeenCalledWith(false);
|
||||
expect(tradeShipExecution.isActive()).toBe(false);
|
||||
});
|
||||
|
||||
it("should pick another port if ship is captured", () => {
|
||||
tradeShip.owner = jest.fn(() => pirate);
|
||||
tradeShip.owner = vi.fn(() => pirate);
|
||||
tradeShipExecution.tick(1);
|
||||
expect(tradeShip.setTargetUnit).toHaveBeenCalledWith(piratePort);
|
||||
});
|
||||
|
||||
it("should complete trade and award gold", () => {
|
||||
tradeShipExecution["pathFinder"] = {
|
||||
nextTile: jest.fn(() => ({ type: 2, node: 2001 })),
|
||||
nextTile: vi.fn(() => ({ type: 2, node: 2001 })),
|
||||
} as any;
|
||||
tradeShipExecution.tick(1);
|
||||
expect(tradeShip.delete).toHaveBeenCalledWith(false);
|
||||
|
||||
@@ -13,52 +13,52 @@ describe("WinCheckExecution", () => {
|
||||
maxTimerValue: 5,
|
||||
instantBuild: true,
|
||||
});
|
||||
mg.setWinner = jest.fn();
|
||||
mg.setWinner = vi.fn();
|
||||
winCheck = new WinCheckExecution();
|
||||
winCheck.init(mg, 0);
|
||||
});
|
||||
|
||||
it("should call checkWinnerFFA in FFA mode", () => {
|
||||
const spy = jest.spyOn(winCheck as any, "checkWinnerFFA");
|
||||
const spy = vi.spyOn(winCheck as any, "checkWinnerFFA");
|
||||
winCheck.tick(10);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call checkWinnerTeam in non-FFA mode", () => {
|
||||
mg.config = jest.fn(() => ({
|
||||
gameConfig: jest.fn(() => ({
|
||||
mg.config = vi.fn(() => ({
|
||||
gameConfig: vi.fn(() => ({
|
||||
maxTimerValue: 5,
|
||||
gameMode: GameMode.Team,
|
||||
})),
|
||||
percentageTilesOwnedToWin: jest.fn(() => 50),
|
||||
percentageTilesOwnedToWin: vi.fn(() => 50),
|
||||
}));
|
||||
winCheck.init(mg, 0);
|
||||
const spy = jest.spyOn(winCheck as any, "checkWinnerTeam");
|
||||
const spy = vi.spyOn(winCheck as any, "checkWinnerTeam");
|
||||
winCheck.tick(10);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should set winner in FFA if percentage is reached", () => {
|
||||
const player = {
|
||||
numTilesOwned: jest.fn(() => 81),
|
||||
name: jest.fn(() => "P1"),
|
||||
numTilesOwned: vi.fn(() => 81),
|
||||
name: vi.fn(() => "P1"),
|
||||
};
|
||||
mg.players = jest.fn(() => [player]);
|
||||
mg.numLandTiles = jest.fn(() => 100);
|
||||
mg.numTilesWithFallout = jest.fn(() => 0);
|
||||
mg.players = vi.fn(() => [player]);
|
||||
mg.numLandTiles = vi.fn(() => 100);
|
||||
mg.numTilesWithFallout = vi.fn(() => 0);
|
||||
winCheck.checkWinnerFFA();
|
||||
expect(mg.setWinner).toHaveBeenCalledWith(player, expect.anything());
|
||||
});
|
||||
|
||||
it("should set winner in FFA if timer is 0", () => {
|
||||
const player = {
|
||||
numTilesOwned: jest.fn(() => 10),
|
||||
name: jest.fn(() => "P1"),
|
||||
numTilesOwned: vi.fn(() => 10),
|
||||
name: vi.fn(() => "P1"),
|
||||
};
|
||||
mg.players = jest.fn(() => [player]);
|
||||
mg.numLandTiles = jest.fn(() => 100);
|
||||
mg.numTilesWithFallout = jest.fn(() => 0);
|
||||
mg.stats = jest.fn(() => ({ stats: () => ({ mocked: true }) }));
|
||||
mg.players = vi.fn(() => [player]);
|
||||
mg.numLandTiles = vi.fn(() => 100);
|
||||
mg.numTilesWithFallout = vi.fn(() => 0);
|
||||
mg.stats = vi.fn(() => ({ stats: () => ({ mocked: true }) }));
|
||||
// Advance ticks until timeElapsed (in seconds) >= maxTimerValue * 60
|
||||
// timeElapsed = (ticks - numSpawnPhaseTurns) / 10 =>
|
||||
// ticks >= numSpawnPhaseTurns + maxTimerValue * 600
|
||||
@@ -73,7 +73,7 @@ describe("WinCheckExecution", () => {
|
||||
});
|
||||
|
||||
it("should not set winner if no players", () => {
|
||||
mg.players = jest.fn(() => []);
|
||||
mg.players = vi.fn(() => []);
|
||||
winCheck.checkWinnerFFA();
|
||||
expect(mg.setWinner).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import { vi, type Mocked } from "vitest";
|
||||
import { Cluster, TrainStation } from "../../../src/core/game/TrainStation";
|
||||
|
||||
const createMockStation = (id: string): jest.Mocked<TrainStation> => {
|
||||
const createMockStation = (id: string): Mocked<TrainStation> => {
|
||||
return {
|
||||
id,
|
||||
setCluster: jest.fn(),
|
||||
getCluster: jest.fn(() => null),
|
||||
setCluster: vi.fn(),
|
||||
getCluster: vi.fn(() => null),
|
||||
} as any;
|
||||
};
|
||||
|
||||
describe("Cluster tests", () => {
|
||||
let cluster: Cluster;
|
||||
let stationA: jest.Mocked<TrainStation>;
|
||||
let stationB: jest.Mocked<TrainStation>;
|
||||
let stationC: jest.Mocked<TrainStation>;
|
||||
let stationA: Mocked<TrainStation>;
|
||||
let stationB: Mocked<TrainStation>;
|
||||
let stationC: Mocked<TrainStation>;
|
||||
|
||||
beforeEach(() => {
|
||||
cluster = new Cluster();
|
||||
|
||||
@@ -67,7 +67,7 @@ describe("GameImpl", () => {
|
||||
});
|
||||
|
||||
test("Don't become traitor when betraying inactive player", async () => {
|
||||
jest.spyOn(attacker, "canSendAllianceRequest").mockReturnValue(true);
|
||||
vi.spyOn(attacker, "canSendAllianceRequest").mockReturnValue(true);
|
||||
game.addExecution(new AllianceRequestExecution(attacker, defender.id()));
|
||||
|
||||
game.executeNextTick();
|
||||
@@ -106,7 +106,7 @@ describe("GameImpl", () => {
|
||||
});
|
||||
|
||||
test("Do become traitor when betraying active player", async () => {
|
||||
jest.spyOn(attacker, "canSendAllianceRequest").mockReturnValue(true);
|
||||
vi.spyOn(attacker, "canSendAllianceRequest").mockReturnValue(true);
|
||||
game.addExecution(new AllianceRequestExecution(attacker, defender.id()));
|
||||
|
||||
game.executeNextTick();
|
||||
|
||||
@@ -13,15 +13,15 @@ const createMockStation = (unitId: number): any => {
|
||||
return {
|
||||
unit: {
|
||||
id: unitId,
|
||||
setTrainStation: jest.fn(),
|
||||
setTrainStation: vi.fn(),
|
||||
},
|
||||
tile: jest.fn(),
|
||||
neighbors: jest.fn(() => []),
|
||||
getCluster: jest.fn(() => cluster),
|
||||
setCluster: jest.fn(),
|
||||
addRailroad: jest.fn(),
|
||||
getRailroads: jest.fn(() => railroads),
|
||||
clearRailroads: jest.fn(),
|
||||
tile: vi.fn(),
|
||||
neighbors: vi.fn(() => []),
|
||||
getCluster: vi.fn(() => cluster),
|
||||
setCluster: vi.fn(),
|
||||
addRailroad: vi.fn(),
|
||||
getRailroads: vi.fn(() => railroads),
|
||||
clearRailroads: vi.fn(),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -54,18 +54,18 @@ describe("RailNetworkImpl", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
stationManager = {
|
||||
addStation: jest.fn(),
|
||||
removeStation: jest.fn(),
|
||||
findStation: jest.fn(),
|
||||
getAll: jest.fn(() => new Set()),
|
||||
addStation: vi.fn(),
|
||||
removeStation: vi.fn(),
|
||||
findStation: vi.fn(),
|
||||
getAll: vi.fn(() => new Set()),
|
||||
};
|
||||
pathService = {
|
||||
findTilePath: jest.fn(() => [0]),
|
||||
findStationsPath: jest.fn(() => [0]),
|
||||
findTilePath: vi.fn(() => [0]),
|
||||
findStationsPath: vi.fn(() => [0]),
|
||||
};
|
||||
game = {
|
||||
nearbyUnits: jest.fn(() => []),
|
||||
addExecution: jest.fn(),
|
||||
nearbyUnits: vi.fn(() => []),
|
||||
addExecution: vi.fn(),
|
||||
config: () => ({
|
||||
trainStationMaxRange: () => 80,
|
||||
trainStationMinRange: () => 10,
|
||||
@@ -86,7 +86,7 @@ describe("RailNetworkImpl", () => {
|
||||
network.connectStation(stationA);
|
||||
|
||||
const cluster = stationB.getCluster();
|
||||
cluster.addStation = jest.fn();
|
||||
cluster.addStation = vi.fn();
|
||||
expect(cluster.addStation).not.toHaveBeenCalled();
|
||||
|
||||
pathService.findTilePath.mockReturnValue(new Array(200));
|
||||
@@ -95,9 +95,9 @@ describe("RailNetworkImpl", () => {
|
||||
});
|
||||
|
||||
test("removeStation removes all neighbor links", () => {
|
||||
const neighbor = { removeNeighboringRails: jest.fn() };
|
||||
const neighbor = { removeNeighboringRails: vi.fn() };
|
||||
const station = createMockStation(1);
|
||||
station.neighbors = jest.fn(() => [neighbor]);
|
||||
station.neighbors = vi.fn(() => [neighbor]);
|
||||
stationManager.findStation.mockReturnValue(station);
|
||||
network.removeStation(station);
|
||||
expect(station.clearRailroads).toHaveBeenCalled();
|
||||
@@ -119,9 +119,9 @@ describe("RailNetworkImpl", () => {
|
||||
const cluster = new Cluster();
|
||||
const neighbor = createMockStation(1);
|
||||
const station = createMockStation(2);
|
||||
station.getCluster = jest.fn(() => cluster);
|
||||
station.neighbors = jest.fn(() => [neighbor]);
|
||||
cluster.removeStation = jest.fn();
|
||||
station.getCluster = vi.fn(() => cluster);
|
||||
station.neighbors = vi.fn(() => [neighbor]);
|
||||
cluster.removeStation = vi.fn();
|
||||
|
||||
stationManager.findStation.mockReturnValue(station);
|
||||
|
||||
@@ -150,8 +150,8 @@ describe("RailNetworkImpl", () => {
|
||||
const neighborStation = createMockStation(2);
|
||||
const cluster = new Cluster();
|
||||
cluster.addStation(neighborStation);
|
||||
neighborStation.getCluster = jest.fn(() => cluster);
|
||||
cluster.has = jest.fn(() => false);
|
||||
neighborStation.getCluster = vi.fn(() => cluster);
|
||||
cluster.has = vi.fn(() => false);
|
||||
|
||||
const neighborUnit = { unit: neighborStation.unit, distSquared: 20 };
|
||||
|
||||
|
||||
@@ -1,47 +1,48 @@
|
||||
import { vi, type Mocked } from "vitest";
|
||||
import { TrainExecution } from "../../../src/core/execution/TrainExecution";
|
||||
import { Game, Player, Unit, UnitType } from "../../../src/core/game/Game";
|
||||
import { Cluster, TrainStation } from "../../../src/core/game/TrainStation";
|
||||
|
||||
jest.mock("../../../src/core/game/Game");
|
||||
jest.mock("../../../src/core/execution/TrainExecution");
|
||||
jest.mock("../../../src/core/PseudoRandom");
|
||||
vi.mock("../../../src/core/game/Game");
|
||||
vi.mock("../../../src/core/execution/TrainExecution");
|
||||
vi.mock("../../../src/core/PseudoRandom");
|
||||
|
||||
describe("TrainStation", () => {
|
||||
let game: jest.Mocked<Game>;
|
||||
let unit: jest.Mocked<Unit>;
|
||||
let player: jest.Mocked<Player>;
|
||||
let trainExecution: jest.Mocked<TrainExecution>;
|
||||
let game: Mocked<Game>;
|
||||
let unit: Mocked<Unit>;
|
||||
let player: Mocked<Player>;
|
||||
let trainExecution: Mocked<TrainExecution>;
|
||||
|
||||
beforeEach(() => {
|
||||
game = {
|
||||
ticks: jest.fn().mockReturnValue(123),
|
||||
config: jest.fn().mockReturnValue({
|
||||
ticks: vi.fn().mockReturnValue(123),
|
||||
config: vi.fn().mockReturnValue({
|
||||
trainGold: (isFriendly: boolean) =>
|
||||
isFriendly ? BigInt(1000) : BigInt(500),
|
||||
}),
|
||||
addUpdate: jest.fn(),
|
||||
addExecution: jest.fn(),
|
||||
addUpdate: vi.fn(),
|
||||
addExecution: vi.fn(),
|
||||
} as any;
|
||||
|
||||
player = {
|
||||
addGold: jest.fn(),
|
||||
addGold: vi.fn(),
|
||||
id: 1,
|
||||
canTrade: jest.fn().mockReturnValue(true),
|
||||
isFriendly: jest.fn().mockReturnValue(false),
|
||||
canTrade: vi.fn().mockReturnValue(true),
|
||||
isFriendly: vi.fn().mockReturnValue(false),
|
||||
} as any;
|
||||
|
||||
unit = {
|
||||
owner: jest.fn().mockReturnValue(player),
|
||||
level: jest.fn().mockReturnValue(1),
|
||||
tile: jest.fn().mockReturnValue({ x: 0, y: 0 }),
|
||||
type: jest.fn(),
|
||||
isActive: jest.fn().mockReturnValue(true),
|
||||
owner: vi.fn().mockReturnValue(player),
|
||||
level: vi.fn().mockReturnValue(1),
|
||||
tile: vi.fn().mockReturnValue({ x: 0, y: 0 }),
|
||||
type: vi.fn(),
|
||||
isActive: vi.fn().mockReturnValue(true),
|
||||
} as any;
|
||||
|
||||
trainExecution = {
|
||||
loadCargo: jest.fn(),
|
||||
owner: jest.fn().mockReturnValue(player),
|
||||
level: jest.fn(),
|
||||
loadCargo: vi.fn(),
|
||||
owner: vi.fn().mockReturnValue(player),
|
||||
level: vi.fn(),
|
||||
} as any;
|
||||
});
|
||||
|
||||
@@ -70,7 +71,7 @@ describe("TrainStation", () => {
|
||||
|
||||
it("checks trade availability (same owner)", () => {
|
||||
const otherUnit = {
|
||||
owner: jest.fn().mockReturnValue(unit.owner()),
|
||||
owner: vi.fn().mockReturnValue(unit.owner()),
|
||||
} as any;
|
||||
|
||||
const station = new TrainStation(game, unit);
|
||||
|
||||
Vendored
-34
@@ -1,34 +0,0 @@
|
||||
declare module "*.png" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
declare module "*.jpg" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module "*.webp" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module "*.jpeg" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
declare module "*.svg" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
declare module "*.bin" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
declare module "*.txt" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
declare module "*.html" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
import { vi } from "vitest";
|
||||
|
||||
// Mock BuildMenu to avoid importing lit and other ESM-heavy deps in this unit test
|
||||
jest.mock(
|
||||
"../src/client/graphics/layers/BuildMenu",
|
||||
() => ({
|
||||
BuildMenu: class {},
|
||||
flattenedBuildTable: [],
|
||||
}),
|
||||
{ virtual: true },
|
||||
);
|
||||
vi.mock("../src/client/graphics/layers/BuildMenu", () => ({
|
||||
BuildMenu: class {},
|
||||
flattenedBuildTable: [],
|
||||
}));
|
||||
|
||||
// Mock Utils to avoid touching DOM (document) during tests
|
||||
jest.mock("../src/client/Utils", () => ({
|
||||
vi.mock("../src/client/Utils", () => ({
|
||||
translateText: (k: string) => k,
|
||||
getSvgAspectRatio: async () => 1,
|
||||
}));
|
||||
@@ -57,20 +55,20 @@ const makeParams = (opts?: Partial<MenuElementParams>): MenuElementParams => {
|
||||
} as any,
|
||||
emojiTable: {} as any,
|
||||
playerActionHandler: {
|
||||
handleBreakAlliance: jest.fn(),
|
||||
handleEmbargo: jest.fn(),
|
||||
handleDonateGold: jest.fn(),
|
||||
handleDonateTroops: jest.fn(),
|
||||
handleTargetPlayer: jest.fn(),
|
||||
handleBreakAlliance: vi.fn(),
|
||||
handleEmbargo: vi.fn(),
|
||||
handleDonateGold: vi.fn(),
|
||||
handleDonateTroops: vi.fn(),
|
||||
handleTargetPlayer: vi.fn(),
|
||||
} as any,
|
||||
playerPanel: {
|
||||
show: jest.fn(),
|
||||
show: vi.fn(),
|
||||
} as any,
|
||||
chatIntegration: {
|
||||
createQuickChatMenu: jest.fn(() => []),
|
||||
createQuickChatMenu: vi.fn(() => []),
|
||||
} as any,
|
||||
eventBus: {} as any,
|
||||
closeMenu: jest.fn(),
|
||||
closeMenu: vi.fn(),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
// Add global mocks or configuration here if needed
|
||||
Reference in New Issue
Block a user