*/
"use strict";
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
const fs = require("fs");
const path = require("path");
const os = require("os");
const { assert } = require("chai");
const sh = require("shelljs");
-const { CascadingConfigArrayFactory } =
- require("@eslint/eslintrc/lib/cascading-config-array-factory");
+const sinon = require("sinon");
+const {
+ Legacy: {
+ CascadingConfigArrayFactory
+ }
+} = require("@eslint/eslintrc");
const { createCustomTeardown } = require("../../_utils");
const { FileEnumerator } = require("../../../lib/cli-engine/file-enumerator");
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
describe("FileEnumerator", () => {
describe("'iterateFiles(patterns)' method should iterate files and configs.", () => {
describe("with three directories ('lib', 'lib/nested', 'test') that contains 'one.js' and 'two.js'", () => {
describe("if 'lib/*.js' was given,", () => {
- /** @type {Array<{config:(typeof import('../../../lib/cli-engine'))["ConfigArray"], filePath:string, ignored:boolean}>} */
+ /** @type {Array<{config:(typeof import('../../../lib/cli-engine')).ConfigArray, filePath:string, ignored:boolean}>} */
let list;
beforeEach(() => {
describe("if 'lib/**/*.js' was given,", () => {
- /** @type {Array<{config:(typeof import('../../../lib/cli-engine'))["ConfigArray"], filePath:string, ignored:boolean}>} */
+ /** @type {Array<{config:(typeof import('../../../lib/cli-engine')).ConfigArray, filePath:string, ignored:boolean}>} */
let list;
beforeEach(() => {
describe("if 'lib/*.js' and 'test/*.js' were given,", () => {
- /** @type {Array<{config:(typeof import('../../../lib/cli-engine'))["ConfigArray"], filePath:string, ignored:boolean}>} */
+ /** @type {Array<{config:(typeof import('../../../lib/cli-engine')).ConfigArray, filePath:string, ignored:boolean}>} */
let list;
beforeEach(() => {
});
});
+ // https://github.com/eslint/eslint/issues/14742
+ describe("with 5 directories ('{lib}', '{lib}/client', '{lib}/client/src', '{lib}/server', '{lib}/server/src') that contains two files '{lib}/client/src/one.js' and '{lib}/server/src/two.js'", () => {
+ const root = path.join(os.tmpdir(), "eslint/file-enumerator");
+ const files = {
+ "{lib}/client/src/one.js": "console.log('one.js');",
+ "{lib}/server/src/two.js": "console.log('two.js');",
+ "{lib}/client/.eslintrc.json": JSON.stringify({
+ rules: {
+ "no-console": "error"
+ },
+ env: {
+ mocha: true
+ }
+ }),
+ "{lib}/server/.eslintrc.json": JSON.stringify({
+ rules: {
+ "no-console": "off"
+ },
+ env: {
+ mocha: true
+ }
+ })
+ };
+ const { prepare, cleanup, getPath } = createCustomTeardown({
+ cwd: root,
+ files
+ });
+
+ /** @type {FileEnumerator} */
+ let enumerator;
+
+ beforeEach(async () => {
+ await prepare();
+ enumerator = new FileEnumerator({
+ cwd: path.resolve(getPath("{lib}/server"))
+ });
+ });
+
+ afterEach(cleanup);
+
+ describe("when running eslint in the server directory", () => {
+ it("should use the config '{lib}/server/.eslintrc.json' for '{lib}/server/src/two.js'.", () => {
+ const spy = sinon.spy(fs, "readdirSync");
+
+ const list = [
+ ...enumerator.iterateFiles(["src/**/*.{js,json}"])
+ ];
+
+ // should enter the directory '{lib}/server/src' directly
+ assert.strictEqual(spy.getCall(0).firstArg, path.join(root, "{lib}/server/src"));
+ assert.strictEqual(list.length, 1);
+ assert.strictEqual(list[0].config.length, 2);
+ assert.strictEqual(list[0].config[0].name, "DefaultIgnorePattern");
+ assert.strictEqual(list[0].config[1].filePath, getPath("{lib}/server/.eslintrc.json"));
+ assert.deepStrictEqual(
+ list.map(entry => entry.filePath),
+ [
+ path.join(root, "{lib}/server/src/two.js")
+ ]
+ );
+
+ // destroy the spy
+ sinon.restore();
+ });
+ });
+ });
+
// This group moved from 'tests/lib/util/glob-utils.js' when refactoring to keep the cumulated test cases.
describe("with 'tests/fixtures/glob-utils' files", () => {
let fixtureDir;
* it just for this hook. Mocha uses `this` to set timeouts on
* an individual hook level.
*/
- this.timeout(60 * 1000); // eslint-disable-line no-invalid-this
+ this.timeout(60 * 1000); // eslint-disable-line no-invalid-this -- Mocha API
fixtureDir = `${os.tmpdir()}/eslint/tests/fixtures/`;
sh.mkdir("-p", fixtureDir);
sh.cp("-r", "./tests/fixtures/*", fixtureDir);
const files = {
"file.js": "",
".eslintrc.json": JSON.stringify({
- extends: ["eslint:recommended"]
+ extends: ["eslint:recommended", "eslint:all"]
})
};
const { prepare, cleanup, getPath } = createCustomTeardown({ cwd: root, files });