import { defineComponent, shallowRef, nextTick } from "vue"; import { expect, test } from "vite-plus/test"; import { render } from "@vue-tui/testing"; import { Box, Text } from "@vue-tui/runtime"; // single node — full width box test("single node - full width box", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │Hello World │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" `); }); // single node — full width box with colorful border test("single node - full width box with colorful border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │Hello World │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" `); }); // single node — fit-content box test("single node - fit-content box", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭───────────╮ │Hello World│ ╰───────────╯" `); }); // single node — fit-content box with wide characters test("single node - fit-content box with wide characters", async () => { const { lastFrame } = await render( defineComponent(() => () => ( こんにちは )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────╮ │こんにちは│ ╰──────────╯" `); }); // single node — fit-content box with emojis test("single node - fit-content box with emojis", async () => { const { lastFrame } = await render( defineComponent(() => () => ( 🌊🌊 )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭────╮ │🌊🌊│ ╰────╯" `); }); // single node — fit-content box with variation selector emojis test("single node - fit-content box with variation selector emojis", async () => { const { lastFrame } = await render( defineComponent(() => () => ( 🌡️⚠️✅ )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────╮ │🌡️⚠️✅ ╰──────╯" `); }); // single node — fixed width box test("single node - fixed width box", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────╮ │Hello World │ ╰──────────────────╯" `); }); // single node — fixed width and height box test("single node - fixed width and height box", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────╮ │Hello World │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰──────────────────╯" `); }); // single node — box with padding test("single node - box with padding", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭─────────────╮ │ │ │ Hello World │ │ │ ╰─────────────╯" `); }); // single node — box with horizontal alignment test("single node - box with horizontal alignment", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────╮ │Hello World │ ╰──────────────────╯" `); }); // single node — box with vertical alignment test("single node - box with vertical alignment", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭───────────╮ │Hello World│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────╯" `); }); // single node — box with wrapping test("single node - box with wrapping", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭────────╮ │Hello │ │World │ ╰────────╯" `); }); // multiple nodes — full width box test("multiple nodes - full width box", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hello "}World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │Hello World │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" `); }); // multiple nodes — full width box with colorful border test("multiple nodes - full width box with colorful border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hello "}World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │Hello World │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" `); }); // multiple nodes — fit-content box test("multiple nodes - fit-content box", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hello "}World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭───────────╮ │Hello World│ ╰───────────╯" `); }); // multiple nodes — fixed width box test("multiple nodes - fixed width box", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hello "}World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────╮ │Hello World │ ╰──────────────────╯" `); }); // multiple nodes — fixed width and height box test("multiple nodes - fixed width and height box", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hello "}World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────╮ │Hello World │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰──────────────────╯" `); }); // multiple nodes — box with padding test("multiple nodes - box with padding", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hello "}World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭─────────────╮ │ │ │ Hello World │ │ │ ╰─────────────╯" `); }); // multiple nodes — box with horizontal alignment test("multiple nodes - box with horizontal alignment", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hello "}World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────╮ │Hello World │ ╰──────────────────╯" `); }); // multiple nodes — box with vertical alignment test("multiple nodes - box with vertical alignment", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hello "}World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭───────────╮ │Hello World│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────╯" `); }); // multiple nodes — box with wrapping test("multiple nodes - box with wrapping", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hello "}World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭────────╮ │Hello │ │World │ ╰────────╯" `); }); // multiple nodes — box with wrapping and long first node test("multiple nodes - box with wrapping and long first node", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Helloooooo"} World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭────────╮ │Helloooo│ │oo World│ ╰────────╯" `); }); // multiple nodes — box with wrapping and very long first node test("multiple nodes - box with wrapping and very long first node", async () => { const { lastFrame } = await render( defineComponent(() => () => ( {"Hellooooooooooooo"} World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭────────╮ │Helloooo│ │oooooooo│ │o World │ ╰────────╯" `); }); // nested boxes test("nested boxes", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────────────────────────╮ │ │ │ ╭──────────────────────────────────╮ │ │ │ │ │ │ │ Hello World │ │ │ │ │ │ │ ╰──────────────────────────────────╯ │ │ │ ╰──────────────────────────────────────╯" `); }); // 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 () => { const { lastFrame } = await render( defineComponent(() => () => ( ミスター スポック カーク船長 )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭────────────╮ │╭──────────╮│ ││ミスター ││ │╰──────────╯│ │╭──────────╮│ ││スポック ││ │╰──────────╯│ │╭──────────╮│ ││カーク船長││ │╰──────────╯│ ╰────────────╯" `); }); // nested boxes — fit-content box with emojis on flex-direction row test("nested boxes - fit-content box with emojis on flex-direction row", async () => { const { lastFrame } = await render( defineComponent(() => () => ( 🦾 🌏 😋 )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭────╮ │╭──╮│ ││🦾││ │╰──╯│ │╭──╮│ ││🌏││ │╰──╯│ │╭──╮│ ││😋││ │╰──╯│ ╰────╯" `); }); // 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 () => { const { lastFrame } = await render( defineComponent(() => () => ( ミスター スポック カーク船長 )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭────────────╮ │╭──────────╮│ ││ミスター ││ │╰──────────╯│ │╭──────────╮│ ││スポック ││ │╰──────────╯│ │╭──────────╮│ ││カーク船長││ │╰──────────╯│ ╰────────────╯" `); }); // nested boxes — fit-content box with emojis on flex-direction column test("nested boxes - fit-content box with emojis on flex-direction column", async () => { const { lastFrame } = await render( defineComponent(() => () => ( 🦾 🌏 😋 )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭────╮ │╭──╮│ ││🦾││ │╰──╯│ │╭──╮│ ││🌏││ │╰──╯│ │╭──╮│ ││😋││ │╰──╯│ ╰────╯" `); }); // render border after update — reactive borderColor changes test("render border after update", async () => { const borderColor = shallowRef(undefined); const { lastFrame } = await render( defineComponent(() => () => ( Hello World )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │Hello World │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" `); borderColor.value = "green"; await nextTick(); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │Hello World │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" `); borderColor.value = undefined; await nextTick(); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │Hello World │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" `); }); // render border edge changes after update when borderStyle is unchanged test("render border edge changes after update when borderStyle is unchanged", async () => { const showTop = shallowRef(true); const { lastFrame } = await render( defineComponent(() => () => ( Content )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭───────╮ │Content│ ╰───────╯" `); showTop.value = false; await nextTick(); expect(lastFrame()).toMatchInlineSnapshot(` " Content ╰───────╯" `); showTop.value = true; await nextTick(); expect(lastFrame()).toMatchInlineSnapshot(` "╭───────╮ │Content│ ╰───────╯" `); }); // hide top border test("hide top border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above Content ╰───────╯ Below" `); }); // hide bottom border test("hide bottom border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭───────╮ Content Below" `); }); // hide top and bottom borders test("hide top and bottom borders", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above Content Below" `); }); // hide left border test("hide left border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ───────╮ Content│ ───────╯ Below" `); }); // hide right border test("hide right border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭─────── │Content ╰─────── Below" `); }); // hide left and right border test("hide left and right border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ─────── Content ─────── Below" `); }); // hide all borders test("hide all borders", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above Content Below" `); }); // change color of top border test("change color of top border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭───────╮ │Content│ ╰───────╯ Below" `); }); // change color of bottom border test("change color of bottom border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭───────╮ │Content│ ╰───────╯ Below" `); }); // change color of left border test("change color of left border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭───────╮ │Content│ ╰───────╯ Below" `); }); // change color of right border test("change color of right border", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭───────╮ │Content│ ╰───────╯ Below" `); }); // custom border style — uses "arrow" named style (same chars as the Ink custom object) test("custom border style", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Content )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "↘↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ →Content ← ↗↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" `); }); // dim border color test("dim border color", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Content )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │Content │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" `); }); // dim top border color test("dim top border color", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭───────╮ │Content│ ╰───────╯ Below" `); }); // dim bottom border color test("dim bottom border color", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭───────╮ │Content│ ╰───────╯ Below" `); }); // dim left border color test("dim left border color", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭───────╮ │Content│ ╰───────╯ Below" `); }); // dim right border color test("dim right border color", async () => { const { lastFrame } = await render( defineComponent(() => () => ( Above Content Below )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "Above ╭───────╮ │Content│ ╰───────╯ Below" `); }); // borderDimColor should not dim styled child Text touching left edge test("borderDimColor does not dim styled child Text touching left edge", async () => { const { lastFrame } = await render( defineComponent(() => () => ( styled text )), { columns: 100 }, ); expect(lastFrame()).toMatchInlineSnapshot(` "╭───────────╮ │styled text│ ╰───────────╯" `); });