test(runtime-tests): run the main suite concurrently by default

Enable sequence.concurrent: true in vite.config.ts so the non-PTY suite runs
concurrently like the PTY suite. Stress-verified stable (8/8 at maxForks=4);
the suite drops from ~13s to ~4-5s.

Three test patterns were incompatible with concurrency; handled per cause:

- Inline snapshots (background-color, borders): the module-level `expect`
  loses snapshot test context under concurrency. Fixed in place by using the
  context-local `expect` (async ({ expect }) => ...), so they stay concurrent.

- Process-global state (throttle/animation-scheduler use fake timers; leak
  asserts on process exit/SIGINT listener counts and live yoga nodes): a
  concurrent sibling clobbers the shared global mid-test. These genuinely
  require serial execution, so they move to *.sequential.test.* files with
  it.sequential / describe.sequential and a header explaining why.

`vp run ready` passes.
This commit is contained in:
Yunfei He
2026-05-29 14:10:27 +08:00
parent fa626dc90f
commit ee6004b8be
6 changed files with 125 additions and 102 deletions
@@ -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(() => <Box backgroundColor="blue" width={5} height={1} />, {
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(
() => <Box backgroundColor="blue" borderStyle="single" width={6} height={3} />,
{ 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(
() => (
<Box backgroundColor="blue" width={10} height={1}>
@@ -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(
() => (
<Box backgroundColor="blue" borderStyle="single" width={10} height={4}>
@@ -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(() => () => (
<Box backgroundColor="green" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="red" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="red" alignSelf="flex-start">
@@ -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(() => () => (
<Box alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="yellow" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="green" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="yellow" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="red" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="#FF0000" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="rgb(255, 0, 0)" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="ansi256(9)" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="yellow" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="red" alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="red" width={10} height={3} alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="cyan" borderStyle="round" width={10} height={5} alignSelf="flex-start">
@@ -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(() => () => (
<Box backgroundColor="magenta" padding={1} width={10} height={5} alignSelf="flex-start">
@@ -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(() => () => (
<Box
@@ -349,7 +349,7 @@ test("Box background with center alignment fills entire area", async () => {
`);
});
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(() => () => (
<Box
@@ -374,7 +374,7 @@ test("Box background with column layout fills entire area", async () => {
`);
});
test("Box background updates on rerender", async () => {
test("Box background updates on rerender", async ({ expect }) => {
const bgColor = shallowRef<string | undefined>(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(() => () => (
<Box backgroundColor="red" width={10} alignSelf="flex-start">
@@ -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(() => () => (
<Box width={10} alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="single" borderColor="white" borderBackgroundColor="blue">
@@ -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(() => () => (
<Box
@@ -480,7 +482,7 @@ test("border with different background colors per side", async () => {
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(() => () => (
<Box borderStyle="single" borderBackgroundColor="magenta" borderTopBackgroundColor="cyan">
@@ -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(() => () => (
<Box borderStyle="classic" borderBackgroundColor="cyan" alignSelf="flex-start" width={12}>
@@ -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(() => () => (
<Box
@@ -1,11 +1,11 @@
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, measureText } from "@vue-tui/runtime";
import stripAnsi from "strip-ansi";
// single node — full width box
test("single node - full width box", async () => {
test("single node - full width box", async ({ expect }) => {
const { lastFrame } = await render(
defineComponent(() => () => (
<Box borderStyle="round">
@@ -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(() => () => (
<Box borderStyle="round" borderColor="green">
@@ -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(() => () => (
<Box borderStyle="round" alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" width={20}>
@@ -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(() => () => (
<Box borderStyle="round" width={20} height={20}>
@@ -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(() => () => (
<Box borderStyle="round" padding={1} alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" width={20} justifyContent="center">
@@ -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(() => () => (
<Box borderStyle="round" height={20} alignItems="center" alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" width={10}>
@@ -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(() => () => (
<Box borderStyle="round">
@@ -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(() => () => (
<Box borderStyle="round" borderColor="green">
@@ -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(() => () => (
<Box borderStyle="round" alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" width={20}>
@@ -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(() => () => (
<Box borderStyle="round" width={20} height={20}>
@@ -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(() => () => (
<Box borderStyle="round" padding={1} alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" width={20} justifyContent="center">
@@ -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(() => () => (
<Box borderStyle="round" height={20} alignItems="center" alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" width={10}>
@@ -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(() => () => (
<Box borderStyle="round" width={10}>
@@ -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(() => () => (
<Box borderStyle="round" width={10}>
@@ -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(() => () => (
<Box borderStyle="round" width={40} padding={1}>
@@ -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(() => () => (
<Box borderStyle="round" alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" alignSelf="flex-start">
@@ -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(() => () => (
<Box borderStyle="round" alignSelf="flex-start" flexDirection="column">
@@ -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(() => () => (
<Box borderStyle="round" alignSelf="flex-start" flexDirection="column">
@@ -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<string | undefined>(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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box borderStyle="arrow">
@@ -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(() => () => (
<Box borderStyle="arrow" width={3} height={3}>
@@ -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(() => () => (
<Box borderDimColor borderStyle="round">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box flexDirection="column" alignItems="flex-start">
@@ -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(() => () => (
<Box borderStyle="single" borderColor="white" borderBackgroundColor="blue">
@@ -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(() => () => (
<Box
@@ -1132,7 +1138,7 @@ test("border with different background colors per side", async () => {
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(() => () => (
<Box borderStyle="single" borderBackgroundColor="magenta" borderTopBackgroundColor="cyan">
@@ -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(() => () => (
<Box borderStyle="classic" borderBackgroundColor="cyan" alignSelf="flex-start" width={12}>
@@ -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(() => () => (
<Box
@@ -1194,7 +1200,7 @@ test("foreground, background and dim combine correctly", async () => {
});
// 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(() => () => (
<Box borderDimColor borderStyle="round" alignSelf="flex-start">
@@ -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(() => () => <Text>x</Text>);
@@ -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(() => {
@@ -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");
@@ -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();
+4
View File
@@ -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/**"],
},