mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-28 08:33:38 +00:00
test(note): add rendered-output regression test for copy-sensitive token preservation
Add a focused test in table.test.ts that verifies clack's note() rendering does not re-break copy-sensitive tokens (session lock paths) after wrapNoteMessage preserves them. Uses resolveNoteOutputColumns to widen the virtual output stream, matching the fix in note.ts. Refs #94730
This commit is contained in:
@@ -186,6 +186,13 @@ export function resolveNoteColumns(columns: number | undefined): number {
|
||||
return columns;
|
||||
}
|
||||
|
||||
export function resolveNoteOutputColumns(message: string, columns: number): number {
|
||||
const widestLine = message
|
||||
.split("\n")
|
||||
.reduce((max, line) => Math.max(max, visibleWidth(line)), 0);
|
||||
return Math.max(columns, widestLine + 6);
|
||||
}
|
||||
|
||||
function createNoteOutput(columns: number): NodeJS.WriteStream {
|
||||
if (process.stdout.columns === columns) {
|
||||
return process.stdout;
|
||||
@@ -207,13 +214,9 @@ export function note(message: unknown, title?: string) {
|
||||
return;
|
||||
}
|
||||
const columns = resolveNoteColumns(process.stdout.columns);
|
||||
const wrapped = wrapNoteMessage(message, { columns });
|
||||
// Use a wide virtual stream so clack's internal wrap (which runs after our
|
||||
// format callback) does not re-break copy-sensitive tokens that
|
||||
// wrapNoteMessage intentionally kept intact.
|
||||
const wideOutput = createNoteOutput(Math.max(columns, visibleWidth(wrapped) + 12));
|
||||
clackNote(wrapped, stylePromptTitle(title), {
|
||||
output: wideOutput,
|
||||
const wrappedMessage = wrapNoteMessage(message, { columns });
|
||||
clackNote(wrappedMessage, stylePromptTitle(title), {
|
||||
output: createNoteOutput(resolveNoteOutputColumns(wrappedMessage, columns)),
|
||||
format: (line) => line,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { note as clackNote } from "@clack/prompts";
|
||||
// Terminal Core tests cover table behavior.
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { visibleWidth } from "./ansi.js";
|
||||
import { resolveNoteColumns, wrapNoteMessage } from "./note.js";
|
||||
import { resolveNoteColumns, resolveNoteOutputColumns, wrapNoteMessage } from "./note.js";
|
||||
import { renderTable } from "./table.js";
|
||||
|
||||
function mockProcessPlatform(platform: NodeJS.Platform): void {
|
||||
@@ -348,6 +349,33 @@ describe("wrapNoteMessage", () => {
|
||||
expect(resolveNoteColumns(120)).toBe(120);
|
||||
});
|
||||
|
||||
it("widens note output columns so clack does not re-wrap copy-sensitive lines", () => {
|
||||
const wrapped = wrapNoteMessage(
|
||||
[
|
||||
"- Found 1 session lock file.",
|
||||
"- ~/.openclaw/agents/main/sessions/9c2acae5-841f-4aea-936b-fdb513b60202.jsonl.lock pid=86519 (alive) age=2m47s stale=no",
|
||||
].join("\n"),
|
||||
{ columns: 80 },
|
||||
);
|
||||
const writes: string[] = [];
|
||||
const output = {
|
||||
columns: resolveNoteOutputColumns(wrapped, 80),
|
||||
write(chunk: string) {
|
||||
writes.push(chunk);
|
||||
return true;
|
||||
},
|
||||
} as unknown as NodeJS.WriteStream;
|
||||
|
||||
clackNote(wrapped, "Session locks", { output, format: (line) => line });
|
||||
|
||||
const rendered = writes.join("");
|
||||
expect(rendered).toContain(".jsonl.lock");
|
||||
expect(rendered).not.toContain(".js\n");
|
||||
expect(rendered).toContain(
|
||||
"- ~/.openclaw/agents/main/sessions/9c2acae5-841f-4aea-936b-fdb513b60202.jsonl.lock",
|
||||
);
|
||||
});
|
||||
|
||||
it("coerces nullish and non-string note messages before wrapping", () => {
|
||||
expect(wrapNoteMessage(undefined, { maxWidth: 20, columns: 80 })).toBe("");
|
||||
expect(wrapNoteMessage(null, { maxWidth: 20, columns: 80 })).toBe("");
|
||||
|
||||
Reference in New Issue
Block a user