playwriter 0.0.16 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdp-session.d.ts +21 -0
- package/dist/cdp-session.d.ts.map +1 -0
- package/dist/cdp-session.js +131 -0
- package/dist/cdp-session.js.map +1 -0
- package/dist/cdp-types.d.ts +15 -0
- package/dist/cdp-types.d.ts.map +1 -1
- package/dist/cdp-types.js.map +1 -1
- package/dist/create-logger.d.ts +9 -0
- package/dist/create-logger.d.ts.map +1 -0
- package/dist/create-logger.js +43 -0
- package/dist/create-logger.js.map +1 -0
- package/dist/extension/cdp-relay.d.ts +7 -3
- package/dist/extension/cdp-relay.d.ts.map +1 -1
- package/dist/extension/cdp-relay.js +22 -12
- package/dist/extension/cdp-relay.js.map +1 -1
- package/dist/mcp.js +86 -44
- package/dist/mcp.js.map +1 -1
- package/dist/mcp.test.d.ts.map +1 -1
- package/dist/mcp.test.js +669 -183
- package/dist/mcp.test.js.map +1 -1
- package/dist/prompt.md +38 -8
- package/dist/selector-generator.js +331 -0
- package/dist/start-relay-server.d.ts +1 -3
- package/dist/start-relay-server.d.ts.map +1 -1
- package/dist/start-relay-server.js +3 -16
- package/dist/start-relay-server.js.map +1 -1
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +36 -0
- package/dist/utils.js.map +1 -1
- package/dist/wait-for-page-load.d.ts +16 -0
- package/dist/wait-for-page-load.d.ts.map +1 -0
- package/dist/wait-for-page-load.js +126 -0
- package/dist/wait-for-page-load.js.map +1 -0
- package/package.json +16 -12
- package/src/cdp-session.ts +156 -0
- package/src/cdp-types.ts +6 -0
- package/src/create-logger.ts +56 -0
- package/src/debugger.md +453 -0
- package/src/extension/cdp-relay.ts +32 -14
- package/src/mcp.test.ts +795 -189
- package/src/mcp.ts +101 -47
- package/src/prompt.md +38 -8
- package/src/snapshots/shadcn-ui-accessibility.md +94 -91
- package/src/start-relay-server.ts +3 -20
- package/src/utils.ts +45 -0
- package/src/wait-for-page-load.ts +173 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { Page } from 'playwright-core'
|
|
2
|
+
|
|
3
|
+
const FILTERED_DOMAINS = [
|
|
4
|
+
'doubleclick',
|
|
5
|
+
'googlesyndication',
|
|
6
|
+
'googleadservices',
|
|
7
|
+
'google-analytics',
|
|
8
|
+
'googletagmanager',
|
|
9
|
+
'facebook.net',
|
|
10
|
+
'fbcdn.net',
|
|
11
|
+
'twitter.com',
|
|
12
|
+
'linkedin.com',
|
|
13
|
+
'hotjar',
|
|
14
|
+
'mixpanel',
|
|
15
|
+
'segment.io',
|
|
16
|
+
'segment.com',
|
|
17
|
+
'newrelic',
|
|
18
|
+
'datadoghq',
|
|
19
|
+
'sentry.io',
|
|
20
|
+
'fullstory',
|
|
21
|
+
'amplitude',
|
|
22
|
+
'intercom',
|
|
23
|
+
'crisp.chat',
|
|
24
|
+
'zdassets.com',
|
|
25
|
+
'zendesk',
|
|
26
|
+
'tawk.to',
|
|
27
|
+
'hubspot',
|
|
28
|
+
'marketo',
|
|
29
|
+
'pardot',
|
|
30
|
+
'optimizely',
|
|
31
|
+
'crazyegg',
|
|
32
|
+
'mouseflow',
|
|
33
|
+
'clarity.ms',
|
|
34
|
+
'bing.com/bat',
|
|
35
|
+
'ads.',
|
|
36
|
+
'analytics.',
|
|
37
|
+
'tracking.',
|
|
38
|
+
'pixel.',
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
const FILTERED_EXTENSIONS = ['.gif', '.ico', '.cur', '.woff', '.woff2', '.ttf', '.otf', '.eot']
|
|
42
|
+
|
|
43
|
+
export interface WaitForPageLoadOptions {
|
|
44
|
+
page: Page
|
|
45
|
+
timeout?: number
|
|
46
|
+
pollInterval?: number
|
|
47
|
+
minWait?: number
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface WaitForPageLoadResult {
|
|
51
|
+
success: boolean
|
|
52
|
+
readyState: string
|
|
53
|
+
pendingRequests: string[]
|
|
54
|
+
waitTimeMs: number
|
|
55
|
+
timedOut: boolean
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function waitForPageLoad(options: WaitForPageLoadOptions): Promise<WaitForPageLoadResult> {
|
|
59
|
+
const { page, timeout = 30000, pollInterval = 100, minWait = 500 } = options
|
|
60
|
+
|
|
61
|
+
const startTime = Date.now()
|
|
62
|
+
let timedOut = false
|
|
63
|
+
let lastReadyState = ''
|
|
64
|
+
let lastPendingRequests: string[] = []
|
|
65
|
+
|
|
66
|
+
const checkPageReady = async (): Promise<{ ready: boolean; readyState: string; pendingRequests: string[] }> => {
|
|
67
|
+
const result = await page.evaluate(
|
|
68
|
+
({ filteredDomains, filteredExtensions, stuckThreshold, slowResourceThreshold }): {
|
|
69
|
+
ready: boolean
|
|
70
|
+
readyState: string
|
|
71
|
+
pendingRequests: string[]
|
|
72
|
+
} => {
|
|
73
|
+
const doc = globalThis.document as { readyState: string }
|
|
74
|
+
const readyState = doc.readyState
|
|
75
|
+
|
|
76
|
+
if (readyState !== 'complete') {
|
|
77
|
+
return { ready: false, readyState, pendingRequests: [`document.readyState: ${readyState}`] }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const resources = (performance as any).getEntriesByType('resource') as Array<{
|
|
81
|
+
name: string
|
|
82
|
+
startTime: number
|
|
83
|
+
responseEnd: number
|
|
84
|
+
}>
|
|
85
|
+
const now = (performance as any).now() as number
|
|
86
|
+
|
|
87
|
+
const pendingRequests = resources
|
|
88
|
+
.filter((r) => {
|
|
89
|
+
if (r.responseEnd > 0) {
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const elapsed = now - r.startTime
|
|
94
|
+
const url = r.name.toLowerCase()
|
|
95
|
+
|
|
96
|
+
if (url.startsWith('data:')) {
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (filteredDomains.some((domain: string) => url.includes(domain))) {
|
|
101
|
+
return false
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (elapsed > stuckThreshold) {
|
|
105
|
+
return false
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (elapsed > slowResourceThreshold && filteredExtensions.some((ext: string) => url.includes(ext))) {
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return true
|
|
113
|
+
})
|
|
114
|
+
.map((r) => r.name)
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
ready: pendingRequests.length === 0,
|
|
118
|
+
readyState,
|
|
119
|
+
pendingRequests,
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
filteredDomains: FILTERED_DOMAINS,
|
|
124
|
+
filteredExtensions: FILTERED_EXTENSIONS,
|
|
125
|
+
stuckThreshold: 10000,
|
|
126
|
+
slowResourceThreshold: 3000,
|
|
127
|
+
},
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
return result
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
await new Promise((resolve) => setTimeout(resolve, minWait))
|
|
134
|
+
|
|
135
|
+
while (Date.now() - startTime < timeout) {
|
|
136
|
+
try {
|
|
137
|
+
const { ready, readyState, pendingRequests } = await checkPageReady()
|
|
138
|
+
lastReadyState = readyState
|
|
139
|
+
lastPendingRequests = pendingRequests
|
|
140
|
+
|
|
141
|
+
if (ready) {
|
|
142
|
+
return {
|
|
143
|
+
success: true,
|
|
144
|
+
readyState,
|
|
145
|
+
pendingRequests: [],
|
|
146
|
+
waitTimeMs: Date.now() - startTime,
|
|
147
|
+
timedOut: false,
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} catch (e) {
|
|
151
|
+
console.error('[waitForPageLoad] page.evaluate failed:', e)
|
|
152
|
+
return {
|
|
153
|
+
success: false,
|
|
154
|
+
readyState: 'error',
|
|
155
|
+
pendingRequests: ['page.evaluate failed - page may have closed or navigated'],
|
|
156
|
+
waitTimeMs: Date.now() - startTime,
|
|
157
|
+
timedOut: false,
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval))
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
timedOut = true
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
success: false,
|
|
168
|
+
readyState: lastReadyState,
|
|
169
|
+
pendingRequests: lastPendingRequests.slice(0, 10),
|
|
170
|
+
waitTimeMs: Date.now() - startTime,
|
|
171
|
+
timedOut,
|
|
172
|
+
}
|
|
173
|
+
}
|