Files
2026-03-21 18:57:10 +08:00

133 lines
3.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, it } from "vitest";
const {
consumeTerminalSyncUpdateFrames,
createTerminalSyncUpdateState,
extractLooseAnsiSgr,
takeTerminalReplaySlice
} = require("./vtParser.js");
describe("vtParser", () => {
it("不会把 CSI 控制序列从中间切开", () => {
const result = takeTerminalReplaySlice("ab\u001b[31mcd", 4);
expect(result).toEqual({
slice: "ab",
rest: "\u001b[31mcd"
});
});
it("不会把 CRLF 从中间拆开", () => {
expect(takeTerminalReplaySlice("ab\r\ncd", 3)).toEqual({
slice: "ab",
rest: "\r\ncd"
});
expect(takeTerminalReplaySlice("ab\r\ncd", 4)).toEqual({
slice: "ab\r\n",
rest: "cd"
});
});
it("文本开头是完整长控制序列时会整段前进,避免卡死在零进度", () => {
const result = takeTerminalReplaySlice("\u001b]10;?\u001b\\X", 3);
expect(result).toEqual({
slice: "\u001b]10;?\u001b\\",
rest: "X"
});
});
it("文本前缀是不完整控制序列时会返回空 slice交由上层缓存尾巴", () => {
const result = takeTerminalReplaySlice("\u001b[31", 16);
expect(result).toEqual({
slice: "",
rest: "\u001b[31"
});
});
it("会识别不带 ESC 的松散 SGR 复位片段", () => {
expect(extractLooseAnsiSgr("39mtext", 0)).toEqual({
end: 2,
codes: [39]
});
expect(extractLooseAnsiSgr("[1;31mtext", 0)).toEqual({
end: 5,
codes: [1, 31]
});
});
it("非可信 SGR 数字串不会被误识别成样式序列", () => {
expect(extractLooseAnsiSgr("123mtext", 0)).toBeNull();
});
it("会把 `CSI ? 2026 h/l` 包裹的同步刷新窗口延后到结束时一次性吐出", () => {
const first = consumeTerminalSyncUpdateFrames(
"ab\u001b[?2026hcd",
createTerminalSyncUpdateState()
);
expect(first.text).toBe("ab");
expect(first.state).toEqual({
depth: 1,
carryText: "",
bufferedText: "cd"
});
const second = consumeTerminalSyncUpdateFrames("ef\u001b[?2026lg", first.state);
expect(second.text).toBe("cdefg");
expect(second.state).toEqual({
depth: 0,
carryText: "",
bufferedText: ""
});
});
it("同步刷新起始序列若被 chunk 边界截断,会保留到下一帧继续拼", () => {
const first = consumeTerminalSyncUpdateFrames(
"ab\u001b[?2026",
createTerminalSyncUpdateState()
);
expect(first.text).toBe("ab");
expect(first.state).toEqual({
depth: 0,
carryText: "\u001b[?2026",
bufferedText: ""
});
const second = consumeTerminalSyncUpdateFrames("hcd\u001b[?2026l", first.state);
expect(second.text).toBe("cd");
expect(second.state).toEqual({
depth: 0,
carryText: "",
bufferedText: ""
});
});
it("会按和 web 端一致的口径收口 `DCS = 1 s / = 2 s` 同步刷新窗口", () => {
const first = consumeTerminalSyncUpdateFrames(
"ab\u001bP=1s\u001b\\cd",
createTerminalSyncUpdateState()
);
expect(first.text).toBe("ab");
expect(first.state).toEqual({
depth: 1,
carryText: "",
bufferedText: "cd"
});
const second = consumeTerminalSyncUpdateFrames("ef\u001bP=2s\u001b\\g", first.state);
expect(second.text).toBe("cdefg");
expect(second.state).toEqual({
depth: 0,
carryText: "",
bufferedText: ""
});
});
});