UNPKG

11.1 kBJavaScriptView Raw
1import path from 'path';
2import {fix, git} from '@commitlint/test';
3import test from 'ava';
4import execa from 'execa';
5import {merge} from 'lodash';
6import * as sander from 'sander';
7import stream from 'string-to-stream';
8
9const bin = path.join(__dirname, './cli.js');
10
11const cli = (args, options) => {
12 return (input = '') => {
13 const c = execa(bin, args, {
14 capture: ['stdout'],
15 cwd: options.cwd,
16 env: options.env
17 });
18 stream(input).pipe(c.stdin);
19 return c.catch(err => err);
20 };
21};
22
23test('should throw when called without [input]', async t => {
24 const cwd = await git.bootstrap('fixtures/default');
25 const actual = await cli([], {cwd})();
26 t.is(actual.code, 1);
27});
28
29test('should reprint input from stdin', async t => {
30 const cwd = await git.bootstrap('fixtures/default');
31 const actual = await cli([], {cwd})('foo: bar');
32 t.true(actual.stdout.includes('foo: bar'));
33});
34
35test('should produce no success output with --quiet flag', async t => {
36 const cwd = await git.bootstrap('fixtures/default');
37 const actual = await cli(['--quiet'], {cwd})('foo: bar');
38 t.is(actual.stdout, '');
39 t.is(actual.stderr, '');
40});
41
42test('should produce no success output with -q flag', async t => {
43 const cwd = await git.bootstrap('fixtures/default');
44 const actual = await cli(['-q'], {cwd})('foo: bar');
45 t.is(actual.stdout, '');
46 t.is(actual.stderr, '');
47});
48
49test('should fail for input from stdin without rules', async t => {
50 const cwd = await git.bootstrap('fixtures/empty');
51 const actual = await cli([], {cwd})('foo: bar');
52 t.is(actual.code, 1);
53});
54
55test('should succeed for input from stdin with rules', async t => {
56 const cwd = await git.bootstrap('fixtures/default');
57 const actual = await cli([], {cwd})('type: bar');
58 t.is(actual.code, 0);
59});
60
61test('should fail for input from stdin with rule from rc', async t => {
62 const cwd = await git.bootstrap('fixtures/simple');
63 const actual = await cli([], {cwd})('foo: bar');
64 t.true(actual.stdout.includes('type must not be one of [foo]'));
65 t.is(actual.code, 1);
66});
67
68test('should work with --config option', async t => {
69 const file = 'config/commitlint.config.js';
70 const cwd = await git.bootstrap('fixtures/specify-config-file');
71 const actual = await cli(['--config', file], {cwd})('foo: bar');
72 t.true(actual.stdout.includes('type must not be one of [foo]'));
73 t.is(actual.code, 1);
74});
75
76test('should fail for input from stdin with rule from js', async t => {
77 const cwd = await git.bootstrap('fixtures/extends-root');
78 const actual = await cli(['--extends', './extended'], {cwd})('foo: bar');
79 t.true(actual.stdout.includes('type must not be one of [foo]'));
80 t.is(actual.code, 1);
81});
82
83test('should produce no error output with --quiet flag', async t => {
84 const cwd = await git.bootstrap('fixtures/simple');
85 const actual = await cli(['--quiet'], {cwd})('foo: bar');
86 t.is(actual.stdout, '');
87 t.is(actual.stderr, '');
88 t.is(actual.code, 1);
89});
90
91test('should produce no error output with -q flag', async t => {
92 const cwd = await git.bootstrap('fixtures/simple');
93 const actual = await cli(['-q'], {cwd})('foo: bar');
94 t.is(actual.stdout, '');
95 t.is(actual.stderr, '');
96 t.is(actual.code, 1);
97});
98
99test('should work with husky commitmsg hook and git commit', async () => {
100 const cwd = await git.bootstrap('fixtures/husky/integration');
101 await writePkg({scripts: {commitmsg: `'${bin}' -e`}}, {cwd});
102
103 await execa('npm', ['install'], {cwd});
104 await execa('git', ['add', 'package.json'], {cwd});
105 await execa('git', ['commit', '-m', '"test: this should work"'], {cwd});
106});
107
108test('should work with husky commitmsg hook in sub packages', async () => {
109 const upper = await git.bootstrap('fixtures/husky');
110 const cwd = path.join(upper, 'integration');
111 await writePkg({scripts: {commitmsg: `'${bin}' -e`}}, {cwd: upper});
112
113 await execa('npm', ['install'], {cwd});
114 await execa('git', ['add', 'package.json'], {cwd});
115 await execa('git', ['commit', '-m', '"test: this should work"'], {cwd});
116});
117
118test('should work with husky via commitlint -e $GIT_PARAMS', async () => {
119 const cwd = await git.bootstrap('fixtures/husky/integration');
120 await writePkg({scripts: {commitmsg: `'${bin}' -e $GIT_PARAMS`}}, {cwd});
121
122 await execa('npm', ['install'], {cwd});
123 await execa('git', ['add', 'package.json'], {cwd});
124 await execa('git', ['commit', '-m', '"test: this should work"'], {cwd});
125});
126
127test('should work with husky via commitlint -e %GIT_PARAMS%', async () => {
128 const cwd = await git.bootstrap('fixtures/husky/integration');
129 await writePkg({scripts: {commitmsg: `'${bin}' -e %GIT_PARAMS%`}}, {cwd});
130
131 await execa('npm', ['install'], {cwd});
132 await execa('git', ['add', 'package.json'], {cwd});
133 await execa('git', ['commit', '-m', '"test: this should work"'], {cwd});
134});
135
136test('should work with husky via commitlint -e $HUSKY_GIT_PARAMS', async () => {
137 const cwd = await git.bootstrap('fixtures/husky/integration');
138 await writePkg(
139 {scripts: {commitmsg: `'${bin}' -e $HUSKY_GIT_PARAMS`}},
140 {cwd}
141 );
142
143 await execa('npm', ['install'], {cwd});
144 await execa('git', ['add', 'package.json'], {cwd});
145 await execa('git', ['commit', '-m', '"test: this should work"'], {cwd});
146});
147
148test('should work with husky via commitlint -e %HUSKY_GIT_PARAMS%', async () => {
149 const cwd = await git.bootstrap('fixtures/husky/integration');
150 await writePkg(
151 {scripts: {commitmsg: `'${bin}' -e %HUSKY_GIT_PARAMS%`}},
152 {cwd}
153 );
154
155 await execa('npm', ['install'], {cwd});
156 await execa('git', ['add', 'package.json'], {cwd});
157 await execa('git', ['commit', '-m', '"test: this should work"'], {cwd});
158});
159
160test('should allow reading of environment variables for edit file, succeeding if valid', async t => {
161 const cwd = await git.bootstrap('fixtures/simple');
162 await sander.writeFile(cwd, 'commit-msg-file', 'foo');
163 const actual = await cli(['--env', 'variable'], {
164 cwd,
165 env: {variable: 'commit-msg-file'}
166 })();
167 t.is(actual.code, 0);
168});
169
170test('should allow reading of environment variables for edit file, failing if invalid', async t => {
171 const cwd = await git.bootstrap('fixtures/simple');
172 await sander.writeFile(
173 cwd,
174 'commit-msg-file',
175 'foo: bar\n\nFoo bar bizz buzz.\n\nCloses #123.'
176 );
177 const actual = await cli(['--env', 'variable'], {
178 cwd,
179 env: {variable: 'commit-msg-file'}
180 })();
181 t.is(actual.code, 1);
182});
183
184test('should pick up parser preset and fail accordingly', async t => {
185 const cwd = await git.bootstrap('fixtures/parser-preset');
186 const actual = await cli(['--parser-preset', './parser-preset'], {cwd})(
187 'type(scope): subject'
188 );
189 t.is(actual.code, 1);
190 t.true(actual.stdout.includes('may not be empty'));
191});
192
193test('should pick up parser preset and succeed accordingly', async t => {
194 const cwd = await git.bootstrap('fixtures/parser-preset');
195 const actual = await cli(['--parser-preset', './parser-preset'], {cwd})(
196 '----type(scope): subject'
197 );
198 t.is(actual.code, 0);
199});
200
201test('should pick up config from outside git repo and fail accordingly', async t => {
202 const outer = await fix.bootstrap('fixtures/outer-scope');
203 const cwd = await git.init(path.join(outer, 'inner-scope'));
204
205 const actual = await cli([], {cwd})('inner: bar');
206 t.is(actual.code, 1);
207});
208
209test('should pick up config from outside git repo and succeed accordingly', async t => {
210 const outer = await fix.bootstrap('fixtures/outer-scope');
211 const cwd = await git.init(path.join(outer, 'inner-scope'));
212
213 const actual = await cli([], {cwd})('outer: bar');
214 t.is(actual.code, 0);
215});
216
217test('should pick up config from inside git repo with precedence and succeed accordingly', async t => {
218 const outer = await fix.bootstrap('fixtures/inner-scope');
219 const cwd = await git.init(path.join(outer, 'inner-scope'));
220
221 const actual = await cli([], {cwd})('inner: bar');
222 t.is(actual.code, 0);
223});
224
225test('should pick up config from inside git repo with precedence and fail accordingly', async t => {
226 const outer = await fix.bootstrap('fixtures/inner-scope');
227 const cwd = await git.init(path.join(outer, 'inner-scope'));
228
229 const actual = await cli([], {cwd})('outer: bar');
230 t.is(actual.code, 1);
231});
232
233test('should handle --amend with signoff', async () => {
234 const cwd = await git.bootstrap('fixtures/signoff');
235 await writePkg({scripts: {commitmsg: `'${bin}' -e`}}, {cwd});
236
237 await execa('npm', ['install'], {cwd});
238 await execa('git', ['add', 'package.json'], {cwd});
239 await execa(
240 'git',
241 ['commit', '-m', '"test: this should work"', '--signoff'],
242 {cwd}
243 );
244 await execa('git', ['commit', '--amend', '--no-edit'], {cwd});
245});
246
247test('should handle linting with issue prefixes', async t => {
248 const cwd = await git.bootstrap('fixtures/issue-prefixes');
249 const actual = await cli([], {cwd})('foobar REF-1');
250 t.is(actual.code, 0);
251});
252
253test('should print full commit message when input from stdin fails', async t => {
254 const cwd = await git.bootstrap('fixtures/simple');
255 const input = 'foo: bar\n\nFoo bar bizz buzz.\n\nCloses #123.';
256 const actual = await cli([], {cwd})(input);
257
258 t.true(actual.stdout.includes(input));
259 t.is(actual.code, 1);
260});
261
262test('should not print full commit message when input succeeds', async t => {
263 const cwd = await git.bootstrap('fixtures/default');
264 const message = 'type: bar\n\nFoo bar bizz buzz.\n\nCloses #123.';
265 const actual = await cli([], {cwd})(message);
266
267 t.false(actual.stdout.includes(message));
268 t.true(actual.stdout.includes(message.split('\n')[0]));
269 t.is(actual.code, 0);
270});
271
272test('should fail for invalid formatters from configuration', async t => {
273 const cwd = await git.bootstrap('fixtures/custom-formatter');
274 const actual = await cli([], {cwd})('foo: bar');
275 t.true(
276 actual.stderr.includes(
277 `Using format custom-formatter, but cannot find the module`
278 )
279 );
280 t.is(actual.stdout, '');
281 t.is(actual.code, 1);
282});
283
284test('should fail for invalid formatters from flags', async t => {
285 const cwd = await git.bootstrap('fixtures/custom-formatter');
286 const actual = await cli(['--format', 'through-flag'], {cwd})('foo: bar');
287 t.true(
288 actual.stderr.includes(
289 `Using format through-flag, but cannot find the module`
290 )
291 );
292 t.is(actual.stdout, '');
293 t.is(actual.code, 1);
294});
295
296test('should work with absolute formatter path', async t => {
297 const formatterPath = path.resolve(
298 __dirname,
299 '../fixtures/custom-formatter/formatters/custom.js'
300 );
301 const cwd = await git.bootstrap('fixtures/custom-formatter');
302 const actual = await cli(['--format', formatterPath], {cwd})(
303 'test: this should work'
304 );
305
306 t.true(actual.stdout.includes('custom-formatter-ok'));
307 t.is(actual.code, 0);
308});
309
310test('should work with relative formatter path', async t => {
311 const cwd = path.resolve(
312 await git.bootstrap('fixtures/custom-formatter'),
313 './formatters'
314 );
315 const actual = await cli(['--format', './custom.js'], {cwd})(
316 'test: this should work'
317 );
318
319 t.true(actual.stdout.includes('custom-formatter-ok'));
320 t.is(actual.code, 0);
321});
322
323async function writePkg(payload, options) {
324 const pkgPath = path.join(options.cwd, 'package.json');
325 const pkg = JSON.parse(await sander.readFile(pkgPath));
326 const result = merge(pkg, payload);
327 await sander.writeFile(pkgPath, JSON.stringify(result, null, ' '));
328}