test(patterns): bounded-latency E2E for client targeted DOM mutation (livetemplate/client#108)#86
Conversation
…(#107) Adds two chromedp subtests for livetemplate/client#107: 1. TestLargeTable/Delete_Bounded_Client_Latency — runs at the existing N=200 CI scale with a 500ms ceiling. Catches catastrophic regressions where the targeted-apply path falls back to full deepClone + reconstructFromTree + morphdom-over-whole-range. 2. TestLargeTable_DeleteLatency_10k — stress test at the demo's default 10,000-row scale with a 3500ms ceiling. The pre-fix path took 6-8s in Chrome desktop; the post-fix targeted-apply path bypasses the 5MB HTML reconstruction + morphdom diff over 10k rows. Skipped under -short. Requires @livetemplate/client@0.8.39+ (post per-op DOM mutation merge). Cross-repo CI builds the client and runs against this test suite. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code ReviewOverviewThis PR adds two chromedp subtests to verify the client-side targeted DOM mutation path introduced in Bugs / Correctness Issues1. Docstring ceiling (3500 ms) doesn't match the constant (2500 ms) In // The 3500 ms ceiling is intentionally generous ...
const ceilingMs = 2500The comment says 3500 ms but 2. Comment references // Verifies the client#107 targeted-apply path actually fires forThe PR summary and all other references say Test Robustness Issues3. No graceful handling when the observability hook is absent Both tests read A safer guard: var hookExists bool
chromedp.Evaluate(`typeof window.__lvtTargetedHits !== "undefined"`, &hookExists),
// ...
if !hookExists {
t.Skip("window.__lvtTargetedHits not present — client < 0.8.39, skipping targeted-apply assertion")
}This converts a confusing "targeted-apply did not fire" failure into a clear skip when the feature is simply absent from the loaded client. 4. Per CLAUDE.md: "Assert full page state after each mutation, not just the changed element." The subtest waits for the count text ( e2etest.WaitFor(`document.querySelector('tbody tr[data-key="row-00100"]') === null`, 5*time.Second),Minor Observations5. Ceiling headroom is tight for CI 2500 ms for a 10k-row delete leaves roughly 1 s headroom above the reported ~1.5 s local time. Headless Chrome in CI can exhibit 2–3× slowdowns during resource contention. The PR already acknowledges the ceiling is "intentionally generous to absorb headless-Chrome variance" — just flagging this is worth re-checking if CI starts flaking, given the PR description also mentions the docstring said 3500 ms (which would give more room). 6. 30 s e2etest.WaitFor(`document.querySelector('tbody tr[data-key="row-05000"]') === null`, 30*time.Second),If the delete operation fails silently (e.g., WebSocket error), this will hang for 30 s before giving a generic chromedp error. Not a blocker, but a tighter initial wait (e.g., 10 s) with a clearer error message would make CI failures faster to diagnose. What's Done Well
SummaryThe approach is solid. Fix the docstring/constant mismatch (#1), the |
There was a problem hiding this comment.
Pull request overview
This PR extends the patterns E2E suite to validate the Large Table demo’s client-side targeted DOM mutation path, adding both a functional signal check and a bounded-latency stress test around single-row deletion at 10k-row scale.
Changes:
- Adds a
TestLargeTablesubtest that inspectswindow.__lvtTargetedHitsafter a delete to confirm the targeted-apply path ran. - Adds a new top-level 10k-row latency test with a wall-clock ceiling and
-shortskip behavior. - Uses
LARGE_TABLE_SIZEoverrides to run the existing suite at CI-friendly scale and the new stress test at full demo scale.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if hits == 0 { | ||
| t.Errorf("Targeted-apply path did NOT fire — canApplyTargeted rejected the LargeTable structure and we hit the fallback (deepClone + reconstructFromTree + morphdom-over-whole-range) path.") |
| // targeted-apply path mutates the live DOM directly and a sentinel attribute | ||
| // tells morphdom to short-circuit the 10k-row subtree. | ||
| // | ||
| // The 3500 ms ceiling is intentionally generous: it catches catastrophic |
|
Bot review fix landed in livetemplate/client v0.8.40 (livetemplate/client#114) — the test-examples failure (TestHighlightOnChange) was caused by livetemplate/client#108 directive-scan over-eagerness, fixed in #114. Re-running CI against the published v0.8.40 client. |
Summary
Adds two chromedp subtests that verify the client-side per-op targeted DOM mutation path shipped in livetemplate/client#108 (released as
@livetemplate/client@0.8.39):TestLargeTable/Delete_Targeted_Apply_Path_Taken— runs at the existing N=200 CI scale. Asserts that after a single-row delete,window.__lvtTargetedHits === 1— confirming theRangeDomApplieractually fired (vs silently hitting the fallback path).TestLargeTable_DeleteLatency_10k— stress test at the demo's default 10,000-row scale with a 2500ms wall-clock ceiling. Skipped under-short. Pre-fix wall-clock at this scale was 6-8s; post-fix is ~1.5s. The ceiling is intentionally generous to absorb headless-Chrome variance and the residual browser layout cost (the floor that drove follow-up issue livetemplate/client#109 for table virtualization).Depends on
@livetemplate/client@0.8.39+for thewindow.__lvtTargetedHitsobservability hook. Cross-repo CI uses the CDN build — should pick up the new version automatically.Test plan
LVT_LOCAL_CLIENT=.../client/dist/livetemplate-client.browser.js go test -v -run "^TestLargeTable$|^TestLargeTable_DeleteLatency_10k$" -timeout 5m— green at 1.5-1.8s wall-clock withtargeted-apply hits: 1@livetemplate/client@0.8.39from CDN🤖 Generated with Claude Code