17
17
import fs from 'fs' ;
18
18
import path from 'path' ;
19
19
import yazl from 'yazl' ;
20
+ import { EventEmitter } from 'events' ;
20
21
import { calculateSha1 , createGuid , mkdirIfNeeded , monotonicTime } from '../../../utils/utils' ;
21
22
import { Artifact } from '../../artifact' ;
22
23
import { BrowserContext } from '../../browserContext' ;
@@ -43,7 +44,7 @@ export class Tracing implements InstrumentationListener {
43
44
private _resourcesDir : string ;
44
45
private _sha1s : string [ ] = [ ] ;
45
46
private _started = false ;
46
- private _tracesDir : string | undefined ;
47
+ private _tracesDir : string ;
47
48
48
49
constructor ( context : BrowserContext ) {
49
50
this . _context = context ;
@@ -54,8 +55,6 @@ export class Tracing implements InstrumentationListener {
54
55
55
56
async start ( options : TracerOptions ) : Promise < void > {
56
57
// context + page must be the first events added, this method can't have awaits before them.
57
- if ( ! this . _tracesDir )
58
- throw new Error ( 'Tracing directory is not specified when launching the browser' ) ;
59
58
if ( this . _started )
60
59
throw new Error ( 'Tracing has already been started' ) ;
61
60
this . _started = true ;
@@ -86,13 +85,13 @@ export class Tracing implements InstrumentationListener {
86
85
if ( ! this . _started )
87
86
return ;
88
87
this . _started = false ;
89
- await this . _snapshotter . stop ( ) ;
90
88
this . _context . instrumentation . removeListener ( this ) ;
91
89
helper . removeEventListeners ( this . _eventListeners ) ;
92
90
for ( const { sdkObject, metadata } of this . _pendingCalls . values ( ) )
93
91
await this . onAfterCall ( sdkObject , metadata ) ;
94
92
for ( const page of this . _context . pages ( ) )
95
93
page . setScreencastOptions ( null ) ;
94
+ await this . _snapshotter . stop ( ) ;
96
95
97
96
// Ensure all writes are finished.
98
97
await this . _appendEventChain ;
@@ -103,21 +102,25 @@ export class Tracing implements InstrumentationListener {
103
102
}
104
103
105
104
async export ( ) : Promise < Artifact > {
106
- if ( ! this . _traceFile )
107
- throw new Error ( 'Tracing directory is not specified when launching the browser ' ) ;
105
+ if ( ! this . _traceFile || this . _started )
106
+ throw new Error ( 'Must start and stop tracing before exporting ' ) ;
108
107
const zipFile = new yazl . ZipFile ( ) ;
109
- zipFile . addFile ( this . _traceFile , 'trace.trace' ) ;
110
- const zipFileName = this . _traceFile + '.zip' ;
111
- this . _traceFile = undefined ;
112
- for ( const sha1 of this . _sha1s )
113
- zipFile . addFile ( path . join ( this . _resourcesDir ! , sha1 ) , path . join ( 'resources' , sha1 ) ) ;
114
- zipFile . end ( ) ;
115
- await new Promise ( f => {
116
- zipFile . outputStream . pipe ( fs . createWriteStream ( zipFileName ) ) . on ( 'close' , f ) ;
108
+ const failedPromise = new Promise < Artifact > ( ( _ , reject ) => ( zipFile as any as EventEmitter ) . on ( 'error' , reject ) ) ;
109
+
110
+ const succeededPromise = new Promise < Artifact > ( async fulfill => {
111
+ zipFile . addFile ( this . _traceFile ! , 'trace.trace' ) ;
112
+ const zipFileName = this . _traceFile ! + '.zip' ;
113
+ for ( const sha1 of this . _sha1s )
114
+ zipFile . addFile ( path . join ( this . _resourcesDir ! , sha1 ) , path . join ( 'resources' , sha1 ) ) ;
115
+ zipFile . end ( ) ;
116
+ await new Promise ( f => {
117
+ zipFile . outputStream . pipe ( fs . createWriteStream ( zipFileName ) ) . on ( 'close' , f ) ;
118
+ } ) ;
119
+ const artifact = new Artifact ( this . _context , zipFileName ) ;
120
+ artifact . reportFinished ( ) ;
121
+ fulfill ( artifact ) ;
117
122
} ) ;
118
- const artifact = new Artifact ( this . _context , zipFileName ) ;
119
- artifact . reportFinished ( ) ;
120
- return artifact ;
123
+ return Promise . race ( [ failedPromise , succeededPromise ] ) ;
121
124
}
122
125
123
126
async _captureSnapshot ( name : 'before' | 'after' | 'action' | 'event' , sdkObject : SdkObject , metadata : CallMetadata , element ?: ElementHandle ) {
@@ -181,6 +184,9 @@ export class Tracing implements InstrumentationListener {
181
184
}
182
185
183
186
private _appendTraceEvent ( event : any ) {
187
+ if ( ! this . _started )
188
+ return ;
189
+
184
190
const visit = ( object : any ) => {
185
191
if ( Array . isArray ( object ) ) {
186
192
object . forEach ( visit ) ;
0 commit comments