feat(KB-027): add autoResolveConflicts toggle in Merge settings
- Add autoResolveConflicts toggle to SettingsModal Merge section - Add unit tests for toggle functionality in SettingsModal - Clean up unrelated changeset files and unused components
This commit is contained in:
@@ -458,6 +458,20 @@ export function SettingsModal({ onClose, addToast, initialSection }: SettingsMod
|
|||||||
</label>
|
</label>
|
||||||
<small>When disabled, merge commit messages omit the task ID from the scope (e.g. <code>feat: ...</code> instead of <code>feat(KB-001): ...</code>)</small>
|
<small>When disabled, merge commit messages omit the task ID from the scope (e.g. <code>feat: ...</code> instead of <code>feat(KB-001): ...</code>)</small>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="autoResolveConflicts" className="checkbox-label">
|
||||||
|
<input
|
||||||
|
id="autoResolveConflicts"
|
||||||
|
type="checkbox"
|
||||||
|
checked={form.autoResolveConflicts !== false}
|
||||||
|
onChange={(e) =>
|
||||||
|
setForm((f) => ({ ...f, autoResolveConflicts: e.target.checked }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
Auto-resolve conflicts in lock files and generated files
|
||||||
|
</label>
|
||||||
|
<small>When enabled, lock files (package-lock.json, pnpm-lock.yaml, etc.), generated files (dist/*, *.gen.ts), and trivial whitespace conflicts are resolved automatically without AI intervention. Complex code conflicts still require AI review.</small>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
case "authentication":
|
case "authentication":
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const defaultSettings: Settings = {
|
|||||||
worktreeInitCommand: "",
|
worktreeInitCommand: "",
|
||||||
testCommand: "",
|
testCommand: "",
|
||||||
buildCommand: "",
|
buildCommand: "",
|
||||||
|
autoResolveConflicts: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
vi.mock("../../api", () => ({
|
vi.mock("../../api", () => ({
|
||||||
@@ -103,6 +104,7 @@ describe("SettingsModal", () => {
|
|||||||
fireEvent.click(screen.getByText("Merge"));
|
fireEvent.click(screen.getByText("Merge"));
|
||||||
expect(screen.getByText("Auto-merge completed tasks")).toBeTruthy();
|
expect(screen.getByText("Auto-merge completed tasks")).toBeTruthy();
|
||||||
expect(screen.getByText("Include task ID in commit scope")).toBeTruthy();
|
expect(screen.getByText("Include task ID in commit scope")).toBeTruthy();
|
||||||
|
expect(screen.getByText("Auto-resolve conflicts in lock files and generated files")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows Recycle worktrees checkbox in Worktrees section", async () => {
|
it("shows Recycle worktrees checkbox in Worktrees section", async () => {
|
||||||
@@ -191,6 +193,16 @@ describe("SettingsModal", () => {
|
|||||||
expect(checkbox.getAttribute("type")).toBe("checkbox");
|
expect(checkbox.getAttribute("type")).toBe("checkbox");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("shows Auto-resolve conflicts checkbox in Merge section", async () => {
|
||||||
|
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||||
|
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByText("Merge"));
|
||||||
|
const checkbox = screen.getByLabelText("Auto-resolve conflicts in lock files and generated files");
|
||||||
|
expect(checkbox).toBeTruthy();
|
||||||
|
expect(checkbox.getAttribute("type")).toBe("checkbox");
|
||||||
|
});
|
||||||
|
|
||||||
it("toggling includeTaskIdInCommit checkbox sends false in save payload", async () => {
|
it("toggling includeTaskIdInCommit checkbox sends false in save payload", async () => {
|
||||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||||
@@ -207,6 +219,36 @@ describe("SettingsModal", () => {
|
|||||||
expect(payload.includeTaskIdInCommit).toBe(false);
|
expect(payload.includeTaskIdInCommit).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("toggling autoResolveConflicts checkbox sends false in save payload when unchecked", async () => {
|
||||||
|
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||||
|
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByText("Merge"));
|
||||||
|
const checkbox = screen.getByLabelText("Auto-resolve conflicts in lock files and generated files");
|
||||||
|
// Default is checked (true), click to uncheck
|
||||||
|
fireEvent.click(checkbox);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByText("Save"));
|
||||||
|
await waitFor(() => expect(updateSettings).toHaveBeenCalledTimes(1));
|
||||||
|
|
||||||
|
const payload = (updateSettings as ReturnType<typeof vi.fn>).mock.calls[0][0];
|
||||||
|
expect(payload.autoResolveConflicts).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("autoResolveConflicts defaults to enabled (true) when setting is true", async () => {
|
||||||
|
(fetchSettings as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||||
|
...defaultSettings,
|
||||||
|
autoResolveConflicts: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||||
|
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByText("Merge"));
|
||||||
|
const checkbox = screen.getByLabelText("Auto-resolve conflicts in lock files and generated files") as HTMLInputElement;
|
||||||
|
expect(checkbox.checked).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("groupOverlappingFiles input has type checkbox", async () => {
|
it("groupOverlappingFiles input has type checkbox", async () => {
|
||||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||||
|
|||||||
Reference in New Issue
Block a user