Skip to content

Commit

Permalink
feat: add ticket-number question (#51)
Browse files Browse the repository at this point in the history
* feat: add ticket-number question
now users can configure a ticket-number question before the subject

ISSUES CLOSED: #50
  • Loading branch information
smollweide authored and leonardoanalista committed Mar 13, 2019
1 parent 4b569b8 commit a935f67
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 28 deletions.
12 changes: 11 additions & 1 deletion buildCommit.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ module.exports = function buildCommit(answers, config) {
return subject.trim();
}

function addTicketNumber(ticketNumber, config) {
if (!ticketNumber) {
return '';
}
if (config.ticketNumberPrefix) {
return config.ticketNumberPrefix + ticketNumber.trim() + ' ';
}
return ticketNumber.trim() + ' ';
}

function escapeSpecialChars(result) {
var specialChars = ['\`'];

Expand All @@ -38,7 +48,7 @@ module.exports = function buildCommit(answers, config) {
}

// Hard limit this line
var head = (answers.type + addScope(answers.scope) + addSubject(answers.subject)).slice(0, maxLineWidth);
var head = (answers.type + addScope(answers.scope) + addTicketNumber(answers.ticketNumber, config) + addSubject(answers.subject)).slice(0, maxLineWidth);

// Wrap these lines at 100 characters
var body = wrap(answers.body, wrapOptions) || '';
Expand Down
6 changes: 6 additions & 0 deletions cz-config-EXAMPLE.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ module.exports = {
{name: 'changeMe'}
],

allowTicketNumber: true,
isTicketNumberRequired: true,
ticketNumberPrefix: 'TICKET-',
ticketNumberRegExp: '\\d{1,5}',

// it needs to match the value for field type. Eg.: 'fix'
/*
scopeOverrides: {
Expand Down Expand Up @@ -55,4 +60,5 @@ module.exports = {
// limit subject length
subjectLimit: 100


};
37 changes: 37 additions & 0 deletions questions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict';


var fs = require('fs');
var path = require('path');
var buildCommit = require('./buildCommit');
var log = require('winston');

Expand All @@ -9,6 +11,23 @@ var isNotWip = function(answers) {
return answers.type.toLowerCase() !== 'wip';
};

var cwd = fs.realpathSync(process.cwd());
var packageData = require(path.join(cwd, 'package.json'));

function isValidateTicketNo(value, config) {
if (!value) {
return config.isTicketNumberRequired ? false : true;
}
if (!config.ticketNumberRegExp) {
return true;
}
var reg = new RegExp(config.ticketNumberRegExp);
if (value.replace(reg, '') !== '') {
return false;
}
return true;
}

module.exports = {

getQuestions: function(config, cz) {
Expand All @@ -21,6 +40,13 @@ module.exports = {
messages.type = messages.type || 'Select the type of change that you\'re committing:';
messages.scope = messages.scope || '\nDenote the SCOPE of this change (optional):';
messages.customScope = messages.customScope || 'Denote the SCOPE of this change:';
if (!messages.ticketNumber) {
if (config.ticketNumberRegExp) {
messages.ticketNumber = messages.ticketNumberPattern || 'Enter the ticket number following this pattern (' + config.ticketNumberRegExp + ')\n';
} else {
messages.ticketNumber = 'Enter the ticket number:\n';
}
}
messages.subject = messages.subject || 'Write a SHORT, IMPERATIVE tense description of the change:\n';
messages.body = messages.body || 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n';
messages.breaking = messages.breaking || 'List any BREAKING CHANGES (optional):\n';
Expand Down Expand Up @@ -77,6 +103,17 @@ module.exports = {
return answers.scope === 'custom';
}
},
{
type: 'input',
name: 'ticketNumber',
message: messages.ticketNumber,
when: function() {
return !!config.allowTicketNumber; // no ticket numbers allowed unless specifed
},
validate: function (value) {
return isValidateTicketNo(value, config);
}
},
{
type: 'input',
name: 'subject',
Expand Down
50 changes: 50 additions & 0 deletions spec/czCustomizableSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,54 @@ describe('cz-customizable', function() {
expect(commit).toHaveBeenCalledWith('feat(myScope): create a new cool feature\n\nBREAKING CHANGE:\nbreaking\n\nFIXES: my footer');
});

it('should call commit() function with ticket number', function() {
var answers = {
confirmCommit: 'yes',
type: 'feat',
scope: 'myScope',
subject: 'create a new cool feature',
ticketNumber: 'TICKET-1234'
};

var mockCz = getMockedCz(answers);
module.prompter(mockCz, commit);
expect(commit).toHaveBeenCalledWith('feat(myScope): TICKET-1234 create a new cool feature');
});

it('should call commit() function with ticket number and prefix', function() {

module.__set__({
// it mocks winston logging tool
log: {
info: function() {}
},

readConfigFile: function() {
return {
types: [{value: 'feat', name: 'feat: my feat'}],
scopes: [{name: 'myScope'}],
scopeOverrides: {
fix: [{name: 'fixOverride'}]
},
allowCustomScopes: true,
allowBreakingChanges: ['feat'],
breakingPrefix: 'WARNING:',
ticketNumberPrefix: 'TICKET-'
};
}
});

var answers = {
confirmCommit: 'yes',
type: 'feat',
scope: 'myScope',
subject: 'create a new cool feature',
ticketNumber: '1234'
};

var mockCz = getMockedCz(answers);
module.prompter(mockCz, commit);
expect(commit).toHaveBeenCalledWith('feat(myScope): TICKET-1234 create a new cool feature');
});

});
143 changes: 116 additions & 27 deletions spec/questionsSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ describe('cz-customizable', function() {
},
allowCustomScopes: true,
allowBreakingChanges: ['feat'],
allowTicketNumber: true,
isTicketNumberRequired: true,
ticketNumberPrefix: 'TICKET-',
ticketNumberRegExp: '\\d{1,5}',
subjectLimit: 20
};

Expand All @@ -48,33 +52,39 @@ describe('cz-customizable', function() {
expect(getQuestion(3).when({scope: false})).toEqual(false);
expect(getQuestion(3).when({scope: 'scope'})).toEqual(false);

// question 4 - SUBJECT
expect(getQuestion(4).name).toEqual('subject');
// question 4 - TICKET_NUMBER
expect(getQuestion(4).name).toEqual('ticketNumber');
expect(getQuestion(4).type).toEqual('input');
expect(getQuestion(4).message).toMatch(/IMPERATIVE tense description/);
expect(getQuestion(4).validate('good subject')).toEqual(true);
expect(getQuestion(4).validate('bad subject that exceed limit')).toEqual('Exceed limit: 20');
expect(getQuestion(4).filter('Subject')).toEqual('subject');
expect(getQuestion(4).message.indexOf('Enter the ticket number following this pattern')).toEqual(0);
expect(getQuestion(4).validate()).toEqual(false); //mandatory question

// question 5 - BODY
expect(getQuestion(5).name).toEqual('body');
// question 5 - SUBJECT
expect(getQuestion(5).name).toEqual('subject');
expect(getQuestion(5).type).toEqual('input');

// question 6 - BREAKING CHANGE
expect(getQuestion(6).name).toEqual('breaking');
expect(getQuestion(5).message).toMatch(/IMPERATIVE tense description/);
expect(getQuestion(5).filter('Subject')).toEqual('subject');
expect(getQuestion(5).validate('bad subject that exceed limit')).toEqual('Exceed limit: 20');
expect(getQuestion(5).validate('good subject')).toEqual(true);

// question 6 - BODY
expect(getQuestion(6).name).toEqual('body');
expect(getQuestion(6).type).toEqual('input');
expect(getQuestion(6).when({type: 'feat'})).toEqual(true);
expect(getQuestion(6).when({type: 'fix'})).toEqual(false);

// question 7 - FOOTER
expect(getQuestion(7).name).toEqual('footer');
// question 7 - BREAKING CHANGE
expect(getQuestion(7).name).toEqual('breaking');
expect(getQuestion(7).type).toEqual('input');
expect(getQuestion(7).when({type: 'fix'})).toEqual(true);
expect(getQuestion(7).when({type: 'WIP'})).toEqual(false);
expect(getQuestion(7).when({type: 'feat'})).toEqual(true);
expect(getQuestion(7).when({type: 'fix'})).toEqual(false);

// question 8 - FOOTER
expect(getQuestion(8).name).toEqual('footer');
expect(getQuestion(8).type).toEqual('input');
expect(getQuestion(8).when({type: 'fix'})).toEqual(true);
expect(getQuestion(8).when({type: 'WIP'})).toEqual(false);

//question 8, last one, CONFIRM COMMIT OR NOT
expect(getQuestion(8).name).toEqual('confirmCommit');
expect(getQuestion(8).type).toEqual('expand');
//question 9, last one, CONFIRM COMMIT OR NOT
expect(getQuestion(9).name).toEqual('confirmCommit');
expect(getQuestion(9).type).toEqual('expand');


var answers = {
Expand All @@ -83,15 +93,15 @@ describe('cz-customizable', function() {
scope: 'myScope',
subject: 'create a new cool feature'
};
expect(getQuestion(8).message(answers)).toMatch('Are you sure you want to proceed with the commit above?');
expect(getQuestion(9).message(answers)).toMatch('Are you sure you want to proceed with the commit above?');
});

it('default length limit of subject should be 100', function() {
config = {
types: [{value: 'feat', name: 'feat: my feat'}]
};
expect(getQuestion(4).validate('good subject')).toEqual(true);
expect(getQuestion(4).validate('bad subject that exceed limit bad subject that exceed limitbad subject that exceed limit test test test')).toEqual('Exceed limit: 100');
expect(getQuestion(5).validate('good subject')).toEqual(true);
expect(getQuestion(5).validate('bad subject that exceed limit bad subject that exceed limitbad subject that exceed limit test test test')).toEqual('Exceed limit: 100');
});


Expand All @@ -103,13 +113,13 @@ describe('cz-customizable', function() {
scopes: [{name: 'myScope'}],
allowBreakingChanges: ['fix']
};
expect(getQuestion(6).name).toEqual('breaking');
expect(getQuestion(7).name).toEqual('breaking');

var answers = {
type: 'feat'
};

expect(getQuestion(6).when(answers)).toEqual(false); // not allowed
expect(getQuestion(7).when(answers)).toEqual(false); // not allowed
});

it('should allow BREAKING CHANGE question when config property "allowBreakingChanges" specifies array of types and answer is one of those', function() {
Expand All @@ -118,13 +128,13 @@ describe('cz-customizable', function() {
scopes: [{name: 'myScope'}],
allowBreakingChanges: ['fix', 'feat']
};
expect(getQuestion(6).name).toEqual('breaking');
expect(getQuestion(7).name).toEqual('breaking');

var answers = {
type: 'feat'
};

expect(getQuestion(6).when(answers)).toEqual(true); // allowed
expect(getQuestion(7).when(answers)).toEqual(true); // allowed
});

});
Expand Down Expand Up @@ -153,5 +163,84 @@ describe('cz-customizable', function() {
});
});

describe('no TicketNumber question', function() {

it('should use scope override', function() {
config = {
types: [{value: 'feat', name: 'feat: my feat'}],
allowTicketNumber: false
};

// question 4 with
expect(getQuestion(4).name).toEqual('ticketNumber');
expect(getQuestion(4).when()).toEqual(false);
});
});

describe('TicketNumber', function() {

it('disable TicketNumber question', function() {
config = {
types: [{value: 'feat', name: 'feat: my feat'}],
allowTicketNumber: false
};

// question 4 with
expect(getQuestion(4).name).toEqual('ticketNumber');
expect(getQuestion(4).when()).toEqual(false);
});

it('custom message defined', function() {
config = {
types: [{value: 'feat', name: 'feat: my feat'}],
allowTicketNumber: true,
messages: {
ticketNumber: 'ticket number'
}
};

// question 4 with
expect(getQuestion(4).name).toEqual('ticketNumber');
expect(getQuestion(4).message).toEqual('ticket number');
});

describe('validation', function() {
it('invalid because empty and required', function() {
config = {
isTicketNumberRequired: true
};
expect(getQuestion(4).validate('')).toEqual(false);
});
it('empty but valid because optional', function() {
config = {
isTicketNumberRequired: false
};
expect(getQuestion(4).validate('')).toEqual(true);
});
it('valid because there is no regexp defined', function() {
config = {
isTicketNumberRequired: true,
ticketNumberRegExp: undefined
};
expect(getQuestion(4).validate('21234')).toEqual(true);
});
it('invalid because regexp don\'t match', function() {
config = {
isTicketNumberRequired: true,
ticketNumberRegExp: '\\d{1,5}'
};
expect(getQuestion(4).validate('sddsa')).toEqual(false);
});
it('valid because regexp match', function() {
config = {
isTicketNumberRequired: true,
ticketNumberRegExp: '\\d{1,5}'
};
expect(getQuestion(4).validate('12345')).toEqual(true);
});
});

});


});

0 comments on commit a935f67

Please sign in to comment.