334e218c7b
In the TUI, EditOrDrill hands an aggregated cell to DrillIntoCell, so `i`
on an aggregate is drill by another door. The help page called it only
"Edit current cell", and the browser refused it in words unrelated to `>`'s,
so a user could not tell the two were one missing feature.
- help.rs: the edit-or-drill row says it drills into an aggregate.
- help.rs: Normal-mode Enter was captioned "Edit current cell (same as i)"
but is bound to enter-advance alone, which only moves down; the row moves
to Cursor movement and says so.
- resolve.rs: the Aggregate arm now reads "an aggregate is edited by
drilling in — " + not_yet("drill"), the same sentence `>` uses.
- context/code/clients.md and the evidence entry reverse the recorded
"different sentences on purpose" rationale, which was false about the TUI.
- harness/tests/drill.spec.js follows the new wording.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
80 lines
3.6 KiB
JavaScript
80 lines
3.6 KiB
JavaScript
// Drill in the browser: what it does today, which is refuse. improvise-gd28
|
|
// says why, and context/test-evidence/clients.md records the layer it stops at.
|
|
|
|
import { test, expect } from "@playwright/test";
|
|
|
|
/// `web/demo.improv` has NO aggregate cell by construction — gotcha 46 puts
|
|
/// exactly one category on each visible axis so every cell is a Record, and
|
|
/// `tests/web_demo_model.rs` asserts it. So a drill test must MAKE one first.
|
|
async function anAggregateGrid(page) {
|
|
await page.goto("/app/index.html");
|
|
await expect(page.locator("#grid table")).toBeVisible({ timeout: 20_000 });
|
|
await page.locator("#grid").focus();
|
|
await expect(page.locator("#grid td.editable").first()).toBeVisible();
|
|
|
|
// Quarter is on Page; one cycle takes it to None, so every cell aggregates
|
|
// over the four quarters. The tile bar is how a user would do it.
|
|
await page.keyboard.press("Shift+T");
|
|
const tiles = page.locator("#tiles .tile");
|
|
const quarter = tiles.filter({ hasText: "Quarter" });
|
|
await expect(quarter).toHaveText("Quarter Page");
|
|
const names = await tiles.allTextContents();
|
|
for (let i = 0; i < names.findIndex((t) => t.startsWith("Quarter")); i++) {
|
|
await page.keyboard.press("ArrowRight");
|
|
}
|
|
await expect(quarter).toHaveClass(/selected/);
|
|
await page.keyboard.press("Enter");
|
|
await expect(quarter).toHaveText("Quarter None", { timeout: 10_000 });
|
|
await page.keyboard.press("Escape");
|
|
|
|
// The precondition, asserted rather than assumed: nothing is editable now,
|
|
// which is `CellId::Aggregate` reaching `render.rs::editable` (ADR 002).
|
|
await expect(page.locator("#grid td.editable")).toHaveCount(0);
|
|
await expect(page.locator("#grid tbody td").first()).toBeVisible();
|
|
}
|
|
|
|
test.describe("drill is refused in the browser, not broken", () => {
|
|
// The honest half: `i`/`a` on an aggregate declines OUT LOUD, because
|
|
// `edit_or_drill` answers the `CellId::Aggregate` arm with a status.
|
|
test("editing an aggregate says it is edited by drilling, and drill is missing", async ({
|
|
page,
|
|
}) => {
|
|
await anAggregateGrid(page);
|
|
|
|
await page.keyboard.press("i");
|
|
await expect(page.locator("#toast")).toContainText(
|
|
"an aggregate is edited by drilling in — drill is not available in the browser yet",
|
|
);
|
|
// And it really is a refusal: no editor opened, no mode change.
|
|
await expect(page.locator("#mode")).toHaveText("NORMAL");
|
|
await expect(page.locator("#grid input")).toHaveCount(0);
|
|
});
|
|
|
|
// `>` is the key the hint line advertises as ":drill", and it used to be a
|
|
// name `resolve::step` did not handle — so `KeyOutcome::Upstream` ->
|
|
// `ClientFrame::Key` -> `Host::handle`'s empty vec, a black hole rather than
|
|
// a slow path (gotcha 47). It now answers. Interim until improvise-gd28.
|
|
test("the drill key says drill is unavailable, not something about aggregates", async ({
|
|
page,
|
|
}) => {
|
|
await anAggregateGrid(page);
|
|
|
|
await page.keyboard.press(">");
|
|
await expect(page.locator("#toast")).toContainText(
|
|
"drill is not available in the browser yet",
|
|
);
|
|
await expect(page.locator("#mode")).toHaveText("NORMAL");
|
|
|
|
// `>` is refused whatever the cell is, so it must not blame the cell.
|
|
await expect(page.locator("#toast")).not.toContainText("aggregate");
|
|
|
|
// `i` reaches the SAME missing feature (in the TUI it drills), so it names
|
|
// it the same way and adds only why — improvise-s8h7, clients.md.
|
|
await page.keyboard.press("i");
|
|
await expect(page.locator("#toast")).toContainText("an aggregate is edited by drilling in");
|
|
await expect(page.locator("#toast")).toContainText(
|
|
"drill is not available in the browser yet",
|
|
);
|
|
});
|
|
});
|