fix(ui-calculator): keep calculator state long-lived; don't eject on planet click
Tests · UI / test (push) Successful in 1m59s

Move the calculator's inputs into a page-level calculatorState singleton so they survive the sidebar unmounting the tab on a tab switch (the inspector auto-opens on a planet click). ensureGame resets the design when the active game changes.

While on the calculator, a planet click no longer switches to the inspector — the calculator consumes the selection in its planet area / reach circles. Halve the reach-circle stroke width.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-21 20:29:08 +02:00
parent 9ae7b88b89
commit 3ea29cf8b5
6 changed files with 264 additions and 109 deletions
+8 -1
View File
@@ -7,10 +7,15 @@
import "@testing-library/jest-dom/vitest";
import "fake-indexeddb/auto";
import { fireEvent, render } from "@testing-library/svelte";
import { afterEach, beforeEach, describe, expect, test } from "vitest";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
// The calculator reads `page.params.id` to scope its long-lived state to
// the active game; stub a stable id so the component test has a router.
vi.mock("$app/state", () => ({ page: { params: { id: "calc-test-game" } } }));
import { i18n } from "../src/lib/i18n/index.svelte";
import CalculatorTab from "../src/lib/sidebar/calculator-tab.svelte";
import { calculatorState } from "../src/lib/calculator/calc-state.svelte";
import { CORE_CONTEXT_KEY, CoreHolder } from "../src/lib/core-context.svelte";
import {
ORDER_DRAFT_CONTEXT_KEY,
@@ -106,6 +111,8 @@ beforeEach(async () => {
draft = new OrderDraftStore();
await draft.init({ cache: new IDBCache(db), gameId: GAME_ID });
i18n.resetForTests("en");
// The calculator state is a module singleton shared across cases.
calculatorState.reset();
});
afterEach(async () => {
@@ -278,3 +278,39 @@ test("calculator draws reach circles for the selected planet", async ({
await calc.getByTestId("calculator-mode-modernization").click();
await expect.poll(() => countReachCircles(page)).toBe(0);
});
test("calculator stays put on a planet click and keeps state across tab switches", async ({
page,
}, testInfo) => {
test.skip(
testInfo.project.name.startsWith("chromium-mobile"),
"calculator is a desktop-sidebar flow",
);
await setupShell(page);
// Open the calculator and enter a design.
await page.getByTestId("sidebar-tab-calculator").click();
await page.getByTestId("calculator-block-drive").fill("10");
// Clicking a planet must NOT eject us to the inspector; it feeds the
// calculator's planet area instead, and the design is untouched.
await clickCanvasCentre(page);
await expect(page.getByTestId("sidebar")).toHaveAttribute(
"data-active-tab",
"calculator",
);
await expect(page.getByTestId("calculator-planet-name")).toContainText(
"Galactica",
);
await expect(page.getByTestId("calculator-block-drive")).toHaveValue("10");
// Switching to the inspector and back keeps the design (long-lived
// tool state survives the tab unmount/remount).
await page.getByTestId("sidebar-tab-inspector").click();
await expect(page.getByTestId("sidebar")).toHaveAttribute(
"data-active-tab",
"inspector",
);
await page.getByTestId("sidebar-tab-calculator").click();
await expect(page.getByTestId("calculator-block-drive")).toHaveValue("10");
});