дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 11:15:40 +02:00
fix(vcs): keep the current branch name in New Branch even though it exists (#1305)
CI / Rust (ubuntu-22.04) (push) Failing after 1h0m11s
CI / Remote server (linux musl) (push) Failing after 33m23s
CI / Plugins (SDK, official, fixtures) (push) Successful in 3m22s
CI / Cargo deny (push) Successful in 43s
CI / Frontend (push) Successful in 28m17s
CI / E2E (push) Failing after 23m35s
CI / Rust (macos-latest) (push) Canceled after 0s
CI / Rust (windows-latest) (push) Canceled after 0s
CI / Rust (ubuntu-22.04) (push) Failing after 1h0m11s
CI / Remote server (linux musl) (push) Failing after 33m23s
CI / Plugins (SDK, official, fixtures) (push) Successful in 3m22s
CI / Cargo deny (push) Successful in 43s
CI / Frontend (push) Successful in 28m17s
CI / E2E (push) Failing after 23m35s
CI / Rust (macos-latest) (push) Canceled after 0s
CI / Rust (windows-latest) (push) Canceled after 0s
New Branch dropped its suggestion when validateBranchName rejected it, and the current branch always exists, so a plain New Branch from HEAD always opened empty; the test never seeded the local branches. The suggestion is kept, the dialog shows that the branch exists from the start and Create stays disabled until the name changes; other prefilled prompts (Rename Branch) keep showing errors only after editing.
Цей коміт міститься в:
1 джерело
b31edc3482
коміт
092a700ddc
3 files changed
+26
-4
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { beforeEach, expect, it, vi } from "vitest";
|
||||
import type { BranchInfo } from "@/bindings";
|
||||
import type { Branch, BranchInfo } from "@/bindings";
|
||||
const mocks = vi.hoisted(() => ({ prompt: vi.fn() }));
|
||||
vi.mock("../dialogs", async (original) => ({
|
||||
...(await original<typeof import("../dialogs")>()),
|
||||
@@ -17,9 +17,25 @@ const branch = (head: string | null): BranchInfo => ({
|
||||
operation: null,
|
||||
});
|
||||
|
||||
const local = (name: string, current = false): Branch => ({
|
||||
name,
|
||||
remote: false,
|
||||
current,
|
||||
upstream: null,
|
||||
ahead: 0,
|
||||
behind: 0,
|
||||
lastCommitMs: null,
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
useVcs.setState({ root: "/p", repo: "/p/front", branch: branch("feature/ui") });
|
||||
// The current branch is always among the local branches, so the suggestion names an existing one.
|
||||
useVcs.setState({
|
||||
root: "/p",
|
||||
repo: "/p/front",
|
||||
branch: branch("feature/ui"),
|
||||
branches: [local("feature/ui", true), local("main")],
|
||||
});
|
||||
// Cancel: only what the dialog was offered matters here, not its outcome.
|
||||
mocks.prompt.mockResolvedValue(null);
|
||||
});
|
||||
@@ -27,6 +43,7 @@ beforeEach(() => {
|
||||
it("prefills a plain New Branch with the current branch name", async () => {
|
||||
await newBranch();
|
||||
expect(mocks.prompt.mock.calls[0]?.[0].initial).toBe("feature/ui");
|
||||
expect(mocks.prompt.mock.calls[0]?.[0].validateInitial).toBe(true);
|
||||
});
|
||||
|
||||
it("prefills nothing when HEAD is detached", async () => {
|
||||
|
||||
@@ -156,10 +156,12 @@ export async function newBranch(from?: string) {
|
||||
const r = await promptText({
|
||||
title: from ? tx`Create New Branch from ${from}` : "Create New Branch",
|
||||
label: "New branch name:",
|
||||
initial: suggestion && !validateBranchName(suggestion) ? suggestion : "",
|
||||
// Kept even when that branch exists (the current one always does): the user edits it.
|
||||
initial: suggestion,
|
||||
mono: true,
|
||||
okLabel: "Create",
|
||||
validate: validateBranchName,
|
||||
validateInitial: true,
|
||||
checkbox: { label: "Checkout branch", initial: true },
|
||||
});
|
||||
if (!r) return;
|
||||
@@ -371,6 +373,7 @@ export async function newBranchInRepos(roots: readonly string[], from?: string)
|
||||
mono: true,
|
||||
okLabel: "Create",
|
||||
validate: validateBranchName,
|
||||
validateInitial: true,
|
||||
checkbox: { label: "Checkout branch", initial: true },
|
||||
});
|
||||
if (!r) return;
|
||||
|
||||
@@ -43,6 +43,8 @@ export interface PromptOptions {
|
||||
mono?: boolean;
|
||||
/** Returns an error message, or null when valid. */
|
||||
validate?: (value: string) => string | null;
|
||||
/** Show the prefilled value's problem (e.g. the branch exists) before it is edited. */
|
||||
validateInitial?: boolean;
|
||||
/** Optional checkbox below the field. */
|
||||
checkbox?: { label: string; initial: boolean };
|
||||
}
|
||||
@@ -70,7 +72,7 @@ function PromptDialog(props: PromptOptions & { onDone: (r: PromptResult | null)
|
||||
const { title, label, initial = "", placeholder, okLabel = "OK", mono, validate, checkbox, onDone } = props;
|
||||
const [value, setValue] = useState(initial);
|
||||
const [checked, setChecked] = useState(checkbox?.initial ?? false);
|
||||
const [touched, setTouched] = useState(false);
|
||||
const [touched, setTouched] = useState(!!props.validateInitial && initial !== "");
|
||||
const error = validate ? validate(value) : value.trim() ? null : "Value must not be empty";
|
||||
const submit = () => {
|
||||
setTouched(true);
|
||||
|
||||
Reference in new issue
Заблокувати користувача