mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 06:04:51 +00:00
fix(tui): reduce flicker by only re-rendering changed lines (#617)
This commit is contained in:
parent
3bb115a39c
commit
df3a220d6b
3 changed files with 118 additions and 5 deletions
|
|
@ -40,4 +40,104 @@ describe("TUI differential rendering", () => {
|
|||
|
||||
tui.stop();
|
||||
});
|
||||
|
||||
it("renders correctly when only a middle line changes (spinner case)", async () => {
|
||||
const terminal = new VirtualTerminal(40, 10);
|
||||
const tui = new TUI(terminal);
|
||||
const component = new TestComponent();
|
||||
tui.addChild(component);
|
||||
|
||||
// Initial render
|
||||
component.lines = ["Header", "Working...", "Footer"];
|
||||
tui.start();
|
||||
await terminal.flush();
|
||||
|
||||
// Simulate spinner animation - only middle line changes
|
||||
const spinnerFrames = ["|", "/", "-", "\\"];
|
||||
for (const frame of spinnerFrames) {
|
||||
component.lines = ["Header", `Working ${frame}`, "Footer"];
|
||||
tui.requestRender();
|
||||
await terminal.flush();
|
||||
|
||||
const viewport = terminal.getViewport();
|
||||
assert.ok(viewport[0]?.includes("Header"), `Header preserved: ${viewport[0]}`);
|
||||
assert.ok(viewport[1]?.includes(`Working ${frame}`), `Spinner updated: ${viewport[1]}`);
|
||||
assert.ok(viewport[2]?.includes("Footer"), `Footer preserved: ${viewport[2]}`);
|
||||
}
|
||||
|
||||
tui.stop();
|
||||
});
|
||||
|
||||
it("renders correctly when first line changes but rest stays same", async () => {
|
||||
const terminal = new VirtualTerminal(40, 10);
|
||||
const tui = new TUI(terminal);
|
||||
const component = new TestComponent();
|
||||
tui.addChild(component);
|
||||
|
||||
component.lines = ["Line 0", "Line 1", "Line 2", "Line 3"];
|
||||
tui.start();
|
||||
await terminal.flush();
|
||||
|
||||
// Change only first line
|
||||
component.lines = ["CHANGED", "Line 1", "Line 2", "Line 3"];
|
||||
tui.requestRender();
|
||||
await terminal.flush();
|
||||
|
||||
const viewport = terminal.getViewport();
|
||||
assert.ok(viewport[0]?.includes("CHANGED"), `First line changed: ${viewport[0]}`);
|
||||
assert.ok(viewport[1]?.includes("Line 1"), `Line 1 preserved: ${viewport[1]}`);
|
||||
assert.ok(viewport[2]?.includes("Line 2"), `Line 2 preserved: ${viewport[2]}`);
|
||||
assert.ok(viewport[3]?.includes("Line 3"), `Line 3 preserved: ${viewport[3]}`);
|
||||
|
||||
tui.stop();
|
||||
});
|
||||
|
||||
it("renders correctly when last line changes but rest stays same", async () => {
|
||||
const terminal = new VirtualTerminal(40, 10);
|
||||
const tui = new TUI(terminal);
|
||||
const component = new TestComponent();
|
||||
tui.addChild(component);
|
||||
|
||||
component.lines = ["Line 0", "Line 1", "Line 2", "Line 3"];
|
||||
tui.start();
|
||||
await terminal.flush();
|
||||
|
||||
// Change only last line
|
||||
component.lines = ["Line 0", "Line 1", "Line 2", "CHANGED"];
|
||||
tui.requestRender();
|
||||
await terminal.flush();
|
||||
|
||||
const viewport = terminal.getViewport();
|
||||
assert.ok(viewport[0]?.includes("Line 0"), `Line 0 preserved: ${viewport[0]}`);
|
||||
assert.ok(viewport[1]?.includes("Line 1"), `Line 1 preserved: ${viewport[1]}`);
|
||||
assert.ok(viewport[2]?.includes("Line 2"), `Line 2 preserved: ${viewport[2]}`);
|
||||
assert.ok(viewport[3]?.includes("CHANGED"), `Last line changed: ${viewport[3]}`);
|
||||
|
||||
tui.stop();
|
||||
});
|
||||
|
||||
it("renders correctly when multiple non-adjacent lines change", async () => {
|
||||
const terminal = new VirtualTerminal(40, 10);
|
||||
const tui = new TUI(terminal);
|
||||
const component = new TestComponent();
|
||||
tui.addChild(component);
|
||||
|
||||
component.lines = ["Line 0", "Line 1", "Line 2", "Line 3", "Line 4"];
|
||||
tui.start();
|
||||
await terminal.flush();
|
||||
|
||||
// Change lines 1 and 3, keep 0, 2, 4 the same
|
||||
component.lines = ["Line 0", "CHANGED 1", "Line 2", "CHANGED 3", "Line 4"];
|
||||
tui.requestRender();
|
||||
await terminal.flush();
|
||||
|
||||
const viewport = terminal.getViewport();
|
||||
assert.ok(viewport[0]?.includes("Line 0"), `Line 0 preserved: ${viewport[0]}`);
|
||||
assert.ok(viewport[1]?.includes("CHANGED 1"), `Line 1 changed: ${viewport[1]}`);
|
||||
assert.ok(viewport[2]?.includes("Line 2"), `Line 2 preserved: ${viewport[2]}`);
|
||||
assert.ok(viewport[3]?.includes("CHANGED 3"), `Line 3 changed: ${viewport[3]}`);
|
||||
assert.ok(viewport[4]?.includes("Line 4"), `Line 4 preserved: ${viewport[4]}`);
|
||||
|
||||
tui.stop();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue