From 918fdef5197e8f959d903e748ca9d003e9a8ec08 Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Fri, 1 May 2026 17:01:36 -0400 Subject: [PATCH] ext(sw): expand active-tab URL filter; isolate chrome stub in tests Expand get_active_tab_url protocol filter regex to include view-source:, data:, devtools:, and other browser-internal/extension contexts that would misbehave if autofilled. Add third regression test for view-source: URLs. Wrap get_active_tab_url tests in dedicated describe block with beforeEach/ afterEach to snapshot/restore globalThis.chrome, preventing stub leakage between tests. Co-Authored-By: Claude Opus 4.7 --- .../router/__tests__/router.test.ts | 20 ++++++++++++++++++- .../src/service-worker/router/popup-only.ts | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/extension/src/service-worker/router/__tests__/router.test.ts b/extension/src/service-worker/router/__tests__/router.test.ts index f503b61..0a41a39 100644 --- a/extension/src/service-worker/router/__tests__/router.test.ts +++ b/extension/src/service-worker/router/__tests__/router.test.ts @@ -1,4 +1,4 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; // --- Mocks (must be declared before `route` is imported so the router's // `import * as vault` / `import * as session` resolve to these doubles) --- @@ -925,6 +925,10 @@ describe('parse_lastpass_csv / import_lastpass_commit sender check', () => { // --- get_active_tab_url --- describe('get_active_tab_url', () => { + let originalChrome: any; + beforeEach(() => { originalChrome = (globalThis as any).chrome; }); + afterEach(() => { (globalThis as any).chrome = originalChrome; }); + it('get_active_tab_url returns active tab url + title', async () => { // happy-dom does not provide chrome.tabs; stub it. (globalThis as any).chrome = { @@ -953,4 +957,18 @@ describe('get_active_tab_url', () => { expect(resp.ok).toBe(true); expect(resp.data).toBeNull(); }); + + it('get_active_tab_url returns null for view-source: URLs', async () => { + (globalThis as any).chrome = { + ...((globalThis as any).chrome ?? {}), + tabs: { + query: (q: any, cb: (tabs: any[]) => void) => { + cb([{ url: 'view-source:https://github.com/login', title: 'View Source' }]); + }, + }, + }; + const resp = await route({ type: 'get_active_tab_url' } as any, makeState(), makePopupSender()); + expect(resp.ok).toBe(true); + expect(resp.data).toBeNull(); + }); }); diff --git a/extension/src/service-worker/router/popup-only.ts b/extension/src/service-worker/router/popup-only.ts index c289be6..f1217e2 100644 --- a/extension/src/service-worker/router/popup-only.ts +++ b/extension/src/service-worker/router/popup-only.ts @@ -153,7 +153,7 @@ export async function handle( const tab = tabs[0]; if (!tab?.url) return { ok: true, data: null }; // Filter out chrome:// and extension URLs — autofill doesn't apply. - if (/^(chrome|chrome-extension|moz-extension|edge|about|file):/i.test(tab.url)) { + if (/^(chrome|chrome-extension|chrome-search|moz-extension|edge|edge-extension|about|file|view-source|data|devtools|javascript):/i.test(tab.url)) { return { ok: true, data: null }; } return { ok: true, data: { url: tab.url, title: tab.title ?? '' } };