feat(terminal): enhance terminal task rendering with progress, lifecycle helpers, and configurable output modes
This commit is contained in:
@@ -3,25 +3,6 @@ import * as smartrx from '@push.rocks/smartrx';
|
||||
|
||||
import * as smartcli from '../ts/index.js';
|
||||
|
||||
class TestWritable implements smartcli.ISmartcliWritable {
|
||||
public chunks: string[] = [];
|
||||
public isTTY: boolean;
|
||||
public columns = 80;
|
||||
|
||||
constructor(isTTYArg: boolean) {
|
||||
this.isTTY = isTTYArg;
|
||||
}
|
||||
|
||||
public write(chunkArg: string): boolean {
|
||||
this.chunks.push(chunkArg);
|
||||
return true;
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return this.chunks.join('');
|
||||
}
|
||||
}
|
||||
|
||||
tap.test('should create a new Smartcli', async () => {
|
||||
const smartCliTestObject = new smartcli.Smartcli();
|
||||
expect(smartCliTestObject).toBeInstanceOf(smartcli.Smartcli);
|
||||
@@ -55,64 +36,4 @@ tap.test('should accept a command', async () => {
|
||||
expect(hasExecuted).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('should render terminal tasks in non-interactive mode', async () => {
|
||||
const stream = new TestWritable(false);
|
||||
const terminal = new smartcli.SmartcliTerminal({ stream, interactive: false, colors: false });
|
||||
const task = terminal.createTask({ job: 'build package', rows: 2 });
|
||||
|
||||
task.update('running tsbuild');
|
||||
task.complete('done');
|
||||
|
||||
const output = stream.toString();
|
||||
expect(output).toInclude('[start] build package');
|
||||
expect(output).toInclude('[build package] running tsbuild');
|
||||
expect(output).toInclude('[ok] build package - done');
|
||||
expect(terminal.getTasks()).toHaveLength(0);
|
||||
});
|
||||
|
||||
tap.test('should render fixed rows in interactive mode', async () => {
|
||||
const stream = new TestWritable(true);
|
||||
const terminal = new smartcli.SmartcliTerminal({ stream, interactive: true, colors: false });
|
||||
const task = terminal.createTask({ job: 'install dependencies', rows: 2 });
|
||||
|
||||
task.update('fetching packages');
|
||||
|
||||
const renderedRows = task.renderPlainRows(80);
|
||||
expect(renderedRows).toHaveLength(2);
|
||||
expect(renderedRows[0]).toInclude('[run] install dependencies');
|
||||
expect(stream.toString()).toInclude('\u001B[2K');
|
||||
|
||||
task.complete('installed');
|
||||
|
||||
expect(stream.toString()).toInclude('[ok] install dependencies - installed');
|
||||
expect(terminal.getTasks()).toHaveLength(0);
|
||||
});
|
||||
|
||||
tap.test('should attach persistent terminal task errors', async () => {
|
||||
const stream = new TestWritable(true);
|
||||
const terminal = new smartcli.SmartcliTerminal({ stream, interactive: true, colors: false });
|
||||
const task = terminal.createTask({ job: 'deploy release', rows: 3 });
|
||||
|
||||
task.attachError('deployment failed', { keepOpen: true });
|
||||
|
||||
expect(task.status).toEqual('failed');
|
||||
expect(task.getErrorLines()).toContain('deployment failed');
|
||||
expect(task.renderPlainRows(80)[0]).toInclude('[err] deploy release');
|
||||
expect(terminal.getTasks()).toHaveLength(1);
|
||||
|
||||
terminal.clear();
|
||||
});
|
||||
|
||||
tap.test('should collapse failed terminal tasks into permanent output', async () => {
|
||||
const stream = new TestWritable(false);
|
||||
const terminal = new smartcli.SmartcliTerminal({ stream, interactive: false, colors: false });
|
||||
const task = terminal.createTask({ job: 'publish package' });
|
||||
|
||||
task.attachError('registry rejected package');
|
||||
|
||||
const output = stream.toString();
|
||||
expect(output).toInclude('[err] publish package - registry rejected package');
|
||||
expect(terminal.getTasks()).toHaveLength(0);
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
|
||||
Reference in New Issue
Block a user