mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-14 23:21:19 +00:00
fix(webview-ui): use crypto.randomUUID for searchFiles requestId; escape spaces for folder mentions and add coverage. Addresses review feedback by @daniel-lxs
This commit is contained in:
parent
3cbb73bc86
commit
eaf3974aa1
2 changed files with 47 additions and 5 deletions
|
|
@ -20,7 +20,7 @@ import {
|
|||
SearchResult,
|
||||
} from "@src/utils/context-mentions"
|
||||
import { cn } from "@src/lib/utils"
|
||||
import { convertToMentionPath } from "@src/utils/path-mentions"
|
||||
import { convertToMentionPath, escapeSpaces } from "@src/utils/path-mentions"
|
||||
import { StandardTooltip } from "@src/components/ui"
|
||||
|
||||
import Thumbnails from "../common/Thumbnails"
|
||||
|
|
@ -354,6 +354,12 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
folderPath = folderPath + "/"
|
||||
}
|
||||
|
||||
// Escape spaces for display (match insertMention behavior)
|
||||
let displayFolderPath = folderPath
|
||||
if (displayFolderPath.includes(" ") && !displayFolderPath.includes("\\ ")) {
|
||||
displayFolderPath = escapeSpaces(displayFolderPath)
|
||||
}
|
||||
|
||||
// Manually build insertion without a trailing space (more deterministic than insertMention)
|
||||
const original = textAreaRef.current.value
|
||||
const beforeCursor = original.slice(0, cursorPosition)
|
||||
|
|
@ -371,9 +377,9 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
afterCursorContent = isAlphaNumSpace ? afterCursor.replace(/^[^\s]*/, "") : afterCursor
|
||||
}
|
||||
|
||||
const updatedValue = beforeMention + "@" + folderPath + afterCursorContent
|
||||
const updatedValue = beforeMention + "@" + displayFolderPath + afterCursorContent
|
||||
const afterMentionPos =
|
||||
(lastAtIndex !== -1 ? lastAtIndex : beforeCursor.length) + 1 + folderPath.length
|
||||
(lastAtIndex !== -1 ? lastAtIndex : beforeCursor.length) + 1 + displayFolderPath.length
|
||||
|
||||
setInputValue(updatedValue)
|
||||
setCursorPosition(afterMentionPos)
|
||||
|
|
@ -391,7 +397,8 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
setSearchQuery(nextQuery)
|
||||
|
||||
// Kick off a search to populate folder children
|
||||
const reqId = Math.random().toString(36).substring(2, 9)
|
||||
const reqId =
|
||||
globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`
|
||||
setSearchRequestId(reqId)
|
||||
setSearchLoading(true)
|
||||
vscode.postMessage({
|
||||
|
|
@ -660,7 +667,9 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
// Set a timeout to debounce the search requests.
|
||||
searchTimeoutRef.current = setTimeout(() => {
|
||||
// Generate a request ID for this search.
|
||||
const reqId = Math.random().toString(36).substring(2, 9)
|
||||
const reqId =
|
||||
globalThis.crypto?.randomUUID?.() ??
|
||||
`${Date.now()}-${Math.random().toString(36).slice(2)}`
|
||||
setSearchRequestId(reqId)
|
||||
setSearchLoading(true)
|
||||
|
||||
|
|
|
|||
|
|
@ -93,4 +93,37 @@ describe("ChatTextArea - folder drilldown behavior", () => {
|
|||
expect(lastMsg.query).toBe("/src/")
|
||||
expect(typeof lastMsg.requestId).toBe("string")
|
||||
})
|
||||
|
||||
it("escapes spaces in input and sends unescaped query for folder with spaces", () => {
|
||||
const setInputValue = vi.fn()
|
||||
|
||||
const { container } = render(<ChatTextArea {...defaultProps} setInputValue={setInputValue} />)
|
||||
|
||||
// Type to open the @-context menu and set a query
|
||||
const textarea = container.querySelector("textarea")!
|
||||
fireEvent.change(textarea, {
|
||||
target: { value: "@m", selectionStart: 2 },
|
||||
})
|
||||
|
||||
// Ensure our mocked ContextMenu rendered and captured props
|
||||
expect(screen.getByTestId("context-menu")).toBeInTheDocument()
|
||||
const props = lastContextMenuProps
|
||||
expect(props).toBeTruthy()
|
||||
expect(typeof props.onSelect).toBe("function")
|
||||
|
||||
// Simulate selecting a concrete folder with a space
|
||||
props.onSelect(ContextMenuOptionType.Folder, "/my folder")
|
||||
|
||||
// The input should contain the escaped path and NO trailing space
|
||||
expect(setInputValue).toHaveBeenCalled()
|
||||
const finalValue2 = setInputValue.mock.calls.at(-1)?.[0]
|
||||
expect(finalValue2).toBe("@/my\\ folder/")
|
||||
|
||||
// It should have kicked off a searchFiles request with unescaped query
|
||||
const pm2 = vscode.postMessage as ReturnType<typeof vi.fn>
|
||||
const lastMsg2 = pm2.mock.calls.at(-1)?.[0]
|
||||
expect(lastMsg2).toMatchObject({ type: "searchFiles" })
|
||||
expect(lastMsg2.query).toBe("/my folder/")
|
||||
expect(typeof lastMsg2.requestId).toBe("string")
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue