mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 06:37:28 +00:00
perf(test): fold ports + terminal note suites
This commit is contained in:
@@ -1,28 +0,0 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
|
||||||
import { normalizeTextForComparison } from "./pi-embedded-helpers.js";
|
|
||||||
import { DEFAULT_AGENTS_FILENAME } from "./workspace.js";
|
|
||||||
|
|
||||||
const _makeFile = (overrides: Partial<WorkspaceBootstrapFile>): WorkspaceBootstrapFile => ({
|
|
||||||
name: DEFAULT_AGENTS_FILENAME,
|
|
||||||
path: "/tmp/AGENTS.md",
|
|
||||||
content: "",
|
|
||||||
missing: false,
|
|
||||||
...overrides,
|
|
||||||
});
|
|
||||||
describe("normalizeTextForComparison", () => {
|
|
||||||
it("lowercases text", () => {
|
|
||||||
expect(normalizeTextForComparison("Hello World")).toBe("hello world");
|
|
||||||
});
|
|
||||||
it("trims whitespace", () => {
|
|
||||||
expect(normalizeTextForComparison(" hello ")).toBe("hello");
|
|
||||||
});
|
|
||||||
it("collapses multiple spaces", () => {
|
|
||||||
expect(normalizeTextForComparison("hello world")).toBe("hello world");
|
|
||||||
});
|
|
||||||
it("strips emoji", () => {
|
|
||||||
expect(normalizeTextForComparison("Hello 👋 World 🌍")).toBe("hello world");
|
|
||||||
});
|
|
||||||
it("handles mixed normalization", () => {
|
|
||||||
expect(normalizeTextForComparison(" Hello 👋 WORLD 🌍 ")).toBe("hello world");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import net from "node:net";
|
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
||||||
|
|
||||||
const runCommandWithTimeoutMock = vi.fn();
|
|
||||||
|
|
||||||
vi.mock("../process/exec.js", () => ({
|
|
||||||
runCommandWithTimeout: (...args: unknown[]) => runCommandWithTimeoutMock(...args),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const describeUnix = process.platform === "win32" ? describe.skip : describe;
|
|
||||||
|
|
||||||
describeUnix("inspectPortUsage", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
runCommandWithTimeoutMock.mockReset();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("reports busy when lsof is missing but loopback listener exists", async () => {
|
|
||||||
const server = net.createServer();
|
|
||||||
await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
||||||
const port = (server.address() as net.AddressInfo).port;
|
|
||||||
|
|
||||||
runCommandWithTimeoutMock.mockRejectedValueOnce(
|
|
||||||
Object.assign(new Error("spawn lsof ENOENT"), { code: "ENOENT" }),
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { inspectPortUsage } = await import("./ports-inspect.js");
|
|
||||||
const result = await inspectPortUsage(port);
|
|
||||||
expect(result.status).toBe("busy");
|
|
||||||
expect(result.errors?.some((err) => err.includes("ENOENT"))).toBe(true);
|
|
||||||
} finally {
|
|
||||||
server.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
import net from "node:net";
|
import net from "node:net";
|
||||||
import { describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
const runCommandWithTimeoutMock = vi.hoisted(() => vi.fn());
|
||||||
|
|
||||||
|
vi.mock("../process/exec.js", () => ({
|
||||||
|
runCommandWithTimeout: (...args: unknown[]) => runCommandWithTimeoutMock(...args),
|
||||||
|
}));
|
||||||
|
import { inspectPortUsage } from "./ports-inspect.js";
|
||||||
import {
|
import {
|
||||||
buildPortHints,
|
buildPortHints,
|
||||||
classifyPortListener,
|
classifyPortListener,
|
||||||
@@ -9,6 +16,8 @@ import {
|
|||||||
PortInUseError,
|
PortInUseError,
|
||||||
} from "./ports.js";
|
} from "./ports.js";
|
||||||
|
|
||||||
|
const describeUnix = process.platform === "win32" ? describe.skip : describe;
|
||||||
|
|
||||||
describe("ports helpers", () => {
|
describe("ports helpers", () => {
|
||||||
it("ensurePortAvailable rejects when port busy", async () => {
|
it("ensurePortAvailable rejects when port busy", async () => {
|
||||||
const server = net.createServer();
|
const server = net.createServer();
|
||||||
@@ -58,3 +67,27 @@ describe("ports helpers", () => {
|
|||||||
expect(lines.some((line) => line.includes("SSH tunnel"))).toBe(true);
|
expect(lines.some((line) => line.includes("SSH tunnel"))).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describeUnix("inspectPortUsage", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
runCommandWithTimeoutMock.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports busy when lsof is missing but loopback listener exists", async () => {
|
||||||
|
const server = net.createServer();
|
||||||
|
await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||||
|
const port = (server.address() as net.AddressInfo).port;
|
||||||
|
|
||||||
|
runCommandWithTimeoutMock.mockRejectedValueOnce(
|
||||||
|
Object.assign(new Error("spawn lsof ENOENT"), { code: "ENOENT" }),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await inspectPortUsage(port);
|
||||||
|
expect(result.status).toBe("busy");
|
||||||
|
expect(result.errors?.some((err) => err.includes("ENOENT"))).toBe(true);
|
||||||
|
} finally {
|
||||||
|
server.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
|
||||||
import { wrapNoteMessage } from "./note.js";
|
|
||||||
|
|
||||||
describe("wrapNoteMessage", () => {
|
|
||||||
it("preserves long filesystem paths without inserting spaces/newlines", () => {
|
|
||||||
const input =
|
|
||||||
"/Users/user/Documents/Github/impact-signals-pipeline/with/really/long/segments/file.txt";
|
|
||||||
const wrapped = wrapNoteMessage(input, { maxWidth: 22, columns: 80 });
|
|
||||||
|
|
||||||
expect(wrapped).toBe(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("preserves long urls without inserting spaces/newlines", () => {
|
|
||||||
const input =
|
|
||||||
"https://example.com/this/is/a/very/long/url/segment/that/should/not/be/split/for-copy";
|
|
||||||
const wrapped = wrapNoteMessage(input, { maxWidth: 24, columns: 80 });
|
|
||||||
|
|
||||||
expect(wrapped).toBe(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("preserves long file-like underscore tokens for copy safety", () => {
|
|
||||||
const input = "administrators_authorized_keys_with_extra_suffix";
|
|
||||||
const wrapped = wrapNoteMessage(input, { maxWidth: 14, columns: 80 });
|
|
||||||
|
|
||||||
expect(wrapped).toBe(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("still chunks generic long opaque tokens to avoid pathological line width", () => {
|
|
||||||
const input = "x".repeat(70);
|
|
||||||
const wrapped = wrapNoteMessage(input, { maxWidth: 20, columns: 80 });
|
|
||||||
|
|
||||||
expect(wrapped).toContain("\n");
|
|
||||||
expect(wrapped.replace(/\n/g, "")).toBe(input);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { visibleWidth } from "./ansi.js";
|
import { visibleWidth } from "./ansi.js";
|
||||||
|
import { wrapNoteMessage } from "./note.js";
|
||||||
import { renderTable } from "./table.js";
|
import { renderTable } from "./table.js";
|
||||||
|
|
||||||
describe("renderTable", () => {
|
describe("renderTable", () => {
|
||||||
@@ -130,3 +131,36 @@ describe("renderTable", () => {
|
|||||||
expect(line2Index).toBe(line1Index + 1);
|
expect(line2Index).toBe(line1Index + 1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("wrapNoteMessage", () => {
|
||||||
|
it("preserves long filesystem paths without inserting spaces/newlines", () => {
|
||||||
|
const input =
|
||||||
|
"/Users/user/Documents/Github/impact-signals-pipeline/with/really/long/segments/file.txt";
|
||||||
|
const wrapped = wrapNoteMessage(input, { maxWidth: 22, columns: 80 });
|
||||||
|
|
||||||
|
expect(wrapped).toBe(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves long urls without inserting spaces/newlines", () => {
|
||||||
|
const input =
|
||||||
|
"https://example.com/this/is/a/very/long/url/segment/that/should/not/be/split/for-copy";
|
||||||
|
const wrapped = wrapNoteMessage(input, { maxWidth: 24, columns: 80 });
|
||||||
|
|
||||||
|
expect(wrapped).toBe(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves long file-like underscore tokens for copy safety", () => {
|
||||||
|
const input = "administrators_authorized_keys_with_extra_suffix";
|
||||||
|
const wrapped = wrapNoteMessage(input, { maxWidth: 14, columns: 80 });
|
||||||
|
|
||||||
|
expect(wrapped).toBe(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("still chunks generic long opaque tokens to avoid pathological line width", () => {
|
||||||
|
const input = "x".repeat(70);
|
||||||
|
const wrapped = wrapNoteMessage(input, { maxWidth: 20, columns: 80 });
|
||||||
|
|
||||||
|
expect(wrapped).toContain("\n");
|
||||||
|
expect(wrapped.replace(/\n/g, "")).toBe(input);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user