]>
Commit | Line | Data |
---|---|---|
eb39fafa DC |
1 | /** |
2 | * @fileoverview Tests for cli. | |
3 | * @author Ian Christian Myers | |
4 | */ | |
5 | ||
6 | "use strict"; | |
7 | ||
8 | /* | |
9 | * NOTE: If you are adding new tests for cli.js, use verifyCLIEngineOpts(). The | |
10 | * test only needs to verify that CLIEngine receives the correct opts. | |
11 | */ | |
12 | ||
13 | //------------------------------------------------------------------------------ | |
14 | // Requirements | |
15 | //------------------------------------------------------------------------------ | |
16 | ||
17 | const assert = require("chai").assert, | |
18 | CLIEngine = require("../../lib/cli-engine/index").CLIEngine, | |
19 | path = require("path"), | |
20 | sinon = require("sinon"), | |
21 | fs = require("fs"), | |
22 | os = require("os"), | |
23 | sh = require("shelljs"); | |
24 | ||
25 | const proxyquire = require("proxyquire").noCallThru().noPreserveCache(); | |
26 | ||
27 | //------------------------------------------------------------------------------ | |
28 | // Tests | |
29 | //------------------------------------------------------------------------------ | |
30 | ||
31 | describe("cli", () => { | |
32 | let fixtureDir; | |
33 | const log = { | |
34 | info: sinon.spy(), | |
35 | error: sinon.spy() | |
36 | }; | |
37 | const RuntimeInfo = { | |
38 | environment: sinon.stub(), | |
39 | version: sinon.stub() | |
40 | }; | |
41 | const cli = proxyquire("../../lib/cli", { | |
42 | "./shared/logging": log, | |
43 | "./shared/runtime-info": RuntimeInfo | |
44 | }); | |
45 | ||
46 | /** | |
47 | * Verify that CLIEngine receives correct opts via cli.execute(). | |
48 | * @param {string} cmd CLI command. | |
49 | * @param {Object} opts Options hash that should match that received by CLIEngine. | |
50 | * @returns {void} | |
51 | */ | |
52 | function verifyCLIEngineOpts(cmd, opts) { | |
53 | ||
54 | // create a fake CLIEngine to test with | |
55 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match(opts)); | |
56 | ||
57 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
58 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({}); | |
59 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(sinon.spy()); | |
60 | ||
61 | const localCLI = proxyquire("../../lib/cli", { | |
62 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
63 | "./shared/logging": log | |
64 | }); | |
65 | ||
66 | localCLI.execute(cmd); | |
67 | sinon.verifyAndRestore(); | |
68 | } | |
69 | ||
70 | // verifyCLIEngineOpts | |
71 | ||
72 | /** | |
73 | * Returns the path inside of the fixture directory. | |
74 | * @param {...string} args file path segments. | |
75 | * @returns {string} The path inside the fixture directory. | |
76 | * @private | |
77 | */ | |
78 | function getFixturePath(...args) { | |
79 | return path.join(fixtureDir, ...args); | |
80 | } | |
81 | ||
82 | // copy into clean area so as not to get "infected" by this project's .eslintrc files | |
83 | before(() => { | |
84 | fixtureDir = `${os.tmpdir()}/eslint/fixtures`; | |
85 | sh.mkdir("-p", fixtureDir); | |
86 | sh.cp("-r", "./tests/fixtures/.", fixtureDir); | |
87 | }); | |
88 | ||
89 | afterEach(() => { | |
90 | log.info.resetHistory(); | |
91 | log.error.resetHistory(); | |
92 | }); | |
93 | ||
94 | after(() => { | |
95 | sh.rm("-r", fixtureDir); | |
96 | }); | |
97 | ||
98 | describe("execute()", () => { | |
99 | it("should return error when text with incorrect quotes is passed as argument", () => { | |
100 | const configFile = getFixturePath("configurations", "quotes-error.json"); | |
101 | const result = cli.execute(`-c ${configFile}`, "var foo = 'bar';"); | |
102 | ||
103 | assert.strictEqual(result, 1); | |
104 | }); | |
105 | ||
106 | it("should not print debug info when passed the empty string as text", () => { | |
107 | const result = cli.execute(["--stdin", "--no-eslintrc"], ""); | |
108 | ||
109 | assert.strictEqual(result, 0); | |
110 | assert.isTrue(log.info.notCalled); | |
111 | }); | |
112 | ||
113 | it("should return no error when --ext .js2 is specified", () => { | |
114 | const filePath = getFixturePath("files"); | |
115 | const result = cli.execute(`--ext .js2 ${filePath}`); | |
116 | ||
117 | assert.strictEqual(result, 0); | |
118 | }); | |
119 | ||
120 | it("should exit with console error when passed unsupported arguments", () => { | |
121 | const filePath = getFixturePath("files"); | |
122 | const result = cli.execute(`--blah --another ${filePath}`); | |
123 | ||
124 | assert.strictEqual(result, 2); | |
125 | }); | |
126 | ||
127 | }); | |
128 | ||
129 | describe("when given a config file", () => { | |
130 | it("should load the specified config file", () => { | |
131 | const configPath = getFixturePath(".eslintrc"); | |
132 | const filePath = getFixturePath("passing.js"); | |
133 | ||
134 | cli.execute(`--config ${configPath} ${filePath}`); | |
135 | }); | |
136 | }); | |
137 | ||
138 | describe("when there is a local config file", () => { | |
139 | const code = "lib/cli.js"; | |
140 | ||
141 | it("should load the local config file", () => { | |
142 | ||
143 | // Mock CWD | |
144 | process.eslintCwd = getFixturePath("configurations", "single-quotes"); | |
145 | ||
146 | cli.execute(code); | |
147 | ||
148 | process.eslintCwd = null; | |
149 | }); | |
150 | }); | |
151 | ||
152 | describe("when given a config with rules with options and severity level set to error", () => { | |
153 | it("should exit with an error status (1)", () => { | |
154 | const configPath = getFixturePath("configurations", "quotes-error.json"); | |
155 | const filePath = getFixturePath("single-quoted.js"); | |
156 | const code = `--no-ignore --config ${configPath} ${filePath}`; | |
157 | ||
158 | const exitStatus = cli.execute(code); | |
159 | ||
160 | assert.strictEqual(exitStatus, 1); | |
161 | }); | |
162 | }); | |
163 | ||
164 | describe("when given a config file and a directory of files", () => { | |
165 | it("should load and execute without error", () => { | |
166 | const configPath = getFixturePath("configurations", "semi-error.json"); | |
167 | const filePath = getFixturePath("formatters"); | |
168 | const code = `--config ${configPath} ${filePath}`; | |
169 | ||
170 | const exitStatus = cli.execute(code); | |
171 | ||
172 | assert.strictEqual(exitStatus, 0); | |
173 | }); | |
174 | }); | |
175 | ||
176 | describe("when given a config with environment set to browser", () => { | |
177 | it("should execute without any errors", () => { | |
178 | const configPath = getFixturePath("configurations", "env-browser.json"); | |
179 | const filePath = getFixturePath("globals-browser.js"); | |
180 | const code = `--config ${configPath} ${filePath}`; | |
181 | ||
182 | const exit = cli.execute(code); | |
183 | ||
184 | assert.strictEqual(exit, 0); | |
185 | }); | |
186 | }); | |
187 | ||
188 | describe("when given a config with environment set to Node.js", () => { | |
189 | it("should execute without any errors", () => { | |
190 | const configPath = getFixturePath("configurations", "env-node.json"); | |
191 | const filePath = getFixturePath("globals-node.js"); | |
192 | const code = `--config ${configPath} ${filePath}`; | |
193 | ||
194 | const exit = cli.execute(code); | |
195 | ||
196 | assert.strictEqual(exit, 0); | |
197 | }); | |
198 | }); | |
199 | ||
200 | describe("when given a config with environment set to Nashorn", () => { | |
201 | it("should execute without any errors", () => { | |
202 | const configPath = getFixturePath("configurations", "env-nashorn.json"); | |
203 | const filePath = getFixturePath("globals-nashorn.js"); | |
204 | const code = `--config ${configPath} ${filePath}`; | |
205 | ||
206 | const exit = cli.execute(code); | |
207 | ||
208 | assert.strictEqual(exit, 0); | |
209 | }); | |
210 | }); | |
211 | ||
212 | describe("when given a config with environment set to WebExtensions", () => { | |
213 | it("should execute without any errors", () => { | |
214 | const configPath = getFixturePath("configurations", "env-webextensions.json"); | |
215 | const filePath = getFixturePath("globals-webextensions.js"); | |
216 | const code = `--config ${configPath} ${filePath}`; | |
217 | ||
218 | const exit = cli.execute(code); | |
219 | ||
220 | assert.strictEqual(exit, 0); | |
221 | }); | |
222 | }); | |
223 | ||
224 | describe("when given a valid built-in formatter name", () => { | |
225 | it("should execute without any errors", () => { | |
226 | const filePath = getFixturePath("passing.js"); | |
227 | const exit = cli.execute(`-f checkstyle ${filePath}`); | |
228 | ||
229 | assert.strictEqual(exit, 0); | |
230 | }); | |
231 | }); | |
232 | ||
233 | describe("when given a valid built-in formatter name that uses rules meta.", () => { | |
234 | it("should execute without any errors", () => { | |
235 | const filePath = getFixturePath("passing.js"); | |
236 | const exit = cli.execute(`-f json-with-metadata ${filePath} --no-eslintrc`); | |
237 | ||
238 | assert.strictEqual(exit, 0); | |
239 | ||
240 | // Check metadata. | |
241 | const { metadata } = JSON.parse(log.info.args[0][0]); | |
242 | const rules = new CLIEngine({ useEslintrc: false }).getRules(); | |
243 | const expectedMetadata = Array.from(rules).reduce((obj, [ruleId, rule]) => { | |
244 | obj.rulesMeta[ruleId] = rule.meta; | |
245 | return obj; | |
246 | }, { rulesMeta: {} }); | |
247 | ||
248 | assert.deepStrictEqual(metadata, expectedMetadata); | |
249 | }); | |
250 | }); | |
251 | ||
252 | describe("when given an invalid built-in formatter name", () => { | |
253 | it("should execute with error", () => { | |
254 | const filePath = getFixturePath("passing.js"); | |
255 | const exit = cli.execute(`-f fakeformatter ${filePath}`); | |
256 | ||
257 | assert.strictEqual(exit, 2); | |
258 | }); | |
259 | }); | |
260 | ||
261 | describe("when given a valid formatter path", () => { | |
262 | it("should execute without any errors", () => { | |
263 | const formatterPath = getFixturePath("formatters", "simple.js"); | |
264 | const filePath = getFixturePath("passing.js"); | |
265 | const exit = cli.execute(`-f ${formatterPath} ${filePath}`); | |
266 | ||
267 | assert.strictEqual(exit, 0); | |
268 | }); | |
269 | }); | |
270 | ||
271 | describe("when given an invalid formatter path", () => { | |
272 | it("should execute with error", () => { | |
273 | const formatterPath = getFixturePath("formatters", "file-does-not-exist.js"); | |
274 | const filePath = getFixturePath("passing.js"); | |
275 | const exit = cli.execute(`-f ${formatterPath} ${filePath}`); | |
276 | ||
277 | assert.strictEqual(exit, 2); | |
278 | }); | |
279 | }); | |
280 | ||
281 | describe("when executing a file with a lint error", () => { | |
282 | it("should exit with error", () => { | |
283 | const filePath = getFixturePath("undef.js"); | |
284 | const code = `--no-ignore --rule no-undef:2 ${filePath}`; | |
285 | ||
286 | const exit = cli.execute(code); | |
287 | ||
288 | assert.strictEqual(exit, 1); | |
289 | }); | |
290 | }); | |
291 | ||
292 | describe("when using --fix-type without --fix or --fix-dry-run", () => { | |
293 | it("should exit with error", () => { | |
294 | const filePath = getFixturePath("passing.js"); | |
295 | const code = `--fix-type suggestion ${filePath}`; | |
296 | ||
297 | const exit = cli.execute(code); | |
298 | ||
299 | assert.strictEqual(exit, 2); | |
300 | }); | |
301 | }); | |
302 | ||
303 | describe("when executing a file with a syntax error", () => { | |
304 | it("should exit with error", () => { | |
305 | const filePath = getFixturePath("syntax-error.js"); | |
306 | const exit = cli.execute(`--no-ignore ${filePath}`); | |
307 | ||
308 | assert.strictEqual(exit, 1); | |
309 | }); | |
310 | }); | |
311 | ||
312 | describe("when calling execute more than once", () => { | |
313 | it("should not print the results from previous execution", () => { | |
314 | const filePath = getFixturePath("missing-semicolon.js"); | |
315 | const passingPath = getFixturePath("passing.js"); | |
316 | ||
317 | cli.execute(`--no-ignore --rule semi:2 ${filePath}`); | |
318 | ||
319 | assert.isTrue(log.info.called, "Log should have been called."); | |
320 | ||
321 | log.info.resetHistory(); | |
322 | ||
323 | cli.execute(`--no-ignore --rule semi:2 ${passingPath}`); | |
324 | assert.isTrue(log.info.notCalled); | |
325 | ||
326 | }); | |
327 | }); | |
328 | ||
329 | describe("when executing with version flag", () => { | |
330 | it("should print out current version", () => { | |
331 | assert.strictEqual(cli.execute("-v"), 0); | |
332 | assert.strictEqual(log.info.callCount, 1); | |
333 | }); | |
334 | }); | |
335 | ||
336 | describe("when executing with env-info flag", () => { | |
337 | it("should print out environment information", () => { | |
338 | assert.strictEqual(cli.execute("--env-info"), 0); | |
339 | assert.strictEqual(log.info.callCount, 1); | |
340 | }); | |
341 | ||
342 | it("should print error message and return error code", () => { | |
343 | RuntimeInfo.environment.throws("There was an error!"); | |
344 | ||
345 | assert.strictEqual(cli.execute("--env-info"), 2); | |
346 | assert.strictEqual(log.error.callCount, 1); | |
347 | }); | |
348 | }); | |
349 | ||
350 | describe("when executing without no-error-on-unmatched-pattern flag", () => { | |
351 | it("should throw an error on unmatched glob pattern", () => { | |
352 | const filePath = getFixturePath("unmatched-patterns"); | |
353 | const globPattern = "*.js3"; | |
354 | ||
355 | assert.throws(() => { | |
356 | cli.execute(`"${filePath}/${globPattern}"`); | |
357 | }, `No files matching '${filePath}/${globPattern}' were found.`); | |
358 | }); | |
359 | ||
360 | it("should throw an error on unmatched --ext", () => { | |
361 | const filePath = getFixturePath("unmatched-patterns"); | |
362 | const extension = ".js3"; | |
363 | ||
364 | assert.throws(() => { | |
365 | cli.execute(`--ext ${extension} ${filePath}`); | |
366 | }, `No files matching '${filePath}' were found`); | |
367 | }); | |
368 | }); | |
369 | ||
370 | describe("when executing with no-error-on-unmatched-pattern flag", () => { | |
371 | it("should not throw an error on unmatched node glob syntax patterns", () => { | |
372 | const filePath = getFixturePath("unmatched-patterns"); | |
373 | const exit = cli.execute(`--no-error-on-unmatched-pattern "${filePath}/*.js3"`); | |
374 | ||
375 | assert.strictEqual(exit, 0); | |
376 | }); | |
377 | ||
378 | it("should not throw an error on unmatched --ext", () => { | |
379 | const filePath = getFixturePath("unmatched-patterns"); | |
380 | const exit = cli.execute(`--no-error-on-unmatched-pattern --ext .js3 ${filePath}`); | |
381 | ||
382 | assert.strictEqual(exit, 0); | |
383 | }); | |
384 | }); | |
385 | ||
386 | describe("when executing with no-error-on-unmatched-pattern flag and multiple patterns", () => { | |
387 | it("should not throw an error on multiple unmatched node glob syntax patterns", () => { | |
388 | const filePath = getFixturePath("unmatched-patterns"); | |
389 | const exit = cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js4`); | |
390 | ||
391 | assert.strictEqual(exit, 0); | |
392 | }); | |
393 | ||
394 | it("should still throw an error on when a matched pattern has lint errors", () => { | |
395 | const filePath = getFixturePath("unmatched-patterns"); | |
396 | const exit = cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js`); | |
397 | ||
398 | assert.strictEqual(exit, 1); | |
399 | }); | |
400 | }); | |
401 | ||
402 | describe("when executing with no-error-on-unmatched-pattern flag and multiple --ext arguments", () => { | |
403 | it("should not throw an error on multiple unmatched --ext arguments", () => { | |
404 | const filePath = getFixturePath("unmatched-patterns"); | |
405 | const exit = cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js4 ${filePath}`); | |
406 | ||
407 | assert.strictEqual(exit, 0); | |
408 | }); | |
409 | ||
410 | it("should still throw an error on when a matched pattern has lint errors", () => { | |
411 | const filePath = getFixturePath("unmatched-patterns"); | |
412 | const exit = cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js ${filePath}`); | |
413 | ||
414 | assert.strictEqual(exit, 1); | |
415 | }); | |
416 | }); | |
417 | ||
418 | describe("when executing with help flag", () => { | |
419 | it("should print out help", () => { | |
420 | assert.strictEqual(cli.execute("-h"), 0); | |
421 | assert.strictEqual(log.info.callCount, 1); | |
422 | }); | |
423 | }); | |
424 | ||
425 | describe("when given a directory with eslint excluded files in the directory", () => { | |
426 | it("should throw an error and not process any files", () => { | |
427 | const ignorePath = getFixturePath(".eslintignore"); | |
428 | const filePath = getFixturePath("cli"); | |
429 | ||
430 | assert.throws(() => { | |
431 | cli.execute(`--ignore-path ${ignorePath} ${filePath}`); | |
432 | }, `All files matched by '${filePath}' are ignored.`); | |
433 | }); | |
434 | }); | |
435 | ||
436 | describe("when given a file in excluded files list", () => { | |
437 | it("should not process the file", () => { | |
438 | const ignorePath = getFixturePath(".eslintignore"); | |
439 | const filePath = getFixturePath("passing.js"); | |
440 | const exit = cli.execute(`--ignore-path ${ignorePath} ${filePath}`); | |
441 | ||
442 | // a warning about the ignored file | |
443 | assert.isTrue(log.info.called); | |
444 | assert.strictEqual(exit, 0); | |
445 | }); | |
446 | ||
447 | it("should process the file when forced", () => { | |
448 | const ignorePath = getFixturePath(".eslintignore"); | |
449 | const filePath = getFixturePath("passing.js"); | |
450 | const exit = cli.execute(`--ignore-path ${ignorePath} --no-ignore ${filePath}`); | |
451 | ||
452 | // no warnings | |
453 | assert.isFalse(log.info.called); | |
454 | assert.strictEqual(exit, 0); | |
455 | }); | |
456 | }); | |
457 | ||
458 | describe("when given a pattern to ignore", () => { | |
459 | it("should not process any files", () => { | |
460 | const ignoredFile = getFixturePath("cli/syntax-error.js"); | |
461 | const filePath = getFixturePath("cli/passing.js"); | |
462 | const exit = cli.execute(`--ignore-pattern cli/ ${ignoredFile} ${filePath}`); | |
463 | ||
464 | // warnings about the ignored files | |
465 | assert.isTrue(log.info.called); | |
466 | assert.strictEqual(exit, 0); | |
467 | }); | |
468 | }); | |
469 | ||
470 | describe("when given patterns to ignore", () => { | |
471 | it("should not process any matching files", () => { | |
472 | const ignorePaths = ["a", "b"]; | |
473 | ||
474 | const cmd = ignorePaths.map(ignorePath => `--ignore-pattern ${ignorePath}`).concat(".").join(" "); | |
475 | ||
476 | const opts = { | |
477 | ignorePattern: ignorePaths | |
478 | }; | |
479 | ||
480 | verifyCLIEngineOpts(cmd, opts); | |
481 | }); | |
482 | }); | |
483 | ||
484 | describe("when executing a file with a shebang", () => { | |
485 | it("should execute without error", () => { | |
486 | const filePath = getFixturePath("shebang.js"); | |
487 | const exit = cli.execute(`--no-ignore ${filePath}`); | |
488 | ||
489 | assert.strictEqual(exit, 0); | |
490 | }); | |
491 | }); | |
492 | ||
493 | describe("when loading a custom rule", () => { | |
494 | it("should return an error when rule isn't found", () => { | |
495 | const rulesPath = getFixturePath("rules", "wrong"); | |
496 | const configPath = getFixturePath("rules", "eslint.json"); | |
497 | const filePath = getFixturePath("rules", "test", "test-custom-rule.js"); | |
498 | const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`; | |
499 | ||
500 | assert.throws(() => { | |
501 | const exit = cli.execute(code); | |
502 | ||
503 | assert.strictEqual(exit, 2); | |
504 | }, /Error while loading rule 'custom-rule': Cannot read property/u); | |
505 | }); | |
506 | ||
507 | it("should return a warning when rule is matched", () => { | |
508 | const rulesPath = getFixturePath("rules"); | |
509 | const configPath = getFixturePath("rules", "eslint.json"); | |
510 | const filePath = getFixturePath("rules", "test", "test-custom-rule.js"); | |
511 | const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`; | |
512 | ||
513 | cli.execute(code); | |
514 | ||
515 | assert.isTrue(log.info.calledOnce); | |
516 | assert.isTrue(log.info.neverCalledWith("")); | |
517 | }); | |
518 | ||
519 | it("should return warnings from multiple rules in different directories", () => { | |
520 | const rulesPath = getFixturePath("rules", "dir1"); | |
521 | const rulesPath2 = getFixturePath("rules", "dir2"); | |
522 | const configPath = getFixturePath("rules", "multi-rulesdirs.json"); | |
523 | const filePath = getFixturePath("rules", "test-multi-rulesdirs.js"); | |
524 | const code = `--rulesdir ${rulesPath} --rulesdir ${rulesPath2} --config ${configPath} --no-ignore ${filePath}`; | |
525 | const exit = cli.execute(code); | |
526 | ||
527 | const call = log.info.getCall(0); | |
528 | ||
529 | assert.isTrue(log.info.calledOnce); | |
530 | assert.isTrue(call.args[0].indexOf("String!") > -1); | |
531 | assert.isTrue(call.args[0].indexOf("Literal!") > -1); | |
532 | assert.isTrue(call.args[0].indexOf("2 problems") > -1); | |
533 | assert.isTrue(log.info.neverCalledWith("")); | |
534 | assert.strictEqual(exit, 1); | |
535 | }); | |
536 | ||
537 | ||
538 | }); | |
539 | ||
540 | describe("when executing with no-eslintrc flag", () => { | |
541 | it("should ignore a local config file", () => { | |
542 | const filePath = getFixturePath("eslintrc", "quotes.js"); | |
543 | const exit = cli.execute(`--no-eslintrc --no-ignore ${filePath}`); | |
544 | ||
545 | assert.isTrue(log.info.notCalled); | |
546 | assert.strictEqual(exit, 0); | |
547 | }); | |
548 | }); | |
549 | ||
550 | describe("when executing without no-eslintrc flag", () => { | |
551 | it("should load a local config file", () => { | |
552 | const filePath = getFixturePath("eslintrc", "quotes.js"); | |
553 | const exit = cli.execute(`--no-ignore ${filePath}`); | |
554 | ||
555 | assert.isTrue(log.info.calledOnce); | |
556 | assert.strictEqual(exit, 1); | |
557 | }); | |
558 | }); | |
559 | ||
560 | describe("when executing without env flag", () => { | |
561 | it("should not define environment-specific globals", () => { | |
562 | const files = [ | |
563 | getFixturePath("globals-browser.js"), | |
564 | getFixturePath("globals-node.js") | |
565 | ]; | |
566 | ||
567 | cli.execute(`--no-eslintrc --config ./conf/eslint-recommended.js --no-ignore ${files.join(" ")}`); | |
568 | ||
569 | assert.strictEqual(log.info.args[0][0].split("\n").length, 10); | |
570 | }); | |
571 | }); | |
572 | ||
573 | describe("when executing with global flag", () => { | |
574 | it("should default defined variables to read-only", () => { | |
575 | const filePath = getFixturePath("undef.js"); | |
576 | const exit = cli.execute(`--global baz,bat --no-ignore --rule no-global-assign:2 ${filePath}`); | |
577 | ||
578 | assert.isTrue(log.info.calledOnce); | |
579 | assert.strictEqual(exit, 1); | |
580 | }); | |
581 | ||
582 | it("should allow defining writable global variables", () => { | |
583 | const filePath = getFixturePath("undef.js"); | |
584 | const exit = cli.execute(`--global baz:false,bat:true --no-ignore ${filePath}`); | |
585 | ||
586 | assert.isTrue(log.info.notCalled); | |
587 | assert.strictEqual(exit, 0); | |
588 | }); | |
589 | ||
590 | it("should allow defining variables with multiple flags", () => { | |
591 | const filePath = getFixturePath("undef.js"); | |
592 | const exit = cli.execute(`--global baz --global bat:true --no-ignore ${filePath}`); | |
593 | ||
594 | assert.isTrue(log.info.notCalled); | |
595 | assert.strictEqual(exit, 0); | |
596 | }); | |
597 | }); | |
598 | ||
599 | describe("when supplied with rule flag and severity level set to error", () => { | |
600 | it("should exit with an error status (2)", () => { | |
601 | const filePath = getFixturePath("single-quoted.js"); | |
602 | const code = `--no-ignore --rule 'quotes: [2, double]' ${filePath}`; | |
603 | const exitStatus = cli.execute(code); | |
604 | ||
605 | assert.strictEqual(exitStatus, 1); | |
606 | }); | |
607 | }); | |
608 | ||
609 | describe("when the quiet option is enabled", () => { | |
610 | ||
611 | it("should only print error", () => { | |
612 | const filePath = getFixturePath("single-quoted.js"); | |
613 | const cliArgs = `--no-ignore --quiet -f compact --rule 'quotes: [2, double]' --rule 'no-unused-vars: 1' ${filePath}`; | |
614 | ||
615 | cli.execute(cliArgs); | |
616 | ||
617 | sinon.assert.calledOnce(log.info); | |
618 | ||
619 | const formattedOutput = log.info.firstCall.args[0]; | |
620 | ||
621 | assert.include(formattedOutput, "Error"); | |
622 | assert.notInclude(formattedOutput, "Warning"); | |
623 | }); | |
624 | ||
625 | it("should print nothing if there are no errors", () => { | |
626 | const filePath = getFixturePath("single-quoted.js"); | |
627 | const cliArgs = `--quiet -f compact --rule 'quotes: [1, double]' --rule 'no-unused-vars: 1' ${filePath}`; | |
628 | ||
629 | cli.execute(cliArgs); | |
630 | ||
631 | sinon.assert.notCalled(log.info); | |
632 | }); | |
633 | }); | |
634 | ||
635 | describe("when supplied with report output file path", () => { | |
636 | afterEach(() => { | |
637 | sh.rm("-rf", "tests/output"); | |
638 | }); | |
639 | ||
640 | it("should write the file and create dirs if they don't exist", () => { | |
641 | const filePath = getFixturePath("single-quoted.js"); | |
642 | const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`; | |
643 | ||
644 | cli.execute(code); | |
645 | ||
646 | assert.include(fs.readFileSync("tests/output/eslint-output.txt", "utf8"), filePath); | |
647 | assert.isTrue(log.info.notCalled); | |
648 | }); | |
649 | ||
650 | it("should return an error if the path is a directory", () => { | |
651 | const filePath = getFixturePath("single-quoted.js"); | |
652 | const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output ${filePath}`; | |
653 | ||
654 | fs.mkdirSync("tests/output"); | |
655 | ||
656 | const exit = cli.execute(code); | |
657 | ||
658 | assert.strictEqual(exit, 2); | |
659 | assert.isTrue(log.info.notCalled); | |
660 | assert.isTrue(log.error.calledOnce); | |
661 | }); | |
662 | ||
663 | it("should return an error if the path could not be written to", () => { | |
664 | const filePath = getFixturePath("single-quoted.js"); | |
665 | const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`; | |
666 | ||
667 | fs.writeFileSync("tests/output", "foo"); | |
668 | ||
669 | const exit = cli.execute(code); | |
670 | ||
671 | assert.strictEqual(exit, 2); | |
672 | assert.isTrue(log.info.notCalled); | |
673 | assert.isTrue(log.error.calledOnce); | |
674 | }); | |
675 | }); | |
676 | ||
677 | describe("when supplied with a plugin", () => { | |
678 | it("should pass plugins to CLIEngine", () => { | |
679 | const examplePluginName = "eslint-plugin-example"; | |
680 | ||
681 | verifyCLIEngineOpts(`--no-ignore --plugin ${examplePluginName} foo.js`, { | |
682 | plugins: [examplePluginName] | |
683 | }); | |
684 | }); | |
685 | ||
686 | }); | |
687 | ||
688 | describe("when supplied with a plugin-loading path", () => { | |
689 | it("should pass the option to CLIEngine", () => { | |
690 | const examplePluginDirPath = "foo/bar"; | |
691 | ||
692 | verifyCLIEngineOpts(`--resolve-plugins-relative-to ${examplePluginDirPath} foo.js`, { | |
693 | resolvePluginsRelativeTo: examplePluginDirPath | |
694 | }); | |
695 | }); | |
696 | }); | |
697 | ||
698 | describe("when given an parser name", () => { | |
699 | it("should exit with a fatal error if parser is invalid", () => { | |
700 | const filePath = getFixturePath("passing.js"); | |
701 | ||
702 | assert.throws(() => cli.execute(`--no-ignore --parser test111 ${filePath}`), "Cannot find module 'test111'"); | |
703 | }); | |
704 | ||
705 | it("should exit with no error if parser is valid", () => { | |
706 | const filePath = getFixturePath("passing.js"); | |
707 | const exit = cli.execute(`--no-ignore --parser espree ${filePath}`); | |
708 | ||
709 | assert.strictEqual(exit, 0); | |
710 | }); | |
711 | }); | |
712 | ||
713 | describe("when given parser options", () => { | |
714 | it("should exit with error if parser options are invalid", () => { | |
715 | const filePath = getFixturePath("passing.js"); | |
716 | const exit = cli.execute(`--no-ignore --parser-options test111 ${filePath}`); | |
717 | ||
718 | assert.strictEqual(exit, 2); | |
719 | }); | |
720 | ||
721 | it("should exit with no error if parser is valid", () => { | |
722 | const filePath = getFixturePath("passing.js"); | |
723 | const exit = cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`); | |
724 | ||
725 | assert.strictEqual(exit, 0); | |
726 | }); | |
727 | ||
728 | it("should exit with an error on ecmaVersion 7 feature in ecmaVersion 6", () => { | |
729 | const filePath = getFixturePath("passing-es7.js"); | |
730 | const exit = cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`); | |
731 | ||
732 | assert.strictEqual(exit, 1); | |
733 | }); | |
734 | ||
735 | it("should exit with no error on ecmaVersion 7 feature in ecmaVersion 7", () => { | |
736 | const filePath = getFixturePath("passing-es7.js"); | |
737 | const exit = cli.execute(`--no-ignore --parser-options=ecmaVersion:7 ${filePath}`); | |
738 | ||
739 | assert.strictEqual(exit, 0); | |
740 | }); | |
741 | ||
742 | it("should exit with no error on ecmaVersion 7 feature with config ecmaVersion 6 and command line ecmaVersion 7", () => { | |
743 | const configPath = getFixturePath("configurations", "es6.json"); | |
744 | const filePath = getFixturePath("passing-es7.js"); | |
745 | const exit = cli.execute(`--no-ignore --config ${configPath} --parser-options=ecmaVersion:7 ${filePath}`); | |
746 | ||
747 | assert.strictEqual(exit, 0); | |
748 | }); | |
749 | }); | |
750 | ||
751 | describe("when given the max-warnings flag", () => { | |
752 | it("should not change exit code if warning count under threshold", () => { | |
753 | const filePath = getFixturePath("max-warnings"); | |
754 | const exitCode = cli.execute(`--no-ignore --max-warnings 10 ${filePath}`); | |
755 | ||
756 | assert.strictEqual(exitCode, 0); | |
757 | }); | |
758 | ||
759 | it("should exit with exit code 1 if warning count exceeds threshold", () => { | |
760 | const filePath = getFixturePath("max-warnings"); | |
761 | const exitCode = cli.execute(`--no-ignore --max-warnings 5 ${filePath}`); | |
762 | ||
763 | assert.strictEqual(exitCode, 1); | |
764 | assert.ok(log.error.calledOnce); | |
765 | assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings"); | |
766 | }); | |
767 | ||
768 | it("should not change exit code if warning count equals threshold", () => { | |
769 | const filePath = getFixturePath("max-warnings"); | |
770 | const exitCode = cli.execute(`--no-ignore --max-warnings 6 ${filePath}`); | |
771 | ||
772 | assert.strictEqual(exitCode, 0); | |
773 | }); | |
774 | ||
775 | it("should not change exit code if flag is not specified and there are warnings", () => { | |
776 | const filePath = getFixturePath("max-warnings"); | |
777 | const exitCode = cli.execute(filePath); | |
778 | ||
779 | assert.strictEqual(exitCode, 0); | |
780 | }); | |
781 | }); | |
782 | ||
783 | describe("when passed --no-inline-config", () => { | |
784 | let localCLI; | |
785 | ||
786 | afterEach(() => { | |
787 | sinon.verifyAndRestore(); | |
788 | }); | |
789 | ||
790 | it("should pass allowInlineConfig:true to CLIEngine when --no-inline-config is used", () => { | |
791 | ||
792 | // create a fake CLIEngine to test with | |
793 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: false })); | |
794 | ||
795 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
796 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({ | |
797 | errorCount: 1, | |
798 | warningCount: 0, | |
799 | results: [{ | |
800 | filePath: "./foo.js", | |
801 | output: "bar", | |
802 | messages: [ | |
803 | { | |
804 | severity: 2, | |
805 | message: "Fake message" | |
806 | } | |
807 | ] | |
808 | }] | |
809 | }); | |
810 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
811 | fakeCLIEngine.outputFixes = sinon.stub(); | |
812 | ||
813 | localCLI = proxyquire("../../lib/cli", { | |
814 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
815 | "./shared/logging": log | |
816 | }); | |
817 | ||
818 | localCLI.execute("--no-inline-config ."); | |
819 | }); | |
820 | ||
821 | it("should not error and allowInlineConfig should be true by default", () => { | |
822 | ||
823 | // create a fake CLIEngine to test with | |
824 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: true })); | |
825 | ||
826 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
827 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({ | |
828 | errorCount: 0, | |
829 | warningCount: 0, | |
830 | results: [] | |
831 | }); | |
832 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
833 | sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map()); | |
834 | fakeCLIEngine.outputFixes = sinon.stub(); | |
835 | ||
836 | localCLI = proxyquire("../../lib/cli", { | |
837 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
838 | "./shared/logging": log | |
839 | }); | |
840 | ||
841 | const exitCode = localCLI.execute("."); | |
842 | ||
843 | assert.strictEqual(exitCode, 0); | |
844 | ||
845 | }); | |
846 | ||
847 | }); | |
848 | ||
849 | describe("when passed --fix", () => { | |
850 | let localCLI; | |
851 | ||
852 | afterEach(() => { | |
853 | sinon.verifyAndRestore(); | |
854 | }); | |
855 | ||
856 | it("should pass fix:true to CLIEngine when executing on files", () => { | |
857 | ||
858 | // create a fake CLIEngine to test with | |
859 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true })); | |
860 | ||
861 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
862 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({ | |
863 | errorCount: 0, | |
864 | warningCount: 0, | |
865 | results: [] | |
866 | }); | |
867 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
868 | sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map()); | |
869 | fakeCLIEngine.outputFixes = sinon.mock().once(); | |
870 | ||
871 | localCLI = proxyquire("../../lib/cli", { | |
872 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
873 | "./shared/logging": log | |
874 | }); | |
875 | ||
876 | const exitCode = localCLI.execute("--fix ."); | |
877 | ||
878 | assert.strictEqual(exitCode, 0); | |
879 | ||
880 | }); | |
881 | ||
882 | ||
883 | it("should rewrite files when in fix mode", () => { | |
884 | ||
885 | const report = { | |
886 | errorCount: 1, | |
887 | warningCount: 0, | |
888 | results: [{ | |
889 | filePath: "./foo.js", | |
890 | output: "bar", | |
891 | messages: [ | |
892 | { | |
893 | severity: 2, | |
894 | message: "Fake message" | |
895 | } | |
896 | ] | |
897 | }] | |
898 | }; | |
899 | ||
900 | // create a fake CLIEngine to test with | |
901 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true })); | |
902 | ||
903 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
904 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns(report); | |
905 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
906 | sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map()); | |
907 | fakeCLIEngine.outputFixes = sinon.mock().withExactArgs(report); | |
908 | ||
909 | localCLI = proxyquire("../../lib/cli", { | |
910 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
911 | "./shared/logging": log | |
912 | }); | |
913 | ||
914 | const exitCode = localCLI.execute("--fix ."); | |
915 | ||
916 | assert.strictEqual(exitCode, 1); | |
917 | ||
918 | }); | |
919 | ||
920 | it("should provide fix predicate and rewrite files when in fix mode and quiet mode", () => { | |
921 | ||
922 | const report = { | |
923 | errorCount: 0, | |
924 | warningCount: 1, | |
925 | results: [{ | |
926 | filePath: "./foo.js", | |
927 | output: "bar", | |
928 | messages: [ | |
929 | { | |
930 | severity: 1, | |
931 | message: "Fake message" | |
932 | } | |
933 | ] | |
934 | }] | |
935 | }; | |
936 | ||
937 | // create a fake CLIEngine to test with | |
938 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func })); | |
939 | ||
940 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
941 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns(report); | |
942 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
943 | sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map()); | |
944 | fakeCLIEngine.getErrorResults = sinon.stub().returns([]); | |
945 | fakeCLIEngine.outputFixes = sinon.mock().withExactArgs(report); | |
946 | ||
947 | localCLI = proxyquire("../../lib/cli", { | |
948 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
949 | "./shared/logging": log | |
950 | }); | |
951 | ||
952 | const exitCode = localCLI.execute("--fix --quiet ."); | |
953 | ||
954 | assert.strictEqual(exitCode, 0); | |
955 | ||
956 | }); | |
957 | ||
958 | it("should not call CLIEngine and return 1 when executing on text", () => { | |
959 | ||
960 | // create a fake CLIEngine to test with | |
961 | const fakeCLIEngine = sinon.mock().never(); | |
962 | ||
963 | localCLI = proxyquire("../../lib/cli", { | |
964 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
965 | "./shared/logging": log | |
966 | }); | |
967 | ||
968 | const exitCode = localCLI.execute("--fix .", "foo = bar;"); | |
969 | ||
970 | assert.strictEqual(exitCode, 2); | |
971 | }); | |
972 | ||
973 | }); | |
974 | ||
975 | describe("when passed --fix-dry-run", () => { | |
976 | let localCLI; | |
977 | ||
978 | afterEach(() => { | |
979 | sinon.verifyAndRestore(); | |
980 | }); | |
981 | ||
982 | it("should pass fix:true to CLIEngine when executing on files", () => { | |
983 | ||
984 | // create a fake CLIEngine to test with | |
985 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true })); | |
986 | ||
987 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
988 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({ | |
989 | errorCount: 0, | |
990 | warningCount: 0, | |
991 | results: [] | |
992 | }); | |
993 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
994 | sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map()); | |
995 | fakeCLIEngine.outputFixes = sinon.mock().never(); | |
996 | ||
997 | localCLI = proxyquire("../../lib/cli", { | |
998 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
999 | "./shared/logging": log | |
1000 | }); | |
1001 | ||
1002 | const exitCode = localCLI.execute("--fix-dry-run ."); | |
1003 | ||
1004 | assert.strictEqual(exitCode, 0); | |
1005 | ||
1006 | }); | |
1007 | ||
1008 | it("should pass fixTypes to CLIEngine when --fix-type is passed", () => { | |
1009 | ||
1010 | const expectedCLIEngineOptions = { | |
1011 | fix: true, | |
1012 | fixTypes: ["suggestion"] | |
1013 | }; | |
1014 | ||
1015 | // create a fake CLIEngine to test with | |
1016 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match(expectedCLIEngineOptions)); | |
1017 | ||
1018 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
1019 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({ | |
1020 | errorCount: 0, | |
1021 | warningCount: 0, | |
1022 | results: [] | |
1023 | }); | |
1024 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
1025 | sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map()); | |
1026 | fakeCLIEngine.outputFixes = sinon.stub(); | |
1027 | ||
1028 | localCLI = proxyquire("../../lib/cli", { | |
1029 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
1030 | "./shared/logging": log | |
1031 | }); | |
1032 | ||
1033 | const exitCode = localCLI.execute("--fix-dry-run --fix-type suggestion ."); | |
1034 | ||
1035 | assert.strictEqual(exitCode, 0); | |
1036 | }); | |
1037 | ||
1038 | it("should not rewrite files when in fix-dry-run mode", () => { | |
1039 | ||
1040 | const report = { | |
1041 | errorCount: 1, | |
1042 | warningCount: 0, | |
1043 | results: [{ | |
1044 | filePath: "./foo.js", | |
1045 | output: "bar", | |
1046 | messages: [ | |
1047 | { | |
1048 | severity: 2, | |
1049 | message: "Fake message" | |
1050 | } | |
1051 | ] | |
1052 | }] | |
1053 | }; | |
1054 | ||
1055 | // create a fake CLIEngine to test with | |
1056 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true })); | |
1057 | ||
1058 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
1059 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns(report); | |
1060 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
1061 | sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map()); | |
1062 | fakeCLIEngine.outputFixes = sinon.mock().never(); | |
1063 | ||
1064 | localCLI = proxyquire("../../lib/cli", { | |
1065 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
1066 | "./shared/logging": log | |
1067 | }); | |
1068 | ||
1069 | const exitCode = localCLI.execute("--fix-dry-run ."); | |
1070 | ||
1071 | assert.strictEqual(exitCode, 1); | |
1072 | ||
1073 | }); | |
1074 | ||
1075 | it("should provide fix predicate when in fix-dry-run mode and quiet mode", () => { | |
1076 | ||
1077 | const report = { | |
1078 | errorCount: 0, | |
1079 | warningCount: 1, | |
1080 | results: [{ | |
1081 | filePath: "./foo.js", | |
1082 | output: "bar", | |
1083 | messages: [ | |
1084 | { | |
1085 | severity: 1, | |
1086 | message: "Fake message" | |
1087 | } | |
1088 | ] | |
1089 | }] | |
1090 | }; | |
1091 | ||
1092 | // create a fake CLIEngine to test with | |
1093 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func })); | |
1094 | ||
1095 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
1096 | sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns(report); | |
1097 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
1098 | sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map()); | |
1099 | fakeCLIEngine.getErrorResults = sinon.stub().returns([]); | |
1100 | fakeCLIEngine.outputFixes = sinon.mock().never(); | |
1101 | ||
1102 | localCLI = proxyquire("../../lib/cli", { | |
1103 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
1104 | "./shared/logging": log | |
1105 | }); | |
1106 | ||
1107 | const exitCode = localCLI.execute("--fix-dry-run --quiet ."); | |
1108 | ||
1109 | assert.strictEqual(exitCode, 0); | |
1110 | ||
1111 | }); | |
1112 | ||
1113 | it("should allow executing on text", () => { | |
1114 | ||
1115 | const report = { | |
1116 | errorCount: 1, | |
1117 | warningCount: 0, | |
1118 | results: [{ | |
1119 | filePath: "./foo.js", | |
1120 | output: "bar", | |
1121 | messages: [ | |
1122 | { | |
1123 | severity: 2, | |
1124 | message: "Fake message" | |
1125 | } | |
1126 | ] | |
1127 | }] | |
1128 | }; | |
1129 | ||
1130 | // create a fake CLIEngine to test with | |
1131 | const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true })); | |
1132 | ||
1133 | Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype)); | |
1134 | sinon.stub(fakeCLIEngine.prototype, "executeOnText").returns(report); | |
1135 | sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done"); | |
1136 | sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map()); | |
1137 | fakeCLIEngine.outputFixes = sinon.mock().never(); | |
1138 | ||
1139 | localCLI = proxyquire("../../lib/cli", { | |
1140 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
1141 | "./shared/logging": log | |
1142 | }); | |
1143 | ||
1144 | const exitCode = localCLI.execute("--fix-dry-run .", "foo = bar;"); | |
1145 | ||
1146 | assert.strictEqual(exitCode, 1); | |
1147 | }); | |
1148 | ||
1149 | it("should not call CLIEngine and return 1 when used with --fix", () => { | |
1150 | ||
1151 | // create a fake CLIEngine to test with | |
1152 | const fakeCLIEngine = sinon.mock().never(); | |
1153 | ||
1154 | localCLI = proxyquire("../../lib/cli", { | |
1155 | "./cli-engine/index": { CLIEngine: fakeCLIEngine }, | |
1156 | "./shared/logging": log | |
1157 | }); | |
1158 | ||
1159 | const exitCode = localCLI.execute("--fix --fix-dry-run .", "foo = bar;"); | |
1160 | ||
1161 | assert.strictEqual(exitCode, 2); | |
1162 | }); | |
1163 | }); | |
1164 | ||
1165 | describe("when passing --print-config", () => { | |
1166 | it("should print out the configuration", () => { | |
1167 | const filePath = getFixturePath("xxxx"); | |
1168 | ||
1169 | const exitCode = cli.execute(`--print-config ${filePath}`); | |
1170 | ||
1171 | assert.isTrue(log.info.calledOnce); | |
1172 | assert.strictEqual(exitCode, 0); | |
1173 | }); | |
1174 | ||
1175 | it("should error if any positional file arguments are passed", () => { | |
1176 | const filePath1 = getFixturePath("files", "bar.js"); | |
1177 | const filePath2 = getFixturePath("files", "foo.js"); | |
1178 | ||
1179 | const exitCode = cli.execute(`--print-config ${filePath1} ${filePath2}`); | |
1180 | ||
1181 | assert.isTrue(log.info.notCalled); | |
1182 | assert.isTrue(log.error.calledOnce); | |
1183 | assert.strictEqual(exitCode, 2); | |
1184 | }); | |
1185 | ||
1186 | it("should error out when executing on text", () => { | |
1187 | const exitCode = cli.execute("--print-config=myFile.js", "foo = bar;"); | |
1188 | ||
1189 | assert.isTrue(log.info.notCalled); | |
1190 | assert.isTrue(log.error.calledOnce); | |
1191 | assert.strictEqual(exitCode, 2); | |
1192 | }); | |
1193 | }); | |
1194 | ||
1195 | }); |