From 66ca10bab842d0a3c75a4f6cda9c4ae4849dbc0f Mon Sep 17 00:00:00 2001 From: Marc Emmanuel Date: Thu, 29 Jan 2026 08:26:53 +0100 Subject: [PATCH] fix: update port type from string to number and add tests for inland burgs --- src/modules/burgs-generator.ts | 12 ++-- tests/e2e/burgs.spec.ts | 109 +++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 tests/e2e/burgs.spec.ts diff --git a/src/modules/burgs-generator.ts b/src/modules/burgs-generator.ts index 2983c30d..ca18a539 100644 --- a/src/modules/burgs-generator.ts +++ b/src/modules/burgs-generator.ts @@ -15,7 +15,7 @@ export interface Burg { feature?: number; capital?: number; lock?: boolean; - port?: string; + port?: number; removed?: boolean; population?: number; type?: string; @@ -81,7 +81,7 @@ class BurgModule { Object.entries(featurePortCandidates).forEach(([featureId, burgs]) => { if (burgs.length < 2) return; // only one port on water body - skip burgs.forEach((burg) => { - burg.port = featureId; + burg.port = Number(featureId); const haven = cells.haven[burg.cell]; const [x, y] = getCloseToEdgePoint(burg.cell, haven); burg.x = x; @@ -237,7 +237,7 @@ class BurgModule { } } - getType(cellId: number, port: string) { + getType(cellId: number, port?: number) { const { cells, features } = pack; if (port) return "Naval"; @@ -272,7 +272,7 @@ class BurgModule { } private defineEmblem(burg: Burg) { - burg.type = this.getType(burg.cell, burg.port as string); + burg.type = this.getType(burg.cell, burg.port); const state = pack.states[burg.state as number]; const stateCOA = state.coa; @@ -485,7 +485,7 @@ class BurgModule { const population = rn(burgPopulation! * populationRate * urbanization); const river = cells.r[cell] ? 1 : 0; - const coast = Number(parseInt(burg.port as string, 10) > 0); + const coast = Number((burg.port || 0) > 0); const sea = (() => { if (!coast || !cells.haven[cell]) return null; @@ -672,7 +672,7 @@ class BurgModule { name, feature, capital: 0, - port: "0", + port: 0, }; this.definePopulation(burg); this.defineEmblem(burg); diff --git a/tests/e2e/burgs.spec.ts b/tests/e2e/burgs.spec.ts new file mode 100644 index 00000000..f78bc38f --- /dev/null +++ b/tests/e2e/burgs.spec.ts @@ -0,0 +1,109 @@ +import { test, expect } from "@playwright/test"; + +test.describe("Burgs.add", () => { + test.beforeEach(async ({ context, page }) => { + await context.clearCookies(); + + await page.goto("/"); + await page.evaluate(() => { + localStorage.clear(); + sessionStorage.clear(); + }); + + // Navigate with seed parameter and wait for full load + await page.goto("/?seed=test-burgs&width=1280&height=720"); + + // Wait for map generation to complete + await page.waitForFunction( + () => (window as any).mapId !== undefined, + { timeout: 60000 } + ); + + // Additional wait for any rendering/animations to settle + await page.waitForTimeout(500); + }); + + test("should create burg with falsy port value when not on coast", async ({ + page, + }) => { + const result = await page.evaluate(() => { + const { cells, burgs } = (window as any).pack; + + // Find a land cell that is not on the coast (no harbor) + let inlandCellId: number | null = null; + for (let i = 1; i < cells.i.length; i++) { + const isLand = cells.h[i] >= 20; + const hasNoHarbor = !cells.harbor[i]; + const hasNoBurg = !cells.burg[i]; + if (isLand && hasNoHarbor && hasNoBurg) { + inlandCellId = i; + break; + } + } + + if (!inlandCellId) { + return { error: "No inland cell found" }; + } + + // Get coordinates for the inland cell + const [x, y] = cells.p[inlandCellId]; + + // Add a new burg at this inland location + const Burgs = (window as any).Burgs; + const burgId = Burgs.add([x, y]); + const burg = burgs[burgId]; + + return { + burgId, + port: burg.port, + portType: typeof burg.port, + portIsFalsy: !burg.port, + x: burg.x, + y: burg.y, + }; + }); + + expect(result.error).toBeUndefined(); + // Port should be 0 (number), not "0" (string) + expect(result.port).toBe(0); + expect(result.portType).toBe("number"); + expect(result.portIsFalsy).toBe(true); + // Explicitly verify it's not the buggy string "0" + expect(result.port).not.toBe("0"); + }); + + test("port toggle button should be inactive for non-coastal burg", async ({ + page, + }) => { + // Add a burg on an inland cell + const burgId = await page.evaluate(() => { + const { cells } = (window as any).pack; + + // Find a land cell that is not on the coast + for (let i = 1; i < cells.i.length; i++) { + const isLand = cells.h[i] >= 20; + const hasNoHarbor = !cells.harbor[i]; + const hasNoBurg = !cells.burg[i]; + if (isLand && hasNoHarbor && hasNoBurg) { + const [x, y] = cells.p[i]; + return (window as any).Burgs.add([x, y]); + } + } + return null; + }); + + expect(burgId).not.toBeNull(); + + // Open the burg editor + await page.evaluate((id: number) => { + (window as any).editBurg(id); + }, burgId!); + + // Wait for the editor dialog to appear + await page.waitForSelector("#burgEditor", { state: "visible" }); + + // The port toggle button should have the "inactive" class + const portButton = page.locator("#burgPort"); + await expect(portButton).toHaveClass(/inactive/); + }); +});