Files
playwriter/docs/mcp-page-ready-plan.md
Tommy D. Rossi 2b0a5db49e adding docs
2026-01-01 12:00:02 +01:00

116 lines
2.9 KiB
Markdown

# Plan: Add Deterministic Page Waiting to mcp.ts
## Current Problem
In `mcp.ts`, both `connect()` and `reconnect()` functions:
```typescript
const browser = await chromium.connectOverCDP(cdpEndpoint)
const context = contexts[0]
const pages = context.pages() // May be empty!
if (pages.length === 0) {
throw new Error(NO_TABS_ERROR)
}
```
This fails when:
1. Extension has tabs connected, but...
2. Playwright hasn't finished processing `Target.attachedToTarget` + `Runtime.executionContextCreated` events
## Solution
Use `context.waitForEvent('page')` with a timeout, similar to our test fix.
## Implementation Plan
### Step 1: Create a helper function
```typescript
async function waitForPages(context: BrowserContext, options?: {
timeout?: number
minPages?: number
}): Promise<Page[]> {
const { timeout = 5000, minPages = 1 } = options || {}
// Check if pages already exist
let pages = context.pages()
if (pages.length >= minPages) {
return pages
}
// Wait for page events
const startTime = Date.now()
while (pages.length < minPages && Date.now() - startTime < timeout) {
try {
await context.waitForEvent('page', { timeout: timeout - (Date.now() - startTime) })
pages = context.pages()
} catch {
// Timeout - check one more time
pages = context.pages()
break
}
}
return pages
}
```
### Step 2: Update `connect()` function (line ~305)
```typescript
// Before:
const pages = context.pages()
if (pages.length === 0) {
throw new Error(NO_TABS_ERROR)
}
// After:
const pages = await waitForPages(context, { timeout: 5000 })
if (pages.length === 0) {
throw new Error(NO_TABS_ERROR)
}
```
### Step 3: Update `reconnect()` function (line ~448)
Same change as above.
### Step 4: Consider the "createInitialTab" flow
The relay server has a `createInitialTab` message for when no tabs exist. We should:
1. First try `waitForPages()` with a short timeout (1-2 seconds)
2. If still no pages, request `createInitialTab`
3. Then `waitForPages()` again for the new tab
```typescript
let pages = await waitForPages(context, { timeout: 2000 })
if (pages.length === 0) {
// No tabs - request extension to create one
await requestCreateInitialTab()
pages = await waitForPages(context, { timeout: 5000 })
}
if (pages.length === 0) {
throw new Error(NO_TABS_ERROR)
}
```
## Testing
1. Run existing tests to ensure no regression
2. Add a new test that:
- Connects immediately after extension toggle
- Verifies pages are available without sleep
## Files to Modify
1. `playwriter/src/mcp.ts`:
- Add `waitForPages()` helper
- Update `connect()` function
- Update `reconnect()` function
## Edge Cases
1. **All pages are `about:blank`**: May need to filter for real pages
2. **Extension not connected**: Existing timeout handling should work
3. **Very slow page load**: 5 second timeout should be sufficient for CDP events (actual page content load is not required)