

















@@ -1,7 +1,8 @@
1-import { beforeEach, describe, expect, it, vi } from "vitest";
1+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
22import { formatCliBannerLine } from "./banner.js";
3344const readCliBannerTaglineModeMock = vi.hoisted(() => vi.fn());
5+const stdoutIsTtyDescriptor = Object.getOwnPropertyDescriptor(process.stdout, "isTTY");
5667vi.mock("./banner-config-lite.js", () => ({
78parseTaglineMode: (value: unknown) =>
@@ -14,6 +15,27 @@ beforeEach(() => {
1415readCliBannerTaglineModeMock.mockReturnValue(undefined);
1516});
161718+afterEach(() => {
19+vi.restoreAllMocks();
20+if (stdoutIsTtyDescriptor) {
21+Object.defineProperty(process.stdout, "isTTY", stdoutIsTtyDescriptor);
22+} else {
23+delete (process.stdout as { isTTY?: boolean }).isTTY;
24+}
25+});
26+27+async function importFreshBannerModule() {
28+vi.resetModules();
29+return await import("./banner.js");
30+}
31+32+function setStdoutIsTty(value: boolean) {
33+Object.defineProperty(process.stdout, "isTTY", {
34+configurable: true,
35+ value,
36+});
37+}
38+1739describe("formatCliBannerLine", () => {
1840it("hides tagline text when cli.banner.taglineMode is off", () => {
1941readCliBannerTaglineModeMock.mockReturnValue("off");
@@ -72,3 +94,41 @@ describe("formatCliBannerLine", () => {
7294expect(line).toBe("OpenClaw 2026.3.7 (abc1234)");
7395});
7496});
97+98+describe("emitCliBanner", () => {
99+it("uses injected non-TTY state before writing to stdout", async () => {
100+const { emitCliBanner, hasEmittedCliBanner } = await importFreshBannerModule();
101+setStdoutIsTty(true);
102+const writeSpy = vi.spyOn(process.stdout, "write").mockImplementation(() => true);
103+104+emitCliBanner("2026.3.7", {
105+argv: ["node", "openclaw"],
106+commit: "abc1234",
107+isTty: false,
108+mode: "off",
109+richTty: false,
110+});
111+112+expect(writeSpy).not.toHaveBeenCalled();
113+expect(hasEmittedCliBanner()).toBe(false);
114+});
115+116+it("allows injected TTY state to emit when stdout lacks isTTY", async () => {
117+const { emitCliBanner, hasEmittedCliBanner } = await importFreshBannerModule();
118+setStdoutIsTty(false);
119+const writeSpy = vi.spyOn(process.stdout, "write").mockImplementation(() => true);
120+121+emitCliBanner("2026.3.7", {
122+argv: ["node", "openclaw"],
123+commit: "abc1234",
124+env: { LANG: "en_US.UTF-8" },
125+isTty: true,
126+mode: "off",
127+platform: "darwin",
128+richTty: false,
129+});
130+131+expect(writeSpy).toHaveBeenCalledWith("\n🦞 OpenClaw 2026.3.7 (abc1234)\n\n");
132+expect(hasEmittedCliBanner()).toBe(true);
133+});
134+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。