Skip to content

Commit 97e88cc

Browse files
committed
fix(block): keep rows stable when favoriting fuel
1 parent 3b299d0 commit 97e88cc

2 files changed

Lines changed: 66 additions & 4 deletions

File tree

app/e2e/mut/count-pin.e2e.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,69 @@ test("an infeasible block keeps its burner row editable", async ({ page }) => {
8989
}
9090
});
9191

92+
test("favoriting a fuel keeps the burner rows on the current solve", async ({ page }) => {
93+
const db = new DatabaseSync(activeProjectDbFile());
94+
db.exec("PRAGMA busy_timeout = 5000");
95+
const favoriteFuels = db
96+
.prepare("SELECT value FROM meta WHERE key = 'favorite_fuels'")
97+
.get() as { value: string } | undefined;
98+
const data = {
99+
recipes: ["boil-steam-250"],
100+
made: ["steam"],
101+
machines: { "boil-steam-250": "boiler" },
102+
fuels: { "boil-steam-250": "coal" },
103+
goals: [{ name: "steam", rate: 1 }],
104+
};
105+
const inserted = db
106+
.prepare("INSERT INTO blocks (name, data) VALUES (?, ?)")
107+
.run(uniqueName("Favorite fuel"), JSON.stringify(data));
108+
const id = Number(inserted.lastInsertRowid);
109+
db.close();
110+
111+
try {
112+
await goto(page, `/block/${id}`);
113+
const row = page.locator('[data-recipe-row="boil-steam-250"]');
114+
115+
// Make a post-load editor change. The solve query's initial loader still
116+
// holds the original coal document, while the live saved solve now uses raw
117+
// coal — invalidating that query would put the row back on stale data.
118+
await row.getByTitle(/Coal .* click to change fuel/).click();
119+
let fuels = page.getByRole("dialog", { name: "Fuel for Boil Steam (250°)" });
120+
await fuels.getByRole("button", { name: /^Raw coal/ }).click();
121+
await expect(fuels).toBeHidden();
122+
await expect(row.getByTitle(/Raw coal .* click to change fuel/)).toBeVisible();
123+
124+
await row.getByTitle(/Raw coal .* click to change fuel/).click();
125+
fuels = page.getByRole("dialog", { name: "Fuel for Boil Steam (250°)" });
126+
const rawCoal = fuels.getByRole("button", { name: /^Raw coal/ });
127+
const star = rawCoal.locator('[title*="favorite fuel" i]');
128+
const previousTitle = await star.getAttribute("title");
129+
await star.click();
130+
await expect(star).not.toHaveAttribute("title", previousTitle!);
131+
132+
// Let any invalidated background query settle: the favorite is an app-level
133+
// default for future rows and must not replace this editor's live solve.
134+
await page.waitForTimeout(750);
135+
await expect(row.getByTitle(/Raw coal .* click to change fuel/)).toBeVisible();
136+
} finally {
137+
const cleanup = new DatabaseSync(activeProjectDbFile());
138+
try {
139+
cleanup.exec("PRAGMA busy_timeout = 5000");
140+
if (favoriteFuels)
141+
cleanup
142+
.prepare(
143+
`INSERT INTO meta (key, value) VALUES ('favorite_fuels', ?)
144+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
145+
)
146+
.run(favoriteFuels.value);
147+
else cleanup.prepare("DELETE FROM meta WHERE key = 'favorite_fuels'").run();
148+
cleanup.prepare("DELETE FROM blocks WHERE id = ?").run(id);
149+
} finally {
150+
cleanup.close();
151+
}
152+
}
153+
});
154+
92155
test("variable generator shows its average and min-max output", async ({ page }) => {
93156
const db = new DatabaseSync(activeProjectDbFile());
94157
db.exec("PRAGMA busy_timeout = 5000");

app/src/components/block/fuel-picker-dialog.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import { Skeleton } from "#/components/ui/skeleton.tsx";
1010

1111
/** Fuel picker — choose what a SOLID burner burns (energy value shown to
1212
* compare), with the favorite star (#18). Favorites are app-level prefs;
13-
* toggling one refetches the solve so its ☆ updates without touching the
14-
* block's picks. Fluid burners never open this: unfiltered ones draw from the
15-
* shared fluid-fuel pool and filtered ones are pinned to one fluid (#25). */
13+
* toggling one refetches the picker so its ☆ updates without touching the block's
14+
* picks or solve. Fluid burners never open this: unfiltered ones draw from the shared
15+
* fluid-fuel pool and filtered ones are pinned to one fluid (#25). */
1616
export function FuelPickerDialog({
1717
recipe,
1818
recipeDisplay,
@@ -38,7 +38,6 @@ export function FuelPickerDialog({
3838
const toggleFavorite = (fuel: string, isFav: boolean) => {
3939
void setFavoriteFuelFn({ data: { fuel, clear: isFav } }).then(() => {
4040
void qc.invalidateQueries({ queryKey: ["fuelOptions"] });
41-
void qc.invalidateQueries({ queryKey: ["solve"] });
4241
});
4342
};
4443
return (

0 commit comments

Comments
 (0)