from pathlib import Path ROOT = Path(__file__).resolve().parents[1] def test_extension_retries_error_page_script_injection_before_failing(): core = (ROOT / "extension" / "src" / "core.ts").read_text() assert "isBrowserErrorUrl" in core assert "isErrorPageScriptError" in core assert "chrome-error://" in core assert "edge-error://" in core assert "brave-error://" in core assert "about:neterror" in core assert "about:certerror" in core assert "isTransientScriptError(e)" in core def test_read_only_dom_commands_have_error_page_fallbacks(): dom = (ROOT / "extension" / "src" / "commands" / "dom.ts").read_text() assert "fallbackForErrorPageDomOp" in dom assert 'case "domExists":' in dom assert "return false;" in dom assert 'case "domQuery":' in dom assert 'case "extractText":' in dom assert "isBrowserErrorUrl(tabUrl)" in dom assert "isErrorPageScriptError(e)" in dom def test_navigation_and_tabs_report_browser_error_pages(): tabs = (ROOT / "extension" / "src" / "commands" / "tabs.ts").read_text() navigation = (ROOT / "extension" / "src" / "commands" / "navigation.ts").read_text() assert "lastUrl" in tabs assert "lastStatus" in tabs assert "showing an error page" in tabs assert "last URL:" in tabs assert "isBrowserErrorUrl" in navigation assert "showing an error page while waiting for load" in navigation def test_large_extension_operations_yield_between_batches(): core = (ROOT / "extension" / "src" / "core.ts").read_text() tabs = (ROOT / "extension" / "src" / "commands" / "tabs.ts").read_text() groups = (ROOT / "extension" / "src" / "commands" / "groups.ts").read_text() session = (ROOT / "extension" / "src" / "commands" / "session.ts").read_text() assert "yieldForLargeOperation" in core assert "getLargeOperationThrottle" in core assert "hasAudibleTabs" in core assert "runLargeOperation" in core assert "largeOperationQueue" in core assert "updateJobProgress" in core assert "throwIfJobCancelled" in core assert "getPerformanceProfile" in core assert "setPerformanceProfile" in core assert "GENTLE_OPERATION_BATCH_SIZE" in core assert "GENTLE_OPERATION_PAUSE_MS" in core assert "itemCount >= 300" in core assert "itemCount >= 100" in core assert "chrome.tabs.query({ audible: true })" in core assert "yieldForLargeOperation" in tabs assert "toClose.slice" in tabs assert "ids.slice" in tabs assert "w.tabs.every" in tabs assert "getLargeOperationThrottle" in tabs assert "runLargeOperation(\"tabs.sort\"" in tabs assert "yieldForLargeOperation" in groups assert "tabIds.slice" in groups assert "getLargeOperationThrottle" in groups assert "runLargeOperation(\"group.close\"" in groups assert "yieldForLargeOperation(createdTabs.length" in session assert "getLargeOperationThrottle" in session assert "runLargeOperation(\"session.load\"" in session assert "chrome.tabs.discard" in session assert "lazyPlaceholderUrl" in session assert "activateLazyTab" in session assert "lazySessionTabs" in session assert "throwIfJobCancelled" in session assert "updateJobProgress" in session index = (ROOT / "extension" / "src" / "index.ts").read_text() assert "BACKGROUND_COMMANDS" in index assert "startBackgroundJob" in index assert "persistJobs" in index assert "recentJobs" in index assert "jobs.status" in index assert "jobs.cancel" in index assert "perf.status" in index assert "perf.set_profile" in index assert "__background" in index def test_session_autosave_is_debounced_and_non_overlapping(): session = (ROOT / "extension" / "src" / "commands" / "session.ts").read_text() assert "autoSaveTimer" in session assert "autoSaveInFlight" in session assert "autoSavePending" in session assert "scheduleAutoSave" in session assert "autoSaveUpdatedHandler" in session assert "saveAutoSessionIfChanged" in session assert "sessionSignature" in session assert "autoSaveSignature" in session assert "chrome.tabs.onUpdated.addListener(autoSaveUpdatedHandler)" in session assert "chrome.tabs.onCreated.addListener(autoSaveHandler)" in session assert "chrome.tabs.onMoved.addListener(autoSaveHandler)" in session assert "if (!(\"url\" in changeInfo)) return;" in session assert "setTimeout(runAutoSave, delayMs)" in session assert "clearTimeout(autoSaveTimer)" in session def test_cli_and_sdk_expose_gentle_restore_controls(): session_cli = (ROOT / "browser_cli" / "commands" / "session.py").read_text() tabs_cli = (ROOT / "browser_cli" / "commands" / "tabs.py").read_text() groups_cli = (ROOT / "browser_cli" / "commands" / "groups.py").read_text() sdk = (ROOT / "browser_cli" / "__init__.py").read_text() assert "--gentle-mode" in session_cli assert "--discard-background-tabs" in session_cli assert "--background" in session_cli assert "--lazy" in session_cli assert "--eager-tabs" in session_cli assert "job-status" in session_cli assert "job-cancel" in session_cli assert "discardBackgroundTabs" in session_cli assert "--gentle-mode" in tabs_cli assert "gentleMode" in tabs_cli assert "--gentle-mode" in groups_cli assert "discard_background_tabs" in sdk assert "discardBackgroundTabs" in sdk assert "session_load_background" in sdk assert "job_status" in sdk assert "job_cancel" in sdk assert "perf_status" in sdk assert "set_performance_profile" in sdk perf_cli = (ROOT / "browser_cli" / "commands" / "perf.py").read_text() root_cli = (ROOT / "browser_cli" / "cli.py").read_text() assert "perf_group" in perf_cli assert "perf.status" in perf_cli assert "perf.set_profile" in perf_cli assert "main.add_command(perf_group)" in root_cli