Skip to content

Replace a 250ms sleep in the work-line test with a real control - #44

Merged
max-sixty merged 4 commits into
mainfrom
fix/work-line-absence-control
Aug 26, 2026
Merged

max-sixty merged 4 commits into
mainfrom
fix/work-line-absence-control

Conversation

@leaf-agent

Copy link
Copy Markdown
Collaborator

test_local_work_chrome_does_not_take_its_holder_gesture asserted an absence — no action in the log after clicking the work line — behind page.wait_for_timeout(250) and with no control. tests/CLAUDE.md names both halves of that: a wait consumes a fact the system states, and "an absence is also what a page that never had the behaviour produces, so a test asserting one names a control that must first produce the presence: the same gesture where it is supposed to work."

The fix keeps the forbidden gesture, then presses a neighbouring option as that control and lets its send settle through round_trip. One outbox in gesture order means a pick the work line had taken would already stand ahead of it, so the whole log is read once and compared exactly — no budget, and the verdict now rests on a product fact.

Bug-back, both directions

The reading this guards is the .lf-work-line entry in worksInside (leaf.js:842).

The new test still catches the real defect. Dropping ".lf-work-line" from that selector list makes the work line cast its holder's pick, and the new assertion fails on it:

At index 0 diff: ('jobs', {'options': ['job-mounts']}) != ('jobs', {'options': ['job-heater']})

The old test went green over a dead gesture. With lf-options' click handler disabled outright — no option pickable anywhere on the page — the old form passed (1 passed), because nothing was left that could have written an action. The new form fails there, as a test with a control should: the control is not met.

Worth being precise about what was not wrong: on this machine the 250 ms budget was not itself load-bearing. With the work-line defect injected, the old test failed even at wait_for_timeout(0) — the POST goes out inside the click and the server is in-process. The sleep is a convention violation and a standing hazard rather than the thing that hid a bug; the missing control is what made the test vacuous.

Verification
  • uv run pytest tests/test_render_options.py -q --run-nightly — 46 passed
  • uv run pytest tests -q — 549 passed, 6 skipped
  • ruff format --diff / ruff check — clean

@leaf-agent leaf-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The control is the right shape and the bug-back in the description checks out — #answer() is reachable only from this.#done.onclick (lf-options.js:242), so the group sends nothing but the one choose in this flow, and jobs being choose multiple keeps the #job-mounts chosen assertion load-bearing rather than letting the heater pick clear it.

One narrowing came along with the rewrite that the fix doesn't need — noted inline.

Comment thread tests/test_render_options.py Outdated
@leaf-agent leaf-agent changed the title Give the work-line absence a control rather than a 250ms budget Replace a 250ms sleep in the work-line test with a real control Aug 26, 2026
@max-sixty
max-sixty merged commit 7037743 into main Aug 26, 2026
4 checks passed
@max-sixty
max-sixty deleted the fix/work-line-absence-control branch August 26, 2026 23:45
max-sixty added a commit that referenced this pull request Aug 27, 2026
`test_local_work_chrome_does_not_take_its_holder_gesture` asserted an
absence — no `action` in the log after clicking the work line — behind
`page.wait_for_timeout(250)` and with no control. `tests/CLAUDE.md`
names both halves of that: a wait consumes a fact the system states, and
"an absence is also what a page that never had the behaviour produces,
so a test asserting one names a control that must first produce the
presence: the same gesture where it is supposed to work."

The fix keeps the forbidden gesture, then presses a neighbouring option
as that control and lets its send settle through `round_trip`. One
outbox in gesture order means a pick the work line had taken would
already stand ahead of it, so the whole log is read once and compared
exactly — no budget, and the verdict now rests on a product fact.

<details><summary>Bug-back, both directions</summary>

The reading this guards is the `.lf-work-line` entry in `worksInside`
([leaf.js:842](https://github.com/max-sixty/leaf/blob/27631a26/plugins/leaf/skills/leaf/assets/leaf.js#L842)).

**The new test still catches the real defect.** Dropping
`".lf-work-line"` from that selector list makes the work line cast its
holder's pick, and the new assertion fails on it:

```
At index 0 diff: ('jobs', {'options': ['job-mounts']}) != ('jobs', {'options': ['job-heater']})
```

**The old test went green over a dead gesture.** With `lf-options`'
click handler disabled outright — no option pickable anywhere on the
page — the old form passed (`1 passed`), because nothing was left that
could have written an `action`. The new form fails there, as a test with
a control should: the control is not met.

Worth being precise about what was *not* wrong: on this machine the 250
ms budget was not itself load-bearing. With the work-line defect
injected, the old test failed even at `wait_for_timeout(0)` — the POST
goes out inside the click and the server is in-process. The sleep is a
convention violation and a standing hazard rather than the thing that
hid a bug; the missing control is what made the test vacuous.

</details>

<details><summary>Verification</summary>

- `uv run pytest tests/test_render_options.py -q --run-nightly` — 46
passed
- `uv run pytest tests -q` — 549 passed, 6 skipped
- `ruff format --diff` / `ruff check` — clean

</details>

---------

Co-authored-by: leaf-agent <318509791+leaf-agent@users.noreply.github.com>
Co-authored-by: Maximilian Roos <m@maxroos.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants