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