UNPKG

@inquirer/testing

Version:
72 lines (71 loc) 2.5 kB
import { Stream } from 'node:stream'; import { stripVTControlCharacters } from 'node:util'; import MuteStream from 'mute-stream'; import ansiEscapes from 'ansi-escapes'; const ignoredAnsi = new Set([ansiEscapes.cursorHide, ansiEscapes.cursorShow]); class BufferedStream extends Stream.Writable { #_fullOutput = ''; #_chunks = []; #_rawChunks = []; _write(chunk, _encoding, callback) { const str = chunk.toString(); this.#_fullOutput += str; // There's some ANSI Inquirer just send to keep state of the terminal clear; we'll ignore those since they're // unlikely to be used by end users or part of prompt code. if (!ignoredAnsi.has(str)) { this.#_rawChunks.push(str); } // Stripping the ANSI codes here because Inquirer will push commands ANSI (like cursor move.) // This is probably fine since we don't care about those for testing; but this could become // an issue if we ever want to test for those. if (stripVTControlCharacters(str).trim().length > 0) { this.#_chunks.push(str); } callback(); } getLastChunk({ raw }) { const chunks = raw ? this.#_rawChunks : this.#_chunks; const lastChunk = chunks.at(-1); return lastChunk ?? ''; } getFullOutput() { return this.#_fullOutput; } } export async function render(prompt, props, options) { const input = new MuteStream(); input.unmute(); const output = new BufferedStream(); const answer = prompt(props, { input, output, ...options }); // Wait for event listeners to be ready await Promise.resolve(); await Promise.resolve(); const events = { keypress(key) { if (typeof key === 'string') { input.emit('keypress', null, { name: key }); } else { input.emit('keypress', null, key); } }, type(text) { input.write(text); for (const char of text) { input.emit('keypress', null, { name: char }); } }, }; return { answer, input, events, getScreen: ({ raw } = {}) => { const lastScreen = output.getLastChunk({ raw: Boolean(raw) }); return raw ? lastScreen : stripVTControlCharacters(lastScreen).trim(); }, getFullOutput: () => { return output.getFullOutput(); }, }; }