mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-22 05:11:06 -05:00
Prettier backfill
This commit is contained in:
@@ -1,154 +1,136 @@
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import ApiConfigManager from '../ApiConfigManager';
|
||||
import { render, screen, fireEvent } from "@testing-library/react"
|
||||
import "@testing-library/jest-dom"
|
||||
import ApiConfigManager from "../ApiConfigManager"
|
||||
|
||||
// Mock VSCode components
|
||||
jest.mock('@vscode/webview-ui-toolkit/react', () => ({
|
||||
VSCodeButton: ({ children, onClick, title, disabled }: any) => (
|
||||
<button onClick={onClick} title={title} disabled={disabled}>
|
||||
{children}
|
||||
</button>
|
||||
),
|
||||
VSCodeTextField: ({ value, onInput, placeholder }: any) => (
|
||||
<input
|
||||
value={value}
|
||||
onChange={e => onInput(e)}
|
||||
placeholder={placeholder}
|
||||
ref={undefined} // Explicitly set ref to undefined to avoid warning
|
||||
/>
|
||||
),
|
||||
}));
|
||||
jest.mock("@vscode/webview-ui-toolkit/react", () => ({
|
||||
VSCodeButton: ({ children, onClick, title, disabled }: any) => (
|
||||
<button onClick={onClick} title={title} disabled={disabled}>
|
||||
{children}
|
||||
</button>
|
||||
),
|
||||
VSCodeTextField: ({ value, onInput, placeholder }: any) => (
|
||||
<input
|
||||
value={value}
|
||||
onChange={(e) => onInput(e)}
|
||||
placeholder={placeholder}
|
||||
ref={undefined} // Explicitly set ref to undefined to avoid warning
|
||||
/>
|
||||
),
|
||||
}))
|
||||
|
||||
describe('ApiConfigManager', () => {
|
||||
const mockOnSelectConfig = jest.fn();
|
||||
const mockOnDeleteConfig = jest.fn();
|
||||
const mockOnRenameConfig = jest.fn();
|
||||
const mockOnUpsertConfig = jest.fn();
|
||||
describe("ApiConfigManager", () => {
|
||||
const mockOnSelectConfig = jest.fn()
|
||||
const mockOnDeleteConfig = jest.fn()
|
||||
const mockOnRenameConfig = jest.fn()
|
||||
const mockOnUpsertConfig = jest.fn()
|
||||
|
||||
const defaultProps = {
|
||||
currentApiConfigName: 'Default Config',
|
||||
listApiConfigMeta: [
|
||||
{ name: 'Default Config' },
|
||||
{ name: 'Another Config' }
|
||||
],
|
||||
onSelectConfig: mockOnSelectConfig,
|
||||
onDeleteConfig: mockOnDeleteConfig,
|
||||
onRenameConfig: mockOnRenameConfig,
|
||||
onUpsertConfig: mockOnUpsertConfig,
|
||||
};
|
||||
const defaultProps = {
|
||||
currentApiConfigName: "Default Config",
|
||||
listApiConfigMeta: [{ name: "Default Config" }, { name: "Another Config" }],
|
||||
onSelectConfig: mockOnSelectConfig,
|
||||
onDeleteConfig: mockOnDeleteConfig,
|
||||
onRenameConfig: mockOnRenameConfig,
|
||||
onUpsertConfig: mockOnUpsertConfig,
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('immediately creates a copy when clicking add button', () => {
|
||||
render(<ApiConfigManager {...defaultProps} />);
|
||||
it("immediately creates a copy when clicking add button", () => {
|
||||
render(<ApiConfigManager {...defaultProps} />)
|
||||
|
||||
// Find and click the add button
|
||||
const addButton = screen.getByTitle('Add profile');
|
||||
fireEvent.click(addButton);
|
||||
// Find and click the add button
|
||||
const addButton = screen.getByTitle("Add profile")
|
||||
fireEvent.click(addButton)
|
||||
|
||||
// Verify that onUpsertConfig was called with the correct name
|
||||
expect(mockOnUpsertConfig).toHaveBeenCalledTimes(1);
|
||||
expect(mockOnUpsertConfig).toHaveBeenCalledWith('Default Config (copy)');
|
||||
});
|
||||
// Verify that onUpsertConfig was called with the correct name
|
||||
expect(mockOnUpsertConfig).toHaveBeenCalledTimes(1)
|
||||
expect(mockOnUpsertConfig).toHaveBeenCalledWith("Default Config (copy)")
|
||||
})
|
||||
|
||||
it('creates copy with correct name when current config has spaces', () => {
|
||||
render(
|
||||
<ApiConfigManager
|
||||
{...defaultProps}
|
||||
currentApiConfigName="My Test Config"
|
||||
/>
|
||||
);
|
||||
it("creates copy with correct name when current config has spaces", () => {
|
||||
render(<ApiConfigManager {...defaultProps} currentApiConfigName="My Test Config" />)
|
||||
|
||||
const addButton = screen.getByTitle('Add profile');
|
||||
fireEvent.click(addButton);
|
||||
const addButton = screen.getByTitle("Add profile")
|
||||
fireEvent.click(addButton)
|
||||
|
||||
expect(mockOnUpsertConfig).toHaveBeenCalledWith('My Test Config (copy)');
|
||||
});
|
||||
expect(mockOnUpsertConfig).toHaveBeenCalledWith("My Test Config (copy)")
|
||||
})
|
||||
|
||||
it('handles empty current config name gracefully', () => {
|
||||
render(
|
||||
<ApiConfigManager
|
||||
{...defaultProps}
|
||||
currentApiConfigName=""
|
||||
/>
|
||||
);
|
||||
it("handles empty current config name gracefully", () => {
|
||||
render(<ApiConfigManager {...defaultProps} currentApiConfigName="" />)
|
||||
|
||||
const addButton = screen.getByTitle('Add profile');
|
||||
fireEvent.click(addButton);
|
||||
const addButton = screen.getByTitle("Add profile")
|
||||
fireEvent.click(addButton)
|
||||
|
||||
expect(mockOnUpsertConfig).toHaveBeenCalledWith(' (copy)');
|
||||
});
|
||||
expect(mockOnUpsertConfig).toHaveBeenCalledWith(" (copy)")
|
||||
})
|
||||
|
||||
it('allows renaming the current config', () => {
|
||||
render(<ApiConfigManager {...defaultProps} />);
|
||||
|
||||
// Start rename
|
||||
const renameButton = screen.getByTitle('Rename profile');
|
||||
fireEvent.click(renameButton);
|
||||
it("allows renaming the current config", () => {
|
||||
render(<ApiConfigManager {...defaultProps} />)
|
||||
|
||||
// Find input and enter new name
|
||||
const input = screen.getByDisplayValue('Default Config');
|
||||
fireEvent.input(input, { target: { value: 'New Name' } });
|
||||
// Start rename
|
||||
const renameButton = screen.getByTitle("Rename profile")
|
||||
fireEvent.click(renameButton)
|
||||
|
||||
// Save
|
||||
const saveButton = screen.getByTitle('Save');
|
||||
fireEvent.click(saveButton);
|
||||
// Find input and enter new name
|
||||
const input = screen.getByDisplayValue("Default Config")
|
||||
fireEvent.input(input, { target: { value: "New Name" } })
|
||||
|
||||
expect(mockOnRenameConfig).toHaveBeenCalledWith('Default Config', 'New Name');
|
||||
});
|
||||
// Save
|
||||
const saveButton = screen.getByTitle("Save")
|
||||
fireEvent.click(saveButton)
|
||||
|
||||
it('allows selecting a different config', () => {
|
||||
render(<ApiConfigManager {...defaultProps} />);
|
||||
|
||||
const select = screen.getByRole('combobox');
|
||||
fireEvent.change(select, { target: { value: 'Another Config' } });
|
||||
expect(mockOnRenameConfig).toHaveBeenCalledWith("Default Config", "New Name")
|
||||
})
|
||||
|
||||
expect(mockOnSelectConfig).toHaveBeenCalledWith('Another Config');
|
||||
});
|
||||
it("allows selecting a different config", () => {
|
||||
render(<ApiConfigManager {...defaultProps} />)
|
||||
|
||||
it('allows deleting the current config when not the only one', () => {
|
||||
render(<ApiConfigManager {...defaultProps} />);
|
||||
|
||||
const deleteButton = screen.getByTitle('Delete profile');
|
||||
expect(deleteButton).not.toBeDisabled();
|
||||
|
||||
fireEvent.click(deleteButton);
|
||||
expect(mockOnDeleteConfig).toHaveBeenCalledWith('Default Config');
|
||||
});
|
||||
const select = screen.getByRole("combobox")
|
||||
fireEvent.change(select, { target: { value: "Another Config" } })
|
||||
|
||||
it('disables delete button when only one config exists', () => {
|
||||
render(
|
||||
<ApiConfigManager
|
||||
{...defaultProps}
|
||||
listApiConfigMeta={[{ name: 'Default Config' }]}
|
||||
/>
|
||||
);
|
||||
|
||||
const deleteButton = screen.getByTitle('Cannot delete the only profile');
|
||||
expect(deleteButton).toHaveAttribute('disabled');
|
||||
});
|
||||
expect(mockOnSelectConfig).toHaveBeenCalledWith("Another Config")
|
||||
})
|
||||
|
||||
it('cancels rename operation when clicking cancel', () => {
|
||||
render(<ApiConfigManager {...defaultProps} />);
|
||||
|
||||
// Start rename
|
||||
const renameButton = screen.getByTitle('Rename profile');
|
||||
fireEvent.click(renameButton);
|
||||
it("allows deleting the current config when not the only one", () => {
|
||||
render(<ApiConfigManager {...defaultProps} />)
|
||||
|
||||
// Find input and enter new name
|
||||
const input = screen.getByDisplayValue('Default Config');
|
||||
fireEvent.input(input, { target: { value: 'New Name' } });
|
||||
const deleteButton = screen.getByTitle("Delete profile")
|
||||
expect(deleteButton).not.toBeDisabled()
|
||||
|
||||
// Cancel
|
||||
const cancelButton = screen.getByTitle('Cancel');
|
||||
fireEvent.click(cancelButton);
|
||||
fireEvent.click(deleteButton)
|
||||
expect(mockOnDeleteConfig).toHaveBeenCalledWith("Default Config")
|
||||
})
|
||||
|
||||
// Verify rename was not called
|
||||
expect(mockOnRenameConfig).not.toHaveBeenCalled();
|
||||
|
||||
// Verify we're back to normal view
|
||||
expect(screen.queryByDisplayValue('New Name')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
it("disables delete button when only one config exists", () => {
|
||||
render(<ApiConfigManager {...defaultProps} listApiConfigMeta={[{ name: "Default Config" }]} />)
|
||||
|
||||
const deleteButton = screen.getByTitle("Cannot delete the only profile")
|
||||
expect(deleteButton).toHaveAttribute("disabled")
|
||||
})
|
||||
|
||||
it("cancels rename operation when clicking cancel", () => {
|
||||
render(<ApiConfigManager {...defaultProps} />)
|
||||
|
||||
// Start rename
|
||||
const renameButton = screen.getByTitle("Rename profile")
|
||||
fireEvent.click(renameButton)
|
||||
|
||||
// Find input and enter new name
|
||||
const input = screen.getByDisplayValue("Default Config")
|
||||
fireEvent.input(input, { target: { value: "New Name" } })
|
||||
|
||||
// Cancel
|
||||
const cancelButton = screen.getByTitle("Cancel")
|
||||
fireEvent.click(cancelButton)
|
||||
|
||||
// Verify rename was not called
|
||||
expect(mockOnRenameConfig).not.toHaveBeenCalled()
|
||||
|
||||
// Verify we're back to normal view
|
||||
expect(screen.queryByDisplayValue("New Name")).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,336 +1,340 @@
|
||||
import React from 'react'
|
||||
import { render, screen, fireEvent } from '@testing-library/react'
|
||||
import SettingsView from '../SettingsView'
|
||||
import { ExtensionStateContextProvider } from '../../../context/ExtensionStateContext'
|
||||
import { vscode } from '../../../utils/vscode'
|
||||
import React from "react"
|
||||
import { render, screen, fireEvent } from "@testing-library/react"
|
||||
import SettingsView from "../SettingsView"
|
||||
import { ExtensionStateContextProvider } from "../../../context/ExtensionStateContext"
|
||||
import { vscode } from "../../../utils/vscode"
|
||||
|
||||
// Mock vscode API
|
||||
jest.mock('../../../utils/vscode', () => ({
|
||||
vscode: {
|
||||
postMessage: jest.fn(),
|
||||
},
|
||||
jest.mock("../../../utils/vscode", () => ({
|
||||
vscode: {
|
||||
postMessage: jest.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
// Mock ApiConfigManager component
|
||||
jest.mock('../ApiConfigManager', () => ({
|
||||
__esModule: true,
|
||||
default: ({ currentApiConfigName, listApiConfigMeta, onSelectConfig, onDeleteConfig, onRenameConfig, onUpsertConfig }: any) => (
|
||||
<div data-testid="api-config-management">
|
||||
<span>Current config: {currentApiConfigName}</span>
|
||||
</div>
|
||||
)
|
||||
jest.mock("../ApiConfigManager", () => ({
|
||||
__esModule: true,
|
||||
default: ({
|
||||
currentApiConfigName,
|
||||
listApiConfigMeta,
|
||||
onSelectConfig,
|
||||
onDeleteConfig,
|
||||
onRenameConfig,
|
||||
onUpsertConfig,
|
||||
}: any) => (
|
||||
<div data-testid="api-config-management">
|
||||
<span>Current config: {currentApiConfigName}</span>
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
// Mock VSCode components
|
||||
jest.mock('@vscode/webview-ui-toolkit/react', () => ({
|
||||
VSCodeButton: ({ children, onClick, appearance }: any) => (
|
||||
appearance === 'icon' ?
|
||||
<button onClick={onClick} className="codicon codicon-close" aria-label="Remove command">
|
||||
<span className="codicon codicon-close" />
|
||||
</button> :
|
||||
<button onClick={onClick} data-appearance={appearance}>{children}</button>
|
||||
),
|
||||
VSCodeCheckbox: ({ children, onChange, checked }: any) => (
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked}
|
||||
onChange={(e) => onChange({ target: { checked: e.target.checked } })}
|
||||
aria-label={typeof children === 'string' ? children : undefined}
|
||||
/>
|
||||
{children}
|
||||
</label>
|
||||
),
|
||||
VSCodeTextField: ({ value, onInput, placeholder }: any) => (
|
||||
<input
|
||||
type="text"
|
||||
value={value}
|
||||
onChange={(e) => onInput({ target: { value: e.target.value } })}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
),
|
||||
VSCodeTextArea: () => <textarea />,
|
||||
VSCodeLink: ({ children, href }: any) => <a href={href || '#'}>{children}</a>,
|
||||
VSCodeDropdown: ({ children, value, onChange }: any) => (
|
||||
<select value={value} onChange={onChange}>
|
||||
{children}
|
||||
</select>
|
||||
),
|
||||
VSCodeOption: ({ children, value }: any) => (
|
||||
<option value={value}>{children}</option>
|
||||
),
|
||||
VSCodeRadio: ({ children, value, checked, onChange }: any) => (
|
||||
<input
|
||||
type="radio"
|
||||
value={value}
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
/>
|
||||
),
|
||||
VSCodeRadioGroup: ({ children, value, onChange }: any) => (
|
||||
<div onChange={onChange}>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
VSCodeSlider: ({ value, onChange }: any) => (
|
||||
<input
|
||||
type="range"
|
||||
value={value}
|
||||
onChange={(e) => onChange({ target: { value: Number(e.target.value) } })}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
style={{ flexGrow: 1, height: '2px' }}
|
||||
/>
|
||||
)
|
||||
jest.mock("@vscode/webview-ui-toolkit/react", () => ({
|
||||
VSCodeButton: ({ children, onClick, appearance }: any) =>
|
||||
appearance === "icon" ? (
|
||||
<button onClick={onClick} className="codicon codicon-close" aria-label="Remove command">
|
||||
<span className="codicon codicon-close" />
|
||||
</button>
|
||||
) : (
|
||||
<button onClick={onClick} data-appearance={appearance}>
|
||||
{children}
|
||||
</button>
|
||||
),
|
||||
VSCodeCheckbox: ({ children, onChange, checked }: any) => (
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked}
|
||||
onChange={(e) => onChange({ target: { checked: e.target.checked } })}
|
||||
aria-label={typeof children === "string" ? children : undefined}
|
||||
/>
|
||||
{children}
|
||||
</label>
|
||||
),
|
||||
VSCodeTextField: ({ value, onInput, placeholder }: any) => (
|
||||
<input
|
||||
type="text"
|
||||
value={value}
|
||||
onChange={(e) => onInput({ target: { value: e.target.value } })}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
),
|
||||
VSCodeTextArea: () => <textarea />,
|
||||
VSCodeLink: ({ children, href }: any) => <a href={href || "#"}>{children}</a>,
|
||||
VSCodeDropdown: ({ children, value, onChange }: any) => (
|
||||
<select value={value} onChange={onChange}>
|
||||
{children}
|
||||
</select>
|
||||
),
|
||||
VSCodeOption: ({ children, value }: any) => <option value={value}>{children}</option>,
|
||||
VSCodeRadio: ({ children, value, checked, onChange }: any) => (
|
||||
<input type="radio" value={value} checked={checked} onChange={onChange} />
|
||||
),
|
||||
VSCodeRadioGroup: ({ children, value, onChange }: any) => <div onChange={onChange}>{children}</div>,
|
||||
VSCodeSlider: ({ value, onChange }: any) => (
|
||||
<input
|
||||
type="range"
|
||||
value={value}
|
||||
onChange={(e) => onChange({ target: { value: Number(e.target.value) } })}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
style={{ flexGrow: 1, height: "2px" }}
|
||||
/>
|
||||
),
|
||||
}))
|
||||
|
||||
// Mock window.postMessage to trigger state hydration
|
||||
const mockPostMessage = (state: any) => {
|
||||
window.postMessage({
|
||||
type: 'state',
|
||||
state: {
|
||||
version: '1.0.0',
|
||||
clineMessages: [],
|
||||
taskHistory: [],
|
||||
shouldShowAnnouncement: false,
|
||||
allowedCommands: [],
|
||||
alwaysAllowExecute: false,
|
||||
soundEnabled: false,
|
||||
soundVolume: 0.5,
|
||||
...state
|
||||
}
|
||||
}, '*')
|
||||
window.postMessage(
|
||||
{
|
||||
type: "state",
|
||||
state: {
|
||||
version: "1.0.0",
|
||||
clineMessages: [],
|
||||
taskHistory: [],
|
||||
shouldShowAnnouncement: false,
|
||||
allowedCommands: [],
|
||||
alwaysAllowExecute: false,
|
||||
soundEnabled: false,
|
||||
soundVolume: 0.5,
|
||||
...state,
|
||||
},
|
||||
},
|
||||
"*",
|
||||
)
|
||||
}
|
||||
|
||||
const renderSettingsView = () => {
|
||||
const onDone = jest.fn()
|
||||
render(
|
||||
<ExtensionStateContextProvider>
|
||||
<SettingsView onDone={onDone} />
|
||||
</ExtensionStateContextProvider>
|
||||
)
|
||||
// Hydrate initial state
|
||||
mockPostMessage({})
|
||||
return { onDone }
|
||||
const onDone = jest.fn()
|
||||
render(
|
||||
<ExtensionStateContextProvider>
|
||||
<SettingsView onDone={onDone} />
|
||||
</ExtensionStateContextProvider>,
|
||||
)
|
||||
// Hydrate initial state
|
||||
mockPostMessage({})
|
||||
return { onDone }
|
||||
}
|
||||
|
||||
describe('SettingsView - Sound Settings', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
describe("SettingsView - Sound Settings", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('initializes with sound disabled by default', () => {
|
||||
renderSettingsView()
|
||||
|
||||
const soundCheckbox = screen.getByRole('checkbox', {
|
||||
name: /Enable sound effects/i
|
||||
})
|
||||
expect(soundCheckbox).not.toBeChecked()
|
||||
|
||||
// Volume slider should not be visible when sound is disabled
|
||||
expect(screen.queryByRole('slider', { name: /volume/i })).not.toBeInTheDocument()
|
||||
})
|
||||
it("initializes with sound disabled by default", () => {
|
||||
renderSettingsView()
|
||||
|
||||
it('toggles sound setting and sends message to VSCode', () => {
|
||||
renderSettingsView()
|
||||
|
||||
const soundCheckbox = screen.getByRole('checkbox', {
|
||||
name: /Enable sound effects/i
|
||||
})
|
||||
|
||||
// Enable sound
|
||||
fireEvent.click(soundCheckbox)
|
||||
expect(soundCheckbox).toBeChecked()
|
||||
|
||||
// Click Done to save settings
|
||||
const doneButton = screen.getByText('Done')
|
||||
fireEvent.click(doneButton)
|
||||
|
||||
expect(vscode.postMessage).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: 'soundEnabled',
|
||||
bool: true
|
||||
})
|
||||
)
|
||||
})
|
||||
const soundCheckbox = screen.getByRole("checkbox", {
|
||||
name: /Enable sound effects/i,
|
||||
})
|
||||
expect(soundCheckbox).not.toBeChecked()
|
||||
|
||||
it('shows volume slider when sound is enabled', () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Enable sound
|
||||
const soundCheckbox = screen.getByRole('checkbox', {
|
||||
name: /Enable sound effects/i
|
||||
})
|
||||
fireEvent.click(soundCheckbox)
|
||||
// Volume slider should not be visible when sound is disabled
|
||||
expect(screen.queryByRole("slider", { name: /volume/i })).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
// Volume slider should be visible
|
||||
const volumeSlider = screen.getByRole('slider', { name: /volume/i })
|
||||
expect(volumeSlider).toBeInTheDocument()
|
||||
expect(volumeSlider).toHaveValue('0.5')
|
||||
})
|
||||
it("toggles sound setting and sends message to VSCode", () => {
|
||||
renderSettingsView()
|
||||
|
||||
it('updates volume and sends message to VSCode when slider changes', () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Enable sound
|
||||
const soundCheckbox = screen.getByRole('checkbox', {
|
||||
name: /Enable sound effects/i
|
||||
})
|
||||
fireEvent.click(soundCheckbox)
|
||||
const soundCheckbox = screen.getByRole("checkbox", {
|
||||
name: /Enable sound effects/i,
|
||||
})
|
||||
|
||||
// Change volume
|
||||
const volumeSlider = screen.getByRole('slider', { name: /volume/i })
|
||||
fireEvent.change(volumeSlider, { target: { value: '0.75' } })
|
||||
// Enable sound
|
||||
fireEvent.click(soundCheckbox)
|
||||
expect(soundCheckbox).toBeChecked()
|
||||
|
||||
// Click Done to save settings
|
||||
const doneButton = screen.getByText('Done')
|
||||
fireEvent.click(doneButton)
|
||||
// Click Done to save settings
|
||||
const doneButton = screen.getByText("Done")
|
||||
fireEvent.click(doneButton)
|
||||
|
||||
// Verify message sent to VSCode
|
||||
expect(vscode.postMessage).toHaveBeenCalledWith({
|
||||
type: 'soundVolume',
|
||||
value: 0.75
|
||||
})
|
||||
})
|
||||
expect(vscode.postMessage).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: "soundEnabled",
|
||||
bool: true,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it("shows volume slider when sound is enabled", () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Enable sound
|
||||
const soundCheckbox = screen.getByRole("checkbox", {
|
||||
name: /Enable sound effects/i,
|
||||
})
|
||||
fireEvent.click(soundCheckbox)
|
||||
|
||||
// Volume slider should be visible
|
||||
const volumeSlider = screen.getByRole("slider", { name: /volume/i })
|
||||
expect(volumeSlider).toBeInTheDocument()
|
||||
expect(volumeSlider).toHaveValue("0.5")
|
||||
})
|
||||
|
||||
it("updates volume and sends message to VSCode when slider changes", () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Enable sound
|
||||
const soundCheckbox = screen.getByRole("checkbox", {
|
||||
name: /Enable sound effects/i,
|
||||
})
|
||||
fireEvent.click(soundCheckbox)
|
||||
|
||||
// Change volume
|
||||
const volumeSlider = screen.getByRole("slider", { name: /volume/i })
|
||||
fireEvent.change(volumeSlider, { target: { value: "0.75" } })
|
||||
|
||||
// Click Done to save settings
|
||||
const doneButton = screen.getByText("Done")
|
||||
fireEvent.click(doneButton)
|
||||
|
||||
// Verify message sent to VSCode
|
||||
expect(vscode.postMessage).toHaveBeenCalledWith({
|
||||
type: "soundVolume",
|
||||
value: 0.75,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('SettingsView - API Configuration', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
describe("SettingsView - API Configuration", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('renders ApiConfigManagement with correct props', () => {
|
||||
renderSettingsView()
|
||||
|
||||
expect(screen.getByTestId('api-config-management')).toBeInTheDocument()
|
||||
})
|
||||
it("renders ApiConfigManagement with correct props", () => {
|
||||
renderSettingsView()
|
||||
|
||||
expect(screen.getByTestId("api-config-management")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe('SettingsView - Allowed Commands', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
describe("SettingsView - Allowed Commands", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('shows allowed commands section when alwaysAllowExecute is enabled', () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole('checkbox', {
|
||||
name: /Always approve allowed execute operations/i
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
it("shows allowed commands section when alwaysAllowExecute is enabled", () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Verify allowed commands section appears
|
||||
expect(screen.getByText(/Allowed Auto-Execute Commands/i)).toBeInTheDocument()
|
||||
expect(screen.getByPlaceholderText(/Enter command prefix/i)).toBeInTheDocument()
|
||||
})
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole("checkbox", {
|
||||
name: /Always approve allowed execute operations/i,
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
|
||||
it('adds new command to the list', () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole('checkbox', {
|
||||
name: /Always approve allowed execute operations/i
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
// Verify allowed commands section appears
|
||||
expect(screen.getByText(/Allowed Auto-Execute Commands/i)).toBeInTheDocument()
|
||||
expect(screen.getByPlaceholderText(/Enter command prefix/i)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
// Add a new command
|
||||
const input = screen.getByPlaceholderText(/Enter command prefix/i)
|
||||
fireEvent.change(input, { target: { value: 'npm test' } })
|
||||
|
||||
const addButton = screen.getByText('Add')
|
||||
fireEvent.click(addButton)
|
||||
it("adds new command to the list", () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Verify command was added
|
||||
expect(screen.getByText('npm test')).toBeInTheDocument()
|
||||
|
||||
// Verify VSCode message was sent
|
||||
expect(vscode.postMessage).toHaveBeenCalledWith({
|
||||
type: 'allowedCommands',
|
||||
commands: ['npm test']
|
||||
})
|
||||
})
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole("checkbox", {
|
||||
name: /Always approve allowed execute operations/i,
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
|
||||
it('removes command from the list', () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole('checkbox', {
|
||||
name: /Always approve allowed execute operations/i
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
// Add a new command
|
||||
const input = screen.getByPlaceholderText(/Enter command prefix/i)
|
||||
fireEvent.change(input, { target: { value: "npm test" } })
|
||||
|
||||
// Add a command
|
||||
const input = screen.getByPlaceholderText(/Enter command prefix/i)
|
||||
fireEvent.change(input, { target: { value: 'npm test' } })
|
||||
const addButton = screen.getByText('Add')
|
||||
fireEvent.click(addButton)
|
||||
const addButton = screen.getByText("Add")
|
||||
fireEvent.click(addButton)
|
||||
|
||||
// Remove the command
|
||||
const removeButton = screen.getByRole('button', { name: 'Remove command' })
|
||||
fireEvent.click(removeButton)
|
||||
// Verify command was added
|
||||
expect(screen.getByText("npm test")).toBeInTheDocument()
|
||||
|
||||
// Verify command was removed
|
||||
expect(screen.queryByText('npm test')).not.toBeInTheDocument()
|
||||
|
||||
// Verify VSCode message was sent
|
||||
expect(vscode.postMessage).toHaveBeenLastCalledWith({
|
||||
type: 'allowedCommands',
|
||||
commands: []
|
||||
})
|
||||
})
|
||||
// Verify VSCode message was sent
|
||||
expect(vscode.postMessage).toHaveBeenCalledWith({
|
||||
type: "allowedCommands",
|
||||
commands: ["npm test"],
|
||||
})
|
||||
})
|
||||
|
||||
it('prevents duplicate commands', () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole('checkbox', {
|
||||
name: /Always approve allowed execute operations/i
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
it("removes command from the list", () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Add a command twice
|
||||
const input = screen.getByPlaceholderText(/Enter command prefix/i)
|
||||
const addButton = screen.getByText('Add')
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole("checkbox", {
|
||||
name: /Always approve allowed execute operations/i,
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
|
||||
// First addition
|
||||
fireEvent.change(input, { target: { value: 'npm test' } })
|
||||
fireEvent.click(addButton)
|
||||
// Add a command
|
||||
const input = screen.getByPlaceholderText(/Enter command prefix/i)
|
||||
fireEvent.change(input, { target: { value: "npm test" } })
|
||||
const addButton = screen.getByText("Add")
|
||||
fireEvent.click(addButton)
|
||||
|
||||
// Second addition attempt
|
||||
fireEvent.change(input, { target: { value: 'npm test' } })
|
||||
fireEvent.click(addButton)
|
||||
// Remove the command
|
||||
const removeButton = screen.getByRole("button", { name: "Remove command" })
|
||||
fireEvent.click(removeButton)
|
||||
|
||||
// Verify command appears only once
|
||||
const commands = screen.getAllByText('npm test')
|
||||
expect(commands).toHaveLength(1)
|
||||
})
|
||||
// Verify command was removed
|
||||
expect(screen.queryByText("npm test")).not.toBeInTheDocument()
|
||||
|
||||
it('saves allowed commands when clicking Done', () => {
|
||||
const { onDone } = renderSettingsView()
|
||||
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole('checkbox', {
|
||||
name: /Always approve allowed execute operations/i
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
// Verify VSCode message was sent
|
||||
expect(vscode.postMessage).toHaveBeenLastCalledWith({
|
||||
type: "allowedCommands",
|
||||
commands: [],
|
||||
})
|
||||
})
|
||||
|
||||
// Add a command
|
||||
const input = screen.getByPlaceholderText(/Enter command prefix/i)
|
||||
fireEvent.change(input, { target: { value: 'npm test' } })
|
||||
const addButton = screen.getByText('Add')
|
||||
fireEvent.click(addButton)
|
||||
it("prevents duplicate commands", () => {
|
||||
renderSettingsView()
|
||||
|
||||
// Click Done
|
||||
const doneButton = screen.getByText('Done')
|
||||
fireEvent.click(doneButton)
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole("checkbox", {
|
||||
name: /Always approve allowed execute operations/i,
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
|
||||
// Verify VSCode messages were sent
|
||||
expect(vscode.postMessage).toHaveBeenCalledWith(expect.objectContaining({
|
||||
type: 'allowedCommands',
|
||||
commands: ['npm test']
|
||||
}))
|
||||
expect(onDone).toHaveBeenCalled()
|
||||
})
|
||||
// Add a command twice
|
||||
const input = screen.getByPlaceholderText(/Enter command prefix/i)
|
||||
const addButton = screen.getByText("Add")
|
||||
|
||||
// First addition
|
||||
fireEvent.change(input, { target: { value: "npm test" } })
|
||||
fireEvent.click(addButton)
|
||||
|
||||
// Second addition attempt
|
||||
fireEvent.change(input, { target: { value: "npm test" } })
|
||||
fireEvent.click(addButton)
|
||||
|
||||
// Verify command appears only once
|
||||
const commands = screen.getAllByText("npm test")
|
||||
expect(commands).toHaveLength(1)
|
||||
})
|
||||
|
||||
it("saves allowed commands when clicking Done", () => {
|
||||
const { onDone } = renderSettingsView()
|
||||
|
||||
// Enable always allow execute
|
||||
const executeCheckbox = screen.getByRole("checkbox", {
|
||||
name: /Always approve allowed execute operations/i,
|
||||
})
|
||||
fireEvent.click(executeCheckbox)
|
||||
|
||||
// Add a command
|
||||
const input = screen.getByPlaceholderText(/Enter command prefix/i)
|
||||
fireEvent.change(input, { target: { value: "npm test" } })
|
||||
const addButton = screen.getByText("Add")
|
||||
fireEvent.click(addButton)
|
||||
|
||||
// Click Done
|
||||
const doneButton = screen.getByText("Done")
|
||||
fireEvent.click(doneButton)
|
||||
|
||||
// Verify VSCode messages were sent
|
||||
expect(vscode.postMessage).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: "allowedCommands",
|
||||
commands: ["npm test"],
|
||||
}),
|
||||
)
|
||||
expect(onDone).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user