diff --git a/packages/runtime-tests/integration/components/background-color.test.tsx b/packages/runtime-tests/integration/components/background-color.test.tsx index fd3133b..ddcac8c 100644 --- a/packages/runtime-tests/integration/components/background-color.test.tsx +++ b/packages/runtime-tests/integration/components/background-color.test.tsx @@ -1,18 +1,18 @@ import { defineComponent, shallowRef, nextTick } from "vue"; -import { expect, test } from "vite-plus/test"; +import { test } from "vite-plus/test"; import { render } from "@vue-tui/testing"; import { Box, Text } from "@vue-tui/runtime"; const BG_BLUE = "\x1b[44m"; -test("Box backgroundColor produces ANSI background codes", async () => { +test("Box backgroundColor produces ANSI background codes", async ({ expect }) => { const { frames } = await render(() => , { columns: 10, }); expect(frames.at(-1)).toContain(BG_BLUE); }); -test("Box backgroundColor survives border rendering", async () => { +test("Box backgroundColor survives border rendering", async ({ expect }) => { const { frames } = await render( () => , { columns: 10 }, @@ -22,7 +22,7 @@ test("Box backgroundColor survives border rendering", async () => { expect(raw).toContain("┌"); }); -test("child Text inherits backgroundColor from parent Box", async () => { +test("child Text inherits backgroundColor from parent Box", async ({ expect }) => { const { frames } = await render( () => ( @@ -36,7 +36,7 @@ test("child Text inherits backgroundColor from parent Box", async () => { expect(raw).toContain(BG_BLUE); }); -test("wrapped text preserves backgroundColor on every line", async () => { +test("wrapped text preserves backgroundColor on every line", async ({ expect }) => { const { frames } = await render( () => ( @@ -54,7 +54,7 @@ test("wrapped text preserves backgroundColor on every line", async () => { // --- Ink background tests --- -test("Text inherits parent Box background color", async () => { +test("Text inherits parent Box background color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -66,7 +66,7 @@ test("Text inherits parent Box background color", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Hello World"`); }); -test("Text explicit background color overrides inherited", async () => { +test("Text explicit background color overrides inherited", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -78,7 +78,7 @@ test("Text explicit background color overrides inherited", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Hello World"`); }); -test("Nested Box background inheritance", async () => { +test("Nested Box background inheritance", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -92,7 +92,7 @@ test("Nested Box background inheritance", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Hello World"`); }); -test("Text without parent Box background has no inheritance", async () => { +test("Text without parent Box background has no inheritance", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -104,7 +104,7 @@ test("Text without parent Box background has no inheritance", async () => { expect(lastFrame()).toBe("Hello World"); }); -test("Multiple Text elements inherit same background", async () => { +test("Multiple Text elements inherit same background", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -117,7 +117,7 @@ test("Multiple Text elements inherit same background", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Hello World"`); }); -test("Mixed text with and without background inheritance", async () => { +test("Mixed text with and without background inheritance", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -131,7 +131,7 @@ test("Mixed text with and without background inheritance", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Inherited No BG Red BG"`); }); -test("Complex nested structure with background inheritance", async () => { +test("Complex nested structure with background inheritance", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -149,7 +149,7 @@ test("Complex nested structure with background inheritance", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Outer: Inner: Explicit"`); }); -test("Box background with standard color", async () => { +test("Box background with standard color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -161,7 +161,7 @@ test("Box background with standard color", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Hello"`); }); -test("Box background with hex color", async () => { +test("Box background with hex color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -173,7 +173,7 @@ test("Box background with hex color", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Hello"`); }); -test("Box background with rgb color", async () => { +test("Box background with rgb color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -185,7 +185,7 @@ test("Box background with rgb color", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Hello"`); }); -test("Box background with ansi256 color", async () => { +test("Box background with ansi256 color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -197,7 +197,7 @@ test("Box background with ansi256 color", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"Hello"`); }); -test("Box background with wide characters", async () => { +test("Box background with wide characters", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -209,7 +209,7 @@ test("Box background with wide characters", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"こんにちは"`); }); -test("Box background with emojis", async () => { +test("Box background with emojis", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -221,7 +221,7 @@ test("Box background with emojis", async () => { expect(lastFrame()).toMatchInlineSnapshot(`"🎉🎊"`); }); -test("Box background fills entire area with standard color", async () => { +test("Box background fills entire area with standard color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -237,7 +237,7 @@ test("Box background fills entire area with standard color", async () => { `); }); -test("Box background fills with hex color", async () => { +test("Box background fills with hex color", async ({ expect }) => { const bgHexRed = "[48;2;255;0;0m"; const bgReset = "[49m"; @@ -255,7 +255,7 @@ test("Box background fills with hex color", async () => { expect(output).toContain(bgReset); }); -test("Box background fills with rgb color", async () => { +test("Box background fills with rgb color", async ({ expect }) => { const bgHexRed = "[48;2;255;0;0m"; const bgReset = "[49m"; @@ -273,7 +273,7 @@ test("Box background fills with rgb color", async () => { expect(output).toContain(bgReset); }); -test("Box background fills with ansi256 color", async () => { +test("Box background fills with ansi256 color", async ({ expect }) => { const bgAnsi256Nine = "[48;5;9m"; const bgReset = "[49m"; @@ -291,7 +291,7 @@ test("Box background fills with ansi256 color", async () => { expect(output).toContain(bgReset); }); -test("Box background with border fills content area", async () => { +test("Box background with border fills content area", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -309,7 +309,7 @@ test("Box background with border fills content area", async () => { `); }); -test("Box background with padding fills entire padded area", async () => { +test("Box background with padding fills entire padded area", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -327,7 +327,7 @@ test("Box background with padding fills entire padded area", async () => { `); }); -test("Box background with center alignment fills entire area", async () => { +test("Box background with center alignment fills entire area", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( { `); }); -test("Box background with column layout fills entire area", async () => { +test("Box background with column layout fills entire area", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( { `); }); -test("Box background updates on rerender", async () => { +test("Box background updates on rerender", async ({ expect }) => { const bgColor = shallowRef(undefined); const { lastFrame } = await render( @@ -397,7 +397,7 @@ test("Box background updates on rerender", async () => { expect(lastFrame()).toBe("Hello"); }); -test("Box backgroundColor fills full width on every line when text wraps", async () => { +test("Box backgroundColor fills full width on every line when text wraps", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -412,7 +412,9 @@ test("Box backgroundColor fills full width on every line when text wraps", async `); }); -test("Text-only backgroundColor colors text content but does not fill Box width", async () => { +test("Text-only backgroundColor colors text content but does not fill Box width", async ({ + expect, +}) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -429,7 +431,7 @@ test("Text-only backgroundColor colors text content but does not fill Box width" // --- Ink border-backgrounds tests --- -test("border with background color", async () => { +test("border with background color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -450,7 +452,7 @@ test("border with background color", async () => { expect(output).toContain("[44m"); }); -test("border with different background colors per side", async () => { +test("border with different background colors per side", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( { expect(output).toContain("[44m"); }); -test("border background color fallback to general borderBackgroundColor", async () => { +test("border background color fallback to general borderBackgroundColor", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -502,7 +504,7 @@ test("border background color fallback to general borderBackgroundColor", async expect(output).toContain("[45m"); }); -test("vertical border background does not bleed into content rows", async () => { +test("vertical border background does not bleed into content rows", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -525,7 +527,7 @@ test("vertical border background does not bleed into content rows", async () => } }); -test("foreground, background and dim combine correctly", async () => { +test("foreground, background and dim combine correctly", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( { +test("single node - full width box", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -22,7 +22,7 @@ test("single node - full width box", async () => { }); // single node — full width box with colorful border -test("single node - full width box with colorful border", async () => { +test("single node - full width box with colorful border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -39,7 +39,7 @@ test("single node - full width box with colorful border", async () => { }); // single node — fit-content box -test("single node - fit-content box", async () => { +test("single node - fit-content box", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -56,7 +56,7 @@ test("single node - fit-content box", async () => { }); // single node — fit-content box with wide characters -test("single node - fit-content box with wide characters", async () => { +test("single node - fit-content box with wide characters", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -73,7 +73,7 @@ test("single node - fit-content box with wide characters", async () => { }); // single node — fit-content box with emojis -test("single node - fit-content box with emojis", async () => { +test("single node - fit-content box with emojis", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -90,7 +90,7 @@ test("single node - fit-content box with emojis", async () => { }); // single node — fit-content box with variation selector emojis -test("single node - fit-content box with variation selector emojis", async () => { +test("single node - fit-content box with variation selector emojis", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -107,7 +107,7 @@ test("single node - fit-content box with variation selector emojis", async () => }); // single node — fixed width box -test("single node - fixed width box", async () => { +test("single node - fixed width box", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -124,7 +124,7 @@ test("single node - fixed width box", async () => { }); // single node — fixed width and height box -test("single node - fixed width and height box", async () => { +test("single node - fixed width and height box", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -158,7 +158,7 @@ test("single node - fixed width and height box", async () => { }); // single node — box with padding -test("single node - box with padding", async () => { +test("single node - box with padding", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -177,7 +177,7 @@ test("single node - box with padding", async () => { }); // single node — box with horizontal alignment -test("single node - box with horizontal alignment", async () => { +test("single node - box with horizontal alignment", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -194,7 +194,7 @@ test("single node - box with horizontal alignment", async () => { }); // single node — box with vertical alignment -test("single node - box with vertical alignment", async () => { +test("single node - box with vertical alignment", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -228,7 +228,7 @@ test("single node - box with vertical alignment", async () => { }); // single node — box with wrapping -test("single node - box with wrapping", async () => { +test("single node - box with wrapping", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -246,7 +246,7 @@ test("single node - box with wrapping", async () => { }); // multiple nodes — full width box -test("multiple nodes - full width box", async () => { +test("multiple nodes - full width box", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -263,7 +263,7 @@ test("multiple nodes - full width box", async () => { }); // multiple nodes — full width box with colorful border -test("multiple nodes - full width box with colorful border", async () => { +test("multiple nodes - full width box with colorful border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -280,7 +280,7 @@ test("multiple nodes - full width box with colorful border", async () => { }); // multiple nodes — fit-content box -test("multiple nodes - fit-content box", async () => { +test("multiple nodes - fit-content box", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -297,7 +297,7 @@ test("multiple nodes - fit-content box", async () => { }); // multiple nodes — fixed width box -test("multiple nodes - fixed width box", async () => { +test("multiple nodes - fixed width box", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -314,7 +314,7 @@ test("multiple nodes - fixed width box", async () => { }); // multiple nodes — fixed width and height box -test("multiple nodes - fixed width and height box", async () => { +test("multiple nodes - fixed width and height box", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -348,7 +348,7 @@ test("multiple nodes - fixed width and height box", async () => { }); // multiple nodes — box with padding -test("multiple nodes - box with padding", async () => { +test("multiple nodes - box with padding", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -367,7 +367,7 @@ test("multiple nodes - box with padding", async () => { }); // multiple nodes — box with horizontal alignment -test("multiple nodes - box with horizontal alignment", async () => { +test("multiple nodes - box with horizontal alignment", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -384,7 +384,7 @@ test("multiple nodes - box with horizontal alignment", async () => { }); // multiple nodes — box with vertical alignment -test("multiple nodes - box with vertical alignment", async () => { +test("multiple nodes - box with vertical alignment", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -418,7 +418,7 @@ test("multiple nodes - box with vertical alignment", async () => { }); // multiple nodes — box with wrapping -test("multiple nodes - box with wrapping", async () => { +test("multiple nodes - box with wrapping", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -436,7 +436,7 @@ test("multiple nodes - box with wrapping", async () => { }); // multiple nodes — box with wrapping and long first node -test("multiple nodes - box with wrapping and long first node", async () => { +test("multiple nodes - box with wrapping and long first node", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -454,7 +454,7 @@ test("multiple nodes - box with wrapping and long first node", async () => { }); // multiple nodes — box with wrapping and very long first node -test("multiple nodes - box with wrapping and very long first node", async () => { +test("multiple nodes - box with wrapping and very long first node", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -473,7 +473,7 @@ test("multiple nodes - box with wrapping and very long first node", async () => }); // nested boxes -test("nested boxes", async () => { +test("nested boxes", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -498,7 +498,9 @@ test("nested boxes", async () => { }); // nested boxes — fit-content box with wide characters on flex-direction row -test("nested boxes - fit-content box with wide characters on flex-direction row", async () => { +test("nested boxes - fit-content box with wide characters on flex-direction row", async ({ + expect, +}) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -525,7 +527,7 @@ test("nested boxes - fit-content box with wide characters on flex-direction row" }); // nested boxes — fit-content box with emojis on flex-direction row -test("nested boxes - fit-content box with emojis on flex-direction row", async () => { +test("nested boxes - fit-content box with emojis on flex-direction row", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -552,7 +554,9 @@ test("nested boxes - fit-content box with emojis on flex-direction row", async ( }); // nested boxes — fit-content box with wide characters on flex-direction column -test("nested boxes - fit-content box with wide characters on flex-direction column", async () => { +test("nested boxes - fit-content box with wide characters on flex-direction column", async ({ + expect, +}) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -585,7 +589,7 @@ test("nested boxes - fit-content box with wide characters on flex-direction colu }); // nested boxes — fit-content box with emojis on flex-direction column -test("nested boxes - fit-content box with emojis on flex-direction column", async () => { +test("nested boxes - fit-content box with emojis on flex-direction column", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -618,7 +622,7 @@ test("nested boxes - fit-content box with emojis on flex-direction column", asyn }); // render border after update — reactive borderColor changes -test("render border after update", async () => { +test("render border after update", async ({ expect }) => { const borderColor = shallowRef(undefined); const { lastFrame } = await render( defineComponent(() => () => ( @@ -652,7 +656,9 @@ test("render border after update", async () => { }); // render border edge changes after update when borderStyle is unchanged -test("render border edge changes after update when borderStyle is unchanged", async () => { +test("render border edge changes after update when borderStyle is unchanged", async ({ + expect, +}) => { const showTop = shallowRef(true); const { lastFrame } = await render( defineComponent(() => () => ( @@ -685,7 +691,7 @@ test("render border edge changes after update when borderStyle is unchanged", as }); // hide top border -test("hide top border", async () => { +test("hide top border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -707,7 +713,7 @@ test("hide top border", async () => { }); // hide bottom border -test("hide bottom border", async () => { +test("hide bottom border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -729,7 +735,7 @@ test("hide bottom border", async () => { }); // hide top and bottom borders -test("hide top and bottom borders", async () => { +test("hide top and bottom borders", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -750,7 +756,7 @@ test("hide top and bottom borders", async () => { }); // hide left border -test("hide left border", async () => { +test("hide left border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -773,7 +779,7 @@ test("hide left border", async () => { }); // hide right border -test("hide right border", async () => { +test("hide right border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -796,7 +802,7 @@ test("hide right border", async () => { }); // hide left and right border -test("hide left and right border", async () => { +test("hide left and right border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -819,7 +825,7 @@ test("hide left and right border", async () => { }); // hide all borders -test("hide all borders", async () => { +test("hide all borders", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -846,7 +852,7 @@ test("hide all borders", async () => { }); // change color of top border -test("change color of top border", async () => { +test("change color of top border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -869,7 +875,7 @@ test("change color of top border", async () => { }); // change color of bottom border -test("change color of bottom border", async () => { +test("change color of bottom border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -892,7 +898,7 @@ test("change color of bottom border", async () => { }); // change color of left border -test("change color of left border", async () => { +test("change color of left border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -915,7 +921,7 @@ test("change color of left border", async () => { }); // change color of right border -test("change color of right border", async () => { +test("change color of right border", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -938,7 +944,7 @@ test("change color of right border", async () => { }); // custom border style — uses "arrow" named style (same chars as the Ink custom object) -test("custom border style", async () => { +test("custom border style", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -955,7 +961,7 @@ test("custom border style", async () => { }); // arrow border on narrow box does not overflow -test("arrow border on narrow box does not overflow", async () => { +test("arrow border on narrow box does not overflow", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -974,7 +980,7 @@ test("arrow border on narrow box does not overflow", async () => { }); // dim border color -test("dim border color", async () => { +test("dim border color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -991,7 +997,7 @@ test("dim border color", async () => { }); // dim top border color -test("dim top border color", async () => { +test("dim top border color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -1014,7 +1020,7 @@ test("dim top border color", async () => { }); // dim bottom border color -test("dim bottom border color", async () => { +test("dim bottom border color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -1037,7 +1043,7 @@ test("dim bottom border color", async () => { }); // dim left border color -test("dim left border color", async () => { +test("dim left border color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -1060,7 +1066,7 @@ test("dim left border color", async () => { }); // dim right border color -test("dim right border color", async () => { +test("dim right border color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -1084,7 +1090,7 @@ test("dim right border color", async () => { // --- borderBackgroundColor tests (ported from Ink border-backgrounds.tsx) --- -test("border with background color", async () => { +test("border with background color", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -1105,7 +1111,7 @@ test("border with background color", async () => { expect(frame).toContain("[44m"); }); -test("border with different background colors per side", async () => { +test("border with different background colors per side", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( { expect(frame).toContain("[44m"); }); -test("border background color fallback to general borderBackgroundColor", async () => { +test("border background color fallback to general borderBackgroundColor", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -1149,7 +1155,7 @@ test("border background color fallback to general borderBackgroundColor", async expect(frame).toContain("[45m"); }); -test("vertical border background does not bleed into content rows", async () => { +test("vertical border background does not bleed into content rows", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( @@ -1171,7 +1177,7 @@ test("vertical border background does not bleed into content rows", async () => } }); -test("foreground, background and dim combine correctly", async () => { +test("foreground, background and dim combine correctly", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( { }); // borderDimColor should not dim styled child Text touching left edge -test("borderDimColor does not dim styled child Text touching left edge", async () => { +test("borderDimColor does not dim styled child Text touching left edge", async ({ expect }) => { const { lastFrame } = await render( defineComponent(() => () => ( diff --git a/packages/runtime-tests/integration/lifecycle/leak.test.tsx b/packages/runtime-tests/integration/lifecycle/leak.sequential.test.tsx similarity index 73% rename from packages/runtime-tests/integration/lifecycle/leak.test.tsx rename to packages/runtime-tests/integration/lifecycle/leak.sequential.test.tsx index 1386a43..913e6a4 100644 --- a/packages/runtime-tests/integration/lifecycle/leak.test.tsx +++ b/packages/runtime-tests/integration/lifecycle/leak.sequential.test.tsx @@ -1,10 +1,14 @@ +// Sequential: asserts on process-global resource counts (process exit/SIGINT +// listeners, live yoga nodes). Concurrent siblings that mount/unmount apps add +// and remove those listeners/nodes, polluting the counts. Tests are it.sequential. + import { defineComponent, nextTick, shallowRef } from "vue"; import { expect, test } from "vite-plus/test"; import { render } from "@vue-tui/testing"; import { Box, Text, useInput } from "@vue-tui/runtime"; import { yogaNodeTracker } from "@vue-tui/runtime/internal"; -test("50 render/unmount cycles leak zero process listeners", async () => { +test.sequential("50 render/unmount cycles leak zero process listeners", async () => { const exitBefore = process.listenerCount("exit"); const sigintBefore = process.listenerCount("SIGINT"); @@ -19,7 +23,7 @@ test("50 render/unmount cycles leak zero process listeners", async () => { expect(process.listenerCount("SIGINT")).toBe(sigintBefore); }); -test("100 render/unmount cycles leak zero yoga nodes", async () => { +test.sequential("100 render/unmount cycles leak zero yoga nodes", async () => { yogaNodeTracker.reset(); const App = defineComponent(() => () => x); @@ -32,7 +36,7 @@ test("100 render/unmount cycles leak zero yoga nodes", async () => { expect(yogaNodeTracker.snapshot().live).toBe(0); }); -test("raw mode stays on when one of two useInput components unmounts", async () => { +test.sequential("raw mode stays on when one of two useInput components unmounts", async () => { const showB = shallowRef(true); const Listener = defineComponent(() => { diff --git a/packages/runtime-tests/integration/lifecycle/throttle.test.tsx b/packages/runtime-tests/integration/lifecycle/throttle.sequential.test.tsx similarity index 91% rename from packages/runtime-tests/integration/lifecycle/throttle.test.tsx rename to packages/runtime-tests/integration/lifecycle/throttle.sequential.test.tsx index 2674c75..2ae580f 100644 --- a/packages/runtime-tests/integration/lifecycle/throttle.test.tsx +++ b/packages/runtime-tests/integration/lifecycle/throttle.sequential.test.tsx @@ -1,3 +1,7 @@ +// Sequential: uses vi.useFakeTimers, which mutates the process-global timer +// functions. Run concurrently, a sibling test calling useRealTimers() would +// pull the mocked timers out mid-advanceTimersByTime. Tests are it.sequential. + import { defineComponent, nextTick, shallowRef } from "vue"; import { expect, test, vi } from "vite-plus/test"; import { createApp, Text } from "@vue-tui/runtime"; @@ -17,7 +21,7 @@ const FAKE_TIMER_OPTS = { toFake: ["setTimeout", "clearTimeout", "Date"] as ("setTimeout" | "clearTimeout" | "Date")[], }; -test("throttle renders to maxFps", async () => { +test.sequential("throttle renders to maxFps", async () => { // Port of Ink's "throttle renders to maxFps" — verifies leading+trailing // throttle pattern with maxFps=1 (1000ms window). vi.useFakeTimers(FAKE_TIMER_OPTS); @@ -73,7 +77,7 @@ test("throttle renders to maxFps", async () => { } }); -test("immediate scheduler in debug mode commits every mutation", async () => { +test.sequential("immediate scheduler in debug mode commits every mutation", async () => { // Counterpart to the throttle test: in debug mode (used by the testing // helper), the scheduler bypasses throttling and commits synchronously. // This verifies the immediate path in createCommitScheduler. @@ -114,7 +118,7 @@ test("immediate scheduler in debug mode commits every mutation", async () => { app.unmount(); }); -test("screen reader mode bypasses throttle (immediate commits)", async () => { +test.sequential("screen reader mode bypasses throttle (immediate commits)", async () => { // Port of Ink's screen reader behavior: isScreenReaderEnabled causes // the scheduler to use immediate mode, ensuring every frame is flushed // without delay for assistive technology. @@ -151,7 +155,7 @@ test("screen reader mode bypasses throttle (immediate commits)", async () => { app.unmount(); }); -test("no throttled renders after unmount", async () => { +test.sequential("no throttled renders after unmount", async () => { vi.useFakeTimers(FAKE_TIMER_OPTS); try { const msg = shallowRef("Foo"); @@ -183,7 +187,7 @@ test("no throttled renders after unmount", async () => { } }); -test("unmount forces pending throttled render", async () => { +test.sequential("unmount forces pending throttled render", async () => { vi.useFakeTimers(FAKE_TIMER_OPTS); try { const msg = shallowRef("Hello"); @@ -214,7 +218,7 @@ test("unmount forces pending throttled render", async () => { } }); -test("unmount cancels pending throttled log writes when stdout is ended", async () => { +test.sequential("unmount cancels pending throttled log writes when stdout is ended", async () => { vi.useFakeTimers(FAKE_TIMER_OPTS); try { const { PassThrough } = await import("node:stream"); @@ -249,7 +253,7 @@ test("unmount cancels pending throttled log writes when stdout is ended", async } }); -test("unmount cancels pending throttled render when stdout is ended", async () => { +test.sequential("unmount cancels pending throttled render when stdout is ended", async () => { vi.useFakeTimers(FAKE_TIMER_OPTS); try { const { PassThrough } = await import("node:stream"); diff --git a/packages/runtime-tests/unit/animation-scheduler.test.ts b/packages/runtime-tests/unit/animation-scheduler.sequential.test.ts similarity index 94% rename from packages/runtime-tests/unit/animation-scheduler.test.ts rename to packages/runtime-tests/unit/animation-scheduler.sequential.test.ts index 24e7f21..184c2e0 100644 --- a/packages/runtime-tests/unit/animation-scheduler.test.ts +++ b/packages/runtime-tests/unit/animation-scheduler.sequential.test.ts @@ -1,3 +1,6 @@ +// Sequential: uses vi.useFakeTimers (process-global timer mocking). See the +// other *.sequential.test files. The describe blocks are describe.sequential. + import { afterEach, beforeEach, describe, expect, test, vi } from "vite-plus/test"; // Internal module not in package exports — import via relative source path, // matching the convention in integration/lifecycle/write-synchronized.test.ts. @@ -7,7 +10,7 @@ import { normalizeInterval, } from "../../runtime/src/animation-scheduler.ts"; -describe("normalizeInterval", () => { +describe.sequential("normalizeInterval", () => { test("clamps and defaults", () => { expect(normalizeInterval(50)).toBe(50); expect(normalizeInterval(0)).toBe(1); @@ -19,7 +22,7 @@ describe("normalizeInterval", () => { }); }); -describe("createAnimationScheduler", () => { +describe.sequential("createAnimationScheduler", () => { beforeEach(() => { vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout", "performance"] }); }); @@ -148,7 +151,7 @@ describe("createAnimationScheduler", () => { }); }); -describe("createNoOpAnimationScheduler", () => { +describe.sequential("createNoOpAnimationScheduler", () => { test("subscribe returns inert handle, never ticks", () => { const s = createNoOpAnimationScheduler(); const cb = vi.fn(); diff --git a/packages/runtime-tests/vite.config.ts b/packages/runtime-tests/vite.config.ts index af17c6c..d969248 100644 --- a/packages/runtime-tests/vite.config.ts +++ b/packages/runtime-tests/vite.config.ts @@ -6,6 +6,10 @@ export default defineConfig({ test: { // chalk disables color in non-TTY envs; force it on so ANSI style bugs don't hide from tests env: { FORCE_COLOR: "3" }, + // Tests run concurrently by default. Tests that genuinely need serial + // execution (process-global fake timers) live in their own *.sequential + // files. Snapshot tests stay concurrent by using the context-local expect. + sequence: { concurrent: true }, // PTY tests run separately via vitest.pty.config.ts (they need node-pty's forks pool and a longer timeout) exclude: ["integration/pty/**", "node_modules/**"], },