f847e17c81
Follow-up cleanup for the 7 confirmed findings from a review of #163. The dominant theme: #163 hard-renamed the public composable useTerminalSize -> useWindowSize (no alias) but left stale references to the dead name in user-facing docs. - README.md + packages/runtime/README.md: the composable tables named the removed `useTerminalSize()` (root README even framed the sole real export `useWindowSize` as an "Ink-compat alias" — now inverted). Point both at `useWindowSize()`. - .agents/docs/ink-divergences.md: two vue-tui-side references to `useTerminalSize` (the shallowRef "object of refs" example and the "composables throw outside a render tree" list) -> `useWindowSize`. The Ink-side `useWindowSize -> WindowSize` naming example is left unchanged. - .agents/docs/accessibility-api.md: the intro cited three "blessed entries" but only aria-camelCase is one; `renderToString` layout-only and the `useWindowSize` name are now Ink parity, not divergences. Reword. - .agents/docs/api-contract.md: tighten the `/internal` wording — the test does assert one tripwire on `/internal`, so "not covered by public-api.test.ts" was imprecise. - public-api.test.ts / render-to-string.test.tsx: the public renderToString dropped the `isScreenReaderEnabled` option but (unlike the sibling `ScreenReaderOptions` type) had no compile-time guard. Replace an obscure, fmt-fragile type-indexing guard with a readable call-site `@ts-expect-error` in render-to-string.test.tsx; re-adding the option to the public RenderToStringOptions makes the directive unused and fails `tsc --noEmit`. - Rename terminal-size.test.tsx / .sequential.test.tsx -> window-size.test.tsx / .sequential.test.tsx to match the migrated symbol. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
87 lines
3.3 KiB
TypeScript
87 lines
3.3 KiB
TypeScript
// Sequential: mutates process-global state — process.env.COLUMNS/LINES and
|
|
// process.stdout/process.stderr columns+rows. The terminal-size package (used by
|
|
// resolveSize's fallback) reads these globals directly, so a concurrent sibling
|
|
// would perturb the result. Tests restore every mutated prop in a finally block.
|
|
|
|
import { PassThrough } from "node:stream";
|
|
import process from "node:process";
|
|
import { defineComponent } from "vue";
|
|
import { expect, test } from "vite-plus/test";
|
|
import { createApp, Text, useWindowSize } from "@vue-tui/runtime";
|
|
|
|
function makeTtyStream(columns: number): NodeJS.WriteStream {
|
|
const s = new PassThrough() as unknown as NodeJS.WriteStream;
|
|
// Deliberately no `rows` — forces resolveSize() into the terminal-size fallback.
|
|
Object.assign(s, { columns, isTTY: true });
|
|
return s;
|
|
}
|
|
|
|
function makeFakeStdin(): NodeJS.ReadStream {
|
|
const s = new PassThrough() as unknown as NodeJS.ReadStream;
|
|
Object.assign(s, {
|
|
isTTY: true,
|
|
setRawMode() {
|
|
return s;
|
|
},
|
|
setEncoding() {
|
|
return s;
|
|
},
|
|
});
|
|
(s as unknown as { ref: () => void }).ref = () => {};
|
|
(s as unknown as { unref: () => void }).unref = () => {};
|
|
return s;
|
|
}
|
|
|
|
// Mirrors Ink terminal-resize.tsx:110-152 ("falls back to terminal-size rows
|
|
// when stdout.rows is missing"). With the mount stdout reporting columns 0 and
|
|
// no rows, resolveSize() calls terminal-size, which — after we zero out the real
|
|
// process.stdout/stderr dimensions — resolves rows from process.env.LINES.
|
|
test.sequential("useWindowSize falls back to terminal-size rows from env.LINES when stdout.rows is missing", async () => {
|
|
const stdout = makeTtyStream(0);
|
|
const stderr = makeTtyStream(0);
|
|
const stdin = makeFakeStdin();
|
|
|
|
const originalColumns = process.env.COLUMNS;
|
|
const originalLines = process.env.LINES;
|
|
const originalStdoutColumns = process.stdout.columns;
|
|
const originalStdoutRows = process.stdout.rows;
|
|
const originalStderrColumns = process.stderr.columns;
|
|
const originalStderrRows = process.stderr.rows;
|
|
|
|
let capturedRows = -1;
|
|
const App = defineComponent(() => {
|
|
const { rows } = useWindowSize();
|
|
capturedRows = rows.value;
|
|
return () => <Text>{String(rows.value)}</Text>;
|
|
});
|
|
|
|
const app = createApp(App);
|
|
try {
|
|
// terminal-size prefers process.stdout/stderr dimensions, then env.
|
|
// Zero the real streams so env.COLUMNS/LINES is the winning source.
|
|
process.env.COLUMNS = "123";
|
|
process.env.LINES = "45";
|
|
process.stdout.columns = 0;
|
|
process.stdout.rows = 0;
|
|
process.stderr.columns = 0;
|
|
process.stderr.rows = 0;
|
|
|
|
app.mount({ stdout, stdin, stderr, debug: true, exitOnCtrlC: false });
|
|
await new Promise<void>((r) => setTimeout(r, 60));
|
|
|
|
expect(capturedRows).toBe(45);
|
|
} finally {
|
|
app.unmount();
|
|
// Restore env precisely: a var that was ABSENT must be DELETED, not set to
|
|
// the string "undefined" (which would pollute later tests' CI/size detection).
|
|
if (originalColumns === undefined) delete process.env.COLUMNS;
|
|
else process.env.COLUMNS = originalColumns;
|
|
if (originalLines === undefined) delete process.env.LINES;
|
|
else process.env.LINES = originalLines;
|
|
process.stdout.columns = originalStdoutColumns;
|
|
process.stdout.rows = originalStdoutRows;
|
|
process.stderr.columns = originalStderrColumns;
|
|
process.stderr.rows = originalStderrRows;
|
|
}
|
|
});
|