@@ -104,142 +104,195 @@ describe('debugger', () => {
104104 ) ;
105105 } ) ;
106106 } ) ;
107+ } ) ;
107108
108- it ( 'reports not paused when execution is running' , async ( ) => {
109- await withMcpContext ( async ( response , context ) => {
110- const page = context . getSelectedMcpPage ( ) ;
111- await enableDebugger . handler ( { params : { } , page} , response , context ) ;
112-
113- response . resetResponseLineForTesting ( ) ;
114- await getPausedState . handler ( { params : { } , page} , response , context ) ;
115- assert . ok ( response . responseLines [ 0 ] . includes ( 'Debugger is not paused' ) ) ;
116- } ) ;
109+ it ( 'escapes backslashes in logpoint message' , async ( ) => {
110+ await withMcpContext ( async ( response , context ) => {
111+ const page = context . getSelectedMcpPage ( ) ;
112+ await page . pptrPage . setContent (
113+ '<script>function test() { console.log("test"); }</script>' ,
114+ ) ;
115+
116+ await setLogpoint . handler (
117+ {
118+ params : {
119+ url : 'http://localhost/' ,
120+ lineNumber : 1 ,
121+ message : 'Path: C:\\Windows\\System32' ,
122+ } ,
123+ page,
124+ } ,
125+ response ,
126+ context ,
127+ ) ;
128+
129+ const setOutput = response . responseLines . join ( '\n' ) ;
130+ const breakpointIdMatch = setOutput . match ( / L o g p o i n t s e t w i t h I D : ( .* ) / ) ;
131+ assert . ok ( breakpointIdMatch , 'Should return logpoint ID' ) ;
132+
133+ // In generated code string: console.log(`Path: C:\\Windows\\System32`)
134+ // But because it's inside a string in code, backslashes are escaped.
135+ // Wait. The code string is `console.log("...")`.
136+ // If we use backticks in code: `console.log(\`Path: C:\\\\Windows\\\\System32\`)`
137+ // My fix: replace `\` with `\\`.
138+ // Input: `C:\Windows`.
139+ // Output string in `condition`: `console.log(`Path: C:\\Windows`)`
140+ // Wait. `console.log` executes at runtime.
141+ // `console.log(`C:\Windows`)` prints `C:Windows` (escapes W? no). `C:\Windows`.
142+ // Check: `console.log(`C:\\Windows`)` prints `C:\Windows`.
143+ // So we want the condition code to contain `console.log(`C:\\Windows`)`.
144+ // So we need `runExpression` string to be `console.log(`C:\\Windows`)`.
145+ // My code: `message.replace(/\\/g, '\\\\')`.
146+ // Input `C:\Windows` -> `C:\\Windows`.
147+ // Result `runExpression`: `console.log(`C:\\Windows`)`.
148+ // This is what we want.
149+
150+ // So expected string in condition: `console.log(\`Path: C:\\\\Windows\\\\System32\`)`?
151+ // No. `C:\\Windows`.
152+ // In JS string literal for test assertion:
153+ // We want to match `C:\\Windows`.
154+ // Regex or string includes: `'C:\\\\Windows'`.
155+
156+ assert . ok (
157+ setOutput . includes ( 'Path: C:\\\\Windows\\\\System32' ) ,
158+ 'Should double escape backslashes for template literal' ,
159+ ) ;
117160 } ) ;
161+ } ) ;
118162
119- it ( 'pauses on breakpoint and resumes ' , async ( ) => {
120- await withMcpContext ( async ( response , context ) => {
121- const page = context . getSelectedMcpPage ( ) ;
122- const pptrPage = page . pptrPage ;
163+ it ( 'reports not paused when execution is running ' , async ( ) => {
164+ await withMcpContext ( async ( response , context ) => {
165+ const page = context . getSelectedMcpPage ( ) ;
166+ await enableDebugger . handler ( { params : { } , page } , response , context ) ;
123167
124- // We need a script that runs somewhat later or triggered by us to hit the breakpoint reliably in test
125- // Or we can use `debugger;` statement.
126- await pptrPage . evaluate ( ( ) => {
127- // @ts -expect-error - Window property
128- window . debugMe = ( ) => {
129- // eslint-disable-next-line no-debugger
130- debugger ;
131- } ;
132- } ) ;
168+ response . resetResponseLineForTesting ( ) ;
169+ await getPausedState . handler ( { params : { } , page} , response , context ) ;
170+ assert . ok ( response . responseLines [ 0 ] . includes ( 'Debugger is not paused' ) ) ;
171+ } ) ;
172+ } ) ;
133173
134- // Enable debugger
135- await enableDebugger . handler ( { params : { } , page} , response , context ) ;
174+ it ( 'pauses on breakpoint and resumes' , async ( ) => {
175+ await withMcpContext ( async ( response , context ) => {
176+ const page = context . getSelectedMcpPage ( ) ;
177+ const pptrPage = page . pptrPage ;
178+
179+ // We need a script that runs somewhat later or triggered by us to hit the breakpoint reliably in test
180+ // Or we can use `debugger;` statement.
181+ await pptrPage . evaluate ( ( ) => {
182+ // @ts -expect-error - Window property
183+ window . debugMe = ( ) => {
184+ // eslint-disable-next-line no-debugger
185+ debugger ;
186+ } ;
187+ } ) ;
136188
137- // Trigger debugger
189+ // Enable debugger
190+ await enableDebugger . handler ( { params : { } , page} , response , context ) ;
138191
139- // We trigger execution, but we usually need to do it without awaiting if it pauses.
140- await pptrPage . evaluate ( ( ) => {
141- setTimeout ( ( ) => {
142- // @ts -expect-error - Window property
143- window . debugMe ( ) ;
144- } , 100 ) ;
145- } ) ;
192+ // Trigger debugger
146193
147- // Wait a bit for pause
148- await new Promise ( r => setTimeout ( r , 500 ) ) ;
194+ // We trigger execution, but we usually need to do it without awaiting if it pauses.
195+ await pptrPage . evaluate ( ( ) => {
196+ setTimeout ( ( ) => {
197+ // @ts -expect-error - Window property
198+ window . debugMe ( ) ;
199+ } , 100 ) ;
200+ } ) ;
149201
150- response . resetResponseLineForTesting ( ) ;
151- await getPausedState . handler ( { params : { } , page } , response , context ) ;
202+ // Wait a bit for pause
203+ await new Promise ( r => setTimeout ( r , 500 ) ) ;
152204
153- const output = response . responseLines . join ( '\n' ) ;
154- assert . ok (
155- output . includes ( 'Paused state' ) ||
156- output . includes ( 'Debugger is not paused' ) ,
157- 'Should report state (flake warning: might not be paused yet)' ,
158- ) ;
205+ response . resetResponseLineForTesting ( ) ;
206+ await getPausedState . handler ( { params : { } , page} , response , context ) ;
159207
160- if ( output . includes ( 'Paused state' ) ) {
161- // Test resume
162- response . resetResponseLineForTesting ( ) ;
163- await resume . handler ( { params : { } , page} , response , context ) ;
164- assert . ok ( response . responseLines [ 0 ] . includes ( 'Resumed execution' ) ) ;
165- }
166- } ) ;
167- } ) ;
208+ const output = response . responseLines . join ( '\n' ) ;
209+ assert . ok (
210+ output . includes ( 'Paused state' ) ||
211+ output . includes ( 'Debugger is not paused' ) ,
212+ 'Should report state (flake warning: might not be paused yet)' ,
213+ ) ;
168214
169- it ( 'reports not enabled when calling getPausedState without enabling' , async ( ) => {
170- await withMcpContext ( async ( response , context ) => {
171- const page = context . getSelectedMcpPage ( ) ;
172- await getPausedState . handler ( { params : { } , page} , response , context ) ;
173- assert . ok ( response . responseLines [ 0 ] . includes ( 'Debugger is not enabled ' ) ) ;
174- } ) ;
215+ if ( output . includes ( 'Paused state' ) ) {
216+ // Test resume
217+ response . resetResponseLineForTesting ( ) ;
218+ await resume . handler ( { params : { } , page} , response , context ) ;
219+ assert . ok ( response . responseLines [ 0 ] . includes ( 'Resumed execution ' ) ) ;
220+ }
175221 } ) ;
222+ } ) ;
176223
177- it ( 'throws when calling getScopeVariables without enabling' , async ( ) => {
178- await withMcpContext ( async ( response , context ) => {
179- const page = context . getSelectedMcpPage ( ) ;
180- try {
181- await getScopeVariables . handler (
182- { params : { callFrameId : '1' , scopeIndex : 0 } , page} ,
183- response ,
184- context ,
185- ) ;
186- assert . fail ( 'Should have thrown' ) ;
187- } catch ( e ) {
188- const error = e as Error ;
189- if ( ! error . message . includes ( 'Debugger is not enabled' ) ) {
190- console . error ( 'Unexpected error:' , e ) ;
191- assert . fail ( `Expected "Debugger is not enabled", got: ${ e . message } ` ) ;
192- }
193- assert . ok ( true ) ;
194- }
195- } ) ;
224+ it ( 'reports not enabled when calling getPausedState without enabling' , async ( ) => {
225+ await withMcpContext ( async ( response , context ) => {
226+ const page = context . getSelectedMcpPage ( ) ;
227+ await getPausedState . handler ( { params : { } , page} , response , context ) ;
228+ assert . ok ( response . responseLines [ 0 ] . includes ( 'Debugger is not enabled' ) ) ;
196229 } ) ;
230+ } ) ;
197231
198- it ( 'evaluates on call frame (mock check)' , async ( ) => {
199- // This is hard to test e2e without actually being paused.
200- // We verified "not paused" error in getPausedState.
201- await withMcpContext ( async ( response , context ) => {
202- const page = context . getSelectedMcpPage ( ) ;
203- try {
204- await evaluateOnCallFrame . handler (
205- { params : { callFrameId : 'fake' , expression : '1+1' } , page} ,
206- response ,
207- context ,
208- ) ;
209- } catch ( e ) {
210- // It might fail because session throws "Invalid parameters" or similar from CDP
211- assert . ok ( e ) ;
232+ it ( 'throws when calling getScopeVariables without enabling' , async ( ) => {
233+ await withMcpContext ( async ( response , context ) => {
234+ const page = context . getSelectedMcpPage ( ) ;
235+ try {
236+ await getScopeVariables . handler (
237+ { params : { callFrameId : '1' , scopeIndex : 0 } , page} ,
238+ response ,
239+ context ,
240+ ) ;
241+ assert . fail ( 'Should have thrown' ) ;
242+ } catch ( e ) {
243+ const error = e as Error ;
244+ if ( ! error . message . includes ( 'Debugger is not enabled' ) ) {
245+ console . error ( 'Unexpected error:' , e ) ;
246+ assert . fail ( `Expected "Debugger is not enabled", got: ${ e . message } ` ) ;
212247 }
213- } ) ;
248+ assert . ok ( true ) ;
249+ }
214250 } ) ;
215- it ( 'removes logpoints via removeAllBreakpoints' , async ( ) => {
216- await withMcpContext ( async ( response , context ) => {
217- const page = context . getSelectedMcpPage ( ) ;
218- await page . pptrPage . setContent ( '<script>function test() {}</script>' ) ;
251+ } ) ;
219252
220- // Set a logpoint
221- await setLogpoint . handler (
222- {
223- params : { url : 'http://localhost/' , lineNumber : 1 , message : 'Log' } ,
224- page,
225- } ,
253+ it ( 'evaluates on call frame (mock check)' , async ( ) => {
254+ // This is hard to test e2e without actually being paused.
255+ // We verified "not paused" error in getPausedState.
256+ await withMcpContext ( async ( response , context ) => {
257+ const page = context . getSelectedMcpPage ( ) ;
258+ try {
259+ await evaluateOnCallFrame . handler (
260+ { params : { callFrameId : 'fake' , expression : '1+1' } , page} ,
226261 response ,
227262 context ,
228263 ) ;
229-
230- response . resetResponseLineForTesting ( ) ;
231-
232- // Remove all
233- // We need to import removeAllBreakpoints
234- const { removeAllBreakpoints} =
235- await import ( '../../src/tools/debugger.js' ) ;
236- await removeAllBreakpoints . handler ( { params : { } , page} , response , context ) ;
237-
238- assert . ok (
239- response . responseLines [ 0 ] . includes (
240- 'All breakpoints and logpoints removed' ,
241- ) ,
242- ) ;
243- } ) ;
264+ } catch ( e ) {
265+ // It might fail because session throws "Invalid parameters" or similar from CDP
266+ assert . ok ( e ) ;
267+ }
268+ } ) ;
269+ } ) ;
270+ it ( 'removes logpoints via removeAllBreakpoints' , async ( ) => {
271+ await withMcpContext ( async ( response , context ) => {
272+ const page = context . getSelectedMcpPage ( ) ;
273+ await page . pptrPage . setContent ( '<script>function test() {}</script>' ) ;
274+
275+ // Set a logpoint
276+ await setLogpoint . handler (
277+ {
278+ params : { url : 'http://localhost/' , lineNumber : 1 , message : 'Log' } ,
279+ page,
280+ } ,
281+ response ,
282+ context ,
283+ ) ;
284+
285+ response . resetResponseLineForTesting ( ) ;
286+
287+ // Remove all
288+ // We need to import removeAllBreakpoints
289+ const { removeAllBreakpoints} = await import ( '../../src/tools/debugger.js' ) ;
290+ await removeAllBreakpoints . handler ( { params : { } , page} , response , context ) ;
291+
292+ assert . ok (
293+ response . responseLines [ 0 ] . includes (
294+ 'All breakpoints and logpoints removed' ,
295+ ) ,
296+ ) ;
244297 } ) ;
245298} ) ;
0 commit comments