1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import path from 'path' ;
18
+ import { expect , tracingTest as test } from './config/browserTest' ;
19
+ import yauzl from 'yauzl' ;
20
+ import removeFolder from 'rimraf' ;
21
+
22
+ test . beforeEach ( async ( { } , testInfo ) => {
23
+ const folder = path . join ( testInfo . config . outputDir , 'trace-' + process . env . FOLIO_WORKER_INDEX ) ;
24
+ await new Promise ( f => removeFolder ( folder , f ) ) ;
25
+ } ) ;
26
+
27
+ test ( 'should collect trace' , async ( { context, page, server, browserName } , testInfo ) => {
28
+ await ( context as any ) . _tracing . start ( { name : 'test' , screenshots : true , snapshots : true } ) ;
29
+ await page . goto ( server . EMPTY_PAGE ) ;
30
+ await page . setContent ( '<button>Click</button>' ) ;
31
+ await page . click ( '"Click"' ) ;
32
+ await page . close ( ) ;
33
+ await ( context as any ) . _tracing . stop ( ) ;
34
+ await ( context as any ) . _tracing . export ( testInfo . outputPath ( 'trace.zip' ) ) ;
35
+
36
+ const { events } = await parseTrace ( testInfo . outputPath ( 'trace.zip' ) ) ;
37
+ expect ( events [ 0 ] . type ) . toBe ( 'context-metadata' ) ;
38
+ expect ( events [ 1 ] . type ) . toBe ( 'page-created' ) ;
39
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.goto' ) ) . toBeTruthy ( ) ;
40
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.setContent' ) ) . toBeTruthy ( ) ;
41
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.click' ) ) . toBeTruthy ( ) ;
42
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.close' ) ) . toBeTruthy ( ) ;
43
+
44
+ expect ( events . some ( e => e . type === 'frame-snapshot' ) ) . toBeTruthy ( ) ;
45
+ expect ( events . some ( e => e . type === 'resource-snapshot' ) ) . toBeTruthy ( ) ;
46
+ if ( browserName === 'chromium' )
47
+ expect ( events . some ( e => e . type === 'screencast-frame' ) ) . toBeTruthy ( ) ;
48
+ } ) ;
49
+
50
+ test ( 'should collect trace' , async ( { context, page, server } , testInfo ) => {
51
+ await ( context as any ) . _tracing . start ( { name : 'test' } ) ;
52
+ await page . goto ( server . EMPTY_PAGE ) ;
53
+ await page . setContent ( '<button>Click</button>' ) ;
54
+ await page . click ( '"Click"' ) ;
55
+ await page . close ( ) ;
56
+ await ( context as any ) . _tracing . stop ( ) ;
57
+ await ( context as any ) . _tracing . export ( testInfo . outputPath ( 'trace.zip' ) ) ;
58
+
59
+ const { events } = await parseTrace ( testInfo . outputPath ( 'trace.zip' ) ) ;
60
+ expect ( events . some ( e => e . type === 'frame-snapshot' ) ) . toBeFalsy ( ) ;
61
+ expect ( events . some ( e => e . type === 'resource-snapshot' ) ) . toBeFalsy ( ) ;
62
+ } ) ;
63
+
64
+ test ( 'should collect two traces' , async ( { context, page, server } , testInfo ) => {
65
+ await ( context as any ) . _tracing . start ( { name : 'test1' , screenshots : true , snapshots : true } ) ;
66
+ await page . goto ( server . EMPTY_PAGE ) ;
67
+ await page . setContent ( '<button>Click</button>' ) ;
68
+ await page . click ( '"Click"' ) ;
69
+ await ( context as any ) . _tracing . stop ( ) ;
70
+ await ( context as any ) . _tracing . export ( testInfo . outputPath ( 'trace1.zip' ) ) ;
71
+
72
+ await ( context as any ) . _tracing . start ( { name : 'test2' , screenshots : true , snapshots : true } ) ;
73
+ await page . dblclick ( '"Click"' ) ;
74
+ await page . close ( ) ;
75
+ await ( context as any ) . _tracing . stop ( ) ;
76
+ await ( context as any ) . _tracing . export ( testInfo . outputPath ( 'trace2.zip' ) ) ;
77
+
78
+ {
79
+ const { events } = await parseTrace ( testInfo . outputPath ( 'trace1.zip' ) ) ;
80
+ expect ( events [ 0 ] . type ) . toBe ( 'context-metadata' ) ;
81
+ expect ( events [ 1 ] . type ) . toBe ( 'page-created' ) ;
82
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.goto' ) ) . toBeTruthy ( ) ;
83
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.setContent' ) ) . toBeTruthy ( ) ;
84
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.click' ) ) . toBeTruthy ( ) ;
85
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.dblclick' ) ) . toBeFalsy ( ) ;
86
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.close' ) ) . toBeFalsy ( ) ;
87
+ }
88
+
89
+ {
90
+ const { events } = await parseTrace ( testInfo . outputPath ( 'trace2.zip' ) ) ;
91
+ expect ( events [ 0 ] . type ) . toBe ( 'context-metadata' ) ;
92
+ expect ( events [ 1 ] . type ) . toBe ( 'page-created' ) ;
93
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.goto' ) ) . toBeFalsy ( ) ;
94
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.setContent' ) ) . toBeFalsy ( ) ;
95
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.click' ) ) . toBeFalsy ( ) ;
96
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.dblclick' ) ) . toBeTruthy ( ) ;
97
+ expect ( events . find ( e => e . metadata ?. apiName === 'page.close' ) ) . toBeTruthy ( ) ;
98
+ }
99
+ } ) ;
100
+
101
+ async function parseTrace ( file : string ) : Promise < { events : any [ ] , resources : Map < string , Buffer > } > {
102
+ const entries = await new Promise < any [ ] > ( f => {
103
+ const entries : Promise < any > [ ] = [ ] ;
104
+ yauzl . open ( file , ( err , zipFile ) => {
105
+ zipFile . on ( 'entry' , entry => {
106
+ const entryPromise = new Promise ( ff => {
107
+ zipFile . openReadStream ( entry , ( err , readStream ) => {
108
+ const buffers = [ ] ;
109
+ if ( readStream ) {
110
+ readStream . on ( 'data' , d => buffers . push ( d ) ) ;
111
+ readStream . on ( 'end' , ( ) => ff ( { name : entry . fileName , buffer : Buffer . concat ( buffers ) } ) ) ;
112
+ } else {
113
+ ff ( { name : entry . fileName } ) ;
114
+ }
115
+ } ) ;
116
+ } ) ;
117
+ entries . push ( entryPromise ) ;
118
+ } ) ;
119
+ zipFile . on ( 'end' , ( ) => f ( entries ) ) ;
120
+ } ) ;
121
+ } ) ;
122
+ const resources = new Map < string , Buffer > ( ) ;
123
+ for ( const { name, buffer } of await Promise . all ( entries ) )
124
+ resources . set ( name , buffer ) ;
125
+ const events = resources . get ( 'trace.trace' ) . toString ( ) . split ( '\n' ) . map ( line => line ? JSON . parse ( line ) : false ) . filter ( Boolean ) ;
126
+ return {
127
+ events,
128
+ resources,
129
+ } ;
130
+ }
0 commit comments