Cover the updates section's assisted-update safety routing - #968
Merged
Conversation
PR #949 split updates-section.tsx into five subcomponents, and nothing mounted any of them: release-utils.test.ts covers the pure predicates (isForceRequired, isAssistedPreferred, describeForceTriggers) but not which UI they drive. The decision that a gated release must route the standard updater through a confirmation spans UpdatesCheckPanel -> UpdateActions -> UpdatesForceConfirmDialog, so the test mounts UpdatesSection with useReleaseUpdates stubbed and drives the real subcomponents. Covers the paths where a regression breaks an install: a required or migration-gated release demotes the standard update into the menu and opens the force confirmation instead of running it, confirming forces the update, and a migration-evaluation error warns without gating. Also pins the wiring a component split is most likely to scramble — the force flag on the confirmed update, plain vs cache-clearing reload, the channel and auto-update handlers — and the two in-flight-update takeovers that hide the controls. Mutation battery: 27 mutants, 23 killed. The survivors are the two saving-state affordances, which exist only as a Tailwind class with no disabled/aria-busy for jsdom to observe, and OperationTakeover's phase order, which belongs to that component's own coverage. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Deleting the scrollIntoView stub in afterEach keeps the mock out of any
later test file sharing the worker — jsdom does not define it at all, so
restoring means removing it. The preferences test was named as
persistence coverage but useReleaseUpdates is stubbed, so it only pins
that each control reports the value it was clicked with; renamed to say
that. Kept rather than deleted: it is what kills the mutants hardcoding
onChannelChange("stable") and onAutoUpdateModeChange("check").
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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.
Recurring Test Enforcer run. The local suite was green on the first pass (29th consecutive), so the whole run went to the queued
next_focus: the five subcomponents PR #949 split out ofupdates-section.tsx, none of which anything mounted.Why here
release-utils.test.tsalready covers the pure predicates —isForceRequired,isAssistedPreferred,describeForceTriggers— but not which UI they drive. The contract that actually protects an install is that a release requiring the agent-assisted flow must demote the standard updater into a dropdown and route it through a force confirmation instead of running it on one click, and that decision spansUpdatesCheckPanel→UpdateActions→UpdatesForceConfirmDialog. No single component owns it, so the test stubsuseReleaseUpdatesand mounts the realUpdatesSection, exercising all five subcomponents plus the assisted and pending-migration gates.forceConfirmOpenis held in real state inside the stub, so click → dialog → confirm is one real interaction rather than an assertion that a setter fired.What it pins
recommendedrelease promotes the assisted flow without forcing a confirmation, which is what separatesassistedPreferredfromforceRequired.{ force: true }flag on the confirmed update, plain vs cache-clearing reload, and the channel / auto-update handlers.Validation
check,format,finalize:web,test(server 163 files/2783, web 65/926, ext 60, scripts 4),test:e2e(180 passed / 12 skipped) andtest:e2e:live(11 passed, 23.9s, no straye2e-*tmux sessions) all green.Mutation battery: 27 mutants, 23 killed. The survivors are not test gaps — three are one root cause (
channelSaving/autoUpdateSavingexist only as a Tailwindopacity-50 pointer-events-noneclass with nodisabledoraria-busy, so jsdom cannot observe them and asserting would mean class-name coupling), and the fourth isOperationTakeover'sphasesOrder, which belongs to that component's own coverage. Both are recorded in the Brain backlog.One review round; both findings applied — restore
Element.prototype.scrollIntoViewinafterEachso the stub cannot leak into later files sharing the worker, and narrow the preferences test's name to the wiring it actually covers.🤖 Generated with Claude Code