1616
1717package com .microsoft .playwright ;
1818
19- import com .google .gson .Gson ;
20- import com .google .gson .annotations .SerializedName ;
2119import com .microsoft .playwright .options .AriaRole ;
2220import com .microsoft .playwright .options .Location ;
2321import com .microsoft .playwright .options .MouseButton ;
2725import org .junit .jupiter .api .Test ;
2826import org .junit .jupiter .api .io .TempDir ;
2927
30- import java .io .File ;
3128import java .io .IOException ;
3229import java .nio .file .Files ;
3330import java .nio .file .Path ;
34- import java .nio .file .Paths ;
35- import java .util .Arrays ;
36- import java .util .List ;
37- import java .util .Map ;
38- import java .util .stream .Collectors ;
39-
40- import static java .nio .charset .StandardCharsets .UTF_8 ;
41- import static java .util .Arrays .asList ;
31+ import java .util .regex .Pattern ;
32+
33+ import static com .microsoft .playwright .assertions .PlaywrightAssertions .assertThat ;
4234import static org .junit .jupiter .api .Assertions .*;
4335
4436public class TestTracing extends TestBase {
@@ -57,7 +49,7 @@ void launchBrowser(@TempDir Path tempDir) {
5749 }
5850
5951 @ Test
60- void shouldCollectTrace1 (@ TempDir Path tempDir ) {
52+ void shouldCollectTrace1 (@ TempDir Path tempDir ) throws Exception {
6153 context .tracing ().start (new Tracing .StartOptions ().setName ("test" )
6254 .setScreenshots (true ).setSnapshots (true ));
6355 page .navigate (server .EMPTY_PAGE );
@@ -68,10 +60,18 @@ void shouldCollectTrace1(@TempDir Path tempDir) {
6860 context .tracing ().stop (new Tracing .StopOptions ().setPath (traceFile ));
6961
7062 assertTrue (Files .exists (traceFile ));
63+ TraceViewerPage .showTraceViewer (this .browserType , traceFile , traceViewer -> {
64+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
65+ Pattern .compile ("Navigate to \" /empty.html\" " ),
66+ Pattern .compile ("Set content" ),
67+ Pattern .compile ("Click" ),
68+ Pattern .compile ("Close" )
69+ });
70+ });
7171 }
7272
7373 @ Test
74- void shouldCollectTwoTraces (@ TempDir Path tempDir ) {
74+ void shouldCollectTwoTraces (@ TempDir Path tempDir ) throws Exception {
7575 context .tracing ().start (new Tracing .StartOptions ().setName ("test1" )
7676 .setScreenshots (true ).setSnapshots (true ));
7777 page .navigate (server .EMPTY_PAGE );
@@ -89,10 +89,25 @@ void shouldCollectTwoTraces(@TempDir Path tempDir) {
8989
9090 assertTrue (Files .exists (traceFile1 ));
9191 assertTrue (Files .exists (traceFile2 ));
92+
93+ TraceViewerPage .showTraceViewer (this .browserType , traceFile1 , traceViewer -> {
94+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
95+ Pattern .compile ("Navigate to \" /empty.html\" " ),
96+ Pattern .compile ("Set content" ),
97+ Pattern .compile ("Click" )
98+ });
99+ });
100+
101+ TraceViewerPage .showTraceViewer (this .browserType , traceFile2 , traceViewer -> {
102+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
103+ Pattern .compile ("Double click" ),
104+ Pattern .compile ("Close" )
105+ });
106+ });
92107 }
93108
94109 @ Test
95- void shouldWorkWithMultipleChunks (@ TempDir Path tempDir ) {
110+ void shouldWorkWithMultipleChunks (@ TempDir Path tempDir ) throws Exception {
96111 context .tracing ().start (new Tracing .StartOptions ().setScreenshots (true ).setSnapshots (true ));
97112 page .navigate (server .PREFIX + "/frames/frame.html" );
98113
@@ -109,28 +124,60 @@ void shouldWorkWithMultipleChunks(@TempDir Path tempDir) {
109124
110125 assertTrue (Files .exists (traceFile1 ));
111126 assertTrue (Files .exists (traceFile2 ));
127+
128+ TraceViewerPage .showTraceViewer (this .browserType , traceFile1 , traceViewer -> {
129+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
130+ Pattern .compile ("Set content" ),
131+ Pattern .compile ("Click" )
132+ });
133+ traceViewer .selectSnapshot ("After" );
134+ FrameLocator frame = traceViewer .snapshotFrame ("Set content" , 0 , false );
135+ assertThat (frame .locator ("button" )).hasText ("Click" );
136+ });
137+
138+ TraceViewerPage .showTraceViewer (this .browserType , traceFile2 , traceViewer -> {
139+ assertThat (traceViewer .actionTitles ()).containsText (new String [] {"Hover" });
140+ FrameLocator frame = traceViewer .snapshotFrame ("Hover" , 0 , false );
141+ assertThat (frame .locator ("button" )).hasText ("Click" );
142+ });
112143 }
113144
114145 @ Test
115- void shouldCollectSources (@ TempDir Path tmpDir ) throws IOException {
146+ void shouldCollectSources (@ TempDir Path tmpDir ) throws Exception {
116147 Assumptions .assumeTrue (System .getenv ("PLAYWRIGHT_JAVA_SRC" ) != null , "PLAYWRIGHT_JAVA_SRC must point to the directory containing this test source." );
117148 context .tracing ().start (new Tracing .StartOptions ().setSources (true ));
118149 page .navigate (server .EMPTY_PAGE );
119150 page .setContent ("<button>Click</button>" );
120- page . click ( "'Click'" );
151+ myMethodOuter ( );
121152 Path trace = tmpDir .resolve ("trace1.zip" );
122153 context .tracing ().stop (new Tracing .StopOptions ().setPath (trace ));
123154
124- Map <String , byte []> entries = Utils .parseZip (trace );
125- Map <String , byte []> sources = entries .entrySet ().stream ().filter (e -> e .getKey ().endsWith (".txt" )).collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue ));
126- assertEquals (1 , sources .size ());
155+ TraceViewerPage .showTraceViewer (this .browserType , trace , traceViewer -> {
156+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
157+ Pattern .compile ("Navigate to \" /empty.html\" " ),
158+ Pattern .compile ("Set content" ),
159+ Pattern .compile ("Click" )
160+ });
161+ traceViewer .showSourceTab ();
162+ assertThat (traceViewer .stackFrames ()).containsText (new Pattern [] {
163+ Pattern .compile ("myMethodInner" ),
164+ Pattern .compile ("myMethodOuter" ),
165+ Pattern .compile ("shouldCollectSources" )
166+ });
167+ traceViewer .selectAction ("Set content" );
168+ assertThat (traceViewer .page ().locator (".source-tab-file-name" ))
169+ .hasAttribute ("title" , Pattern .compile (".*TestTracing\\ .java" ));
170+ assertThat (traceViewer .page ().locator (".source-line-running" ))
171+ .containsText ("page.setContent(\" <button>Click</button>\" );" );
172+ });
173+ }
174+
175+ private void myMethodOuter () {
176+ myMethodInner ();
177+ }
127178
128- String path = getClass ().getName ().replace ('.' , File .separatorChar );
129- String [] srcRoots = System .getenv ("PLAYWRIGHT_JAVA_SRC" ).split (File .pathSeparator );
130- // Resolve in the last specified source dir.
131- Path sourceFile = Paths .get (srcRoots [srcRoots .length - 1 ], path + ".java" );
132- byte [] thisFile = Files .readAllBytes (sourceFile );
133- assertEquals (new String (thisFile , UTF_8 ), new String (sources .values ().iterator ().next (), UTF_8 ));
179+ private void myMethodInner () {
180+ page .getByText ("Click" ).click ();
134181 }
135182
136183 @ Test
@@ -140,7 +187,7 @@ void shouldNotFailWhenSourcesSetExplicitlyToFalse() throws IOException {
140187 }
141188
142189 @ Test
143- void shouldRespectTracesDirAndName (@ TempDir Path tempDir ) {
190+ void shouldRespectTracesDirAndName (@ TempDir Path tempDir ) throws Exception {
144191 Path tracesDir = tempDir .resolve ("trace-dir" );
145192 BrowserType .LaunchOptions options = createLaunchOptions ();
146193 options .setTracesDir (tracesDir );
@@ -159,6 +206,24 @@ void shouldRespectTracesDirAndName(@TempDir Path tempDir) {
159206 context .tracing ().stop (new Tracing .StopOptions ().setPath (tempDir .resolve ("trace2.zip" )));
160207 assertTrue (Files .exists (tracesDir .resolve ("name2.trace" )));
161208 assertTrue (Files .exists (tracesDir .resolve ("name2.network" )));
209+
210+ TraceViewerPage .showTraceViewer (this .browserType , tempDir .resolve ("trace1.zip" ), traceViewer -> {
211+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
212+ Pattern .compile ("Navigate to \" /one-style.html\" " )
213+ });
214+ FrameLocator frame = traceViewer .snapshotFrame ("Navigate" , 0 , false );
215+ assertThat (frame .locator ("body" )).hasCSS ("background-color" , "rgb(255, 192, 203)" );
216+ assertThat (frame .locator ("body" )).hasText ("hello, world!" );
217+ });
218+
219+ TraceViewerPage .showTraceViewer (this .browserType , tempDir .resolve ("trace2.zip" ), traceViewer -> {
220+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
221+ Pattern .compile ("Navigate to \" /har.html\" " )
222+ });
223+ FrameLocator frame = traceViewer .snapshotFrame ("Navigate" , 0 , false );
224+ assertThat (frame .locator ("body" )).hasCSS ("background-color" , "rgb(255, 192, 203)" );
225+ assertThat (frame .locator ("body" )).hasText ("hello, world!" );
226+ });
162227 }
163228 }
164229
@@ -179,11 +244,9 @@ void canCallTracingGroupGroupEndAtAnyTimeAndAutoClose(@TempDir Path tempDir) thr
179244 context .tracing ().groupEnd ();
180245 context .tracing ().groupEnd ();
181246
182- List <TraceEvent > events = parseTraceEvents (traceFile1 );
183- List <TraceEvent > groups = events .stream ().filter (e -> "tracingGroup" .equals (e .method )).collect (Collectors .toList ());
184- assertEquals (1 , groups .size ());
185- assertEquals ("actual" , groups .get (0 ).title );
186-
247+ TraceViewerPage .showTraceViewer (this .browserType , traceFile1 , traceViewer -> {
248+ assertThat (traceViewer .actionTitles ()).containsText (new String [] {"actual" , "Navigate to \" /empty.html\" " });
249+ });
187250 }
188251
189252 @ Test
@@ -202,9 +265,16 @@ void traceGroupGroupEnd(@TempDir Path tempDir) throws Exception {
202265 Path traceFile1 = tempDir .resolve ("trace1.zip" );
203266 context .tracing ().stop (new Tracing .StopOptions ().setPath (traceFile1 ));
204267
205- List <TraceEvent > events = parseTraceEvents (traceFile1 );
206- List <String > calls = events .stream ().filter (e -> e .renderedTitle () != null ).map (e -> e .renderedTitle ()).collect (Collectors .toList ());
207- assertEquals (asList ("outer group" , "Frame.goto" , "inner group 1" , "Frame.click" , "inner group 2" , "Frame.isVisible" ), calls );
268+ TraceViewerPage .showTraceViewer (this .browserType , traceFile1 , traceViewer -> {
269+ traceViewer .expandAction ("inner group 1" );
270+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
271+ Pattern .compile ("outer group" ),
272+ Pattern .compile ("Navigate to \" data:" ),
273+ Pattern .compile ("inner group 1" ),
274+ Pattern .compile ("Click" ),
275+ Pattern .compile ("inner group 2" ),
276+ });
277+ });
208278 }
209279
210280 @ Test
@@ -240,64 +310,53 @@ void shouldTraceVariousAPIs(@TempDir Path tempDir) throws Exception {
240310 Path traceFile1 = tempDir .resolve ("trace1.zip" );
241311 context .tracing ().stop (new Tracing .StopOptions ().setPath (traceFile1 ));
242312
243- List <TraceEvent > events = parseTraceEvents (traceFile1 );
244- List <String > calls = events .stream ().filter (e -> e .renderedTitle () != null ).map (e -> e .renderedTitle ())
245- .collect (Collectors .toList ());
246- assertEquals (asList (
247- "BrowserContext.clockInstall" ,
248- "Frame.setContent" ,
249- "Frame.click" ,
250- "Frame.click" ,
251- "Page.keyboardType" ,
252- "Page.keyboardPress" ,
253- "Page.keyboardDown" ,
254- "Page.keyboardInsertText" ,
255- "Page.keyboardUp" ,
256- "Page.mouseMove" ,
257- "Page.mouseDown" ,
258- "Page.mouseMove" ,
259- "Page.mouseWheel" ,
260- "Page.mouseUp" ,
261- "BrowserContext.clockFastForward" ,
262- "BrowserContext.clockFastForward" ,
263- "BrowserContext.clockPauseAt" ,
264- "BrowserContext.clockRunFor" ,
265- "BrowserContext.clockSetFixedTime" ,
266- "BrowserContext.clockSetSystemTime" ,
267- "BrowserContext.clockResume" ,
268- "Frame.click" ),
269- calls );
313+ TraceViewerPage .showTraceViewer (this .browserType , traceFile1 , traceViewer -> {
314+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
315+ Pattern .compile ("Install clock" ),
316+ Pattern .compile ("Set content" ),
317+ Pattern .compile ("Click" ),
318+ Pattern .compile ("Click" ),
319+ Pattern .compile ("Type" ),
320+ Pattern .compile ("Press" ),
321+ Pattern .compile ("Key down" ),
322+ Pattern .compile ("Insert" ),
323+ Pattern .compile ("Key up" ),
324+ Pattern .compile ("Mouse move" ),
325+ Pattern .compile ("Mouse down" ),
326+ Pattern .compile ("Mouse move" ),
327+ Pattern .compile ("Mouse wheel" ),
328+ Pattern .compile ("Mouse up" ),
329+ Pattern .compile ("Fast forward clock" ),
330+ Pattern .compile ("Fast forward clock" ),
331+ Pattern .compile ("Pause clock" ),
332+ Pattern .compile ("Run clock" ),
333+ Pattern .compile ("Set fixed time" ),
334+ Pattern .compile ("Set system time" ),
335+ Pattern .compile ("Resume clock" ),
336+ Pattern .compile ("Click" )
337+ });
338+ });
270339 }
271340
272- private static class TraceEvent {
273- String type ;
274- String name ;
275- String title ;
276- @ SerializedName ("class" )
277- String clazz ;
278- String method ;
279- Double startTime ;
280- Double endTime ;
281- String callId ;
282-
283- String renderedTitle () {
284- if (title != null ) {
285- return title ;
286- }
287- if (clazz != null && method != null ) {
288- return clazz + "." + method ;
289- }
290- return null ;
291- }
292- }
341+ @ Test
342+ public void shouldNotRecordNetworkActions (@ TempDir Path tempDir ) throws Exception {
343+ context .tracing ().start (new Tracing .StartOptions ());
344+
345+ page .onRequest (request -> {
346+ request .allHeaders ();
347+ });
348+ page .onResponse (response -> {
349+ response .text ();
350+ });
351+ page .navigate (server .EMPTY_PAGE );
352+
353+ Path traceFile1 = tempDir .resolve ("trace1.zip" );
354+ context .tracing ().stop (new Tracing .StopOptions ().setPath (traceFile1 ));
293355
294- private static List <TraceEvent > parseTraceEvents (Path traceFile ) throws IOException {
295- Map <String , byte []> files = Utils .parseZip (traceFile );
296- Map <String , byte []> traces = files .entrySet ().stream ().filter (e -> e .getKey ().endsWith (".trace" )).collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue ));
297- assertNotNull (traces .get ("trace.trace" ));
298- return Arrays .stream (new String (traces .get ("trace.trace" ), UTF_8 )
299- .split ("\n " ))
300- .map (s -> new Gson ().fromJson (s , TraceEvent .class ))
301- .collect (Collectors .toList ());
356+ TraceViewerPage .showTraceViewer (this .browserType , traceFile1 , traceViewer -> {
357+ assertThat (traceViewer .actionTitles ()).hasText (new Pattern [] {
358+ Pattern .compile ("Navigate to \" /empty.html\" " )
359+ });
360+ });
302361 }
303362}
0 commit comments