From 0022c5cc49c5a24773e986cf5b7cccaad8ca48b7 Mon Sep 17 00:00:00 2001 From: Yunfei He Date: Wed, 27 May 2026 13:25:33 +0800 Subject: [PATCH] test: alternate screen guard condition tests Co-Authored-By: Claude Opus 4.7 (1M context) --- .../lifecycle/alternate-screen.test.tsx | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 packages/runtime-tests/integration/lifecycle/alternate-screen.test.tsx diff --git a/packages/runtime-tests/integration/lifecycle/alternate-screen.test.tsx b/packages/runtime-tests/integration/lifecycle/alternate-screen.test.tsx new file mode 100644 index 0000000..11c2fe1 --- /dev/null +++ b/packages/runtime-tests/integration/lifecycle/alternate-screen.test.tsx @@ -0,0 +1,121 @@ +import { defineComponent, nextTick } from "vue"; +import { expect, test } from "vite-plus/test"; +import { createApp, Text } from "@vue-tui/runtime"; +import ansiEscapes from "ansi-escapes"; +import { PassThrough } from "node:stream"; + +function makeTtyStream(options?: { isTTY?: boolean }) { + const stream = new PassThrough() as unknown as NodeJS.WriteStream & { chunks: string[] }; + Object.assign(stream, { isTTY: options?.isTTY ?? true, columns: 80, rows: 24 }); + stream.chunks = []; + (stream as unknown as PassThrough).on("data", (chunk: Buffer) => + stream.chunks.push(chunk.toString()), + ); + return stream; +} + +function makeFakeStdin() { + const stdin = new PassThrough() as unknown as NodeJS.ReadStream; + Object.assign(stdin, { + isTTY: true, + setRawMode() { + return stdin; + }, + ref() {}, + unref() {}, + setEncoding() { + return stdin; + }, + }); + return stdin; +} + +const App = defineComponent(() => () => Hello); + +test("alternate screen - disabled by default", async () => { + const stdout = makeTtyStream(); + const stdin = makeFakeStdin(); + + const app = createApp(App); + app.mount({ stdout, stdin, stderr: makeTtyStream(), interactive: true, exitOnCtrlC: false }); + await nextTick(); + + const exited = app.waitUntilExit(); + app.unmount(); + await exited; + + const output = stdout.chunks.join(""); + expect(output).not.toContain(ansiEscapes.enterAlternativeScreen); + expect(output).not.toContain(ansiEscapes.exitAlternativeScreen); +}); + +test("alternate screen - ignored when non-interactive", async () => { + const stdout = makeTtyStream(); + const stdin = makeFakeStdin(); + + const app = createApp(App); + app.mount({ + stdout, + stdin, + stderr: makeTtyStream(), + alternateScreen: true, + interactive: false, + exitOnCtrlC: false, + }); + await nextTick(); + + const exited = app.waitUntilExit(); + app.unmount(); + await exited; + + const output = stdout.chunks.join(""); + expect(output).not.toContain(ansiEscapes.enterAlternativeScreen); + expect(output).not.toContain(ansiEscapes.exitAlternativeScreen); +}); + +test("alternate screen - ignored when isTTY is false", async () => { + const stdout = makeTtyStream({ isTTY: false }); + const stdin = makeFakeStdin(); + + const app = createApp(App); + app.mount({ + stdout, + stdin, + stderr: makeTtyStream(), + alternateScreen: true, + exitOnCtrlC: false, + }); + await nextTick(); + + const exited = app.waitUntilExit(); + app.unmount(); + await exited; + + const output = stdout.chunks.join(""); + expect(output).not.toContain(ansiEscapes.enterAlternativeScreen); + expect(output).not.toContain(ansiEscapes.exitAlternativeScreen); +}); + +test("alternate screen - ignored when isTTY is false even if interactive is true", async () => { + const stdout = makeTtyStream({ isTTY: false }); + const stdin = makeFakeStdin(); + + const app = createApp(App); + app.mount({ + stdout, + stdin, + stderr: makeTtyStream(), + alternateScreen: true, + interactive: true, + exitOnCtrlC: false, + }); + await nextTick(); + + const exited = app.waitUntilExit(); + app.unmount(); + await exited; + + const output = stdout.chunks.join(""); + expect(output).not.toContain(ansiEscapes.enterAlternativeScreen); + expect(output).not.toContain(ansiEscapes.exitAlternativeScreen); +});