e2e-pilot 0.0.69
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/bin.js +3 -0
- package/dist/aria-snapshot.d.ts +95 -0
- package/dist/aria-snapshot.d.ts.map +1 -0
- package/dist/aria-snapshot.js +490 -0
- package/dist/aria-snapshot.js.map +1 -0
- package/dist/bippy.js +971 -0
- package/dist/cdp-relay.d.ts +16 -0
- package/dist/cdp-relay.d.ts.map +1 -0
- package/dist/cdp-relay.js +715 -0
- package/dist/cdp-relay.js.map +1 -0
- package/dist/cdp-session.d.ts +42 -0
- package/dist/cdp-session.d.ts.map +1 -0
- package/dist/cdp-session.js +154 -0
- package/dist/cdp-session.js.map +1 -0
- package/dist/cdp-types.d.ts +63 -0
- package/dist/cdp-types.d.ts.map +1 -0
- package/dist/cdp-types.js +91 -0
- package/dist/cdp-types.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +213 -0
- package/dist/cli.js.map +1 -0
- package/dist/create-logger.d.ts +9 -0
- package/dist/create-logger.d.ts.map +1 -0
- package/dist/create-logger.js +25 -0
- package/dist/create-logger.js.map +1 -0
- package/dist/debugger-api.md +458 -0
- package/dist/debugger-examples-types.d.ts +24 -0
- package/dist/debugger-examples-types.d.ts.map +1 -0
- package/dist/debugger-examples-types.js +2 -0
- package/dist/debugger-examples-types.js.map +1 -0
- package/dist/debugger-examples.d.ts +6 -0
- package/dist/debugger-examples.d.ts.map +1 -0
- package/dist/debugger-examples.js +53 -0
- package/dist/debugger-examples.js.map +1 -0
- package/dist/debugger.d.ts +381 -0
- package/dist/debugger.d.ts.map +1 -0
- package/dist/debugger.js +633 -0
- package/dist/debugger.js.map +1 -0
- package/dist/editor-api.md +364 -0
- package/dist/editor-examples.d.ts +11 -0
- package/dist/editor-examples.d.ts.map +1 -0
- package/dist/editor-examples.js +124 -0
- package/dist/editor-examples.js.map +1 -0
- package/dist/editor.d.ts +203 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +336 -0
- package/dist/editor.js.map +1 -0
- package/dist/execute.d.ts +50 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +576 -0
- package/dist/execute.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-client.d.ts +20 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +56 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/mcp.d.ts +5 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +720 -0
- package/dist/mcp.js.map +1 -0
- package/dist/mcp.test.d.ts +10 -0
- package/dist/mcp.test.d.ts.map +1 -0
- package/dist/mcp.test.js +2999 -0
- package/dist/mcp.test.js.map +1 -0
- package/dist/network-capture.d.ts +23 -0
- package/dist/network-capture.d.ts.map +1 -0
- package/dist/network-capture.js +98 -0
- package/dist/network-capture.js.map +1 -0
- package/dist/protocol.d.ts +54 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +2 -0
- package/dist/protocol.js.map +1 -0
- package/dist/react-source.d.ts +13 -0
- package/dist/react-source.d.ts.map +1 -0
- package/dist/react-source.js +68 -0
- package/dist/react-source.js.map +1 -0
- package/dist/scoped-fs.d.ts +94 -0
- package/dist/scoped-fs.d.ts.map +1 -0
- package/dist/scoped-fs.js +356 -0
- package/dist/scoped-fs.js.map +1 -0
- package/dist/selector-generator.js +8126 -0
- package/dist/start-relay-server.d.ts +6 -0
- package/dist/start-relay-server.d.ts.map +1 -0
- package/dist/start-relay-server.js +33 -0
- package/dist/start-relay-server.js.map +1 -0
- package/dist/styles-api.md +117 -0
- package/dist/styles-examples.d.ts +8 -0
- package/dist/styles-examples.d.ts.map +1 -0
- package/dist/styles-examples.js +64 -0
- package/dist/styles-examples.js.map +1 -0
- package/dist/styles.d.ts +27 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +234 -0
- package/dist/styles.js.map +1 -0
- package/dist/trace-utils.d.ts +14 -0
- package/dist/trace-utils.d.ts.map +1 -0
- package/dist/trace-utils.js +21 -0
- package/dist/trace-utils.js.map +1 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +75 -0
- package/dist/utils.js.map +1 -0
- 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 +127 -0
- package/dist/wait-for-page-load.js.map +1 -0
- package/package.json +67 -0
- package/src/aria-snapshot.ts +610 -0
- package/src/assets/aria-labels-github-snapshot.txt +605 -0
- package/src/assets/aria-labels-github.png +0 -0
- package/src/assets/aria-labels-google-snapshot.txt +49 -0
- package/src/assets/aria-labels-google.png +0 -0
- package/src/assets/aria-labels-hacker-news-snapshot.txt +1023 -0
- package/src/assets/aria-labels-hacker-news.png +0 -0
- package/src/cdp-relay.ts +925 -0
- package/src/cdp-session.ts +203 -0
- package/src/cdp-timing.md +128 -0
- package/src/cdp-types.ts +155 -0
- package/src/cli.ts +250 -0
- package/src/create-logger.ts +36 -0
- package/src/debugger-examples-types.ts +13 -0
- package/src/debugger-examples.ts +66 -0
- package/src/debugger.md +453 -0
- package/src/debugger.ts +713 -0
- package/src/editor-examples.ts +148 -0
- package/src/editor.ts +390 -0
- package/src/execute.ts +763 -0
- package/src/index.ts +10 -0
- package/src/mcp-client.ts +78 -0
- package/src/mcp.test.ts +3596 -0
- package/src/mcp.ts +876 -0
- package/src/network-capture.ts +140 -0
- package/src/prompt.bak.md +323 -0
- package/src/prompt.md +7 -0
- package/src/protocol.ts +63 -0
- package/src/react-source.ts +94 -0
- package/src/resource.md +436 -0
- package/src/scoped-fs.ts +411 -0
- package/src/snapshots/hacker-news-focused-accessibility.md +202 -0
- package/src/snapshots/hacker-news-initial-accessibility.md +11 -0
- package/src/snapshots/hacker-news-tabbed-accessibility.md +202 -0
- package/src/snapshots/shadcn-ui-accessibility.md +11 -0
- package/src/start-relay-server.ts +43 -0
- package/src/styles-examples.ts +77 -0
- package/src/styles.ts +345 -0
- package/src/trace-utils.ts +43 -0
- package/src/utils.ts +91 -0
- package/src/wait-for-page-load.ts +174 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
- table [ref=e3]:
|
|
2
|
+
- rowgroup [ref=e4]:
|
|
3
|
+
- row "Hacker Newsnew | past | comments | ask | show | jobs | submit login" [ref=e5]:
|
|
4
|
+
- cell "Hacker Newsnew | past | comments | ask | show | jobs | submit login" [ref=e6]:
|
|
5
|
+
- table [ref=e7]:
|
|
6
|
+
- rowgroup [ref=e8]:
|
|
7
|
+
- row "Hacker Newsnew | past | comments | ask | show | jobs | submit login" [ref=e9]:
|
|
8
|
+
- cell [ref=e10]:
|
|
9
|
+
- link [ref=e11] [cursor=pointer]:
|
|
10
|
+
- /url: https://news.ycombinator.com
|
|
11
|
+
- img [ref=e12] [cursor=pointer]
|
|
12
|
+
- cell "Hacker Newsnew | past | comments | ask | show | jobs | submit" [ref=e13]:
|
|
13
|
+
- generic [ref=e14]:
|
|
14
|
+
- link "Hacker News" [active] [ref=e16] [cursor=pointer]:
|
|
15
|
+
- /url: news
|
|
16
|
+
- link "new" [ref=e17] [cursor=pointer]:
|
|
17
|
+
- /url: newest
|
|
18
|
+
- text: "|"
|
|
19
|
+
- link "past" [ref=e18] [cursor=pointer]:
|
|
20
|
+
- /url: front
|
|
21
|
+
- text: "|"
|
|
22
|
+
- link "comments" [ref=e19] [cursor=pointer]:
|
|
23
|
+
- /url: newcomments
|
|
24
|
+
- text: "|"
|
|
25
|
+
- link "ask" [ref=e20] [cursor=pointer]:
|
|
26
|
+
- /url: ask
|
|
27
|
+
- text: "|"
|
|
28
|
+
- link "show" [ref=e21] [cursor=pointer]:
|
|
29
|
+
- /url: show
|
|
30
|
+
- text: "|"
|
|
31
|
+
- link "jobs" [ref=e22] [cursor=pointer]:
|
|
32
|
+
- /url: jobs
|
|
33
|
+
- text: "|"
|
|
34
|
+
- link "submit" [ref=e23] [cursor=pointer]:
|
|
35
|
+
- /url: submit
|
|
36
|
+
- cell "login" [ref=e24]:
|
|
37
|
+
- link "login" [ref=e26] [cursor=pointer]:
|
|
38
|
+
- /url: login?goto=item%3Fid%3D1
|
|
39
|
+
- row [ref=e27]
|
|
40
|
+
- row "upvote Y Combinator (ycombinator.com) 57 points by pg on Oct 9, 2006 | hide | past | favorite | 3 comments upvote sama on Oct 9, 2006 [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR upvote pg on Oct 9, 2006 | [–] Is there anywhere to eat on Sandhill Road? upvote dmon on Feb 25, 2007 | | [–] sure" [ref=e28]:
|
|
41
|
+
- cell "upvote Y Combinator (ycombinator.com) 57 points by pg on Oct 9, 2006 | hide | past | favorite | 3 comments upvote sama on Oct 9, 2006 [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR upvote pg on Oct 9, 2006 | [–] Is there anywhere to eat on Sandhill Road? upvote dmon on Feb 25, 2007 | | [–] sure" [ref=e29]:
|
|
42
|
+
- table [ref=e30]:
|
|
43
|
+
- rowgroup [ref=e31]:
|
|
44
|
+
- row "upvote Y Combinator (ycombinator.com)" [ref=e32]:
|
|
45
|
+
- cell [ref=e33]
|
|
46
|
+
- cell "upvote" [ref=e35]:
|
|
47
|
+
- link "upvote" [ref=e37] [cursor=pointer]:
|
|
48
|
+
- /url: vote?id=1&how=up&goto=item%3Fid%3D1
|
|
49
|
+
- cell "Y Combinator (ycombinator.com)" [ref=e39]:
|
|
50
|
+
- generic [ref=e40]:
|
|
51
|
+
- link "Y Combinator" [ref=e41] [cursor=pointer]:
|
|
52
|
+
- /url: http://ycombinator.com
|
|
53
|
+
- generic [ref=e42]:
|
|
54
|
+
- text: (
|
|
55
|
+
- link "ycombinator.com" [ref=e43] [cursor=pointer]:
|
|
56
|
+
- /url: from?site=ycombinator.com
|
|
57
|
+
- generic [ref=e44] [cursor=pointer]: ycombinator.com
|
|
58
|
+
- text: )
|
|
59
|
+
- row "57 points by pg on Oct 9, 2006 | hide | past | favorite | 3 comments" [ref=e45]:
|
|
60
|
+
- cell [ref=e46]
|
|
61
|
+
- cell "57 points by pg on Oct 9, 2006 | hide | past | favorite | 3 comments" [ref=e47]:
|
|
62
|
+
- generic [ref=e48]:
|
|
63
|
+
- generic [ref=e49]: 57 points
|
|
64
|
+
- text: by
|
|
65
|
+
- link "pg" [ref=e50] [cursor=pointer]:
|
|
66
|
+
- /url: user?id=pg
|
|
67
|
+
- link "on Oct 9, 2006" [ref=e52] [cursor=pointer]:
|
|
68
|
+
- /url: item?id=1
|
|
69
|
+
- text: "|"
|
|
70
|
+
- link "hide" [ref=e54] [cursor=pointer]:
|
|
71
|
+
- /url: hide?id=1&goto=item%3Fid%3D1
|
|
72
|
+
- text: "|"
|
|
73
|
+
- link "past" [ref=e55] [cursor=pointer]:
|
|
74
|
+
- /url: https://hn.algolia.com/?query=Y%20Combinator&type=story&dateRange=all&sort=byDate&storyText=false&prefix&page=0
|
|
75
|
+
- text: "|"
|
|
76
|
+
- link "favorite" [ref=e56] [cursor=pointer]:
|
|
77
|
+
- /url: fave?id=1&auth=5328fcfde7333d68e67a8a2334e25acee5599932
|
|
78
|
+
- text: "|"
|
|
79
|
+
- link "3 comments" [ref=e57] [cursor=pointer]:
|
|
80
|
+
- /url: item?id=1
|
|
81
|
+
- row [ref=e58]:
|
|
82
|
+
- cell [ref=e59]
|
|
83
|
+
- cell [ref=e60]
|
|
84
|
+
- table [ref=e63]:
|
|
85
|
+
- rowgroup [ref=e64]:
|
|
86
|
+
- row "upvote sama on Oct 9, 2006 [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e65]:
|
|
87
|
+
- cell "upvote sama on Oct 9, 2006 [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e66]:
|
|
88
|
+
- table [ref=e67]:
|
|
89
|
+
- rowgroup [ref=e68]:
|
|
90
|
+
- row "upvote sama on Oct 9, 2006 [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e69]:
|
|
91
|
+
- cell [ref=e70]:
|
|
92
|
+
- img
|
|
93
|
+
- cell "upvote" [ref=e72]:
|
|
94
|
+
- link "upvote" [ref=e74] [cursor=pointer]:
|
|
95
|
+
- /url: vote?id=15&how=up&goto=item%3Fid%3D1
|
|
96
|
+
- cell "sama on Oct 9, 2006 [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e76]:
|
|
97
|
+
- generic [ref=e78]:
|
|
98
|
+
- link "sama" [ref=e79] [cursor=pointer]:
|
|
99
|
+
- /url: user?id=sama
|
|
100
|
+
- link "on Oct 9, 2006" [ref=e81] [cursor=pointer]:
|
|
101
|
+
- /url: item?id=15
|
|
102
|
+
- link "[–]" [ref=e84] [cursor=pointer]:
|
|
103
|
+
- /url: javascript:void(0)
|
|
104
|
+
- generic [ref=e87]:
|
|
105
|
+
- generic [ref=e88]: "\"the rising star of venture capital\" -unknown VC eating lunch on SHR"
|
|
106
|
+
- generic:
|
|
107
|
+
- paragraph
|
|
108
|
+
- row "upvote pg on Oct 9, 2006 | [–] Is there anywhere to eat on Sandhill Road?" [ref=e92]:
|
|
109
|
+
- cell "upvote pg on Oct 9, 2006 | [–] Is there anywhere to eat on Sandhill Road?" [ref=e93]:
|
|
110
|
+
- table [ref=e94]:
|
|
111
|
+
- rowgroup [ref=e95]:
|
|
112
|
+
- row "upvote pg on Oct 9, 2006 | [–] Is there anywhere to eat on Sandhill Road?" [ref=e96]:
|
|
113
|
+
- cell [ref=e97]:
|
|
114
|
+
- img [ref=e98]
|
|
115
|
+
- cell "upvote" [ref=e99]:
|
|
116
|
+
- link "upvote" [ref=e101] [cursor=pointer]:
|
|
117
|
+
- /url: vote?id=17&how=up&goto=item%3Fid%3D1
|
|
118
|
+
- cell "pg on Oct 9, 2006 | [–] Is there anywhere to eat on Sandhill Road?" [ref=e103]:
|
|
119
|
+
- generic [ref=e105]:
|
|
120
|
+
- link "pg" [ref=e106] [cursor=pointer]:
|
|
121
|
+
- /url: user?id=pg
|
|
122
|
+
- link "on Oct 9, 2006" [ref=e108] [cursor=pointer]:
|
|
123
|
+
- /url: item?id=17
|
|
124
|
+
- generic [ref=e110]:
|
|
125
|
+
- text: "|"
|
|
126
|
+
- link [ref=e111] [cursor=pointer]:
|
|
127
|
+
- /url: "#15"
|
|
128
|
+
- text: parent
|
|
129
|
+
- link "[–]" [ref=e112] [cursor=pointer]:
|
|
130
|
+
- /url: javascript:void(0)
|
|
131
|
+
- generic [ref=e115]:
|
|
132
|
+
- generic [ref=e116]: Is there anywhere to eat on Sandhill Road?
|
|
133
|
+
- generic:
|
|
134
|
+
- paragraph
|
|
135
|
+
- row "upvote dmon on Feb 25, 2007 | | [–] sure" [ref=e120]:
|
|
136
|
+
- cell "upvote dmon on Feb 25, 2007 | | [–] sure" [ref=e121]:
|
|
137
|
+
- table [ref=e122]:
|
|
138
|
+
- rowgroup [ref=e123]:
|
|
139
|
+
- row "upvote dmon on Feb 25, 2007 | | [–] sure" [ref=e124]:
|
|
140
|
+
- cell [ref=e125]:
|
|
141
|
+
- img [ref=e126]
|
|
142
|
+
- cell "upvote" [ref=e127]:
|
|
143
|
+
- link "upvote" [ref=e129] [cursor=pointer]:
|
|
144
|
+
- /url: vote?id=1079&how=up&goto=item%3Fid%3D1
|
|
145
|
+
- cell "dmon on Feb 25, 2007 | | [–] sure" [ref=e131]:
|
|
146
|
+
- generic [ref=e133]:
|
|
147
|
+
- link "dmon" [ref=e134] [cursor=pointer]:
|
|
148
|
+
- /url: user?id=dmon
|
|
149
|
+
- link "on Feb 25, 2007" [ref=e136] [cursor=pointer]:
|
|
150
|
+
- /url: item?id=1079
|
|
151
|
+
- generic [ref=e138]:
|
|
152
|
+
- text: "|"
|
|
153
|
+
- link [ref=e139] [cursor=pointer]:
|
|
154
|
+
- /url: "#15"
|
|
155
|
+
- text: root
|
|
156
|
+
- text: "|"
|
|
157
|
+
- link [ref=e140] [cursor=pointer]:
|
|
158
|
+
- /url: "#17"
|
|
159
|
+
- text: parent
|
|
160
|
+
- link "[–]" [ref=e141] [cursor=pointer]:
|
|
161
|
+
- /url: javascript:void(0)
|
|
162
|
+
- generic [ref=e144]:
|
|
163
|
+
- generic [ref=e145]: sure
|
|
164
|
+
- generic:
|
|
165
|
+
- paragraph
|
|
166
|
+
- row "Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4 Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact Search:" [ref=e151]:
|
|
167
|
+
- cell "Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4 Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact Search:" [ref=e152]:
|
|
168
|
+
- img
|
|
169
|
+
- table [ref=e154]:
|
|
170
|
+
- rowgroup [ref=e155]:
|
|
171
|
+
- row [ref=e156]:
|
|
172
|
+
- cell [ref=e157]
|
|
173
|
+
- link "Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4" [ref=e160] [cursor=pointer]:
|
|
174
|
+
- /url: https://www.ycombinator.com/apply/
|
|
175
|
+
- generic [ref=e162]:
|
|
176
|
+
- generic [ref=e163]:
|
|
177
|
+
- link "Guidelines" [ref=e164] [cursor=pointer]:
|
|
178
|
+
- /url: newsguidelines.html
|
|
179
|
+
- text: "|"
|
|
180
|
+
- link "FAQ" [ref=e165] [cursor=pointer]:
|
|
181
|
+
- /url: newsfaq.html
|
|
182
|
+
- text: "|"
|
|
183
|
+
- link "Lists" [ref=e166] [cursor=pointer]:
|
|
184
|
+
- /url: lists
|
|
185
|
+
- text: "|"
|
|
186
|
+
- link "API" [ref=e167] [cursor=pointer]:
|
|
187
|
+
- /url: https://github.com/HackerNews/API
|
|
188
|
+
- text: "|"
|
|
189
|
+
- link "Security" [ref=e168] [cursor=pointer]:
|
|
190
|
+
- /url: security.html
|
|
191
|
+
- text: "|"
|
|
192
|
+
- link "Legal" [ref=e169] [cursor=pointer]:
|
|
193
|
+
- /url: https://www.ycombinator.com/legal/
|
|
194
|
+
- text: "|"
|
|
195
|
+
- link "Apply to YC" [ref=e170] [cursor=pointer]:
|
|
196
|
+
- /url: https://www.ycombinator.com/apply/
|
|
197
|
+
- text: "|"
|
|
198
|
+
- link "Contact" [ref=e171] [cursor=pointer]:
|
|
199
|
+
- /url: mailto:hn@ycombinator.com
|
|
200
|
+
- generic [ref=e174]:
|
|
201
|
+
- text: "Search:"
|
|
202
|
+
- textbox [ref=e175]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { startE2EPilotCDPRelayServer } from './cdp-relay.js'
|
|
2
|
+
import { createFileLogger } from './create-logger.js'
|
|
3
|
+
|
|
4
|
+
process.title = 'e2e-pilot-ws-server'
|
|
5
|
+
|
|
6
|
+
const logger = createFileLogger()
|
|
7
|
+
|
|
8
|
+
process.on('uncaughtException', async (err) => {
|
|
9
|
+
await logger.error('Uncaught Exception:', err);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
process.on('unhandledRejection', async (reason) => {
|
|
14
|
+
await logger.error('Unhandled Rejection:', reason);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
process.on('exit', async (code) => {
|
|
19
|
+
await logger.log(`Process exiting with code: ${code}`);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
export async function startServer({ port = 19988, host = '127.0.0.1', token }: { port?: number; host?: string; token?: string } = {}) {
|
|
24
|
+
const server = await startE2EPilotCDPRelayServer({ port, host, token, logger })
|
|
25
|
+
|
|
26
|
+
console.log('CDP Relay Server running. Press Ctrl+C to stop.')
|
|
27
|
+
console.log('Logs are being written to:', logger.logFilePath)
|
|
28
|
+
|
|
29
|
+
process.on('SIGINT', () => {
|
|
30
|
+
console.log('\nShutting down...')
|
|
31
|
+
server.close()
|
|
32
|
+
process.exit(0)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
process.on('SIGTERM', () => {
|
|
36
|
+
console.log('\nShutting down...')
|
|
37
|
+
server.close()
|
|
38
|
+
process.exit(0)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
return server
|
|
42
|
+
}
|
|
43
|
+
startServer().catch(logger.error)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { page, getStylesForLocator, formatStylesAsText, console } from './debugger-examples-types.js'
|
|
2
|
+
|
|
3
|
+
// Example: Get styles for an element and display them
|
|
4
|
+
async function getElementStyles() {
|
|
5
|
+
const loc = page.locator('.my-button')
|
|
6
|
+
const styles = await getStylesForLocator({ locator: loc })
|
|
7
|
+
console.log(formatStylesAsText(styles))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Example: Inspect computed styles for a specific element
|
|
11
|
+
async function inspectButtonStyles() {
|
|
12
|
+
const button = page.getByRole('button', { name: 'Submit' })
|
|
13
|
+
const styles = await getStylesForLocator({ locator: button })
|
|
14
|
+
|
|
15
|
+
console.log('Element:', styles.element)
|
|
16
|
+
|
|
17
|
+
if (styles.inlineStyle) {
|
|
18
|
+
console.log('Inline styles:', styles.inlineStyle)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (const rule of styles.rules) {
|
|
22
|
+
console.log(`${rule.selector}: ${JSON.stringify(rule.declarations)}`)
|
|
23
|
+
if (rule.source) {
|
|
24
|
+
console.log(` Source: ${rule.source.url}:${rule.source.line}`)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Example: Include browser default (user-agent) styles
|
|
30
|
+
async function getStylesWithUserAgent() {
|
|
31
|
+
const loc = page.locator('input[type="text"]')
|
|
32
|
+
const styles = await getStylesForLocator({
|
|
33
|
+
locator: loc,
|
|
34
|
+
includeUserAgentStyles: true,
|
|
35
|
+
})
|
|
36
|
+
console.log(formatStylesAsText(styles))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Example: Find where a CSS property is defined
|
|
40
|
+
async function findPropertySource() {
|
|
41
|
+
const loc = page.locator('.card')
|
|
42
|
+
const styles = await getStylesForLocator({ locator: loc })
|
|
43
|
+
|
|
44
|
+
const backgroundRule = styles.rules.find((r) => 'background-color' in r.declarations)
|
|
45
|
+
if (backgroundRule) {
|
|
46
|
+
console.log('background-color defined by:', backgroundRule.selector)
|
|
47
|
+
if (backgroundRule.source) {
|
|
48
|
+
console.log(` at ${backgroundRule.source.url}:${backgroundRule.source.line}`)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Example: Check inherited styles
|
|
54
|
+
async function checkInheritedStyles() {
|
|
55
|
+
const loc = page.locator('.nested-text')
|
|
56
|
+
const styles = await getStylesForLocator({ locator: loc })
|
|
57
|
+
|
|
58
|
+
const inheritedRules = styles.rules.filter((r) => r.inheritedFrom)
|
|
59
|
+
for (const rule of inheritedRules) {
|
|
60
|
+
console.log(`Inherited from ${rule.inheritedFrom}: ${rule.selector}`)
|
|
61
|
+
console.log(' Properties:', rule.declarations)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Example: Compare styles between two elements
|
|
66
|
+
async function compareStyles() {
|
|
67
|
+
const primary = await getStylesForLocator({ locator: page.locator('.btn-primary') })
|
|
68
|
+
const secondary = await getStylesForLocator({ locator: page.locator('.btn-secondary') })
|
|
69
|
+
|
|
70
|
+
console.log('Primary button:')
|
|
71
|
+
console.log(formatStylesAsText(primary))
|
|
72
|
+
|
|
73
|
+
console.log('Secondary button:')
|
|
74
|
+
console.log(formatStylesAsText(secondary))
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { getElementStyles, inspectButtonStyles, getStylesWithUserAgent, findPropertySource, checkInheritedStyles, compareStyles }
|
package/src/styles.ts
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import type { ICDPSession, CDPSession } from './cdp-session.js'
|
|
2
|
+
import type { Locator } from 'playwright-core'
|
|
3
|
+
|
|
4
|
+
export interface StyleSource {
|
|
5
|
+
url: string
|
|
6
|
+
line: number
|
|
7
|
+
column: number
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type StyleDeclarations = Record<string, string>
|
|
11
|
+
|
|
12
|
+
export interface StyleRule {
|
|
13
|
+
selector: string
|
|
14
|
+
source: StyleSource | null
|
|
15
|
+
origin: 'regular' | 'user-agent' | 'injected' | 'inspector'
|
|
16
|
+
declarations: StyleDeclarations
|
|
17
|
+
inheritedFrom: string | null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface StylesResult {
|
|
21
|
+
element: string
|
|
22
|
+
inlineStyle: StyleDeclarations | null
|
|
23
|
+
rules: StyleRule[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface CSSProperty {
|
|
27
|
+
name: string
|
|
28
|
+
value: string
|
|
29
|
+
important?: boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface CSSStyle {
|
|
33
|
+
cssProperties: CSSProperty[]
|
|
34
|
+
cssText?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface CSSRule {
|
|
38
|
+
selectorList: { text: string }
|
|
39
|
+
style: CSSStyle
|
|
40
|
+
styleSheetId?: string
|
|
41
|
+
origin: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface RuleMatch {
|
|
45
|
+
rule: CSSRule
|
|
46
|
+
matchingSelectors: number[]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface InheritedStyleEntry {
|
|
50
|
+
inlineStyle?: CSSStyle
|
|
51
|
+
matchedCSSRules: RuleMatch[]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface SourceRange {
|
|
55
|
+
startLine: number
|
|
56
|
+
startColumn: number
|
|
57
|
+
endLine: number
|
|
58
|
+
endColumn: number
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface CSSStyleSheetHeader {
|
|
62
|
+
styleSheetId: string
|
|
63
|
+
sourceURL?: string
|
|
64
|
+
origin: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function getStylesForLocator({
|
|
68
|
+
locator,
|
|
69
|
+
cdp: cdpSession,
|
|
70
|
+
includeUserAgentStyles = false,
|
|
71
|
+
}: {
|
|
72
|
+
locator: Locator
|
|
73
|
+
cdp: ICDPSession
|
|
74
|
+
includeUserAgentStyles?: boolean
|
|
75
|
+
}): Promise<StylesResult> {
|
|
76
|
+
// Cast to CDPSession for internal type safety - at runtime both are compatible
|
|
77
|
+
const cdp = cdpSession as CDPSession
|
|
78
|
+
await cdp.send('DOM.enable')
|
|
79
|
+
await cdp.send('CSS.enable')
|
|
80
|
+
|
|
81
|
+
const elementHandle = await locator.elementHandle()
|
|
82
|
+
if (!elementHandle) {
|
|
83
|
+
throw new Error('Could not get element handle from locator')
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const remoteObject = (elementHandle as any)._channel?.objectId
|
|
87
|
+
? { objectId: (elementHandle as any)._channel.objectId }
|
|
88
|
+
: null
|
|
89
|
+
|
|
90
|
+
let backendNodeId: number
|
|
91
|
+
if (remoteObject?.objectId) {
|
|
92
|
+
const nodeInfo = await cdp.send('DOM.describeNode', {
|
|
93
|
+
objectId: remoteObject.objectId,
|
|
94
|
+
})
|
|
95
|
+
backendNodeId = nodeInfo.node.backendNodeId
|
|
96
|
+
} else {
|
|
97
|
+
const box = await elementHandle.boundingBox()
|
|
98
|
+
if (!box) {
|
|
99
|
+
throw new Error('Element has no bounding box')
|
|
100
|
+
}
|
|
101
|
+
const docResult = await cdp.send('DOM.getDocument', { depth: 0 })
|
|
102
|
+
const nodeAtPoint = await cdp.send('DOM.getNodeForLocation', {
|
|
103
|
+
x: Math.round(box.x + box.width / 2),
|
|
104
|
+
y: Math.round(box.y + box.height / 2),
|
|
105
|
+
})
|
|
106
|
+
backendNodeId = nodeAtPoint.backendNodeId
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const pushResult = await cdp.send('DOM.pushNodesByBackendIdsToFrontend', {
|
|
110
|
+
backendNodeIds: [backendNodeId],
|
|
111
|
+
})
|
|
112
|
+
const nodeId = pushResult.nodeIds[0]
|
|
113
|
+
|
|
114
|
+
if (!nodeId) {
|
|
115
|
+
throw new Error('Could not get nodeId for element')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const nodeInfo = await cdp.send('DOM.describeNode', { nodeId })
|
|
119
|
+
const elementDescription = formatElementDescription(nodeInfo.node)
|
|
120
|
+
|
|
121
|
+
const matchedStyles = await cdp.send('CSS.getMatchedStylesForNode', { nodeId })
|
|
122
|
+
|
|
123
|
+
const stylesheetUrls = new Map<string, string>()
|
|
124
|
+
|
|
125
|
+
const processStyleSheetId = async (styleSheetId: string | undefined): Promise<StyleSource | null> => {
|
|
126
|
+
if (!styleSheetId) {
|
|
127
|
+
return null
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (!stylesheetUrls.has(styleSheetId)) {
|
|
131
|
+
try {
|
|
132
|
+
const header = await cdp.send('CSS.getStyleSheetText', { styleSheetId })
|
|
133
|
+
stylesheetUrls.set(styleSheetId, '')
|
|
134
|
+
} catch {
|
|
135
|
+
stylesheetUrls.set(styleSheetId, '')
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return null
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const rules: StyleRule[] = []
|
|
143
|
+
|
|
144
|
+
if (matchedStyles.matchedCSSRules) {
|
|
145
|
+
for (const ruleMatch of matchedStyles.matchedCSSRules) {
|
|
146
|
+
const rule = ruleMatch.rule
|
|
147
|
+
const sourceRange = (rule as any).selectorList?.range as SourceRange | undefined
|
|
148
|
+
const styleSheetId = rule.styleSheetId
|
|
149
|
+
|
|
150
|
+
let source: StyleSource | null = null
|
|
151
|
+
if (styleSheetId && sourceRange) {
|
|
152
|
+
const styleSheet = (matchedStyles as any).cssStyleSheetHeaders?.find(
|
|
153
|
+
(h: CSSStyleSheetHeader) => h.styleSheetId === styleSheetId
|
|
154
|
+
)
|
|
155
|
+
const url = styleSheet?.sourceURL || (rule as any).origin === 'user-agent' ? 'user-agent' : `stylesheet:${styleSheetId}`
|
|
156
|
+
|
|
157
|
+
source = {
|
|
158
|
+
url: (rule as any).styleSheetId ? await getStylesheetUrl(cdp, styleSheetId) : 'user-agent',
|
|
159
|
+
line: sourceRange.startLine + 1,
|
|
160
|
+
column: sourceRange.startColumn,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
rules.push({
|
|
165
|
+
selector: rule.selectorList.text,
|
|
166
|
+
source,
|
|
167
|
+
origin: rule.origin as StyleRule['origin'],
|
|
168
|
+
declarations: extractDeclarations(rule.style),
|
|
169
|
+
inheritedFrom: null,
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (matchedStyles.inherited) {
|
|
175
|
+
for (let i = 0; i < matchedStyles.inherited.length; i++) {
|
|
176
|
+
const inheritedEntry = matchedStyles.inherited[i] as InheritedStyleEntry
|
|
177
|
+
const ancestorDesc = `ancestor[${i + 1}]`
|
|
178
|
+
|
|
179
|
+
if (inheritedEntry.inlineStyle) {
|
|
180
|
+
const declarations = extractDeclarations(inheritedEntry.inlineStyle)
|
|
181
|
+
if (Object.keys(declarations).length > 0) {
|
|
182
|
+
rules.push({
|
|
183
|
+
selector: 'element.style',
|
|
184
|
+
source: null,
|
|
185
|
+
origin: 'regular',
|
|
186
|
+
declarations,
|
|
187
|
+
inheritedFrom: ancestorDesc,
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
for (const ruleMatch of inheritedEntry.matchedCSSRules) {
|
|
193
|
+
const rule = ruleMatch.rule
|
|
194
|
+
const sourceRange = (rule as any).selectorList?.range as SourceRange | undefined
|
|
195
|
+
const styleSheetId = rule.styleSheetId
|
|
196
|
+
|
|
197
|
+
let source: StyleSource | null = null
|
|
198
|
+
if (styleSheetId && sourceRange) {
|
|
199
|
+
source = {
|
|
200
|
+
url: await getStylesheetUrl(cdp, styleSheetId),
|
|
201
|
+
line: sourceRange.startLine + 1,
|
|
202
|
+
column: sourceRange.startColumn,
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const declarations = extractDeclarations(rule.style)
|
|
207
|
+
if (Object.keys(declarations).length > 0) {
|
|
208
|
+
rules.push({
|
|
209
|
+
selector: rule.selectorList.text,
|
|
210
|
+
source,
|
|
211
|
+
origin: rule.origin as StyleRule['origin'],
|
|
212
|
+
declarations,
|
|
213
|
+
inheritedFrom: ancestorDesc,
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
let inlineStyle: StyleDeclarations | null = null
|
|
221
|
+
if (matchedStyles.inlineStyle) {
|
|
222
|
+
const declarations = extractDeclarations(matchedStyles.inlineStyle as CSSStyle)
|
|
223
|
+
if (Object.keys(declarations).length > 0) {
|
|
224
|
+
inlineStyle = declarations
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const filteredRules = includeUserAgentStyles
|
|
229
|
+
? rules
|
|
230
|
+
: rules.filter((r) => r.origin !== 'user-agent')
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
element: elementDescription,
|
|
234
|
+
inlineStyle,
|
|
235
|
+
rules: filteredRules,
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function extractDeclarations(style: CSSStyle): StyleDeclarations {
|
|
240
|
+
if (!style?.cssProperties) {
|
|
241
|
+
return {}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const result: StyleDeclarations = {}
|
|
245
|
+
for (const prop of style.cssProperties) {
|
|
246
|
+
if (!prop.value || prop.value === 'initial' || prop.name.startsWith('-webkit-')) {
|
|
247
|
+
continue
|
|
248
|
+
}
|
|
249
|
+
const value = prop.important ? `${prop.value} !important` : prop.value
|
|
250
|
+
result[prop.name] = value
|
|
251
|
+
}
|
|
252
|
+
return result
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function formatElementDescription(node: any): string {
|
|
256
|
+
let desc = node.localName || node.nodeName?.toLowerCase() || 'element'
|
|
257
|
+
|
|
258
|
+
if (node.attributes) {
|
|
259
|
+
const attrs: Record<string, string> = {}
|
|
260
|
+
for (let i = 0; i < node.attributes.length; i += 2) {
|
|
261
|
+
attrs[node.attributes[i]] = node.attributes[i + 1]
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (attrs.id) {
|
|
265
|
+
desc += `#${attrs.id}`
|
|
266
|
+
}
|
|
267
|
+
if (attrs.class) {
|
|
268
|
+
desc += `.${attrs.class.split(' ').join('.')}`
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return desc
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function getStylesheetUrl(cdp: CDPSession, styleSheetId: string): Promise<string> {
|
|
276
|
+
try {
|
|
277
|
+
await cdp.send('CSS.getStyleSheetText', { styleSheetId })
|
|
278
|
+
return `stylesheet:${styleSheetId}`
|
|
279
|
+
} catch {
|
|
280
|
+
return `stylesheet:${styleSheetId}`
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function formatStylesAsText(styles: StylesResult): string {
|
|
285
|
+
const lines: string[] = []
|
|
286
|
+
|
|
287
|
+
lines.push(`Element: ${styles.element}`)
|
|
288
|
+
lines.push('')
|
|
289
|
+
|
|
290
|
+
if (styles.inlineStyle) {
|
|
291
|
+
lines.push('Inline styles:')
|
|
292
|
+
for (const [prop, value] of Object.entries(styles.inlineStyle)) {
|
|
293
|
+
lines.push(` ${prop}: ${value}`)
|
|
294
|
+
}
|
|
295
|
+
lines.push('')
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const directRules = styles.rules.filter((r) => !r.inheritedFrom)
|
|
299
|
+
const inheritedRules = styles.rules.filter((r) => r.inheritedFrom)
|
|
300
|
+
|
|
301
|
+
if (directRules.length > 0) {
|
|
302
|
+
lines.push('Matched rules:')
|
|
303
|
+
for (const rule of directRules) {
|
|
304
|
+
lines.push(` ${rule.selector} {`)
|
|
305
|
+
const sourceInfo = rule.source ? ` /* ${rule.source.url}:${rule.source.line}:${rule.source.column} */` : ''
|
|
306
|
+
if (sourceInfo) {
|
|
307
|
+
lines.push(` ${sourceInfo}`)
|
|
308
|
+
}
|
|
309
|
+
for (const [prop, value] of Object.entries(rule.declarations)) {
|
|
310
|
+
lines.push(` ${prop}: ${value};`)
|
|
311
|
+
}
|
|
312
|
+
lines.push(' }')
|
|
313
|
+
}
|
|
314
|
+
lines.push('')
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (inheritedRules.length > 0) {
|
|
318
|
+
const byAncestor = new Map<string, StyleRule[]>()
|
|
319
|
+
for (const rule of inheritedRules) {
|
|
320
|
+
const key = rule.inheritedFrom!
|
|
321
|
+
if (!byAncestor.has(key)) {
|
|
322
|
+
byAncestor.set(key, [])
|
|
323
|
+
}
|
|
324
|
+
byAncestor.get(key)!.push(rule)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
for (const [ancestor, rules] of byAncestor) {
|
|
328
|
+
lines.push(`Inherited from ${ancestor}:`)
|
|
329
|
+
for (const rule of rules) {
|
|
330
|
+
lines.push(` ${rule.selector} {`)
|
|
331
|
+
const sourceInfo = rule.source ? ` /* ${rule.source.url}:${rule.source.line}:${rule.source.column} */` : ''
|
|
332
|
+
if (sourceInfo) {
|
|
333
|
+
lines.push(` ${sourceInfo}`)
|
|
334
|
+
}
|
|
335
|
+
for (const [prop, value] of Object.entries(rule.declarations)) {
|
|
336
|
+
lines.push(` ${prop}: ${value};`)
|
|
337
|
+
}
|
|
338
|
+
lines.push(' }')
|
|
339
|
+
}
|
|
340
|
+
lines.push('')
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return lines.join('\n')
|
|
345
|
+
}
|