UNPKG

@inquirer/testing

Version:
67 lines (66 loc) 2.19 kB
import { Stream } from 'node:stream'; import { stripVTControlCharacters } from 'node:util'; import MuteStream from 'mute-stream'; class BufferedStream extends Stream.Writable { #_fullOutput = ''; #_chunks = []; #_rawChunks = []; _write(chunk, _encoding, callback) { const str = chunk.toString(); this.#_fullOutput += str; // Keep track of every chunk send through. 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, config, options) { const input = new MuteStream(); input.unmute(); const output = new BufferedStream(); const answer = prompt(config, { 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(); }, }; }