concurrent tabs test works

This commit is contained in:
Tommy D. Rossi
2025-11-22 12:43:52 +01:00
parent c658c153b2
commit 27172cf7ca
4 changed files with 57 additions and 259 deletions
+12
View File
@@ -37,3 +37,15 @@ curl -sL https://raw.githubusercontent.com/ChromeDevTools/devtools-protocol/mast
``` ```
you can list other files in that folder on github to read more if you need to control things like DOM, performance, etc you can list other files in that folder on github to read more if you need to control things like DOM, performance, etc
## testing
run `cd playwriter && pnpm test` to test the extension and mcp and CDP directly in a chrome instance automated. with the extension loaded too.
the test script will also pass -u to update some inline snapshots used
you can run singular tests with `-t "testname"`
each test() block should reset the extension connection to make sure tests are independent.
NEVER call browser.close() in the tests
-225
View File
@@ -1,225 +0,0 @@
CDP relay server started
Host: 127.0.0.1
Port: 19988
Extension endpoint: ws://127.0.0.1:19988/extension
CDP endpoint: ws://127.0.0.1:19988/cdp
Extension connected with clean state
← Extension: Target.attachedToTarget targetId=37BE179F93AF8207BD1E2372B9C515BA, sessionId=pw-tab-1
→ Playwright [ALL]: Target.attachedToTarget targetId=37BE179F93AF8207BD1E2372B9C515BA, sessionId=pw-tab-1
← Extension: Target.attachedToTarget targetId=E3E15D82C13B4A15D3CF71E44B260036, sessionId=pw-tab-2
→ Playwright [ALL]: Target.attachedToTarget targetId=E3E15D82C13B4A15D3CF71E44B260036, sessionId=pw-tab-2
← Extension: Target.attachedToTarget targetId=16E435409CFBF47529751B04E9F9021D, sessionId=pw-tab-3
→ Playwright [ALL]: Target.attachedToTarget targetId=16E435409CFBF47529751B04E9F9021D, sessionId=pw-tab-3
Playwright client connected: E3E15D82C13B4A15D3CF71E44B260036 (1 total)
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Browser.getVersion id=1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Target.setAutoAttach id=2
→ Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Target.attachedToTarget targetId=37BE179F93AF8207BD1E2372B9C515BA, sessionId=pw-tab-1 (server-generated)
→ Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Target.attachedToTarget targetId=E3E15D82C13B4A15D3CF71E44B260036, sessionId=pw-tab-2 (server-generated)
→ Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Target.attachedToTarget targetId=16E435409CFBF47529751B04E9F9021D, sessionId=pw-tab-3 (server-generated)
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Browser.setDownloadBehavior id=3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.enable id=4, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.getFrameTree id=5, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Log.enable id=6, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.setLifecycleEventsEnabled id=7, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Runtime.enable id=8, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.addScriptToEvaluateOnNewDocument id=9, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Network.enable id=10, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Target.setAutoAttach id=11, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Emulation.setFocusEmulationEnabled id=12, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Emulation.setEmulatedMedia id=13, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Runtime.runIfWaitingForDebugger id=14, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.enable id=15, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.getFrameTree id=16, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Log.enable id=17, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.setLifecycleEventsEnabled id=18, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Runtime.enable id=19, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.addScriptToEvaluateOnNewDocument id=20, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Network.enable id=21, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Target.setAutoAttach id=22, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Emulation.setFocusEmulationEnabled id=23, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Emulation.setEmulatedMedia id=24, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Runtime.runIfWaitingForDebugger id=25, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.enable id=26, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.getFrameTree id=27, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Log.enable id=28, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.setLifecycleEventsEnabled id=29, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Runtime.enable id=30, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.addScriptToEvaluateOnNewDocument id=31, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Network.enable id=32, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Target.setAutoAttach id=33, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Emulation.setFocusEmulationEnabled id=34, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Emulation.setEmulatedMedia id=35, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Runtime.runIfWaitingForDebugger id=36, sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Target.getTargetInfo id=37
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Extension: Runtime.executionContextCreated sessionId=pw-tab-1
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-1
← Extension: Runtime.executionContextCreated sessionId=pw-tab-1
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-1
← Extension: Log.entryAdded sessionId=pw-tab-2
→ Playwright [ALL]: Log.entryAdded sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Extension: Runtime.executionContextCreated sessionId=pw-tab-2
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-2
← Extension: Runtime.executionContextCreated sessionId=pw-tab-2
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-2
← Extension: Runtime.executionContextCreated sessionId=pw-tab-2
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Runtime.executionContextCreated sessionId=pw-tab-3
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-3
← Extension: Runtime.executionContextCreated sessionId=pw-tab-3
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.createIsolatedWorld id=38, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.createIsolatedWorld id=39, sessionId=pw-tab-2
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Page.createIsolatedWorld id=40, sessionId=pw-tab-3
Playwright client connected: 16E435409CFBF47529751B04E9F9021D (2 total)
← Extension: Runtime.executionContextCreated sessionId=pw-tab-1
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-1
← Extension: Runtime.executionContextCreated sessionId=pw-tab-2
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-2
← Extension: Runtime.executionContextCreated sessionId=pw-tab-3
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Browser.getVersion id=1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Target.setAutoAttach id=2
→ Playwright [16E435409CFBF47529751B04E9F9021D]: Target.attachedToTarget targetId=37BE179F93AF8207BD1E2372B9C515BA, sessionId=pw-tab-1 (server-generated)
→ Playwright [16E435409CFBF47529751B04E9F9021D]: Target.attachedToTarget targetId=E3E15D82C13B4A15D3CF71E44B260036, sessionId=pw-tab-2 (server-generated)
→ Playwright [16E435409CFBF47529751B04E9F9021D]: Target.attachedToTarget targetId=16E435409CFBF47529751B04E9F9021D, sessionId=pw-tab-3 (server-generated)
← Playwright [16E435409CFBF47529751B04E9F9021D]: Browser.setDownloadBehavior id=3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.enable id=4, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.getFrameTree id=5, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Log.enable id=6, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.setLifecycleEventsEnabled id=7, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Runtime.enable id=8, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.addScriptToEvaluateOnNewDocument id=9, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Network.enable id=10, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Target.setAutoAttach id=11, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Emulation.setFocusEmulationEnabled id=12, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Emulation.setEmulatedMedia id=13, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Runtime.runIfWaitingForDebugger id=14, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.enable id=15, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.getFrameTree id=16, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Log.enable id=17, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.setLifecycleEventsEnabled id=18, sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Runtime.enable id=19, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.addScriptToEvaluateOnNewDocument id=20, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Network.enable id=21, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Target.setAutoAttach id=22, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Emulation.setFocusEmulationEnabled id=23, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Emulation.setEmulatedMedia id=24, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Runtime.runIfWaitingForDebugger id=25, sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.enable id=26, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.getFrameTree id=27, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Log.enable id=28, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.setLifecycleEventsEnabled id=29, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Runtime.enable id=30, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.addScriptToEvaluateOnNewDocument id=31, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Network.enable id=32, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Target.setAutoAttach id=33, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Emulation.setFocusEmulationEnabled id=34, sessionId=pw-tab-3
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Extension: Runtime.executionContextCreated sessionId=pw-tab-1
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-1
← Extension: Runtime.executionContextCreated sessionId=pw-tab-1
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-1
← Extension: Runtime.executionContextCreated sessionId=pw-tab-1
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-1
← Extension: Page.lifecycleEvent sessionId=pw-tab-1
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-1
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Playwright [16E435409CFBF47529751B04E9F9021D]: Emulation.setEmulatedMedia id=35, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Runtime.runIfWaitingForDebugger id=36, sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Target.getTargetInfo id=37
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.createIsolatedWorld id=38, sessionId=pw-tab-1
← Extension: Page.lifecycleEvent sessionId=pw-tab-2
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-2
← Extension: Runtime.executionContextCreated sessionId=pw-tab-2
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-2
← Extension: Runtime.executionContextCreated sessionId=pw-tab-2
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-2
← Extension: Runtime.executionContextCreated sessionId=pw-tab-2
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Runtime.executionContextCreated sessionId=pw-tab-3
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-3
← Extension: Runtime.executionContextCreated sessionId=pw-tab-3
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-3
← Extension: Runtime.executionContextCreated sessionId=pw-tab-3
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-3
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.createIsolatedWorld id=39, sessionId=pw-tab-2
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Page.lifecycleEvent sessionId=pw-tab-3
→ Playwright [ALL]: Page.lifecycleEvent sessionId=pw-tab-3
← Extension: Runtime.executionContextCreated sessionId=pw-tab-1
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Page.createIsolatedWorld id=40, sessionId=pw-tab-3
← Extension: Runtime.executionContextCreated sessionId=pw-tab-2
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-2
← Extension: Runtime.executionContextCreated sessionId=pw-tab-3
→ Playwright [ALL]: Runtime.executionContextCreated sessionId=pw-tab-3
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Runtime.evaluate id=41, sessionId=pw-tab-1
← Playwright [E3E15D82C13B4A15D3CF71E44B260036]: Runtime.callFunctionOn id=42, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Runtime.evaluate id=41, sessionId=pw-tab-1
← Playwright [16E435409CFBF47529751B04E9F9021D]: Runtime.callFunctionOn id=42, sessionId=pw-tab-1
← Extension: Inspector.detached sessionId=pw-tab-3
→ Playwright [ALL]: Inspector.detached sessionId=pw-tab-3
← Extension: Inspector.detached sessionId=pw-tab-2
→ Playwright [ALL]: Inspector.detached sessionId=pw-tab-2
← Extension: Inspector.detached sessionId=pw-tab-1
→ Playwright [ALL]: Inspector.detached sessionId=pw-tab-1
← Extension: Target.detachedFromTarget targetId=16E435409CFBF47529751B04E9F9021D, sessionId=pw-tab-3
→ Playwright [ALL]: Target.detachedFromTarget targetId=16E435409CFBF47529751B04E9F9021D, sessionId=pw-tab-3
← Extension: Target.detachedFromTarget targetId=E3E15D82C13B4A15D3CF71E44B260036, sessionId=pw-tab-2
→ Playwright [ALL]: Target.detachedFromTarget targetId=E3E15D82C13B4A15D3CF71E44B260036, sessionId=pw-tab-2
← Extension: Target.detachedFromTarget targetId=37BE179F93AF8207BD1E2372B9C515BA, sessionId=pw-tab-1
→ Playwright [ALL]: Target.detachedFromTarget targetId=37BE179F93AF8207BD1E2372B9C515BA, sessionId=pw-tab-1
Extension disconnected
Playwright client disconnected: E3E15D82C13B4A15D3CF71E44B260036 (0 remaining)
Playwright client disconnected: 16E435409CFBF47529751B04E9F9021D (0 remaining)
+44 -33
View File
@@ -45,6 +45,12 @@ async function killProcessOnPort(port: number): Promise<void> {
} }
} }
declare global {
var toggleExtensionForActiveTab: () => Promise<{ isConnected: boolean; state: any }>;
var getExtensionState: () => { connectedTabs: Map<number, { targetId: string }> };
var chrome: any;
}
describe('MCP Server Tests', () => { describe('MCP Server Tests', () => {
let client: Awaited<ReturnType<typeof createMCPClient>>['client'] let client: Awaited<ReturnType<typeof createMCPClient>>['client']
let cleanup: (() => Promise<void>) | null = null let cleanup: (() => Promise<void>) | null = null
@@ -114,7 +120,6 @@ describe('MCP Server Tests', () => {
// Connect the tab // Connect the tab
await serviceWorker.evaluate(async () => { await serviceWorker.evaluate(async () => {
// @ts-ignore
await globalThis.toggleExtensionForActiveTab() await globalThis.toggleExtensionForActiveTab()
}) })
@@ -289,7 +294,6 @@ describe('MCP Server Tests', () => {
// 2. Enable extension on this new tab // 2. Enable extension on this new tab
// Since it's a new page, extension is not connected yet // Since it's a new page, extension is not connected yet
const result = await serviceWorker.evaluate(async () => { const result = await serviceWorker.evaluate(async () => {
// @ts-ignore
return await globalThis.toggleExtensionForActiveTab() return await globalThis.toggleExtensionForActiveTab()
}) })
expect(result.isConnected).toBe(true) expect(result.isConnected).toBe(true)
@@ -305,11 +309,10 @@ describe('MCP Server Tests', () => {
expect(foundPage).toBeDefined() expect(foundPage).toBeDefined()
expect(foundPage?.url()).toBe(testUrl) expect(foundPage?.url()).toBe(testUrl)
await directBrowser.close()
// 4. Disable extension on this tab // 4. Disable extension on this tab
const resultDisabled = await serviceWorker.evaluate(async () => { const resultDisabled = await serviceWorker.evaluate(async () => {
// @ts-ignore
return await globalThis.toggleExtensionForActiveTab() return await globalThis.toggleExtensionForActiveTab()
}) })
expect(resultDisabled.isConnected).toBe(false) expect(resultDisabled.isConnected).toBe(false)
@@ -325,11 +328,10 @@ describe('MCP Server Tests', () => {
foundPage = pages.find(p => p.url() === testUrl) foundPage = pages.find(p => p.url() === testUrl)
expect(foundPage).toBeUndefined() expect(foundPage).toBeUndefined()
await directBrowser.close()
// 6. Re-enable extension // 6. Re-enable extension
const resultEnabled = await serviceWorker.evaluate(async () => { const resultEnabled = await serviceWorker.evaluate(async () => {
// @ts-ignore
return await globalThis.toggleExtensionForActiveTab() return await globalThis.toggleExtensionForActiveTab()
}) })
expect(resultEnabled.isConnected).toBe(true) expect(resultEnabled.isConnected).toBe(true)
@@ -351,7 +353,7 @@ describe('MCP Server Tests', () => {
expect(foundPage).toBeDefined() expect(foundPage).toBeDefined()
expect(foundPage?.url()).toBe(testUrl) expect(foundPage?.url()).toBe(testUrl)
await directBrowser.close()
await page.close() await page.close()
}) })
it('should maintain connection across reloads and navigation', async () => { it('should maintain connection across reloads and navigation', async () => {
@@ -366,7 +368,6 @@ describe('MCP Server Tests', () => {
// 2. Enable extension // 2. Enable extension
await serviceWorker.evaluate(async () => { await serviceWorker.evaluate(async () => {
// @ts-ignore
await globalThis.toggleExtensionForActiveTab() await globalThis.toggleExtensionForActiveTab()
}) })
@@ -391,7 +392,7 @@ describe('MCP Server Tests', () => {
expect(connectedPage?.url()).toBe(newUrl) expect(connectedPage?.url()).toBe(newUrl)
expect(await connectedPage?.title()).toContain('Hacker News') expect(await connectedPage?.title()).toContain('Hacker News')
await directBrowser.close()
await page.close() await page.close()
}) })
@@ -406,7 +407,6 @@ describe('MCP Server Tests', () => {
await pageA.bringToFront() await pageA.bringToFront()
await new Promise(resolve => setTimeout(resolve, 500)) await new Promise(resolve => setTimeout(resolve, 500))
await serviceWorker.evaluate(async () => { await serviceWorker.evaluate(async () => {
// @ts-ignore
await globalThis.toggleExtensionForActiveTab() await globalThis.toggleExtensionForActiveTab()
}) })
@@ -416,49 +416,60 @@ describe('MCP Server Tests', () => {
await pageB.bringToFront() await pageB.bringToFront()
await new Promise(resolve => setTimeout(resolve, 500)) await new Promise(resolve => setTimeout(resolve, 500))
await serviceWorker.evaluate(async () => { await serviceWorker.evaluate(async () => {
// @ts-ignore
await globalThis.toggleExtensionForActiveTab() await globalThis.toggleExtensionForActiveTab()
}) })
// Get target IDs for both // Get target IDs for both
const targetIds = await serviceWorker.evaluate(async () => { const targetIds = await serviceWorker.evaluate(async () => {
// @ts-ignore
const state = globalThis.getExtensionState() const state = globalThis.getExtensionState()
// @ts-ignore const chrome = globalThis.chrome
const tabs = await chrome.tabs.query({}) const tabs = await chrome.tabs.query({})
const tabA = tabs.find(t => t.url?.includes('tab-a')) const tabA = tabs.find((t: any) => t.url?.includes('tab-a'))
const tabB = tabs.find(t => t.url?.includes('tab-b')) const tabB = tabs.find((t: any) => t.url?.includes('tab-b'))
return { return {
// @ts-ignore
idA: state.connectedTabs.get(tabA?.id)?.targetId, idA: state.connectedTabs.get(tabA?.id)?.targetId,
// @ts-ignore
idB: state.connectedTabs.get(tabB?.id)?.targetId idB: state.connectedTabs.get(tabB?.id)?.targetId
} }
}) })
expect(targetIds.idA).toBeTruthy() expect(targetIds).toMatchInlineSnapshot({
expect(targetIds.idB).toBeTruthy() idA: expect.any(String),
idB: expect.any(String)
}, `
{
"idA": Any<String>,
"idB": Any<String>,
}
`)
expect(targetIds.idA).not.toBe(targetIds.idB) expect(targetIds.idA).not.toBe(targetIds.idB)
// Verify independent connections // Verify independent connections
const browserA = await chromium.connectOverCDP(getCdpUrl({ clientId: targetIds.idA })) const browser = await chromium.connectOverCDP(getCdpUrl())
const browserB = await chromium.connectOverCDP(getCdpUrl({ clientId: targetIds.idB }))
const titleA = await browserA.contexts()[0].pages()[0].title() const pages = browser.contexts()[0].pages()
const titleB = await browserB.contexts()[0].pages()[0].title()
// Both are "Example Domain" but we verified they are distinct pages via target ID const results = await Promise.all(pages.map(async (p) => ({
expect(titleA).toBe('Example Domain') url: p.url(),
expect(titleB).toBe('Example Domain') title: await p.title()
})))
// Verify URL to be sure expect(results).toMatchInlineSnapshot(`
const urlA = browserA.contexts()[0].pages()[0].url() [
const urlB = browserB.contexts()[0].pages()[0].url() {
expect(urlA).toContain('tab-a') "title": "",
expect(urlB).toContain('tab-b') "url": "about:blank",
},
{
"title": "Example Domain",
"url": "https://example.com/tab-a",
},
{
"title": "Example Domain",
"url": "https://example.com/tab-b",
},
]
`)
await browserA.close()
await browserB.close()
await pageA.close() await pageA.close()
await pageB.close() await pageB.close()
}) })
+1 -1
View File
@@ -1,4 +1,4 @@
export function getCdpUrl({ port = 19988, host = '127.0.0.1', clientId }: { port?: number; host?: string; clientId?: string } = {}) { export function getCdpUrl({ port = 19988, host = '127.0.0.1', clientId }: { port?: number; host?: string; clientId?: string } = {}) {
const id = clientId || Date.now().toString() const id = clientId || Math.random().toString(36).substring(2, 15)
return `ws://${host}:${port}/cdp/${id}` return `ws://${host}:${port}/cdp/${id}`
} }