fix: local updates for PR #4873

Co-authored-by: Hisleren <Hisleren@users.noreply.github.com>
This commit is contained in:
Gustavo Madeira Santana
2026-01-30 16:11:10 -05:00
committed by Gustavo Madeira Santana
parent 201d7fa956
commit e5a95b5b66
6 changed files with 173 additions and 8 deletions

View File

@@ -0,0 +1,74 @@
import { describe, expect, it, vi } from "vitest";
import type { RuntimeEnv } from "../runtime.js";
const mocks = vi.hoisted(() => ({
text: vi.fn(),
select: vi.fn(),
confirm: vi.fn(),
resolveGatewayPort: vi.fn(),
buildGatewayAuthConfig: vi.fn(),
note: vi.fn(),
randomToken: vi.fn(),
}));
vi.mock("../config/config.js", async (importActual) => {
const actual = await importActual<typeof import("../config/config.js")>();
return {
...actual,
resolveGatewayPort: mocks.resolveGatewayPort,
};
});
vi.mock("./configure.shared.js", () => ({
text: mocks.text,
select: mocks.select,
confirm: mocks.confirm,
}));
vi.mock("../terminal/note.js", () => ({
note: mocks.note,
}));
vi.mock("./configure.gateway-auth.js", () => ({
buildGatewayAuthConfig: mocks.buildGatewayAuthConfig,
}));
vi.mock("../infra/tailscale.js", () => ({
findTailscaleBinary: vi.fn(async () => undefined),
}));
vi.mock("./onboard-helpers.js", async (importActual) => {
const actual = await importActual<typeof import("./onboard-helpers.js")>();
return {
...actual,
randomToken: mocks.randomToken,
};
});
import { promptGatewayConfig } from "./configure.gateway.js";
describe("promptGatewayConfig", () => {
it("generates a token when the prompt returns undefined", async () => {
mocks.resolveGatewayPort.mockReturnValue(18789);
const selectQueue = ["loopback", "token", "off"];
mocks.select.mockImplementation(async () => selectQueue.shift());
const textQueue = ["18789", undefined];
mocks.text.mockImplementation(async () => textQueue.shift());
mocks.randomToken.mockReturnValue("generated-token");
mocks.buildGatewayAuthConfig.mockImplementation(({ mode, token, password }) => ({
mode,
token,
password,
}));
const runtime: RuntimeEnv = {
log: vi.fn(),
error: vi.fn(),
exit: vi.fn(),
};
const result = await promptGatewayConfig({}, runtime);
expect(result.token).toBe("generated-token");
});
});

View File

@@ -5,7 +5,7 @@ import type { RuntimeEnv } from "../runtime.js";
import { note } from "../terminal/note.js";
import { buildGatewayAuthConfig } from "./configure.gateway-auth.js";
import { confirm, select, text } from "./configure.shared.js";
import { guardCancel, randomToken } from "./onboard-helpers.js";
import { guardCancel, normalizeGatewayTokenInput, randomToken } from "./onboard-helpers.js";
type GatewayAuthChoice = "token" | "password";
@@ -177,8 +177,7 @@ export async function promptGatewayConfig(
}),
runtime,
);
const rawInput = tokenInput ? String(tokenInput).trim() : "";
gatewayToken = rawInput || randomToken();
gatewayToken = normalizeGatewayTokenInput(tokenInput) || randomToken();
}
if (authMode === "password") {

View File

@@ -1,6 +1,11 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { openUrl, resolveBrowserOpenCommand, resolveControlUiLinks } from "./onboard-helpers.js";
import {
normalizeGatewayTokenInput,
openUrl,
resolveBrowserOpenCommand,
resolveControlUiLinks,
} from "./onboard-helpers.js";
const mocks = vi.hoisted(() => ({
runCommandWithTimeout: vi.fn(async () => ({
@@ -103,3 +108,18 @@ describe("resolveControlUiLinks", () => {
expect(links.wsUrl).toBe("ws://127.0.0.1:18789");
});
});
describe("normalizeGatewayTokenInput", () => {
it("returns empty string for undefined or null", () => {
expect(normalizeGatewayTokenInput(undefined)).toBe("");
expect(normalizeGatewayTokenInput(null)).toBe("");
});
it("trims string input", () => {
expect(normalizeGatewayTokenInput(" token ")).toBe("token");
});
it("coerces non-string input to string", () => {
expect(normalizeGatewayTokenInput(123)).toBe("123");
});
});

View File

@@ -62,6 +62,11 @@ export function randomToken(): string {
return crypto.randomBytes(24).toString("hex");
}
export function normalizeGatewayTokenInput(value: unknown): string {
if (value == null) return "";
return String(value).trim();
}
export function printWizardHeader(runtime: RuntimeEnv) {
const header = [
"▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄",