feat: add performance controls for large browser ops

- Add throttled large-operation handling for tab, group, and session commands.
- Introduce performance profiles, audible-tab aware gentle mode, and job progress tracking.
- Support background session restores with status/cancel commands and lazy placeholders.
- Expose new perf and extension CLI groups plus matching Python SDK methods.
- Preserve pinned tabs during session snapshots and debounce auto-save updates.
- Bump browser-cli and extension versions to 0.10.0 and add pytest-cov to dev deps.
- Add coverage for performance controls, background jobs, lazy restores, and tab metadata.
This commit is contained in:
2026-05-20 22:13:57 +02:00
parent e1e4adbb25
commit 545abeb515
18 changed files with 1054 additions and 148 deletions
+103
View File
@@ -35,3 +35,106 @@ def test_navigation_and_tabs_report_browser_error_pages():
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