Animate active task indicators
This commit is contained in:
+33
-3
@@ -156,6 +156,31 @@ test("uses sibling-local Roman and numeric widget labels while leaving leaf sub-
|
||||
assert.match(timedChild, /◉/);
|
||||
});
|
||||
|
||||
test("animates only in-progress widget circles while preserving narrow-width status markers", () => {
|
||||
const state = new TaskState(() => 0);
|
||||
state.add([
|
||||
{ name: "Active", status: "in-progress" },
|
||||
{ name: "Pending" },
|
||||
{ name: "Blocked", status: "blocked" },
|
||||
{ name: "Done", status: "done" },
|
||||
]);
|
||||
|
||||
const orbitFrames = ["◐", "◓", "◑", "◒"];
|
||||
for (const [frame, icon] of orbitFrames.entries()) {
|
||||
const lines = renderWidgetTree(state.list(), plainTheme as never, 80, " ", frame).map(stripAnsi);
|
||||
assert.match(lines[0] ?? "", new RegExp(icon));
|
||||
assert.match(lines[1] ?? "", /○/);
|
||||
assert.match(lines[2] ?? "", /!/);
|
||||
assert.match(lines[3] ?? "", /✓/);
|
||||
|
||||
const narrow = renderWidgetTree(state.list(), plainTheme as never, 6, " ", frame).map(stripAnsi);
|
||||
assert.match(narrow[0] ?? "", new RegExp(icon));
|
||||
assert.ok(narrow.every((line) => visibleWidth(line) <= 6));
|
||||
}
|
||||
|
||||
assert.match(stripAnsi(renderTree(state.list(), plainTheme as never, 80)[0] ?? ""), /◉/);
|
||||
});
|
||||
|
||||
test("renumbers widget labels after task reordering and reparenting", () => {
|
||||
const state = new TaskState(() => 0);
|
||||
state.add([
|
||||
@@ -344,7 +369,9 @@ test("live widgets request rerenders and dispose their interval", async () => {
|
||||
updateTaskWidget(state, ctx as never, true, 5);
|
||||
|
||||
let renderRequests = 0;
|
||||
const component = (
|
||||
const observedFrames = new Set<string>();
|
||||
let component: { render(width: number): string[]; dispose?(): void };
|
||||
component = (
|
||||
widget as unknown as (
|
||||
tui: { requestRender(): void },
|
||||
theme: unknown,
|
||||
@@ -353,17 +380,20 @@ test("live widgets request rerenders and dispose their interval", async () => {
|
||||
{
|
||||
requestRender() {
|
||||
renderRequests += 1;
|
||||
const frame = stripAnsi(component.render(40)[1] ?? "").match(/[◐◓◑◒]/)?.[0];
|
||||
if (frame !== undefined) observedFrames.add(frame);
|
||||
},
|
||||
},
|
||||
plainTheme,
|
||||
);
|
||||
|
||||
try {
|
||||
assert.match(stripAnsi(component.render(40)[1] ?? ""), / · 00:00$/);
|
||||
assert.match(stripAnsi(component.render(40)[1] ?? ""), /◐.* · 00:00$/);
|
||||
now = 65_000;
|
||||
await new Promise((resolve) => setTimeout(resolve, 20));
|
||||
assert.ok(renderRequests > 0);
|
||||
assert.match(stripAnsi(component.render(40)[1] ?? ""), / · 01:05$/);
|
||||
assert.ok(observedFrames.size > 0);
|
||||
assert.match(stripAnsi(component.render(40)[1] ?? ""), /[◐◓◑◒].* · 01:05$/);
|
||||
} finally {
|
||||
component.dispose?.();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user