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.
Files changed (47) hide show
  1. package/dist/cdp-session.d.ts +21 -0
  2. package/dist/cdp-session.d.ts.map +1 -0
  3. package/dist/cdp-session.js +131 -0
  4. package/dist/cdp-session.js.map +1 -0
  5. package/dist/cdp-types.d.ts +15 -0
  6. package/dist/cdp-types.d.ts.map +1 -1
  7. package/dist/cdp-types.js.map +1 -1
  8. package/dist/create-logger.d.ts +9 -0
  9. package/dist/create-logger.d.ts.map +1 -0
  10. package/dist/create-logger.js +43 -0
  11. package/dist/create-logger.js.map +1 -0
  12. package/dist/extension/cdp-relay.d.ts +7 -3
  13. package/dist/extension/cdp-relay.d.ts.map +1 -1
  14. package/dist/extension/cdp-relay.js +22 -12
  15. package/dist/extension/cdp-relay.js.map +1 -1
  16. package/dist/mcp.js +86 -44
  17. package/dist/mcp.js.map +1 -1
  18. package/dist/mcp.test.d.ts.map +1 -1
  19. package/dist/mcp.test.js +669 -183
  20. package/dist/mcp.test.js.map +1 -1
  21. package/dist/prompt.md +38 -8
  22. package/dist/selector-generator.js +331 -0
  23. package/dist/start-relay-server.d.ts +1 -3
  24. package/dist/start-relay-server.d.ts.map +1 -1
  25. package/dist/start-relay-server.js +3 -16
  26. package/dist/start-relay-server.js.map +1 -1
  27. package/dist/utils.d.ts +3 -0
  28. package/dist/utils.d.ts.map +1 -1
  29. package/dist/utils.js +36 -0
  30. package/dist/utils.js.map +1 -1
  31. package/dist/wait-for-page-load.d.ts +16 -0
  32. package/dist/wait-for-page-load.d.ts.map +1 -0
  33. package/dist/wait-for-page-load.js +126 -0
  34. package/dist/wait-for-page-load.js.map +1 -0
  35. package/package.json +16 -12
  36. package/src/cdp-session.ts +156 -0
  37. package/src/cdp-types.ts +6 -0
  38. package/src/create-logger.ts +56 -0
  39. package/src/debugger.md +453 -0
  40. package/src/extension/cdp-relay.ts +32 -14
  41. package/src/mcp.test.ts +795 -189
  42. package/src/mcp.ts +101 -47
  43. package/src/prompt.md +38 -8
  44. package/src/snapshots/shadcn-ui-accessibility.md +94 -91
  45. package/src/start-relay-server.ts +3 -20
  46. package/src/utils.ts +45 -0
  47. 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
+ }