@@ -3,13 +3,22 @@ import { runSlashCommandTool } from "../runSlashCommandTool"
33import { Task } from "../../task/Task"
44import { formatResponse } from "../../prompts/responses"
55import { getCommand , getCommandNames } from "../../../services/command/commands"
6+ import { parseMentions } from "../../mentions"
67
78// Mock dependencies
89vi . mock ( "../../../services/command/commands" , ( ) => ( {
910 getCommand : vi . fn ( ) ,
1011 getCommandNames : vi . fn ( ) ,
1112} ) )
1213
14+ vi . mock ( "../../mentions" , ( ) => ( {
15+ parseMentions : vi . fn ( ) ,
16+ } ) )
17+
18+ vi . mock ( "../../../services/browser/UrlContentFetcher" , ( ) => ( {
19+ UrlContentFetcher : vi . fn ( ) . mockImplementation ( ( ) => ( { } ) ) ,
20+ } ) )
21+
1322describe ( "runSlashCommandTool" , ( ) => {
1423 let mockTask : any
1524 let mockAskApproval : any
@@ -20,6 +29,9 @@ describe("runSlashCommandTool", () => {
2029 beforeEach ( ( ) => {
2130 vi . clearAllMocks ( )
2231
32+ // By default, mock parseMentions to return the original content unchanged
33+ vi . mocked ( parseMentions ) . mockImplementation ( ( content ) => Promise . resolve ( content ) )
34+
2335 mockTask = {
2436 consecutiveMistakeCount : 0 ,
2537 recordToolError : vi . fn ( ) ,
@@ -377,4 +389,147 @@ Deploy application to production`,
377389
378390 expect ( mockTask . consecutiveMistakeCount ) . toBe ( 0 )
379391 } )
392+
393+ it ( "should process mentions in command content" , async ( ) => {
394+ const mockCommand = {
395+ name : "test" ,
396+ content : "Check @/README.md for details" ,
397+ source : "project" as const ,
398+ filePath : ".roo/commands/test.md" ,
399+ description : "Test command with file reference" ,
400+ }
401+
402+ vi . mocked ( getCommand ) . mockResolvedValue ( mockCommand )
403+ vi . mocked ( parseMentions ) . mockResolvedValue (
404+ "Check 'README.md' (see below for file content)\n\n<file_content path=\"README.md\">\n# README\nTest content\n</file_content>" ,
405+ )
406+
407+ mockAskApproval . mockResolvedValue ( true )
408+
409+ const block = {
410+ type : "tool_use" as const ,
411+ name : "run_slash_command" as const ,
412+ params : {
413+ command : "test" ,
414+ } ,
415+ partial : false ,
416+ }
417+
418+ await runSlashCommandTool (
419+ mockTask as Task ,
420+ block ,
421+ mockAskApproval ,
422+ mockHandleError ,
423+ mockPushToolResult ,
424+ mockRemoveClosingTag ,
425+ )
426+
427+ // Verify parseMentions was called with the command content
428+ expect ( vi . mocked ( parseMentions ) ) . toHaveBeenCalledWith (
429+ "Check @/README.md for details" ,
430+ "/test/project" ,
431+ expect . any ( Object ) , // UrlContentFetcher instance
432+ undefined ,
433+ undefined ,
434+ false ,
435+ true ,
436+ 50 ,
437+ undefined ,
438+ )
439+
440+ // Verify the processed content is included in the result
441+ expect ( mockPushToolResult ) . toHaveBeenCalledWith (
442+ expect . stringContaining ( "Check 'README.md' (see below for file content)" ) ,
443+ )
444+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( expect . stringContaining ( '<file_content path="README.md">' ) )
445+ } )
446+
447+ it ( "should handle mention processing errors gracefully" , async ( ) => {
448+ const mockCommand = {
449+ name : "test" ,
450+ content : "Check @/README.md for details" ,
451+ source : "project" as const ,
452+ filePath : ".roo/commands/test.md" ,
453+ description : "Test command with file reference" ,
454+ }
455+
456+ vi . mocked ( getCommand ) . mockResolvedValue ( mockCommand )
457+ vi . mocked ( parseMentions ) . mockRejectedValue ( new Error ( "Failed to process mentions" ) )
458+
459+ mockAskApproval . mockResolvedValue ( true )
460+
461+ const block = {
462+ type : "tool_use" as const ,
463+ name : "run_slash_command" as const ,
464+ params : {
465+ command : "test" ,
466+ } ,
467+ partial : false ,
468+ }
469+
470+ // Mock console.warn to verify it's called
471+ const consoleWarnSpy = vi . spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } )
472+
473+ await runSlashCommandTool (
474+ mockTask as Task ,
475+ block ,
476+ mockAskApproval ,
477+ mockHandleError ,
478+ mockPushToolResult ,
479+ mockRemoveClosingTag ,
480+ )
481+
482+ // Should log a warning when mention processing fails
483+ expect ( consoleWarnSpy ) . toHaveBeenCalledWith (
484+ expect . stringContaining ( "Failed to process mentions in slash command content:" ) ,
485+ )
486+
487+ // Should still return the original content when mention processing fails
488+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( expect . stringContaining ( "Check @/README.md for details" ) )
489+
490+ consoleWarnSpy . mockRestore ( )
491+ } )
492+
493+ it ( "should process multiple file references in command content" , async ( ) => {
494+ const mockCommand = {
495+ name : "docs" ,
496+ content : "Review @/README.md and @/CONTRIBUTING.md for guidelines" ,
497+ source : "project" as const ,
498+ filePath : ".roo/commands/docs.md" ,
499+ description : "Documentation command" ,
500+ }
501+
502+ vi . mocked ( getCommand ) . mockResolvedValue ( mockCommand )
503+ vi . mocked ( parseMentions ) . mockResolvedValue (
504+ "Review 'README.md' (see below for file content) and 'CONTRIBUTING.md' (see below for file content)\n\n" +
505+ '<file_content path="README.md">\n# README\n</file_content>\n\n' +
506+ '<file_content path="CONTRIBUTING.md">\n# Contributing\n</file_content>' ,
507+ )
508+
509+ mockAskApproval . mockResolvedValue ( true )
510+
511+ const block = {
512+ type : "tool_use" as const ,
513+ name : "run_slash_command" as const ,
514+ params : {
515+ command : "docs" ,
516+ } ,
517+ partial : false ,
518+ }
519+
520+ await runSlashCommandTool (
521+ mockTask as Task ,
522+ block ,
523+ mockAskApproval ,
524+ mockHandleError ,
525+ mockPushToolResult ,
526+ mockRemoveClosingTag ,
527+ )
528+
529+ // Verify both files are included in the processed content
530+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( expect . stringContaining ( '<file_content path="README.md">' ) )
531+ expect ( mockPushToolResult ) . toHaveBeenCalledWith (
532+ expect . stringContaining ( '<file_content path="CONTRIBUTING.md">' ) ,
533+ )
534+ } )
380535} )
0 commit comments