@@ -14,6 +14,12 @@ import { type CommandLog, type TraceLog, TraceType } from './types.js'
1414
1515let commandsLog : CommandLog [ ] = [ ]
1616let currentTraceId : string | undefined
17+ let sources = new Map < string , string > ( )
18+
19+ function getBrowserObject ( elem : WebdriverIO . Element | WebdriverIO . Browser ) : WebdriverIO . Browser {
20+ const elemObject = elem as WebdriverIO . Element
21+ return ( elemObject as WebdriverIO . Element ) . parent ? getBrowserObject ( elemObject . parent ) : elem as WebdriverIO . Browser
22+ }
1723
1824export function setupForDevtools ( opts : Options . WebdriverIO ) {
1925 /**
@@ -39,16 +45,30 @@ export function setupForDevtools (opts: Options.WebdriverIO) {
3945 */
4046 if ( command === 'deleteSession' ) {
4147 await this . pause ( 1000 )
42- await captureTrace ( this , command as keyof WebDriverCommands , [ ] )
48+ const browser = getBrowserObject ( this )
49+ await captureTrace ( browser )
4350 }
4451 } )
4552
4653 opts . afterCommand = Array . isArray ( opts . afterCommand )
4754 ? opts . afterCommand
4855 : opts . afterCommand ? [ opts . afterCommand ] : [ ]
4956 opts . afterCommand . push ( async function ( this : WebdriverIO . Browser , command : keyof WebDriverCommands , args , result , error ) {
57+ const timestamp = Date . now ( )
58+ const callSource = ( new Error ( '' ) ) . stack ?. split ( '\n' ) . pop ( ) ?. split ( ' ' ) . pop ( ) !
59+ const sourceFile = callSource . split ( ':' ) . slice ( 0 , - 2 ) . join ( ':' )
60+ const absPath = sourceFile . startsWith ( 'file://' )
61+ ? url . fileURLToPath ( sourceFile )
62+ : sourceFile
63+ if ( sourceFile && ! sources . has ( sourceFile ) ) {
64+ const sourceCode = await fs . readFile ( absPath , 'utf-8' )
65+ sources . set ( absPath , sourceCode . toString ( ) )
66+ }
67+ commandsLog . push ( { command, args, result, error, timestamp, callSource : absPath } )
68+
5069 if ( PAGE_TRANSITION_COMMANDS . includes ( command ) ) {
51- await captureTrace ( this , command as keyof WebDriverCommands , args , result , error )
70+ const browser = getBrowserObject ( this )
71+ await captureTrace ( browser )
5272 }
5373 } )
5474
@@ -75,39 +95,44 @@ async function injectScript (browser: WebdriverIO.Browser) {
7595 } )
7696}
7797
78- async function captureTrace ( browser : WebdriverIO . Browser , command : ( keyof WebDriverCommands ) , args : any , result ?: any , error ?: Error ) {
79- const timestamp = Date . now ( )
80-
98+ async function captureTrace ( browser : WebdriverIO . Browser ) {
8199 /**
82100 * only capture trace if script was injected and command is a page transition command
83101 */
84102 if ( ! isInjected ) {
85103 return
86104 }
87105
88- const [ mutations , logs , pageMetadata ] = await browser . execute ( ( ) => [
106+ const [ mutations , logs , pageMetadata , consoleLogs ] = await browser . execute ( ( ) => [
89107 window . wdioDOMChanges ,
90108 window . wdioTraceLogs ,
91- window . wdioMetadata
109+ window . wdioMetadata ,
110+ window . wdioConsoleLogs
92111 ] )
93112
113+ if ( ! currentTraceId ) {
114+ currentTraceId = pageMetadata . id
115+ }
116+
94117 if ( currentTraceId !== pageMetadata . id ) {
95118 commandsLog = [ ]
119+ sources = new Map ( )
96120 }
97121
98- commandsLog . push ( { command, args, result, error, timestamp } )
99122 const outputDir = browser . options . outputDir || process . cwd ( )
100123 const { capabilities, ...options } = browser . options as Options . WebdriverIO
101124 const traceLog : TraceLog = {
102125 mutations,
103126 logs,
127+ consoleLogs,
104128 metadata : {
105129 type : TraceType . Standalone ,
106130 ...pageMetadata ,
107131 options,
108132 capabilities
109133 } ,
110- commands : commandsLog
134+ commands : commandsLog ,
135+ sources : Object . fromEntries ( sources )
111136 }
112137 await fs . writeFile ( path . join ( outputDir , `${ pageMetadata . id } .json` ) , JSON . stringify ( traceLog ) )
113138}
0 commit comments