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(`"[42mHello World[49m"`);
});
-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(`"[44mHello World[49m"`);
});
-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(`"[44mHello World[49m"`);
});
-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(`"[43mHello World[49m"`);
});
-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(`"[42mInherited No BG [41mRed BG[49m"`);
});
-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(`"[43mOuter: [44mInner: [41mExplicit[49m"`);
});
-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(`"[41mHello[49m"`);
});
-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(`"[48;2;255;0;0mHello[49m"`);
});
-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(`"[48;2;255;0;0mHello[49m"`);
});
-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(`"[48;5;9mHello[49m"`);
});
-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(`"[43mこんにちは[49m"`);
});
-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(`"[41m🎉🎊[49m"`);
});
-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/**"],
},