Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add ticket-number question #51

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
leonardoanalista marked this conversation as resolved.
Show resolved Hide resolved

// 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 @@ -50,4 +55,5 @@ module.exports = {
allowCustomScopes: true,
allowBreakingChanges: ['feat', 'fix']


};
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 @@ -20,6 +39,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 folloing this patter (' + 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 @@ -76,6 +102,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');
leonardoanalista marked this conversation as resolved.
Show resolved Hide resolved
});

});
135 changes: 112 additions & 23 deletions spec/questionsSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ describe('cz-customizable', function() {
fix: [{name: 'fixOverride'}]
},
allowCustomScopes: true,
allowBreakingChanges: ['feat']
allowBreakingChanges: ['feat'],
allowTicketNumber: true,
isTicketNumberRequired: true,
ticketNumberPrefix: 'TICKET-',
ticketNumberRegExp: '\\d{1,5}'
};

// question 1 - TYPE
Expand All @@ -47,32 +51,38 @@ 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).message.indexOf('Enter the ticket number folloing this patter')).toEqual(0);
expect(getQuestion(4).validate()).toEqual(false); //mandatory question
expect(getQuestion(4).filter('Subject')).toEqual('subject');

// question 5 - BODY
expect(getQuestion(5).name).toEqual('body');
// question 5 - SUBJECT
expect(getQuestion(5).name).toEqual('subject');
expect(getQuestion(5).type).toEqual('input');
expect(getQuestion(5).message).toMatch(/IMPERATIVE tense description/);
expect(getQuestion(5).validate()).toEqual(false); //mandatory question
expect(getQuestion(5).filter('Subject')).toEqual('subject');

// question 6 - BREAKING CHANGE
expect(getQuestion(6).name).toEqual('breaking');
// 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, last one, CONFIRM COMMIT OR NOT
expect(getQuestion(8).name).toEqual('confirmCommit');
expect(getQuestion(8).type).toEqual('expand');
// 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 9, last one, CONFIRM COMMIT OR NOT
expect(getQuestion(9).name).toEqual('confirmCommit');
expect(getQuestion(9).type).toEqual('expand');


var answers = {
Expand All @@ -81,7 +91,7 @@ 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?');
});


Expand All @@ -93,13 +103,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 @@ -108,13 +118,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 @@ -143,5 +153,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);
});
});

});


});