UNPKG

10.3 kBJavaScriptView Raw
1/* eslint-disable nada/path-case */
2const fs = require('fs');
3const questions = require('../questions.js');
4
5describe('cz-customizable', () => {
6 let config;
7
8 beforeEach(() => {
9 config = null;
10 });
11
12 const mockedCz = {
13 // Separator: jasmine.createSpy(),
14 // Separator: jest.fn().mockReturnValue(null),
15 Separator: jest.fn(),
16 // Separator: () => '',
17 };
18
19 const getQuestion = number => questions.getQuestions(config, mockedCz)[number - 1];
20
21 it('should array of questions be returned', () => {
22 config = {
23 types: [{ value: 'feat', name: 'feat: my feat' }],
24 scopes: [{ name: 'myScope' }],
25 scopeOverrides: {
26 fix: [{ name: 'fixOverride' }],
27 },
28 allowCustomScopes: true,
29 allowBreakingChanges: ['feat'],
30 allowTicketNumber: true,
31 isTicketNumberRequired: true,
32 ticketNumberPrefix: 'TICKET-',
33 ticketNumberRegExp: '\\d{1,5}',
34 subjectLimit: 40,
35 };
36
37 // question 1 - TYPE
38 expect(getQuestion(1).name).toEqual('type');
39 expect(getQuestion(1).type).toEqual('list');
40 expect(getQuestion(1).choices[0]).toEqual({
41 value: 'feat',
42 name: 'feat: my feat',
43 });
44
45 // question 2 - SCOPE
46 expect(getQuestion(2).name).toEqual('scope');
47 expect(getQuestion(2).choices({})[0]).toEqual({ name: 'myScope' });
48 expect(getQuestion(2).choices({ type: 'fix' })[0]).toEqual({
49 name: 'fixOverride',
50 }); // should override scope
51 expect(getQuestion(2).when({ type: 'fix' })).toEqual(true);
52 expect(getQuestion(2).when({ type: 'WIP' })).toEqual(false);
53 expect(getQuestion(2).when({ type: 'wip' })).toEqual(false);
54
55 // question 3 - SCOPE CUSTOM
56 expect(getQuestion(3).name).toEqual('scope');
57 expect(getQuestion(3).when({ scope: 'custom' })).toEqual(true);
58 expect(getQuestion(3).when({ scope: false })).toEqual(false);
59 expect(getQuestion(3).when({ scope: 'scope' })).toEqual(false);
60
61 // question 4 - TICKET_NUMBER
62 expect(getQuestion(4).name).toEqual('ticketNumber');
63 expect(getQuestion(4).type).toEqual('input');
64 expect(getQuestion(4).message.indexOf('Enter the ticket number following this pattern')).toEqual(0);
65 expect(getQuestion(4).validate()).toEqual(false); // mandatory question
66
67 // question 5 - SUBJECT
68 expect(getQuestion(5).name).toEqual('subject');
69 expect(getQuestion(5).type).toEqual('input');
70 // expect(getQuestion(5).default).toEqual(null);
71 expect(getQuestion(5).message).toMatch(/IMPERATIVE tense description/);
72 expect(getQuestion(5).filter('Subject')).toEqual('subject');
73 expect(getQuestion(5).validate('bad subject that exceed limit for 6 characters')).toEqual('Exceed limit: 40');
74 expect(getQuestion(5).validate('good subject')).toEqual(true);
75
76 // question 6 - BODY
77 expect(getQuestion(6).name).toEqual('body');
78 expect(getQuestion(6).type).toEqual('input');
79 expect(getQuestion(6).default).toEqual(null);
80
81 // question 7 - BREAKING CHANGE
82 expect(getQuestion(7).name).toEqual('breaking');
83 expect(getQuestion(7).type).toEqual('input');
84 expect(getQuestion(7).when({ type: 'feat' })).toEqual(true);
85 expect(getQuestion(7).when({ type: 'fix' })).toEqual(false);
86
87 // question 8 - FOOTER
88 expect(getQuestion(8).name).toEqual('footer');
89 expect(getQuestion(8).type).toEqual('input');
90 expect(getQuestion(8).when({ type: 'fix' })).toEqual(true);
91 expect(getQuestion(8).when({ type: 'WIP' })).toEqual(false);
92
93 // question 9, last one, CONFIRM COMMIT OR NOT
94 expect(getQuestion(9).name).toEqual('confirmCommit');
95 expect(getQuestion(9).type).toEqual('expand');
96
97 const answers = {
98 confirmCommit: 'yes',
99 type: 'feat',
100 scope: 'myScope',
101 subject: 'create a new cool feature',
102 };
103 expect(getQuestion(9).message(answers)).toMatch('Are you sure you want to proceed with the commit above?');
104 });
105
106 it('default length limit of subject should be 100', () => {
107 config = {
108 types: [{ value: 'feat', name: 'feat: my feat' }],
109 };
110 expect(getQuestion(5).validate('good subject')).toEqual(true);
111 expect(
112 getQuestion(5).validate(
113 'bad subject that exceed limit bad subject that exceed limitbad subject that exceed limit test test test'
114 )
115 ).toEqual('Exceed limit: 100');
116 });
117
118 it('subject should be lowercased by default', () => {
119 config = {};
120 expect(getQuestion(5).filter('Some subject')).toEqual('some subject');
121 });
122
123 it('subject should be capitilized when config property "upperCaseSubject" is set to true', () => {
124 config = {
125 upperCaseSubject: true,
126 };
127
128 expect(getQuestion(5).filter('some subject')).toEqual('Some subject');
129 });
130
131 describe('optional fixOverride and allowBreakingChanges', () => {
132 it('should restrict BREAKING CHANGE question when config property "allowBreakingChanges" specifies array of types', () => {
133 config = {
134 types: [{ value: 'feat', name: 'feat: my feat' }],
135 scopes: [{ name: 'myScope' }],
136 allowBreakingChanges: ['fix'],
137 };
138 expect(getQuestion(7).name).toEqual('breaking');
139
140 const answers = {
141 type: 'feat',
142 };
143
144 expect(getQuestion(7).when(answers)).toEqual(false); // not allowed
145 });
146
147 it('should allow BREAKING CHANGE question when config property "allowBreakingChanges" specifies array of types and answer is one of those', () => {
148 config = {
149 types: [{ value: 'feat', name: 'feat: my feat' }],
150 scopes: [{ name: 'myScope' }],
151 allowBreakingChanges: ['fix', 'feat'],
152 };
153 expect(getQuestion(7).name).toEqual('breaking');
154
155 const answers = {
156 type: 'feat',
157 };
158
159 expect(getQuestion(7).when(answers)).toEqual(true); // allowed
160 });
161 });
162
163 describe('Optional scopes', () => {
164 it('should use scope override', () => {
165 config = {
166 types: [{ value: 'feat', name: 'feat: my feat' }],
167 scopeOverrides: {
168 feat: [{ name: 'myScope' }],
169 },
170 };
171
172 // question 2 with
173 expect(getQuestion(2).name).toEqual('scope');
174 expect(getQuestion(2).choices({})[0]).toBeUndefined();
175 expect(getQuestion(2).choices({ type: 'feat' })[0]).toEqual({
176 name: 'myScope',
177 }); // should override scope
178 expect(getQuestion(2).when({ type: 'feat' })).toEqual(true);
179
180 const answers = { type: 'fix' };
181 expect(getQuestion(2).when(answers)).toEqual(false);
182 expect(answers.scope).toEqual('custom');
183 });
184 });
185
186 describe('no TicketNumber question', () => {
187 it('should use scope override', () => {
188 config = {
189 types: [{ value: 'feat', name: 'feat: my feat' }],
190 allowTicketNumber: false,
191 };
192
193 expect(getQuestion(4).name).toEqual('ticketNumber');
194 expect(getQuestion(4).when()).toEqual(false);
195 });
196 });
197
198 describe('ask for breaking change first', () => {
199 it('when config askForBreakingChangeFirst is true', () => {
200 config = {
201 types: [{ value: 'feat', name: 'feat: my feat' }],
202 askForBreakingChangeFirst: true,
203 };
204
205 expect(getQuestion(1).name).toEqual('breaking');
206 expect(getQuestion(1).when()).toEqual(true);
207 });
208 });
209
210 describe('TicketNumber', () => {
211 it('disable TicketNumber question', () => {
212 config = {
213 types: [{ value: 'feat', name: 'feat: my feat' }],
214 allowTicketNumber: false,
215 };
216
217 expect(getQuestion(4).name).toEqual('ticketNumber');
218 expect(getQuestion(4).when()).toEqual(false);
219 });
220
221 it('custom message defined', () => {
222 config = {
223 types: [{ value: 'feat', name: 'feat: my feat' }],
224 allowTicketNumber: true,
225 messages: {
226 ticketNumber: 'ticket number',
227 },
228 };
229
230 expect(getQuestion(4).name).toEqual('ticketNumber');
231 expect(getQuestion(4).message).toEqual('ticket number');
232 });
233
234 describe('validation', () => {
235 it('invalid because empty and required', () => {
236 config = {
237 isTicketNumberRequired: true,
238 };
239 expect(getQuestion(4).validate('')).toEqual(false);
240 });
241 it('empty but valid because optional', () => {
242 config = {
243 isTicketNumberRequired: false,
244 };
245 expect(getQuestion(4).validate('')).toEqual(true);
246 });
247 it('valid because there is no regexp defined', () => {
248 config = {
249 isTicketNumberRequired: true,
250 ticketNumberRegExp: undefined,
251 };
252 expect(getQuestion(4).validate('21234')).toEqual(true);
253 });
254 it("invalid because regexp don't match", () => {
255 config = {
256 isTicketNumberRequired: true,
257 ticketNumberRegExp: '\\d{1,5}',
258 };
259 expect(getQuestion(4).validate('sddsa')).toEqual(false);
260 });
261 it('valid because regexp match', () => {
262 config = {
263 isTicketNumberRequired: true,
264 ticketNumberRegExp: '\\d{1,5}',
265 };
266 expect(getQuestion(4).validate('12345')).toEqual(true);
267 });
268 });
269 });
270
271 describe.skip('commit already prepared', () => {
272 let existsSync;
273 let readFileSync;
274
275 beforeEach(() => {
276 config = {};
277 existsSync = spyOn(fs, 'existsSync');
278 readFileSync = spyOn(fs, 'readFileSync');
279 });
280
281 it('should ignore if there is no prepared commit file', () => {
282 existsSync.andReturn(false);
283 expect(getQuestion(5).default).toEqual(null);
284 expect(getQuestion(6).default).toEqual(null);
285 });
286
287 it('should ignore an empty prepared commit', () => {
288 existsSync.andReturn(true);
289 readFileSync.andReturn('');
290 expect(getQuestion(5).default).toEqual(null);
291 expect(getQuestion(6).default).toEqual(null);
292 });
293
294 it('should take a single line commit as the subject', () => {
295 existsSync.andReturn(true);
296 readFileSync.andReturn('my commit');
297 expect(getQuestion(5).default).toEqual('my commit');
298 expect(getQuestion(6).default).toEqual(null);
299 });
300
301 it('should split multi line commit between the subject and the body', () => {
302 existsSync.andReturn(true);
303 readFileSync.andReturn('my commit\nmessage\n\nis on several lines');
304 expect(getQuestion(5).default).toEqual('my commit');
305 expect(getQuestion(6).default).toEqual(`message|is on several lines`);
306 });
307 });
308});