import { defineComponent } from "vue";
import { test, expect } from "vite-plus/test";
import stripAnsi from "strip-ansi";
import stringWidth from "string-width";
import { renderToString, Box, Text } from "@vue-tui/runtime";
test("wide characters do not add extra space inside fixed-width Box", () => {
const output = renderToString(
defineComponent(() => () => (
๐
|
โณ
|
)),
{ columns: 100 },
);
const lines = output.split("\n");
expect(lines.length).toBe(2);
expect(lines[0]).toBe("๐|");
expect(lines[1]).toBe("โณ|");
});
test("CJK characters occupy correct width in fixed-width Box", () => {
const output = renderToString(
defineComponent(() => () => (
ไฝ ๅฅฝ
|
)),
{ columns: 100 },
);
expect(output).toBe("ไฝ ๅฅฝ|");
});
test("mixed ASCII and wide characters align correctly", () => {
const output = renderToString(
defineComponent(() => () => (
ab๐cd
|
abcdef
|
)),
{ columns: 100 },
);
const lines = output.split("\n");
expect(lines.length).toBe(2);
expect(lines[0]).toBe("ab๐cd|");
expect(lines[1]).toBe("abcdef|");
});
test("ANSI styled text does not affect layout width", () => {
const output = renderToString(
defineComponent(() => () => (
hello
|
)),
{ columns: 100 },
);
expect(stripAnsi(output)).toBe("hello|");
});
test("empty Text does not affect sibling layout", () => {
const output = renderToString(
defineComponent(() => () => (
hello
)),
{ columns: 100 },
);
expect(output).toBe("hello");
});
test("truncate CJK text at end", () => {
const output = renderToString(
defineComponent(() => () => (
ใใใใใใใใใใ|end
)),
{ columns: 100 },
);
expect(stringWidth(stripAnsi(output))).toBeLessThanOrEqual(20);
});
test("truncate CJK text in the middle", () => {
const output = renderToString(
defineComponent(() => () => (
ใใใใใใใใใใ|end
)),
{ columns: 100 },
);
expect(stringWidth(stripAnsi(output))).toBeLessThanOrEqual(20);
});
test("truncate CJK text at start", () => {
const output = renderToString(
defineComponent(() => () => (
ใใใใใใใใใใ|end
)),
{ columns: 100 },
);
expect(stringWidth(stripAnsi(output))).toBeLessThanOrEqual(20);
});
test("truncate CJK text does not exceed Box width", () => {
const output = renderToString(
defineComponent(() => () => (
ใใใใใใใใใใ|end
|
)),
{ columns: 100 },
);
const lines = output.split("\n");
expect(lines.length).toBe(1);
expect(stripAnsi(lines[0]!).endsWith("|")).toBe(true);
});
test("overlay on 2nd cell of CJK character clears the full character", () => {
const output = renderToString(
defineComponent(() => () => (
ใใใใใใใใใใ
XYZ
)),
{ columns: 20 },
);
const lines = output.split("\n");
expect(stringWidth(lines[0]!)).toBe(20);
expect(stripAnsi(lines[0]!)).toBe("ใใใใ XYZใใใใ");
});
test("overlay on 1st cell of CJK character clears trailing placeholder", () => {
const output = renderToString(
defineComponent(() => () => (
ใใใใใใใใใใ
X
)),
{ columns: 20 },
);
const lines = output.split("\n");
expect(stringWidth(lines[0]!)).toBe(20);
expect(stripAnsi(lines[0]!)).toBe("ใใใใใX ใใใใ");
});
test("CJK overlay on 2nd cell of CJK clears both sides", () => {
const output = renderToString(
defineComponent(() => () => (
ใใใใใใใใใใ
ๆผขๅญใในใ
)),
{ columns: 20 },
);
const lines = output.split("\n");
expect(stringWidth(lines[0]!)).toBe(20);
expect(stripAnsi(lines[0]!)).toBe("ใใ ๆผขๅญใในใ ใใ");
});
test("clipped empty write does not corrupt existing wide characters", () => {
const output = renderToString(
defineComponent(() => () => (
ใใ
Z
)),
{ columns: 4 },
);
expect(stripAnsi(output)).toBe("ใใ");
});