Files
remoteconn-gitea/apps/miniprogram/pages/terminal/terminalViewportModel.test.ts
2026-03-21 18:57:10 +08:00

137 lines
4.6 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 {
buildTerminalViewportState,
resolveTerminalMaxScrollTop,
resolveTerminalRenderRows
} = require("./terminalViewportModel.js");
describe("terminalViewportModel", () => {
it("normal buffer 会裁掉 cursor 行之后的虚假尾部,避免 prompt 下方继续可滚动", () => {
const rows = [[{ text: "a" }], [{ text: "b" }], [], []];
const renderRows = resolveTerminalRenderRows(rows, 1, "normal");
expect(renderRows).toHaveLength(2);
expect(renderRows).toEqual(rows.slice(0, 2));
});
it("alternate screen 保留整屏行数,不裁掉底部空白", () => {
const rows = [[{ text: "a" }], [], [], []];
const renderRows = resolveTerminalRenderRows(rows, 0, "alt");
expect(renderRows).toHaveLength(4);
expect(renderRows).toEqual(rows);
});
it("normal buffer 在 cursor 行之后若仍有真实 footer会保留到最后一个非空行", () => {
const rows = [[{ text: "prompt" }], [], [{ text: "footer" }], []];
const renderRows = resolveTerminalRenderRows(rows, 0, "normal");
expect(renderRows).toHaveLength(3);
expect(renderRows).toEqual(rows.slice(0, 3));
});
it("最大滚动值基于最终渲染行数,而不是旧尾部空行", () => {
const viewport = buildTerminalViewportState({
bufferRows: [[{ text: "a" }], [{ text: "b" }], [], []],
cursorRow: 1,
activeBufferName: "normal",
visibleRows: 1,
lineHeight: 20
});
expect(viewport.renderRowCount).toBe(2);
expect(viewport.maxScrollTop).toBe(20);
expect(resolveTerminalMaxScrollTop(2, 1, 20)).toBe(20);
});
it("最大滚动值会把 cursor 后的真实 footer 也算进去,而不是只看 cursor 行", () => {
const viewport = buildTerminalViewportState({
bufferRows: [[{ text: "prompt" }], [], [{ text: "footer" }], []],
cursorRow: 0,
activeBufferName: "normal",
visibleRows: 1,
lineHeight: 20
});
expect(viewport.renderRowCount).toBe(3);
expect(viewport.maxScrollTop).toBe(40);
});
it("followTail 模式只渲染底部可视区附近窗口,并用 spacer 保留完整滚动高度", () => {
const rows = Array.from({ length: 400 }, (_, index) => [{ text: `row-${index}` }]);
const viewport = buildTerminalViewportState({
bufferRows: rows,
cursorRow: 399,
activeBufferName: "normal",
visibleRows: 5,
lineHeight: 10,
followTail: true,
scrollDirection: 1
});
expect(viewport.contentRowCount).toBe(400);
expect(viewport.maxScrollTop).toBe(3950);
expect(viewport.clampedScrollTop).toBe(3950);
expect(viewport.renderStartRow).toBe(240);
expect(viewport.renderEndRow).toBe(400);
expect(viewport.renderRowCount).toBe(160);
expect(viewport.topSpacerHeight).toBe(2400);
expect(viewport.bottomSpacerHeight).toBe(0);
expect(viewport.backwardBufferRows).toBe(155);
expect(viewport.forwardBufferRows).toBe(0);
expect(viewport.renderRows[0]).toEqual(rows[240]);
expect(viewport.renderRows.at(-1)).toEqual(rows[399]);
});
it("传入 scrollTop 时,会围绕当前滚动窗口裁出中段正文", () => {
const rows = Array.from({ length: 400 }, (_, index) => [{ text: `row-${index}` }]);
const viewport = buildTerminalViewportState({
bufferRows: rows,
cursorRow: 399,
activeBufferName: "normal",
visibleRows: 5,
lineHeight: 10,
scrollTop: 1000,
scrollDirection: 1
});
expect(viewport.clampedScrollTop).toBe(1000);
expect(viewport.renderStartRow).toBe(54);
expect(viewport.renderEndRow).toBe(214);
expect(viewport.renderRowCount).toBe(160);
expect(viewport.topSpacerHeight).toBe(540);
expect(viewport.bottomSpacerHeight).toBe(1860);
expect(viewport.backwardBufferRows).toBe(46);
expect(viewport.forwardBufferRows).toBe(109);
expect(viewport.renderRows[0]).toEqual(rows[54]);
expect(viewport.renderRows.at(-1)).toEqual(rows[213]);
});
it("滚动补刷模式会扩大窗口预算,减少快速滑动时频繁换窗", () => {
const rows = Array.from({ length: 400 }, (_, index) => [{ text: `row-${index}` }]);
const viewport = buildTerminalViewportState({
bufferRows: rows,
cursorRow: 399,
activeBufferName: "normal",
visibleRows: 5,
lineHeight: 10,
scrollTop: 1000,
scrollDirection: -1,
scrollViewport: true
});
expect(viewport.renderRowCount).toBe(224);
expect(viewport.renderStartRow).toBe(0);
expect(viewport.renderEndRow).toBe(224);
expect(viewport.topSpacerHeight).toBe(0);
expect(viewport.bottomSpacerHeight).toBe(1760);
});
});