diff --git a/src/lib/onboard/prompt-helpers.test.ts b/src/lib/onboard/prompt-helpers.test.ts new file mode 100644 index 0000000000..33c6ea43bb --- /dev/null +++ b/src/lib/onboard/prompt-helpers.test.ts @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { describe, expect, it, vi } from "vitest"; +// Import from compiled dist/ so coverage is attributed correctly. +import { promptOrDefault } from "../../../dist/lib/onboard/prompt-helpers"; + +function makeDeps(promptReply: string) { + return { + isNonInteractive: () => false, + note: vi.fn(), + prompt: vi.fn().mockResolvedValue(promptReply), + }; +} + +describe("promptOrDefault interactive default fallback (#4387)", () => { + it("returns defaultValue when the user just presses Enter (empty reply)", async () => { + const deps = makeDeps(""); + expect(await promptOrDefault(deps, " Choose [6]: ", null, "6")).toBe("6"); + }); + + it("treats a whitespace-only reply as the default", async () => { + const deps = makeDeps(" "); + expect(await promptOrDefault(deps, " Choose [6]: ", null, "6")).toBe("6"); + }); + + it("returns the user's reply verbatim when non-empty", async () => { + const deps = makeDeps("3"); + expect(await promptOrDefault(deps, " Choose [6]: ", null, "6")).toBe("3"); + }); +}); diff --git a/src/lib/onboard/prompt-helpers.ts b/src/lib/onboard/prompt-helpers.ts index c99e92f828..4c335f2581 100644 --- a/src/lib/onboard/prompt-helpers.ts +++ b/src/lib/onboard/prompt-helpers.ts @@ -49,7 +49,12 @@ export async function promptOrDefault( deps.note(` [non-interactive] ${question.trim()} → ${result}`); return result; } - return deps.prompt(question); + // The prompt label advertises the default in brackets (e.g. `Choose [6]:`), + // so an empty/whitespace reply must resolve to that default. Without this, + // every interactive caller had to re-implement the empty-reply fallback, + // and any that forgot hard-rejected the displayed default (#4387). + const reply = await deps.prompt(question); + return reply.trim() === "" ? defaultValue : reply; } // Yes/no prompt with a typed default. The `[Y/n]` / `[y/N]` indicator and