@@ -23,13 +23,13 @@ const log = logger('@wdio/devtools-service:SessionCapturer')
2323/**
2424 * Generic helper to strip ANSI escape codes from text
2525 */
26- const stripAnsi = ( text : string ) : string => text . replace ( ANSI_REGEX , '' )
26+ const stripAnsiCodes = ( text : string ) : string => text . replace ( ANSI_REGEX , '' )
2727
2828/**
2929 * Generic helper to detect log level from text content
3030 */
3131const detectLogLevel = ( text : string ) : LogLevel => {
32- const cleanText = stripAnsi ( text ) . toLowerCase ( )
32+ const cleanText = stripAnsiCodes ( text ) . toLowerCase ( )
3333
3434 // Check log level patterns in priority order
3535 for ( const { level, pattern } of LOG_LEVEL_PATTERNS ) {
@@ -53,7 +53,7 @@ const detectLogLevel = (text: string): LogLevel => {
5353/**
5454 * Generic helper to create a console log entry
5555 */
56- const createLogEntry = (
56+ const createConsoleLogEntry = (
5757 type : LogLevel ,
5858 args : any [ ] ,
5959 source : ( typeof LOG_SOURCES ) [ keyof typeof LOG_SOURCES ]
@@ -66,7 +66,7 @@ const createLogEntry = (
6666
6767export class SessionCapturer {
6868 #ws: WebSocket | undefined
69- #isInjected = false
69+ #isScriptInjected = false
7070 #originalConsoleMethods: Record <
7171 ( typeof CONSOLE_METHODS ) [ number ] ,
7272 typeof console . log
@@ -121,14 +121,14 @@ export class SessionCapturer {
121121 }
122122
123123 this . #patchConsole( )
124- this . #patchProcessOutput ( )
124+ this . #interceptProcessStreams ( )
125125 }
126126
127127 #patchConsole( ) {
128128 CONSOLE_METHODS . forEach ( ( method ) => {
129129 const originalMethod = this . #originalConsoleMethods[ method ]
130- console [ method ] = ( ...args : any [ ] ) => {
131- const serializedArgs = args . map ( ( arg ) =>
130+ console [ method ] = ( ...consoleArgs : any [ ] ) => {
131+ const serializedArgs = consoleArgs . map ( ( arg ) =>
132132 typeof arg === 'object' && arg !== null
133133 ? ( ( ) => {
134134 try {
@@ -140,7 +140,7 @@ export class SessionCapturer {
140140 : String ( arg )
141141 )
142142
143- const logEntry = createLogEntry (
143+ const logEntry = createConsoleLogEntry (
144144 method ,
145145 serializedArgs ,
146146 LOG_SOURCES . TEST
@@ -149,50 +149,61 @@ export class SessionCapturer {
149149 this . sendUpstream ( 'consoleLogs' , [ logEntry ] )
150150
151151 this . #isCapturingConsole = true
152- const result = originalMethod . apply ( console , args )
152+ const result = originalMethod . apply ( console , consoleArgs )
153153 this . #isCapturingConsole = false
154154 return result
155155 }
156156 } )
157157 }
158158
159- #patchProcessOutput( ) {
160- const captureOutput = ( data : string | Uint8Array ) => {
161- const text = typeof data === 'string' ? data : data . toString ( )
162- if ( ! text ?. trim ( ) ) {
159+ #interceptProcessStreams( ) {
160+ const captureTerminalOutput = ( outputData : string | Uint8Array ) => {
161+ const outputText =
162+ typeof outputData === 'string' ? outputData : outputData . toString ( )
163+ if ( ! outputText ?. trim ( ) ) {
163164 return
164165 }
165166
166- text
167+ outputText
167168 . split ( '\n' )
168169 . filter ( ( line ) => line . trim ( ) )
169170 . forEach ( ( line ) => {
170- const logEntry = createLogEntry (
171+ const logEntry = createConsoleLogEntry (
171172 detectLogLevel ( line ) ,
172- [ stripAnsi ( line ) ] ,
173+ [ stripAnsiCodes ( line ) ] ,
173174 LOG_SOURCES . TERMINAL
174175 )
175176 this . consoleLogs . push ( logEntry )
176177 this . sendUpstream ( 'consoleLogs' , [ logEntry ] )
177178 } )
178179 }
179180
180- const patchStream = (
181+ const interceptStreamWrite = (
181182 stream : NodeJS . WriteStream ,
182- originalWrite : ( ...args : any [ ] ) => boolean
183+ originalWriteMethod : ( ...args : any [ ] ) => boolean
183184 ) => {
184- const self = this
185- stream . write = function ( data : any , ...rest : any [ ] ) : boolean {
186- const result = originalWrite . call ( stream , data , ...rest )
187- if ( data && ! self . #isCapturingConsole) {
188- captureOutput ( data )
185+ const capturer = this
186+ stream . write = function ( chunk : any , ...additionalArgs : any [ ] ) : boolean {
187+ const writeResult = originalWriteMethod . call (
188+ stream ,
189+ chunk ,
190+ ...additionalArgs
191+ )
192+ if ( chunk && ! capturer . #isCapturingConsole) {
193+ captureTerminalOutput ( chunk )
189194 }
190- return result
195+ return writeResult
191196 } as any
192197 }
193198
194- patchStream ( process . stdout , this . #originalProcessMethods. stdoutWrite )
195- patchStream ( process . stderr , this . #originalProcessMethods. stderrWrite )
199+ interceptStreamWrite (
200+ process . stdout ,
201+ this . #originalProcessMethods. stdoutWrite
202+ )
203+ interceptStreamWrite (
204+ process . stderr ,
205+ this . #originalProcessMethods. stderrWrite
206+ )
196207 }
197208
198209 #restoreConsole( ) {
@@ -217,7 +228,7 @@ export class SessionCapturer {
217228 error : Error | undefined ,
218229 callSource ?: string
219230 ) {
220- const sourceFile =
231+ const sourceFileLocation =
221232 parse ( new Error ( '' ) )
222233 . filter ( ( frame ) => Boolean ( frame . getFileName ( ) ) )
223234 . map ( ( frame ) =>
@@ -235,34 +246,40 @@ export class SessionCapturer {
235246 ! fileName . includes ( '/dist/' )
236247 )
237248 . shift ( ) || ''
238- const absPath = sourceFile . startsWith ( 'file://' )
239- ? url . fileURLToPath ( sourceFile )
240- : sourceFile
241- const sourceFilePath = absPath . split ( ':' ) [ 0 ]
242- const fileExist = await fs . access ( sourceFilePath ) . then (
249+ const absolutePath = sourceFileLocation . startsWith ( 'file://' )
250+ ? url . fileURLToPath ( sourceFileLocation )
251+ : sourceFileLocation
252+ const sourceFilePath = absolutePath . split ( ':' ) [ 0 ]
253+ const doesFileExist = await fs . access ( sourceFilePath ) . then (
243254 ( ) => true ,
244255 ( ) => false
245256 )
246- if ( sourceFile && ! this . sources . has ( sourceFile ) && fileExist ) {
257+ if (
258+ sourceFileLocation &&
259+ ! this . sources . has ( sourceFileLocation ) &&
260+ doesFileExist
261+ ) {
247262 const sourceCode = await fs . readFile ( sourceFilePath , 'utf-8' )
248263 this . sources . set ( sourceFilePath , sourceCode . toString ( ) )
249264 this . sendUpstream ( 'sources' , { [ sourceFilePath ] : sourceCode . toString ( ) } )
250265 }
251- const newCommand : CommandLog = {
266+ const commandLogEntry : CommandLog = {
252267 command,
253268 args,
254269 result,
255270 error,
256271 timestamp : Date . now ( ) ,
257- callSource : callSource ?? absPath
272+ callSource : callSource ?? absolutePath
258273 }
259274 try {
260- newCommand . screenshot = await browser . takeScreenshot ( )
261- } catch ( shotErr ) {
262- log . warn ( `failed to capture screenshot: ${ ( shotErr as Error ) . message } ` )
275+ commandLogEntry . screenshot = await browser . takeScreenshot ( )
276+ } catch ( screenshotError ) {
277+ log . warn (
278+ `failed to capture screenshot: ${ ( screenshotError as Error ) . message } `
279+ )
263280 }
264- this . commandsLog . push ( newCommand )
265- this . sendUpstream ( 'commands' , [ newCommand ] )
281+ this . commandsLog . push ( commandLogEntry )
282+ this . sendUpstream ( 'commands' , [ commandLogEntry ] )
266283
267284 /**
268285 * capture trace and write to file on commands that could trigger a page transition
@@ -273,7 +290,7 @@ export class SessionCapturer {
273290 }
274291
275292 async injectScript ( browser : WebdriverIO . Browser ) {
276- if ( this . #isInjected ) {
293+ if ( this . #isScriptInjected ) {
277294 log . info ( 'Script already injected, skipping' )
278295 return
279296 }
@@ -284,7 +301,7 @@ export class SessionCapturer {
284301 )
285302 }
286303
287- this . #isInjected = true
304+ this . #isScriptInjected = true
288305 log . info ( 'Injecting devtools script...' )
289306 const script = await resolve ( '@wdio/devtools-script' , import . meta. url )
290307 const source = ( await fs . readFile ( url . fileURLToPath ( script ) ) ) . toString ( )
@@ -297,7 +314,7 @@ export class SessionCapturer {
297314 }
298315
299316 async #captureTrace( browser : WebdriverIO . Browser ) {
300- if ( ! this . #isInjected ) {
317+ if ( ! this . #isScriptInjected ) {
301318 log . warn ( 'Script not injected, skipping trace capture' )
302319 return
303320 }
0 commit comments