hardening and bugfixing prior to stable release
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* The variable form, on a terminal that reports no size.
|
||||
*
|
||||
* This is the one case that cannot be tested from inside a vitest worker: there
|
||||
* is no TTY there for enquirer to misread, so the mocked tests in
|
||||
* `prompts.test.ts` prove only that `rows` is *passed*, never that passing it
|
||||
* matters. Here a real pty is opened at 0x0 — `pty.fork()`'s own default, and
|
||||
* what `script -q` and some CI terminals report — and a real form is answered
|
||||
* through it.
|
||||
*
|
||||
* Measured both ways while writing this: with `terminalSize()` removed from
|
||||
* `nopy.prompts.ts`, the form never renders and the driver times out with
|
||||
* nothing on the wire.
|
||||
*
|
||||
* Needs `python3` for the pty; skipped, loudly, where there is none.
|
||||
*/
|
||||
|
||||
import { execFileSync, spawnSync } from 'node:child_process';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
const EXPECT_PY = fileURLToPath(new URL('../../../scripts/expect.py', import.meta.url));
|
||||
const TSX = fileURLToPath(new URL('../node_modules/.bin/tsx', import.meta.url));
|
||||
const PROBE = fileURLToPath(new URL('./fixtures/form-probe.ts', import.meta.url));
|
||||
|
||||
const hasPython = spawnSync('python3', ['--version']).status === 0;
|
||||
|
||||
/** Down arrow — how the form moves from one field to the next. */
|
||||
const DOWN = '\u001b[B';
|
||||
|
||||
const STEPS = [
|
||||
{ expect: 'ALPHA', send: 'alpha-typed', settle: 0.6 },
|
||||
{ send: DOWN, settle: 0.4 },
|
||||
{ send: 'beta-typed', settle: 0.4 },
|
||||
{ send: '\r', settle: 1.2 },
|
||||
];
|
||||
|
||||
describe.skipIf(!hasPython)('variable form over a pty', () => {
|
||||
let tmpDir: string;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nopy-pty-'));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
/** Answers the probe form on a pty of the given size; returns what it assigned. */
|
||||
const answerForm = (rows: number, cols: number) => {
|
||||
const stepsPath = path.join(tmpDir, 'steps.json');
|
||||
const logPath = path.join(tmpDir, 'session.log');
|
||||
fs.writeFileSync(stepsPath, JSON.stringify(STEPS));
|
||||
|
||||
execFileSync('python3', [EXPECT_PY, stepsPath, '--', TSX, PROBE], {
|
||||
env: {
|
||||
...process.env,
|
||||
PTY_ROWS: String(rows),
|
||||
PTY_COLS: String(cols),
|
||||
EXPECT_TIMEOUT: '60',
|
||||
EXPECT_LOG: logPath,
|
||||
},
|
||||
stdio: 'pipe',
|
||||
});
|
||||
|
||||
const transcript = fs.readFileSync(logPath, 'utf-8').replace(/\r/g, '');
|
||||
const line = transcript.split('\n').find((l) => l.startsWith('NOPY_PROBE '));
|
||||
return line ? JSON.parse(line.slice('NOPY_PROBE '.length)) : undefined;
|
||||
};
|
||||
|
||||
it('collects every field on a terminal reporting 0x0', () => {
|
||||
expect(answerForm(0, 0)).toEqual({ ALPHA: 'alpha-typed', BETA: 'beta-typed' });
|
||||
}, 90_000);
|
||||
});
|
||||
Reference in New Issue
Block a user