current commit
260924.1 · feat: add ncu-ci resume command (#1187)
import { describe, it, beforeEach, afterEach } from 'node:test';
import assert from 'node:assert';

import CLI from '../../lib/cli.js';
import * as figures from '../../lib/figures.js';

import LogStream from '../fixtures/log_stream.js';

function strip(text) {
  // eslint-disable-next-line
  return text.replace(/\u001b\[.*?m/g, '');
}

const warning = strip(figures.warning);
const error = strip(figures.error);
const info = strip(figures.info);
const success = strip(figures.success);

describe('cli', () => {
  let cli = null;
  let stream = null;

  const logResult = () => strip(stream.toString());

  describe('instantiation', () => {
    it('should set `process.stderr` as stream if no stream is specified',
      () => {
        cli = new CLI();
        assert.strictEqual(cli.stream, process.stderr);

        cli.setFigureIndent(2);
        assert.strictEqual(cli.figureIndent, '  ');
      });
  });

  describe('methods', () => {
    beforeEach(() => {
      stream = new LogStream();
      cli = new CLI(stream);
    });

    describe('spinners', () => {
      beforeEach(() => {
        stream = new LogStream();
        cli = new CLI(stream);
        cli.startSpinner('foo');
      });

      it('should set the text and start the spinner', () => {
        assert.strictEqual(cli.spinner.text, 'foo');
      });

      it('should update the spinner text', () => {
        cli.updateSpinner('bar');
        assert.strictEqual(cli.spinner.text, 'bar');
      });

      it('prints the result after a nested operation has stopped the spinner', () => {
        cli.stopSpinner('Data downloaded');
        cli.stopSpinner('Refusing to resume CI', cli.SPINNER_STATUS.FAILED);
        assert.ok(logResult().endsWith(
          `${success}  Data downloaded\n${error}  Refusing to resume CI\n`));
      });

      afterEach(() => {
        cli.stopSpinner('stop', 'info');
      });
    });

    describe('write', () => {
      beforeEach(() => {
        stream = new LogStream();
        cli = new CLI(stream);
      });
      it('should write in stream', () => {
        const stream = new LogStream();
        const cli = new CLI(stream);
        cli.write('Getting commits...');
        assert.strictEqual(strip(stream.toString()), 'Getting commits...');
      });
    });

    describe('log', () => {
      beforeEach(() => {
        stream = new LogStream();
        cli = new CLI(stream);
      });
      it('should write in stream', () => {
        cli.log('Getting commits...');
        assert.strictEqual(logResult(), 'Getting commits...\n');
      });
    });

    describe('table', () => {
      beforeEach(() => {
        stream = new LogStream();
        cli = new CLI(stream);
      });
      it('should print the first element with bold style and padding', () => {
        cli.table('Title', 'description');
        assert.strictEqual(logResult(),
          'Title      description\n');
      });
    });

    describe('separator', () => {
      beforeEach(() => {
        stream = new LogStream();
        cli = new CLI(stream);
      });
      it('should print a separator line with the specified text', () => {
        cli.separator('Separator');
        assert.strictEqual(
          logResult(),
          '---------------------------------- Separator' +
            ' -----------------------------------\n');
      });

      it('should print a separator line with a custom separator', () => {
        cli.separator('PR', 20, '+');
        assert.strictEqual(
          logResult(),
          '++++++++ PR ++++++++\n');
      });

      it('should print a separator line without text', () => {
        cli.separator();
        assert.strictEqual(
          logResult(),
          '-------------------------------------------------------' +
            '-------------------------\n');
      });
    });

    describe('ok', () => {
      beforeEach(() => {
        stream = new LogStream();
        cli = new CLI(stream);
      });
      it('should print a success message', () => {
        cli.ok('Perfect!');
        assert.strictEqual(logResult(), `   ${success}  Perfect!\n`);
      });

      it('should print a success message in a new line if specified', () => {
        cli.ok('Perfect!', { newline: true });
        assert.strictEqual(logResult(),
          `\n   ${success}  Perfect!\n`);
      });
    });

    describe('warn', () => {
      beforeEach(() => {
        stream = new LogStream();
        cli = new CLI(stream);
      });
      it('should print a warning message', () => {
        cli.warn('Warning!');
        assert.strictEqual(logResult(), `   ${warning}  Warning!\n`);
      });

      it('should print a warning message in a new line if specified', () => {
        cli.warn('Warning!', { newline: true });
        assert.strictEqual(logResult(),
          `\n   ${warning}  Warning!\n`);
      });
    });

    describe('info', () => {
      beforeEach(() => {
        stream = new LogStream();
        cli = new CLI(stream);
      });
      it('should print an info message', () => {
        cli.info('Info!');
        assert.strictEqual(logResult(), `   ${info}  Info!\n`);
      });

      it('should print an info message in a new line if specified', () => {
        cli.info('Info!', { newline: true });
        assert.strictEqual(logResult(), `\n   ${info}  Info!\n`);
      });
    });

    describe('error', () => {
      beforeEach(() => {
        stream = new LogStream();
        cli = new CLI(stream);
      });
      it('should print an error message', () => {
        cli.error('Error!');
        assert.strictEqual(logResult(), `   ${error}  Error!\n`);
      });

      it('should print an error message in a new line if specified', () => {
        cli.error('Error!', { newline: true });
        assert.strictEqual(logResult(), `\n   ${error}  Error!\n`);
      });

      it('should print an error message', () => {
        cli.error(new Error('Error!'));
        assert.ok(logResult().startsWith(`   ${error}  Error!\n`));
      });

      it('should print an error message in a new line if specified', () => {
        cli.error(new Error('Error!'), { newline: true });
        assert.ok(logResult().startsWith(`\n   ${error}  Error!\n`));
      });
    });
  });

  describe('prompt cares about spinner', () => {
    beforeEach(() => {
      stream = new LogStream();
      cli = new CLI(stream, {
        spinner: { isEnabled: true }
      });
      cli.setAssumeYes();
    });

    it('pauses when prompt a question', async() => {
      cli.startSpinner('foo');
      assert.deepEqual(cli.spinner.text, 'foo');
      assert.deepEqual(cli.spinner.isSpinning, true);
      await cli.prompt('So you think darkness is your ally?', {
        defaultAnswer: 'Yes, I was born in it. Molded by it.',
        questionType: cli.QUESTION_TYPE.INPUT
      });
      assert.strictEqual(cli.spinner.isSpinning, true);
      cli.stopSpinner('foo');
    });
  });

  describe('prompt assume yes', () => {
    beforeEach(() => {
      stream = new LogStream();
      cli = new CLI(stream);
      cli.setAssumeYes();
    });

    it('rejects when no default answer is provided for \'input\' type', () => {
      return assert.rejects(async() => {
        await cli.prompt('What is your favorite color', {
          questionType: cli.QUESTION_TYPE.INPUT
        });
      }, /defaultAnswer must be provided for non-confirmation prompts/);
    });

    it('rejects when no default answer is provided for \'number\' type', () => {
      return assert.rejects(async() => {
        await cli.prompt('Pick a number from 1-10', {
          questionType: cli.QUESTION_TYPE.NUMBER
        });
      }, /defaultAnswer must be provided for non-confirmation prompts/);
    });

    it('should return the default answer for an \'input\' type', async() => {
      assert.strictEqual(await cli.prompt('What is your favorite color', {
        defaultAnswer: 'blue',
        questionType: cli.QUESTION_TYPE.INPUT
      }), 'blue');
    });

    it('should return the default answer for a \'number\' type', async() => {
      assert.strictEqual(await cli.prompt('Pick a number from 1-10', {
        defaultAnswer: 10,
        questionType: cli.QUESTION_TYPE.NUMBER
      }), 10);
    });

    it('should return true if no default is given', async() => {
      assert.strictEqual(await cli.prompt('Question?'), true);
    });

    it('should return true if default is set to true', async() => {
      assert.strictEqual(await cli.prompt('Question?', {
        defaultAnswer: true
      }), true);
    });

    it('should return false if default is set to false', async() => {
      assert.strictEqual(await cli.prompt('Question?', {
        defaultAnswer: false
      }), false);
    });
  });
});