Skip to content

Commit 60ea3c2

Browse files
authored
Merge pull request #912 from RooVetGit/blur_on_save_settings
Make sure to blur fields when user hits Done in settings
2 parents d8274ac + 2caa320 commit 60ea3c2

File tree

3 files changed

+39
-30
lines changed

3 files changed

+39
-30
lines changed

.changeset/fair-boxes-smile.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"roo-cline": patch
3+
---
4+
5+
Make sure that we fire the onBlur for edited fields when the user hits Done in settings

webview-ui/src/components/settings/SettingsView.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,13 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
6868
const [modelIdErrorMessage, setModelIdErrorMessage] = useState<string | undefined>(undefined)
6969
const [commandInput, setCommandInput] = useState("")
7070

71-
const handleSubmit = () => {
71+
const handleSubmit = async () => {
72+
// Focus the active element's parent to trigger blur
73+
document.activeElement?.parentElement?.focus()
74+
75+
// Small delay to let blur events complete
76+
await new Promise((resolve) => setTimeout(resolve, 50))
77+
7278
const apiValidationResult = validateApiConfiguration(apiConfiguration)
7379
const modelIdValidationResult = validateModelId(apiConfiguration, glamaModels, openRouterModels)
7480

webview-ui/src/components/settings/__tests__/SettingsView.test.tsx

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import React from "react"
2-
import { render, screen, fireEvent } from "@testing-library/react"
1+
import { render, screen, fireEvent, waitFor } from "@testing-library/react"
32
import SettingsView from "../SettingsView"
43
import { ExtensionStateContextProvider } from "../../../context/ExtensionStateContext"
54
import { vscode } from "../../../utils/vscode"
@@ -14,14 +13,7 @@ jest.mock("../../../utils/vscode", () => ({
1413
// Mock ApiConfigManager component
1514
jest.mock("../ApiConfigManager", () => ({
1615
__esModule: true,
17-
default: ({
18-
currentApiConfigName,
19-
listApiConfigMeta,
20-
onSelectConfig,
21-
onDeleteConfig,
22-
onRenameConfig,
23-
onUpsertConfig,
24-
}: any) => (
16+
default: ({ currentApiConfigName }: any) => (
2517
<div data-testid="api-config-management">
2618
<span>Current config: {currentApiConfigName}</span>
2719
</div>
@@ -134,7 +126,7 @@ describe("SettingsView - Sound Settings", () => {
134126
expect(screen.queryByRole("slider", { name: /volume/i })).not.toBeInTheDocument()
135127
})
136128

137-
it("toggles sound setting and sends message to VSCode", () => {
129+
it("toggles sound setting and sends message to VSCode", async () => {
138130
renderSettingsView()
139131

140132
const soundCheckbox = screen.getByRole("checkbox", {
@@ -149,12 +141,14 @@ describe("SettingsView - Sound Settings", () => {
149141
const doneButton = screen.getByText("Done")
150142
fireEvent.click(doneButton)
151143

152-
expect(vscode.postMessage).toHaveBeenCalledWith(
153-
expect.objectContaining({
154-
type: "soundEnabled",
155-
bool: true,
156-
}),
157-
)
144+
await waitFor(() => {
145+
expect(vscode.postMessage).toHaveBeenCalledWith(
146+
expect.objectContaining({
147+
type: "soundEnabled",
148+
bool: true,
149+
}),
150+
)
151+
})
158152
})
159153

160154
it("shows volume slider when sound is enabled", () => {
@@ -172,7 +166,7 @@ describe("SettingsView - Sound Settings", () => {
172166
expect(volumeSlider).toHaveValue("0.5")
173167
})
174168

175-
it("updates volume and sends message to VSCode when slider changes", () => {
169+
it("updates volume and sends message to VSCode when slider changes", async () => {
176170
renderSettingsView()
177171

178172
// Enable sound
@@ -190,9 +184,11 @@ describe("SettingsView - Sound Settings", () => {
190184
fireEvent.click(doneButton)
191185

192186
// Verify message sent to VSCode
193-
expect(vscode.postMessage).toHaveBeenCalledWith({
194-
type: "soundVolume",
195-
value: 0.75,
187+
await waitFor(() => {
188+
expect(vscode.postMessage).toHaveBeenCalledWith({
189+
type: "soundVolume",
190+
value: 0.75,
191+
})
196192
})
197193
})
198194
})
@@ -309,7 +305,7 @@ describe("SettingsView - Allowed Commands", () => {
309305
expect(commands).toHaveLength(1)
310306
})
311307

312-
it("saves allowed commands when clicking Done", () => {
308+
it("saves allowed commands when clicking Done", async () => {
313309
const { onDone } = renderSettingsView()
314310

315311
// Enable always allow execute
@@ -329,12 +325,14 @@ describe("SettingsView - Allowed Commands", () => {
329325
fireEvent.click(doneButton)
330326

331327
// Verify VSCode messages were sent
332-
expect(vscode.postMessage).toHaveBeenCalledWith(
333-
expect.objectContaining({
334-
type: "allowedCommands",
335-
commands: ["npm test"],
336-
}),
337-
)
338-
expect(onDone).toHaveBeenCalled()
328+
await waitFor(() => {
329+
expect(vscode.postMessage).toHaveBeenCalledWith(
330+
expect.objectContaining({
331+
type: "allowedCommands",
332+
commands: ["npm test"],
333+
}),
334+
)
335+
expect(onDone).toHaveBeenCalled()
336+
})
339337
})
340338
})

0 commit comments

Comments
 (0)