feat(sim): wheel + label-tap auto-scrub then lock; retire discrete advance()

Per plan Task 4. onWheel + jumpToScale now animate pos via autoScrub() (drives the
same setPos scrub path, ~600ms, lands exactly on the integer + locks). Removes the
now-dead advance()/playTransition()/FAST_BLEND_RATE (the server /api/ring/advance
round-trip is no longer used by the client). Post-landing morph warm-up folded into
setPos's settle branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BenStullsBets
2026-06-27 15:45:37 -07:00
parent 20f49e936a
commit 8458ab59eb
2 changed files with 34 additions and 92 deletions
+11
View File
@@ -66,6 +66,17 @@ test("dragging the dial scrubs morph currentTime and audio gains", async ({ page
await page.mouse.up();
});
test("wheel auto-scrubs one altitude and locks", async ({ page }) => {
await boot(page);
const start = (await page.locator("#scale-name").textContent())!;
await wheelOnStage(page, 60); // wheel down = descend one altitude
await page.waitForFunction((s) => document.querySelector("#scale-name")?.textContent !== s, start, { timeout: 20000 });
const landed = (await page.locator("#scale-name").textContent())!;
expect(landed).toContain("orbit");
await page.waitForTimeout(1500);
expect(await page.locator("#scale-name").textContent()).toBe(landed); // locked
});
test("zoom in plays the matching morph, lands locked, and stays put while parked", async ({ page }) => {
await boot(page);
const start = (await page.locator("#scale-name").textContent())!;