@@ -78,6 +78,119 @@ def test_should_collect_sources(
78
78
assert found_current_file
79
79
80
80
81
+ def test_should_collect_trace_with_resources_but_no_js (
82
+ context : BrowserContext , page : Page , server : Server , tmpdir : Path
83
+ ) -> None :
84
+ context .tracing .start (screenshots = True , snapshots = True )
85
+ page .goto (server .PREFIX + "/frames/frame.html" )
86
+ page .set_content ("<button>Click</button>" )
87
+ page .click ('"Click"' )
88
+ page .mouse .move (20 , 20 )
89
+ page .mouse .dblclick (30 , 30 )
90
+ page .keyboard .insert_text ("abc" )
91
+ page .wait_for_timeout (2000 ) # Give it some time to produce screenshots.
92
+ page .close ()
93
+ trace_file_path = tmpdir / "trace.zip"
94
+ context .tracing .stop (path = trace_file_path )
95
+
96
+ (_ , events ) = parse_trace (trace_file_path )
97
+ assert events [0 ]["type" ] == "context-options"
98
+ assert events_have_entry (events , "Page.goto" ) is True
99
+ assert events_have_entry (events , "Page.set_content" ) is True
100
+ assert events_have_entry (events , "Page.click" ) is True
101
+ assert events_have_entry (events , "Mouse.move" ) is True
102
+ assert events_have_entry (events , "Mouse.dblclick" ) is True
103
+ assert events_have_entry (events , "Keyboard.insert_text" ) is True
104
+ assert events_have_entry (events , "Page.close" ) is True
105
+
106
+ assert len (list (filter (lambda e : e ["type" ] == "frame-snapshot" , events ))) > 1
107
+ assert len (list (filter (lambda e : e ["type" ] == "screencast-frame" , events ))) > 1
108
+ style = list (
109
+ filter (
110
+ lambda e : e ["type" ] == "resource-snapshot"
111
+ and e ["snapshot" ]["request" ]["url" ].endswith ("style.css" ),
112
+ events ,
113
+ )
114
+ )[0 ]
115
+ assert style
116
+ assert style ["snapshot" ]["response" ]["content" ]["_sha1" ]
117
+ script = list (
118
+ filter (
119
+ lambda e : e ["type" ] == "resource-snapshot"
120
+ and e ["snapshot" ]["request" ]["url" ].endswith ("script.js" ),
121
+ events ,
122
+ )
123
+ )[0 ]
124
+ assert script
125
+ assert script ["snapshot" ]["response" ]["content" ].get ("_sha1" ) is None
126
+
127
+
128
+ def test_should_collect_two_traces (
129
+ context : BrowserContext , page : Page , server : Server , tmpdir : Path
130
+ ) -> None :
131
+ context .tracing .start (screenshots = True , snapshots = True )
132
+ page .goto (server .EMPTY_PAGE )
133
+ page .set_content ("<button>Click</button>" )
134
+ page .click ('"Click"' )
135
+ tracing1_path = tmpdir / "trace1.zip"
136
+ context .tracing .stop (path = tracing1_path )
137
+
138
+ context .tracing .start (screenshots = True , snapshots = True )
139
+ page .dblclick ('"Click"' )
140
+ page .close ()
141
+ tracing2_path = tmpdir / "trace2.zip"
142
+ context .tracing .stop (path = tracing2_path )
143
+
144
+ (_ , events ) = parse_trace (tracing1_path )
145
+ assert events [0 ]["type" ] == "context-options"
146
+ assert events_have_entry (events , "Page.goto" ) is True
147
+ assert events_have_entry (events , "Page.set_content" ) is True
148
+ assert events_have_entry (events , "Page.click" ) is True
149
+ assert events_have_entry (events , "Page.dblclick" ) is False
150
+ assert events_have_entry (events , "Page.close" ) is False
151
+
152
+ (_ , events ) = parse_trace (tracing2_path )
153
+ assert events [0 ]["type" ] == "context-options"
154
+ assert events_have_entry (events , "Page.goto" ) is False
155
+ assert events_have_entry (events , "Page.set_content" ) is False
156
+ assert events_have_entry (events , "Page.click" ) is False
157
+ assert events_have_entry (events , "Page.dblclick" ) is True
158
+ assert events_have_entry (events , "Page.close" ) is True
159
+
160
+
161
+ def test_should_not_throw_when_stopping_without_start_but_not_exporting (
162
+ context : BrowserContext ,
163
+ ) -> None :
164
+ context .tracing .stop ()
165
+
166
+
167
+ def test_should_work_with_playwright_context_managers (
168
+ context : BrowserContext , page : Page , server : Server , tmpdir : Path
169
+ ) -> None :
170
+ context .tracing .start (screenshots = True , snapshots = True )
171
+ page .goto (server .EMPTY_PAGE )
172
+ page .set_content ("<button>Click</button>" )
173
+ with page .expect_console_message () as message_info :
174
+ page .evaluate ('() => console.log("hello")' )
175
+ page .click ('"Click"' )
176
+ assert (message_info .value ).text == "hello"
177
+
178
+ with page .expect_popup ():
179
+ page .evaluate ("window._popup = window.open(document.location.href)" )
180
+ trace_file_path = tmpdir / "trace.zip"
181
+ context .tracing .stop (path = trace_file_path )
182
+
183
+ (_ , events ) = parse_trace (trace_file_path )
184
+ assert events [0 ]["type" ] == "context-options"
185
+ assert events_have_entry (events , "Page.goto" )
186
+ assert events_have_entry (events , "Page.set_content" )
187
+ assert events_have_entry (events , "Page.expect_console_message" )
188
+ assert events_have_entry (events , "Page.evaluate" )
189
+ assert events_have_entry (events , "Page.click" )
190
+ assert events_have_entry (events , "Page.expect_popup" )
191
+ assert events_have_entry (events , "Page.evaluate" )
192
+
193
+
81
194
def parse_trace (path : Path ) -> Tuple [Dict [str , bytes ], List [Any ]]:
82
195
resources : Dict [str , bytes ] = {}
83
196
with zipfile .ZipFile (path , "r" ) as zip :
@@ -88,3 +201,7 @@ def parse_trace(path: Path) -> Tuple[Dict[str, bytes], List[Any]]:
88
201
for line in resources [name ].decode ().splitlines ():
89
202
events .append (json .loads (line ))
90
203
return (resources , events )
204
+
205
+
206
+ def events_have_entry (events : List [Any ], api_name : str ) -> bool :
207
+ return any (e .get ("metadata" , {}).get ("apiName" ) == api_name for e in events )
0 commit comments