add browser console log capture and fix test contamination
- Add getLatestLogs function to capture and retrieve browser console logs - Support filtering by page, search string/regex, and count limit - Add clearAllLogs function to prevent log persistence across tests - Make console listeners synchronous using page _guid for immediate capture - Add critical test verifying extension reconnection after disconnectEverything - Preserve console logs across browser reconnections for stability
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@
|
||||
"watch": "pnpm -r watch",
|
||||
"build": "pnpm -r build",
|
||||
"agents.md": "agentsdotmd ./PLAYWRITER_AGENTS.md core.md typescript.md pnpm.md vitest.md changelog.md docs-writing.md github.md playwright.md zod.md gitchamber.md",
|
||||
"release": "pnpm build && changeset"
|
||||
"release": "pnpm build && "
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.29.7",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
## 0.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- **Browser console log capture**: Added `getLatestLogs` function to capture and retrieve browser console logs
|
||||
- Automatically captures up to 5000 logs per page
|
||||
- Logs cleared on page reload/navigation
|
||||
- Logs deleted when page is closed
|
||||
- Supports filtering by page, search string/regex, and count limit
|
||||
- **Fixed test contamination**: Added `clearAllLogs` function to prevent log persistence across tests
|
||||
- **Improved console listener setup**: Made listeners synchronous using page `_guid` for immediate log capture
|
||||
- **Critical reconnection test**: Added test verifying extension reconnection after `disconnectEverything()`
|
||||
- Tests full disconnect/reconnect cycle
|
||||
- Verifies MCP client can reconnect with `resetPlaywright()`
|
||||
- Ensures pages are visible after reconnection
|
||||
- **Persistent console listeners**: Console logs now persist across browser reconnections (not cleared in `resetConnection`)
|
||||
|
||||
## 0.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -706,6 +706,143 @@ describe('MCP Server Tests', () => {
|
||||
await page.close()
|
||||
})
|
||||
|
||||
it('should be able to reconnect after disconnecting everything', async () => {
|
||||
if (!browserContext) throw new Error('Browser not initialized')
|
||||
const serviceWorker = await getExtensionServiceWorker(browserContext)
|
||||
|
||||
// 1. Use the existing about:blank page from beforeAll
|
||||
const pages = await browserContext.pages()
|
||||
expect(pages.length).toBeGreaterThan(0)
|
||||
const page = pages[0]
|
||||
|
||||
await page.goto('https://example.com/disconnect-test')
|
||||
await page.waitForLoadState('networkidle')
|
||||
await page.bringToFront()
|
||||
|
||||
// Enable extension on this page
|
||||
const initialEnable = await serviceWorker.evaluate(async () => {
|
||||
return await globalThis.toggleExtensionForActiveTab()
|
||||
})
|
||||
console.log('Initial enable result:', initialEnable)
|
||||
expect(initialEnable.isConnected).toBe(true)
|
||||
|
||||
// Wait for extension to fully connect
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
|
||||
// Verify MCP can see the page
|
||||
const beforeDisconnect = await client.callTool({
|
||||
name: 'execute',
|
||||
arguments: {
|
||||
code: js`
|
||||
const pages = context.pages();
|
||||
console.log('Pages before disconnect:', pages.length);
|
||||
const testPage = pages.find(p => p.url().includes('disconnect-test'));
|
||||
console.log('Found test page:', !!testPage);
|
||||
return { pagesCount: pages.length, foundTestPage: !!testPage };
|
||||
`,
|
||||
},
|
||||
})
|
||||
|
||||
const beforeOutput = (beforeDisconnect as any).content[0].text
|
||||
expect(beforeOutput).toContain('foundTestPage')
|
||||
console.log('Before disconnect:', beforeOutput)
|
||||
|
||||
// 2. Disconnect everything
|
||||
console.log('Calling disconnectEverything...')
|
||||
await serviceWorker.evaluate(async () => {
|
||||
await globalThis.disconnectEverything()
|
||||
})
|
||||
|
||||
// Wait for disconnect to complete
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
|
||||
// 3. Verify MCP cannot see the page anymore
|
||||
const afterDisconnect = await client.callTool({
|
||||
name: 'execute',
|
||||
arguments: {
|
||||
code: js`
|
||||
const pages = context.pages();
|
||||
console.log('Pages after disconnect:', pages.length);
|
||||
return { pagesCount: pages.length };
|
||||
`,
|
||||
},
|
||||
})
|
||||
|
||||
const afterDisconnectOutput = (afterDisconnect as any).content[0].text
|
||||
console.log('After disconnect:', afterDisconnectOutput)
|
||||
expect(afterDisconnectOutput).toContain('Pages after disconnect: 0')
|
||||
|
||||
// 4. Re-enable extension on the same page
|
||||
console.log('Re-enabling extension...')
|
||||
await page.bringToFront()
|
||||
const reconnectResult = await serviceWorker.evaluate(async () => {
|
||||
console.log('About to call toggleExtensionForActiveTab')
|
||||
const result = await globalThis.toggleExtensionForActiveTab()
|
||||
console.log('toggleExtensionForActiveTab result:', result)
|
||||
return result
|
||||
})
|
||||
|
||||
console.log('Reconnect result:', reconnectResult)
|
||||
expect(reconnectResult.isConnected).toBe(true)
|
||||
|
||||
// Wait for extension to fully reconnect and relay server to be ready
|
||||
console.log('Waiting for reconnection to stabilize...')
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
|
||||
// 5. Reset the MCP client's playwright connection since it was closed by disconnectEverything
|
||||
console.log('Resetting MCP playwright connection...')
|
||||
const resetResult = await client.callTool({
|
||||
name: 'execute',
|
||||
arguments: {
|
||||
code: js`
|
||||
console.log('Resetting playwright connection');
|
||||
const result = await resetPlaywright();
|
||||
console.log('Reset complete, checking pages');
|
||||
const pages = context.pages();
|
||||
console.log('Pages after reset:', pages.length);
|
||||
return { reset: true, pagesCount: pages.length };
|
||||
`,
|
||||
},
|
||||
})
|
||||
console.log('Reset result:', (resetResult as any).content[0].text)
|
||||
|
||||
// 6. Verify MCP can see the page again
|
||||
console.log('Attempting to access page via MCP...')
|
||||
const afterReconnect = await client.callTool({
|
||||
name: 'execute',
|
||||
arguments: {
|
||||
code: js`
|
||||
console.log('Checking pages after reconnect...');
|
||||
const pages = context.pages();
|
||||
console.log('Pages after reconnect:', pages.length);
|
||||
|
||||
if (pages.length === 0) {
|
||||
console.log('No pages found!');
|
||||
return { pagesCount: 0, foundTestPage: false };
|
||||
}
|
||||
|
||||
const testPage = pages.find(p => p.url().includes('disconnect-test'));
|
||||
console.log('Found test page after reconnect:', !!testPage);
|
||||
|
||||
if (testPage) {
|
||||
console.log('Test page URL:', testPage.url());
|
||||
return { pagesCount: pages.length, foundTestPage: true, url: testPage.url() };
|
||||
}
|
||||
|
||||
return { pagesCount: pages.length, foundTestPage: false };
|
||||
`,
|
||||
},
|
||||
})
|
||||
|
||||
const afterReconnectOutput = (afterReconnect as any).content[0].text
|
||||
console.log('After reconnect:', afterReconnectOutput)
|
||||
expect(afterReconnectOutput).toContain('foundTestPage')
|
||||
expect(afterReconnectOutput).toContain('disconnect-test')
|
||||
|
||||
// Clean up - navigate page back to about:blank to not interfere with other tests
|
||||
await page.goto('about:blank')
|
||||
})
|
||||
|
||||
it('should capture browser console logs with getLatestLogs', async () => {
|
||||
// Ensure clean state and clear any existing logs
|
||||
const resetResult = await client.callTool({
|
||||
|
||||
@@ -248,8 +248,8 @@ async function resetConnection(): Promise<{ browser: Browser; page: Page; contex
|
||||
state.context = null
|
||||
state.isConnected = false
|
||||
|
||||
// Clear all browser logs on reset
|
||||
browserLogs.clear()
|
||||
// DO NOT clear browser logs on reset - logs should persist across reconnections
|
||||
// browserLogs.clear()
|
||||
|
||||
await ensureRelayServer()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user