Skip to content

Commit

Permalink
Adds a NumberPrompt type for convenience when prompting for numbers(#654
Browse files Browse the repository at this point in the history
) (#663)
  • Loading branch information
CaAlden authored and SBoudrias committed May 14, 2018
1 parent 78bd4da commit 156e5b0
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/inquirer.js
Expand Up @@ -54,6 +54,7 @@ inquirer.createPromptModule = function(opt) {
promptModule.restoreDefaultPrompts = function() {
this.registerPrompt('list', require('./prompts/list'));
this.registerPrompt('input', require('./prompts/input'));
this.registerPrompt('number', require('./prompts/number'));
this.registerPrompt('confirm', require('./prompts/confirm'));
this.registerPrompt('rawlist', require('./prompts/rawlist'));
this.registerPrompt('expand', require('./prompts/expand'));
Expand Down
28 changes: 28 additions & 0 deletions lib/prompts/number.js
@@ -0,0 +1,28 @@
'use strict';
/**
* `input` type prompt
*/

var Input = require('./input');

/**
* Extention of the Input prompt specifically for use with number inputs.
*/

class NumberPrompt extends Input {
filterInput(input) {
if (input && typeof input === 'string') {
input = input.trim();
// Match a number in the input
let numberMatch = input.match(/(^-?\d+|^\d+\.\d*|^\d*\.\d+)(e\d+)?$/);
// If a number is found, return that input.
if (numberMatch) {
return Number(numberMatch[0]);
}
}
// If the input was invalid return the default value.
return this.opt.default == null ? NaN : this.opt.default;
}
}

module.exports = NumberPrompt;
5 changes: 5 additions & 0 deletions test/helpers/fixtures.js
Expand Up @@ -6,6 +6,11 @@ module.exports = {
name: 'name'
},

number: {
message: 'message',
name: 'name'
},

confirm: {
message: 'message',
name: 'name'
Expand Down
116 changes: 116 additions & 0 deletions test/specs/prompts/number.js
@@ -0,0 +1,116 @@
var expect = require('chai').expect;
var _ = require('lodash');
var ReadlineStub = require('../../helpers/readline');
var fixtures = require('../../helpers/fixtures');

var NumberPrompt = require('../../../lib/prompts/number');

const ACCEPTABLE_ERROR = 0.001;

describe('`number` prompt', function() {
beforeEach(function() {
this.fixture = _.clone(fixtures.number);
this.rl = new ReadlineStub();
this.number = new NumberPrompt(this.fixture, this.rl);
});

it('should parse the largest number', function(done) {
this.number.run().then(answer => {
expect(answer).to.equal(Number.MAX_SAFE_INTEGER);
done();
});

this.rl.emit('line', String(Number.MAX_SAFE_INTEGER));
});

it('should parse the smallest number', function(done) {
this.number.run().then(answer => {
expect(answer).to.equal(Number.MIN_SAFE_INTEGER);
done();
});

this.rl.emit('line', String(Number.MIN_SAFE_INTEGER));
});

it('should parse an integer', function(done) {
this.number.run().then(answer => {
expect(answer).to.equal(42);
done();
});

this.rl.emit('line', '42');
});

it('should parse negative numbers', function(done) {
this.number.run().then(answer => {
expect(answer).to.equal(-363);
done();
});

this.rl.emit('line', '-363');
});

it('should parse a regular float', function(done) {
this.number.run().then(answer => {
expect(answer).to.be.closeTo(4353.43, ACCEPTABLE_ERROR);
done();
});

this.rl.emit('line', '4353.43');
});

it('should parse a float with no digits before the decimal', function(done) {
this.number.run().then(answer => {
expect(answer).to.be.closeTo(0.01264, ACCEPTABLE_ERROR);
done();
});

this.rl.emit('line', '.01264');
});

it('should parse a float with no digits after the decimal', function(done) {
this.number.run().then(answer => {
expect(answer).to.be.closeTo(1234.0, ACCEPTABLE_ERROR);
done();
});

this.rl.emit('line', '1234.');
});

it('should parse a float with exponents', function(done) {
this.number.run().then(answer => {
expect(answer).to.be.closeTo(534e12, ACCEPTABLE_ERROR);
done();
});

this.rl.emit('line', '534e12');
});

it('should parse any other string as NaN', function(done) {
this.number.run().then(answer => {
expect(answer).to.be.NaN; // eslint-disable-line no-unused-expressions
done();
});

this.rl.emit('line', 'The cat');
});

it('should parse the empty string as NaN', function(done) {
this.number.run().then(answer => {
expect(answer).to.be.NaN; // eslint-disable-line no-unused-expressions
done();
});

this.rl.emit('line', '');
});

it('should return default value if it is set on a bad input', function(done) {
this.number.opt.default = 11;
this.number.run().then(answer => {
expect(answer).to.equal(11);
done();
});

this.rl.emit('line', '');
});
});

0 comments on commit 156e5b0

Please sign in to comment.