✔ scan → preview → save → undo retains manual rules and restores their text (49.750579ms)
✔ review-only and invalid model plans cannot write or touch page content (19.845113ms)
✔ failed persistent rule write leaves the previous rules and can revert the preview (137.593345ms)
✔ CSS insertion failure removes only the new batch and keeps a reversible preview (19.249373ms)
✔ finish failure removes injected CSS and rolls back only the newly saved rules (14.124739ms)
✔ changed document, changed SPA URL, expired scan and mismatched scan cannot save (30.764227ms)
✔ page cannot swap selectors, text or styles between preview and persistence (38.099964ms)
✔ only a same-extension UI can invoke AI scan, save, undo or focus (18.451008ms)
✔ restricted Chrome and store pages reject both editor launch and scanning (48.651851ms)
✔ reopening focuses one editor and closing it removes unsaved changes (17.488305ms)
✔ window cleanup survives a destroyed document and tab cleanup removes the undo record (23.112364ms)
✔ new scans revert an old preview and invalidate its save token (12.404321ms)
✔ scan forwards only bounded request text and supported ranking profiles (29.353924ms)
✔ concurrent focused scans serialize stop and scan, leaving only the newest token valid (19.020257ms)
✔ failed session persistence after preview does not strand a live untracked edit (6.425868ms)
✔ failed undo-metadata persistence cannot report failure after committing saved changes (12.726659ms)
✔ post-commit session cleanup or badge failure cannot turn a saved batch into a reported failure (28.517863ms)
✔ an AI save and concurrent manual picker save cannot overwrite each other (59.472602ms)
✔ normalizes only allowed data, clones it, and retains literal text safely (23.373498ms)
✔ accepts a review without changes and a deliberately empty replacement (3.20645ms)
✔ rejects executable properties, extra fields, and prototype-shaped input (2.081191ms)
✔ enforces all numeric style boundaries with no expressions or coercion (25.835273ms)
✔ rejects unknown and duplicate targets, noneditable text, and hidden page roots (5.411448ms)
✔ bounds responses and operations, and rejects malformed target snapshots (1.92819ms)
✔ rejects sparse or accessor operation arrays without reading them (0.900489ms)
✔ CSS accepts local selector paths and blocks selector/declaration injection (5.550848ms)
✔ model context never includes selectors, URL secrets or original text and strips unsupported CSS (8.54069ms)
✔ context fits 14k even for worst case text/styles while preserving all target IDs (35.737739ms)
✔ schema excludes unsupported fields and has a valid empty-scan operation array (0.49089ms)
✔ parse accepts only JSON or one complete JSON fence and still validates all output (2.524079ms)
✔ optional compact context includes only validated metadata and chosen style fields (0.535348ms)
✔ compact context rejects invalid budgets and unsupported style filters (0.814639ms)
✔ marked text excerpts and leading target priority stay within compact budget (0.707959ms)
✔ AI results remain inert text; preview and save require separate explicit actions (92.170914ms)
✔ navigation invalidates a model result that completes later but preserves the clean baseline (28.945368ms)
✔ review-only mode constrains operations and refuses a model that proposes edits (31.446022ms)
✔ every request clones synchronously, then reverts and rescans before planning (39.297532ms)
✔ a new request uses refreshed page text and forwards the chosen coverage (42.640358ms)
✔ a navigation while a fresh scan is pending cannot revive an old request (19.840315ms)
✔ cancel aborts a prompt and destroys only its clone, allowing a clean retry (16.485232ms)
✔ streamed partial JSON never enables preview or save, even if complete before stream end (28.288956ms)
✔ cancelling a stream releases its reader and never exposes the partial plan (16.916162ms)
✔ an excessive streamed response is stopped without applying any operation (23.347118ms)
✔ older APIs use the prepared session once, then create a fresh session in the next gesture (15.98774ms)
✔ closing the editor destroys the baseline and a clone that resolves late (11.787561ms)
✔ unsupported Edge explains preview availability and leaves manual editing available (8.538828ms)
✔ Edge availability and model creation omit Chrome-specific language options (9.565988ms)
✔ an unavailable Edge model never enables Prepare AI even when the API exists (11.595927ms)
✔ Edge download progress divides loaded by total and accepts normalized fallback events (13.897485ms)
✔ a baseline clone reject exposes Prepare AI and recovers through a fresh user gesture (31.755158ms)
✔ a baseline clone throw exposes Prepare AI and recovers through a fresh user gesture (14.536099ms)
✔ quoted requests retain an exact offscreen target despite navigation noise (22.914906ms)
✔ semantic requests prioritize headings and requested page regions (3.835048ms)
✔ review ranks visible main content and limits repeated navigation labels (9.539358ms)
✔ include nearest available parent containers without dangling parent IDs (1.0007ms)
✔ profiles bound context, targets and schema operations before model generation (220.418049ms)
✔ selection and context generation never mutate the complete scan (8.56096ms)
✔ model context contains only sanitized data; page commands never become guidance (0.683051ms)
✔ rejects hostile snapshot getters before ranking and rejects oversized requests (0.793788ms)
✔ copy edits omit irrelevant styles and keep leading excerpts longer than secondary targets (7.339258ms)
✔ empty scans produce a valid zero-operation schema and unknown profiles use Fast (0.568919ms)
✔ worst-case escaped text and identifiers still fit both profile budgets (12.84706ms)
✔ scanner excludes input values, form subtrees, hidden descendants and contenteditable (54.987012ms)
✔ scanner bounds targets and returns unique selectors even with duplicate or unsafe IDs (85.080076ms)
✔ preview preserves node identity and listeners, prepares baseline, then cleanly restores (13.258922ms)
✔ invalid operations are rejected before any element changes (5.350125ms)
✔ preview rolls back earlier targets if a later write fails (12.294896ms)
✔ preflight catches detached targets and changed text before writing any target (13.287636ms)
✔ revert preserves website-owned text and styles changed during preview (14.964676ms)
✔ preview replacement restores mixed-priority longhands and keeps the scan reusable (9.652729ms)
✔ pushState invalidates save and restores only local preview changes (5.477738ms)
✔ navigation events restore immediately and stale scan IDs cannot write (11.287245ms)
✔ manual picker and AI preview cannot overlap (11.601641ms)
✔ finish restores preview, refreshes persistence and invalidates the scan (15.87437ms)
✔ saved text rules are paused in preview and resynchronized after finish (9.132573ms)
✔ API scan outputs cannot mutate internal target records and injection reuses singleton (14.840854ms)
✔ ranked scan keeps main headings and copy when crowded navigation comes first (72.694293ms)
✔ request words and quoted text recover a deep footer target before the target cap (38.209289ms)
✔ snapshot landmarks, viewport flags and nearest selected ancestors reflect the page (7.168439ms)
✔ request matching never reads hidden, form or editable descendant text (5.887436ms)
✔ request ranking obeys the 5000-node traversal bound (831.314566ms)
✔ hidden sibling nodes count toward the traversal bound without text reads (127.705897ms)
✔ manual rule preserves CSS → HTML → JavaScript order and pins the document (13.55896ms)
✔ navigation reads saved rules after a fresh service worker start (4.297486ms)
✔ matching ignores disabled, invalid patterns, and forbidden child frames (2.488126ms)
✔ missing user-script permission gives actionable feedback before any injection (2.721027ms)
✔ Edge without userScripts.getScripts fails before a mixed rule changes the page (21.45033ms)
✔ Edge without userScripts.execute fails before a mixed rule changes the page (8.721107ms)
✔ Edge internal pages and both extension stores cannot be edited (22.516244ms)
✔ CSS-only rules with editor placeholder comments do not require user-script permission (4.585952ms)
✔ JavaScript runtime errors and remote HTTP errors are surfaced (5.115732ms)
✔ local files require consent, support Windows paths, and close their reader (5.964371ms)
✔ remote CSS keeps its URL for relative assets; remote JS fetch omits credentials (1.69568ms)
✔ manual injection rejects restricted pages and disabled rules (1.639314ms)
✔ only the extension UI can request injection through runtime messages (5.272859ms)
✔ picker starts in the isolated top document without user-script permission (4.096904ms)
✔ keyboard quick edit loads the compact mode in the current document and starts a save session (4.851553ms)
✔ shortcut rejects restricted pages with a visible error and ignores unknown commands (4.750099ms)
✔ picker save validates the target, applies CSS, and appends a named persistent rule (6.368521ms)
✔ site scope cannot match lookalike domains and exact page scope escapes query punctuation (2.813306ms)
✔ picker rejects CSS injection, unknown properties, empty drafts, and out-of-range values (3.071636ms)
✔ saving requires the current picker document and a still-unique target (4.299919ms)
✔ failed persistence removes the applied CSS and keeps previous rules (12.566237ms)
✔ concurrent picker saves for different elements retain both rules (4.030834ms)
✔ text-only saves persist literal text without generated code or script permission (9.473303ms)
✔ revising a saved element updates one rule and retains its original baseline and styles (4.704952ms)
✔ invalid text recipes fail before persistence or CSS injection (7.600056ms)
✔ failed text update preserves the previously saved value and does not announce sync (9.565758ms)
✔ runtime receives only matching enabled valid text recipes and no code (2.364169ms)
✔ text-only manual injection loads the runtime and document-scoped sync without user scripts (4.385919ms)
✔ manual text injection outside its saved URL scope gives an actionable error (1.626064ms)
✔ history and hash route updates sync the top document only (4.137144ms)
✔ content picker messages have a narrow save route and cannot launch arbitrary injection (1.551171ms)
✔ extension details opens the Edge settings page for this extension (43.823873ms)
✔ remote JSON import appends downloaded rules and retains existing rules: https://example.test/rules.json (30.29896ms)
✔ remote JSON import appends downloaded rules and retains existing rules: https://example.test/RULES.JSON?version=2 (9.363402ms)
✔ remote import rejects non-JSON paths and unsupported schemes before fetching (3.426813ms)
✔ HTTP errors, malformed JSON and non-array JSON do not change saved rules (30.786652ms)
✔ named visual rules retain their URL pattern and metadata through edit and save (109.379742ms)
✔ Quick text launch reports failures, stays retryable, and closes only after a successful launch (25.020348ms)
✔ opening a saved text rule selects its visible Text tab and shows literal metadata (25.195197ms)
✔ popup Save persists edited text without losing the original rule metadata (47.159017ms)
✔ popup Save persists an empty string without losing the original rule metadata (32.108401ms)
✔ popup Save persists HTML-looking literal text without losing the original rule metadata (21.146066ms)
✔ opening a nontext rule after a text rule hides the Text tab and clears stale text metadata (30.182839ms)
✔ Use website text restores the original baseline into the textarea and Save preserves identity (24.924209ms)
✔ Tab and Shift+Tab cycle through the text editor controls without entering hidden code editors (23.747332ms)
✔ standalone static HTML preserves text, nesting, semantic markup and safe attributes (38.309661ms)
✔ safe URLs resolve against the live page and new tabs cannot access their opener (9.062478ms)
✔ script-bearing elements, executable attributes and dangerous containers fail atomically (17.656689ms)
✔ nested foreign namespaces and mutation-XSS payloads are rejected (6.778331ms)
✔ HTML-decoded executable URL schemes and control-character obfuscation are rejected (14.60935ms)
✔ percent-encoded scheme-like strings stay inert absolute HTTP paths (5.12147ms)
✔ file pages retain in-page anchors but cannot inject local resource URLs (4.256104ms)
✔ plain text edits preserve decorative child identity and existing event handlers (34.310134ms)
✔ multiple direct text nodes and comments survive preview and restoration (5.971903ms)
✔ empty leaves get a reversible text node (4.788047ms)
✔ controls, contenteditable and nested text are ineligible (8.556594ms)
✔ website text changes are never overwritten by later preview or restore (7.117042ms)
✔ restoration does not touch removed or replaced nodes (4.843721ms)
✔ saved rules apply at startup and in a fresh document after a reload (7.494271ms)
✔ deleting or disabling a saved rule restores only its owned text (10.539538ms)
✔ async inserted and replaced matching targets receive saved text (202.399572ms)
✔ changed server text remains visible until the stored baseline returns (196.717396ms)
✔ unique selector, original text and matching tag are all required (5.109672ms)
✔ last conflicting rule wins and disabling it restores the preceding rule (6.708655ms)
✔ reference-counted pauses protect picker drafts through refresh and DOM changes (200.923976ms)
✔ pause does not implicitly restore a currently saved rule (3.705152ms)
✔ route changes restore exact-page rules, then apply them again on return (3.838132ms)
✔ a hash change triggers a fetch and restores an exact URL rule (3.707226ms)
✔ old page text is restored immediately while a new route fetch is still pending (3.709649ms)
✔ picker baseline does not claim ownership after an intervening website update (4.981028ms)
✔ latest fetch wins when storage responses arrive out of order (8.062589ms)
✔ idempotent reinjection keeps one listener and the same API instance (3.84985ms)
✔ observer writes do not spin and unrelated mutations coalesce (194.631508ms)
✔ extension invalidation restores owned changes and disconnects listeners (4.217836ms)
✔ malformed selectors and regexes do not prevent valid rules from running (3.462736ms)
✔ picking intercepts the click and shows the chosen link without activating the page (81.549213ms)
✔ selection distinguishes repeated siblings in repeated containers (14.240272ms)
✔ selection handles CSS punctuation in an element ID (9.793352ms)
✔ style controls preview only the selected element and do not save automatically (15.719571ms)
✔ preview toggle restores original styling and reapplies the same unsaved draft (13.803403ms)
✔ Reset changes restores exact preexisting styles and clears the draft (16.839936ms)
✔ Close clears the draft, removes the picker, and restores earlier focus (10.946751ms)
✔ Choose another discards the first draft before styling the next element (40.578646ms)
✔ Save sends the selected CSS rule, removes its draft, and prevents duplicate saves (21.124773ms)
✔ a pending save cannot be duplicated or silently overwrite newly edited controls (11.119873ms)
✔ a failed save leaves the draft editable and supports a corrected retry (13.96375ms)
✔ a reloaded-extension error gives recovery guidance while retaining the draft (9.136029ms)
✔ reinjection keeps one picker and Escape cleanup does not leave keyboard interception (17.954173ms)
✔ an element removed from the page cannot be saved and its preview is cleared (12.689121ms)
✔ a selector that becomes ambiguous cannot create a rule for multiple elements (35.361892ms)
✔ out-of-range numbers block saving until corrected (11.73402ms)
✔ text preview changes the existing text node while preserving child markup and event listeners (10.70033ms)
✔ text preview toggle, Reset changes, and Close restore the exact original node content (13.494688ms)
✔ Choose another restores unsaved text before selecting the next element (13.361717ms)
✔ HTML-looking input is literal text throughout preview, save, and saved runtime application (38.005241ms)
✔ a failed text save retains an editable preview and a retry keeps the original baseline (15.849812ms)
✔ editing a saved text rule sends the underlying page baseline and Reset restores the saved display (23.10342ms)
✔ Restore original previews the underlying page text and can save that explicit restoration (10.711246ms)
✔ complex text containers explain their limitation while remaining available for styling (8.809436ms)
✔ Save rejects a website text update while preview is off without losing the website update or draft (7.958692ms)
✔ Save rejects a replacement text node even when the website kept the same displayed preview text (9.088247ms)
✔ quick mode opens a compact editor and focuses the selected text field (7.254129ms)
✔ quick Ctrl+Enter saves one exact-page text rule, refreshes it, and closes the editor (8.600641ms)
✔ quick Command+Enter saves one exact-page text rule, refreshes it, and closes the editor (12.824665ms)
✔ Escape leaves quick mode and restores its unsaved text draft (10.042748ms)
✔ quick Enter remains text entry, and IME composition cannot trigger a save shortcut (11.665517ms)
✔ a failed quick save keeps the editor and draft available for correction and retry (16.528537ms)
✔ switching full and quick launches discards old drafts and keeps only one active editor (26.740189ms)
✔ a quick save in progress cannot be cancelled or closed before persistence finishes (40.910216ms)
ℹ tests 191
ℹ suites 0
ℹ pass 191
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 2544.723062
