Popup follow-ups: teardown safety, entry pacing, sleep lint - #37
Open
mmkal wants to merge 6 commits into
Open
Conversation
Cursor bugbot caught that a throwing child asyncDispose (e.g. a popup screencast copy failure) aborted the parent's afterTest/afterTestFinalize, dropping the main page's video artifacts. Child wrap and dispose failures are now collected and rethrown only after the parent's own teardown runs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
commit: |
Removing the demo's waitForTimeout calls (antithetical to this repo's goal) broke the render: instant flows act before the popup screencast's first captured frame, so synthetic fill annotations floated over a popup that wasn't visible yet, and action holds froze successive mid-slide frames - replaying the enter animation in slow motion. Three-part fix, all library-side: - Entry pacing: the child recorder holds the popup's first action until the popup fires load and the enter animation window (~450ms) has real footage. Video mode already paces deliberately at close (recorder settling); this is the entry-side counterpart. Real auth popups load slower than this, so it usually costs nothing. - Dead air recorded during an animation window is carved out before segment planning, so compression can't fast-forward a slide. - Render-time backstop: a projected child highlight starting mid-slide defers past the enter window, so holds can't freeze mid-slide frames even when pacing was bypassed. The demo and overlay specs now run with zero waitForTimeout calls. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
page.waitForTimeout joins the require-timeout-comment rule: a sleep waits whether or not the app is ready, so it needs the same nearby justification comment as an explicit timeout. New allowSleeps option exempts the video-mode footage specs via .oxlintrc overrides - there the sleeps ARE the test input (they shape the recorded timeline under test) and annotating every one would be noise. The timeout-option check stays active in those files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The fixture config pointed at the package's ./lint-plugin export, which resolves to dist - so rule changes silently no-oped in the spec until a manual pnpm build. Point it at lint-plugin.local.js through the node_modules symlink instead (a path bypasses the exports map): the plugin loads from ./src via tsx exactly like the repo's own config. Verified by running the spec with dist renamed away. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The popup screencast emits frames only on change, so the fill reveal's frozen composite base could lag the logical state: the password fill's base frame usually predated any captured frame containing the username value, blanking 'mmkal' for the password reveal's whole hold before live footage brought it back. The pre-action screenshot has the exact right state (earlier values present, this field empty), so it now covers the whole overlay box on the frozen base; footage supplies only the backdrop dim and the page behind. The ring and typed-reveal overlays sit on top as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-ups to the popup overlay feature (#36), bundled per review:
1. Popup teardown can't drop the main page's video
A throwing popup dispose (e.g. a screencast copy failure) aborted the parent's finalize, silently losing the main page's artifacts (cursor bugbot's catch on #36 — the fix landed on that branch minutes after the squash-merge snapshot, so it missed main).
2. Consumers never need
waitForTimeoutfor popup videosDeleting the demo's
waitForTimeoutcalls broke the render — instant flows act before the popup screencast's first captured frame (annotations floating over a not-yet-visible popup), and action holds froze successive mid-slide frames, replaying the enter animation in slow motion. Now videoMode paces itself: the popup's first action holds until the popup has loaded and the enter animation window has real footage (~450ms ceiling; real auth popups load slower than that anyway). Animation windows are also protected from dead-air compression, and a render-time backstop defers any highlight that still lands mid-slide. The demo and overlay specs run with zerowaitForTimeoutcalls.3.
page.waitForTimeoutjoins the timeout lintA sleep waits whether or not the app is ready, so it now needs the same nearby justification comment as an explicit timeout:
The video-mode footage specs are exempted via a new
allowSleepsoption in.oxlintrc.jsonoverrides — there the sleeps are the test input shaping the recorded timeline — while the timeout-option check stays active in them.Latest main merged in.
Before / after
All three from the same demo spec (
spec/popup-overlay-demo.spec.ts).a) Before — on main, with the spec's
waitForTimeoutcalls papering over the flaw:a-before-with-timeouts.mp4
b) On main with the timeouts removed — input fields float over a popup that isn't visible yet, and the enter animation plays in slow motion (holds freezing successive mid-slide frames):
b-timeouts-removed.mp4
c) This PR, no timeouts anywhere — videoMode paces the popup entry itself:
c-with-fixes-v2.mp4
🤖 Generated with Claude Code
Session:
b7f6f792-6606-44be-9ec3-207eb762c4b6Note
Medium Risk
Changes affect plugin teardown ordering, video render timing/compositing, and lint rules across specs—high user-visible impact but covered by new tests and targeted overrides.
Overview
Follow-ups to popup overlay video: parent teardown no longer depends on popup dispose succeeding, videoMode paces popup entry without spec
waitForTimeout, andwaitForTimeoutis linted like explicit timeouts with footage-spec exemptions.Teardown:
addPluginsasync dispose now collects failures from rejected child wraps and from throwing childasyncDispose, still runs the parent’safterTest/afterTestFinalize, then rethrows the first child failure. A new popup spec asserts the parent finalizer runs when popup teardown throws.Popup video pacing: The first action on a popup waits for
load(bounded timeout) and until ~450ms after open so screencast footage covers the enter animation. Render path addssubtractVideoSpansso dead-air compression cannot eat enter/exit windows, defers highlights that still start mid-slide, and improves overlay fill-reveal compositing when sparse child frames lag state.Lint & specs:
middlewright/require-timeout-commentreports barewaitForTimeoutunless a justified comment is nearby;allowSleeps: truein.oxlintrc.jsonoverrides for video-mode footage specs. Demo/popup specs drop manual pacing sleeps;debug-modeadds a comment for an intentional sleep.Reviewed by Cursor Bugbot for commit 6776d21. Bugbot is set up for automated code reviews on this repo. Configure here.