]> git.proxmox.com Git - pve-eslint.git/blame - eslint/tests/lib/cli-engine/file-enumerator.js
upgrade to v7.0.0
[pve-eslint.git] / eslint / tests / lib / cli-engine / file-enumerator.js
CommitLineData
eb39fafa
DC
1/**
2 * @fileoverview Tests for FileEnumerator class.
3 * @author Toru Nagashima <https://github.com/mysticatea>
4 */
5"use strict";
6
7const fs = require("fs");
8const path = require("path");
9const os = require("os");
10const { assert } = require("chai");
11const sh = require("shelljs");
12const { CascadingConfigArrayFactory } =
13 require("../../../lib/cli-engine/cascading-config-array-factory");
56c4a2cb 14const { defineFileEnumeratorWithInMemoryFileSystem } = require("../../_utils");
eb39fafa
DC
15
16describe("FileEnumerator", () => {
17 describe("'iterateFiles(patterns)' method should iterate files and configs.", () => {
18 describe("with three directories ('lib', 'lib/nested', 'test') that contains 'one.js' and 'two.js'", () => {
19 const root = path.join(os.tmpdir(), "eslint/file-enumerator");
20 const files = {
21 /* eslint-disable quote-props */
22 "lib": {
23 "nested": {
24 "one.js": "",
25 "two.js": "",
26 "parser.js": "",
27 ".eslintrc.yml": "parser: './parser'"
28 },
29 "one.js": "",
30 "two.js": ""
31 },
32 "test": {
33 "one.js": "",
34 "two.js": "",
35 ".eslintrc.yml": "env: { mocha: true }"
36 },
37 ".eslintignore": "/lib/nested/parser.js",
38 ".eslintrc.json": JSON.stringify({
39 rules: {
40 "no-undef": "error",
41 "no-unused-vars": "error"
42 }
43 })
44 /* eslint-enable quote-props */
45 };
46 const { FileEnumerator } = defineFileEnumeratorWithInMemoryFileSystem({ cwd: () => root, files });
47
48 /** @type {FileEnumerator} */
49 let enumerator;
50
51 beforeEach(() => {
52 enumerator = new FileEnumerator();
53 });
54
55 it("should ignore empty strings.", () => {
56 Array.from(enumerator.iterateFiles(["lib/*.js", ""])); // don't throw "file not found" error.
57 });
58
59 describe("if 'lib/*.js' was given,", () => {
60
61 /** @type {Array<{config:(typeof import('../../../lib/cli-engine'))["ConfigArray"], filePath:string, ignored:boolean}>} */
62 let list;
63
64 beforeEach(() => {
65 list = [...enumerator.iterateFiles("lib/*.js")];
66 });
67
68 it("should list two files.", () => {
69 assert.strictEqual(list.length, 2);
70 });
71
72 it("should list 'lib/one.js' and 'lib/two.js'.", () => {
73 assert.deepStrictEqual(
74 list.map(entry => entry.filePath),
75 [
76 path.join(root, "lib/one.js"),
77 path.join(root, "lib/two.js")
78 ]
79 );
80 });
81
82 it("should use the config '.eslintrc.json' for both files.", () => {
83 assert.strictEqual(list[0].config, list[1].config);
84 assert.strictEqual(list[0].config.length, 3);
85 assert.strictEqual(list[0].config[0].name, "DefaultIgnorePattern");
86 assert.strictEqual(list[0].config[1].filePath, path.join(root, ".eslintrc.json"));
87 assert.strictEqual(list[0].config[2].filePath, path.join(root, ".eslintignore"));
88 });
89 });
90
91 describe("if 'lib/**/*.js' was given,", () => {
92
93 /** @type {Array<{config:(typeof import('../../../lib/cli-engine'))["ConfigArray"], filePath:string, ignored:boolean}>} */
94 let list;
95
96 beforeEach(() => {
97 list = [...enumerator.iterateFiles("lib/**/*.js")];
98 });
99
100 it("should list four files.", () => {
101 assert.strictEqual(list.length, 4);
102 });
103
104 it("should list 'lib/nested/one.js', 'lib/nested/two.js', 'lib/one.js', 'lib/two.js'.", () => {
105 assert.deepStrictEqual(
106 list.map(entry => entry.filePath),
107 [
108 path.join(root, "lib/nested/one.js"),
109 path.join(root, "lib/nested/two.js"),
110 path.join(root, "lib/one.js"),
111 path.join(root, "lib/two.js")
112 ]
113 );
114 });
115
116 it("should use the merged config of '.eslintrc.json' and 'lib/nested/.eslintrc.yml' for 'lib/nested/one.js' and 'lib/nested/two.js'.", () => {
117 assert.strictEqual(list[0].config, list[1].config);
118 assert.strictEqual(list[0].config.length, 4);
119 assert.strictEqual(list[0].config[0].name, "DefaultIgnorePattern");
120 assert.strictEqual(list[0].config[1].filePath, path.join(root, ".eslintrc.json"));
121 assert.strictEqual(list[0].config[2].filePath, path.join(root, "lib/nested/.eslintrc.yml"));
122 assert.strictEqual(list[0].config[3].filePath, path.join(root, ".eslintignore"));
123 });
124
125 it("should use the config '.eslintrc.json' for 'lib/one.js' and 'lib/two.js'.", () => {
126 assert.strictEqual(list[2].config, list[3].config);
127 assert.strictEqual(list[2].config.length, 3);
128 assert.strictEqual(list[2].config[0].name, "DefaultIgnorePattern");
129 assert.strictEqual(list[2].config[1].filePath, path.join(root, ".eslintrc.json"));
130 assert.strictEqual(list[2].config[2].filePath, path.join(root, ".eslintignore"));
131 });
132 });
133
134 describe("if 'lib/*.js' and 'test/*.js' were given,", () => {
135
136 /** @type {Array<{config:(typeof import('../../../lib/cli-engine'))["ConfigArray"], filePath:string, ignored:boolean}>} */
137 let list;
138
139 beforeEach(() => {
140 list = [...enumerator.iterateFiles(["lib/*.js", "test/*.js"])];
141 });
142
143 it("should list four files.", () => {
144 assert.strictEqual(list.length, 4);
145 });
146
147 it("should list 'lib/one.js', 'lib/two.js', 'test/one.js', 'test/two.js'.", () => {
148 assert.deepStrictEqual(
149 list.map(entry => entry.filePath),
150 [
151 path.join(root, "lib/one.js"),
152 path.join(root, "lib/two.js"),
153 path.join(root, "test/one.js"),
154 path.join(root, "test/two.js")
155 ]
156 );
157 });
158
159 it("should use the config '.eslintrc.json' for 'lib/one.js' and 'lib/two.js'.", () => {
160 assert.strictEqual(list[0].config, list[1].config);
161 assert.strictEqual(list[0].config.length, 3);
162 assert.strictEqual(list[0].config[0].name, "DefaultIgnorePattern");
163 assert.strictEqual(list[0].config[1].filePath, path.join(root, ".eslintrc.json"));
164 assert.strictEqual(list[0].config[2].filePath, path.join(root, ".eslintignore"));
165 });
166
167 it("should use the merged config of '.eslintrc.json' and 'test/.eslintrc.yml' for 'test/one.js' and 'test/two.js'.", () => {
168 assert.strictEqual(list[2].config, list[3].config);
169 assert.strictEqual(list[2].config.length, 4);
170 assert.strictEqual(list[2].config[0].name, "DefaultIgnorePattern");
171 assert.strictEqual(list[2].config[1].filePath, path.join(root, ".eslintrc.json"));
172 assert.strictEqual(list[2].config[2].filePath, path.join(root, "test/.eslintrc.yml"));
173 assert.strictEqual(list[2].config[3].filePath, path.join(root, ".eslintignore"));
174 });
175 });
176 });
177
178 // This group moved from 'tests/lib/util/glob-utils.js' when refactoring to keep the cumulated test cases.
179 describe("with 'tests/fixtures/glob-utils' files", () => {
180 const { FileEnumerator } = require("../../../lib/cli-engine/file-enumerator");
181 let fixtureDir;
182
183 /**
184 * Returns the path inside of the fixture directory.
185 * @param {...string} args file path segments.
186 * @returns {string} The path inside the fixture directory.
187 * @private
188 */
189 function getFixturePath(...args) {
190 return path.join(fs.realpathSync(fixtureDir), ...args);
191 }
192
193 /**
194 * List files as a compatible shape with glob-utils.
195 * @param {string|string[]} patterns The patterns to list files.
196 * @param {Object} options The option for FileEnumerator.
197 * @returns {{filename:string,ignored:boolean}[]} The listed files.
198 */
199 function listFiles(patterns, options) {
200 return Array.from(
201 new FileEnumerator({
202 ...options,
203 configArrayFactory: new CascadingConfigArrayFactory({
204 ...options,
205
206 // Disable "No Configuration Found" error.
207 useEslintrc: false
208 })
209 }).iterateFiles(patterns),
210 ({ filePath, ignored }) => ({ filename: filePath, ignored })
211 );
212 }
213
214 before(() => {
215 fixtureDir = `${os.tmpdir()}/eslint/tests/fixtures/`;
216 sh.mkdir("-p", fixtureDir);
217 sh.cp("-r", "./tests/fixtures/*", fixtureDir);
218 });
219
220 after(() => {
221 sh.rm("-r", fixtureDir);
222 });
223
224 describe("listFilesToProcess()", () => {
225 it("should return an array with a resolved (absolute) filename", () => {
226 const patterns = [getFixturePath("glob-util", "one-js-file", "**/*.js")];
227 const result = listFiles(patterns, {
228 cwd: getFixturePath()
229 });
230
231 const file1 = getFixturePath("glob-util", "one-js-file", "baz.js");
232
233 assert.isArray(result);
234 assert.deepStrictEqual(result, [{ filename: file1, ignored: false }]);
235 });
236
237 it("should return all files matching a glob pattern", () => {
238 const patterns = [getFixturePath("glob-util", "two-js-files", "**/*.js")];
239 const result = listFiles(patterns, {
240 cwd: getFixturePath()
241 });
242
243 const file1 = getFixturePath("glob-util", "two-js-files", "bar.js");
244 const file2 = getFixturePath("glob-util", "two-js-files", "foo.js");
245
246 assert.strictEqual(result.length, 2);
247 assert.deepStrictEqual(result, [
248 { filename: file1, ignored: false },
249 { filename: file2, ignored: false }
250 ]);
251 });
252
253 it("should return all files matching multiple glob patterns", () => {
254 const patterns = [
255 getFixturePath("glob-util", "two-js-files", "**/*.js"),
256 getFixturePath("glob-util", "one-js-file", "**/*.js")
257 ];
258 const result = listFiles(patterns, {
259 cwd: getFixturePath()
260 });
261
262 const file1 = getFixturePath("glob-util", "two-js-files", "bar.js");
263 const file2 = getFixturePath("glob-util", "two-js-files", "foo.js");
264 const file3 = getFixturePath("glob-util", "one-js-file", "baz.js");
265
266 assert.strictEqual(result.length, 3);
267 assert.deepStrictEqual(result, [
268 { filename: file1, ignored: false },
269 { filename: file2, ignored: false },
270 { filename: file3, ignored: false }
271 ]);
272 });
273
274 it("should ignore hidden files for standard glob patterns", () => {
275 const patterns = [getFixturePath("glob-util", "hidden", "**/*.js")];
276
277 assert.throws(() => {
278 listFiles(patterns, {
279 cwd: getFixturePath()
280 });
281 }, `All files matched by '${patterns[0]}' are ignored.`);
282 });
283
284 it("should return hidden files if included in glob pattern", () => {
285 const patterns = [getFixturePath("glob-util", "hidden", "**/.*.js")];
286 const result = listFiles(patterns, {
287 cwd: getFixturePath()
288 });
289
290 const file1 = getFixturePath("glob-util", "hidden", ".foo.js");
291
292 assert.strictEqual(result.length, 1);
293 assert.deepStrictEqual(result, [
294 { filename: file1, ignored: false }
295 ]);
296 });
297
298 it("should ignore default ignored files if not passed explicitly", () => {
299 const directory = getFixturePath("glob-util", "hidden");
300 const patterns = [directory];
301
302 assert.throws(() => {
303 listFiles(patterns, {
304 cwd: getFixturePath()
305 });
306 }, `All files matched by '${directory}' are ignored.`);
307 });
308
309 it("should ignore and warn for default ignored files when passed explicitly", () => {
310 const filename = getFixturePath("glob-util", "hidden", ".foo.js");
311 const patterns = [filename];
312 const result = listFiles(patterns, {
313 cwd: getFixturePath()
314 });
315
316 assert.strictEqual(result.length, 1);
317 assert.deepStrictEqual(result[0], { filename, ignored: true });
318 });
319
320 it("should ignore default ignored files if not passed explicitly even if ignore is false", () => {
321 const directory = getFixturePath("glob-util", "hidden");
322 const patterns = [directory];
323
324 assert.throws(() => {
325 listFiles(patterns, {
326 cwd: getFixturePath(),
327 ignore: false
328 });
329 }, `All files matched by '${directory}' are ignored.`);
330 });
331
332 it("should not ignore default ignored files when passed explicitly if ignore is false", () => {
333 const filename = getFixturePath("glob-util", "hidden", ".foo.js");
334 const patterns = [filename];
335 const result = listFiles(patterns, {
336 cwd: getFixturePath(),
337 ignore: false
338 });
339
340 assert.strictEqual(result.length, 1);
341 assert.deepStrictEqual(result[0], { filename, ignored: false });
342 });
343
344 it("should throw an error for a file which does not exist", () => {
345 const filename = getFixturePath("glob-util", "hidden", "bar.js");
346 const patterns = [filename];
347
348 assert.throws(() => {
349 listFiles(patterns, {
350 cwd: getFixturePath(),
351 allowMissingGlobs: true
352 });
353 }, `No files matching '${filename}' were found.`);
354 });
355
356 it("should throw if a folder that does not have any applicable files is linted", () => {
357 const filename = getFixturePath("glob-util", "empty");
358 const patterns = [filename];
359
360 assert.throws(() => {
361 listFiles(patterns, {
362 cwd: getFixturePath()
363 });
364 }, `No files matching '${filename}' were found.`);
365 });
366
367 it("should throw if only ignored files match a glob", () => {
368 const pattern = getFixturePath("glob-util", "ignored");
369 const options = { ignore: true, ignorePath: getFixturePath("glob-util", "ignored", ".eslintignore") };
370
371 assert.throws(() => {
372 listFiles([pattern], options);
373 }, `All files matched by '${pattern}' are ignored.`);
374 });
375
376 it("should throw an error if no files match a glob", () => {
377
378 // Relying here on the .eslintignore from the repo root
379 const patterns = ["tests/fixtures/glob-util/ignored/**/*.js"];
380
381 assert.throws(() => {
382 listFiles(patterns);
383 }, `All files matched by '${patterns[0]}' are ignored.`);
384 });
385
386 it("should return an ignored file, if ignore option is turned off", () => {
387 const options = { ignore: false };
388 const patterns = [getFixturePath("glob-util", "ignored", "**/*.js")];
389 const result = listFiles(patterns, options);
390
391 assert.strictEqual(result.length, 1);
392 });
393
394 it("should ignore a file from a glob if it matches a pattern in an ignore file", () => {
395 const options = { ignore: true, ignorePath: getFixturePath("glob-util", "ignored", ".eslintignore") };
396 const patterns = [getFixturePath("glob-util", "ignored", "**/*.js")];
397
398 assert.throws(() => {
399 listFiles(patterns, options);
400 }, `All files matched by '${patterns[0]}' are ignored.`);
401 });
402
403 it("should ignore a file from a glob if matching a specified ignore pattern", () => {
404 const options = { ignore: true, cliConfig: { ignorePatterns: ["foo.js"] }, cwd: getFixturePath() };
405 const patterns = [getFixturePath("glob-util", "ignored", "**/*.js")];
406
407 assert.throws(() => {
408 listFiles(patterns, options);
409 }, `All files matched by '${patterns[0]}' are ignored.`);
410 });
411
412 it("should return a file only once if listed in more than 1 pattern", () => {
413 const patterns = [
414 getFixturePath("glob-util", "one-js-file", "**/*.js"),
415 getFixturePath("glob-util", "one-js-file", "baz.js")
416 ];
417 const result = listFiles(patterns, {
418 cwd: path.join(fixtureDir, "..")
419 });
420
421 const file1 = getFixturePath("glob-util", "one-js-file", "baz.js");
422
423 assert.isArray(result);
424 assert.deepStrictEqual(result, [
425 { filename: file1, ignored: false }
426 ]);
427 });
428
429 it("should set 'ignored: true' for files that are explicitly specified but ignored", () => {
430 const options = { ignore: true, cliConfig: { ignorePatterns: ["foo.js"] }, cwd: getFixturePath() };
431 const filename = getFixturePath("glob-util", "ignored", "foo.js");
432 const patterns = [filename];
433 const result = listFiles(patterns, options);
434
435 assert.strictEqual(result.length, 1);
436 assert.deepStrictEqual(result, [
437 { filename, ignored: true }
438 ]);
439 });
440
441 it("should not return files from default ignored folders", () => {
442 const options = { cwd: getFixturePath("glob-util") };
443 const glob = getFixturePath("glob-util", "**/*.js");
444 const patterns = [glob];
445 const result = listFiles(patterns, options);
446 const resultFilenames = result.map(resultObj => resultObj.filename);
447
448 assert.notInclude(resultFilenames, getFixturePath("glob-util", "node_modules", "dependency.js"));
449 });
450
451 it("should return unignored files from default ignored folders", () => {
452 const options = { cliConfig: { ignorePatterns: ["!/node_modules/dependency.js"] }, cwd: getFixturePath("glob-util") };
453 const glob = getFixturePath("glob-util", "**/*.js");
454 const patterns = [glob];
455 const result = listFiles(patterns, options);
456 const unignoredFilename = getFixturePath("glob-util", "node_modules", "dependency.js");
457
458 assert.includeDeepMembers(result, [{ filename: unignoredFilename, ignored: false }]);
459 });
460
461 it("should return unignored files from folders unignored in .eslintignore", () => {
462 const options = { cwd: getFixturePath("glob-util", "unignored"), ignore: true };
463 const glob = getFixturePath("glob-util", "unignored", "**/*.js");
464 const patterns = [glob];
465 const result = listFiles(patterns, options);
466
467 const filename = getFixturePath("glob-util", "unignored", "dir", "foo.js");
468
469 assert.strictEqual(result.length, 1);
470 assert.deepStrictEqual(result, [{ filename, ignored: false }]);
471 });
472
473 it("should return unignored files from folders unignored in .eslintignore for explicitly specified folder", () => {
474 const options = { cwd: getFixturePath("glob-util", "unignored"), ignore: true };
475 const dir = getFixturePath("glob-util", "unignored", "dir");
476 const patterns = [dir];
477 const result = listFiles(patterns, options);
478
479 const filename = getFixturePath("glob-util", "unignored", "dir", "foo.js");
480
481 assert.strictEqual(result.length, 1);
482 assert.deepStrictEqual(result, [{ filename, ignored: false }]);
483 });
484 });
485 });
486 });
487});