]> git.proxmox.com Git - pve-eslint.git/blobdiff - eslint/tests/lib/cli.js
import 8.23.1 source
[pve-eslint.git] / eslint / tests / lib / cli.js
index 59ff0eaf7a417ab8c710a7ea4ee679f13b05bed7..a58a8c910fccb8dac3e1895b45ad302ec3593621 100644 (file)
@@ -49,9 +49,10 @@ describe("cli", () => {
      * Verify that ESLint class receives correct opts via await cli.execute().
      * @param {string} cmd CLI command.
      * @param {Object} opts Options hash that should match that received by ESLint class.
+     * @param {string} configType The config type to work with.
      * @returns {void}
      */
-    async function verifyESLintOpts(cmd, opts) {
+    async function verifyESLintOpts(cmd, opts, configType) {
 
         // create a fake ESLint class to test with
         const fakeESLint = sinon.mock().withExactArgs(sinon.match(opts));
@@ -62,10 +63,11 @@ describe("cli", () => {
 
         const localCLI = proxyquire("../../lib/cli", {
             "./eslint": { ESLint: fakeESLint },
+            "./flat-eslint": { FlatESLint: fakeESLint, findFlatConfigFile: () => null },
             "./shared/logging": log
         });
 
-        await localCLI.execute(cmd);
+        await localCLI.execute(cmd, null, configType === "flat");
         sinon.verifyAndRestore();
     }
 
@@ -105,1123 +107,1237 @@ describe("cli", () => {
         sh.rm("-r", fixtureDir);
     });
 
-    describe("execute()", () => {
-        it("should return error when text with incorrect quotes is passed as argument", async () => {
-            const configFile = getFixturePath("configurations", "quotes-error.json");
-            const result = await cli.execute(`-c ${configFile}`, "var foo = 'bar';");
+    ["eslintrc", "flat"].forEach(configType => {
 
-            assert.strictEqual(result, 1);
-        });
+        const useFlatConfig = configType === "flat";
 
-        it("should not print debug info when passed the empty string as text", async () => {
-            const result = await cli.execute(["--stdin", "--no-eslintrc"], "");
+        describe("execute()", () => {
 
-            assert.strictEqual(result, 0);
-            assert.isTrue(log.info.notCalled);
-        });
+            it(`should return error when text with incorrect quotes is passed as argument with configType:${configType}`, async () => {
+                const configFile = getFixturePath("configurations", "quotes-error.js");
+                const result = await cli.execute(`-c ${configFile} --stdin --stdin-filename foo.js`, "var foo = 'bar';", useFlatConfig);
 
-        it("should return no error when --ext .js2 is specified", async () => {
-            const filePath = getFixturePath("files");
-            const result = await cli.execute(`--ext .js2 ${filePath}`);
+                assert.strictEqual(result, 1);
+            });
 
-            assert.strictEqual(result, 0);
-        });
+            it(`should not print debug info when passed the empty string as text with configType:${configType}`, async () => {
+                const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+                const result = await cli.execute(["--stdin", flag, "--stdin-filename", "foo.js"], "", useFlatConfig);
 
-        it("should exit with console error when passed unsupported arguments", async () => {
-            const filePath = getFixturePath("files");
-            const result = await cli.execute(`--blah --another ${filePath}`);
+                assert.strictEqual(result, 0);
+                assert.isTrue(log.info.notCalled);
+            });
+
+            it(`should exit with console error when passed unsupported arguments with configType:${configType}`, async () => {
+                const filePath = getFixturePath("files");
+                const result = await cli.execute(`--blah --another ${filePath}`, null, useFlatConfig);
+
+                assert.strictEqual(result, 2);
+            });
 
-            assert.strictEqual(result, 2);
         });
 
-    });
+        describe("when given a config with rules with options and severity level set to error", () => {
 
-    describe("when given a config file", () => {
-        it("should load the specified config file", async () => {
-            const configPath = getFixturePath(".eslintrc");
-            const filePath = getFixturePath("passing.js");
+            const originalCwd = process.cwd;
 
-            await cli.execute(`--config ${configPath} ${filePath}`);
-        });
-    });
+            beforeEach(() => {
+                process.cwd = () => getFixturePath();
+            });
 
-    describe("when there is a local config file", () => {
-        const code = "lib/cli.js";
+            afterEach(() => {
+                process.cwd = originalCwd;
+            });
+
+            it(`should exit with an error status (1) with configType:${configType}`, async () => {
+                const configPath = getFixturePath("configurations", "quotes-error.js");
+                const filePath = getFixturePath("single-quoted.js");
+                const code = `--no-ignore --config ${configPath} ${filePath}`;
 
-        it("should load the local config file", async () => {
+                const exitStatus = await cli.execute(code, null, useFlatConfig);
 
-            // Mock CWD
-            process.eslintCwd = getFixturePath("configurations", "single-quotes");
+                assert.strictEqual(exitStatus, 1);
+            });
+        });
 
-            await cli.execute(code);
+        describe("when given a config file and a directory of files", () => {
+            it(`should load and execute without error with configType:${configType}`, async () => {
+                const configPath = getFixturePath("configurations", "semi-error.js");
+                const filePath = getFixturePath("formatters");
+                const code = `--config ${configPath} ${filePath}`;
+                const exitStatus = await cli.execute(code, null, useFlatConfig);
 
-            process.eslintCwd = null;
+                assert.strictEqual(exitStatus, 0);
+            });
         });
-    });
 
-    describe("when given a config with rules with options and severity level set to error", () => {
-        it("should exit with an error status (1)", async () => {
-            const configPath = getFixturePath("configurations", "quotes-error.json");
-            const filePath = getFixturePath("single-quoted.js");
-            const code = `--no-ignore --config ${configPath} ${filePath}`;
+        describe("when there is a local config file", () => {
+
+            it(`should load the local config file with configType:${configType}`, async () => {
+                await cli.execute("lib/cli.js", null, useFlatConfig);
+            });
 
-            const exitStatus = await cli.execute(code);
+            if (useFlatConfig) {
+                it(`should load the local config file with glob pattern and configType:${configType}`, async () => {
+                    await cli.execute("lib/cli*.js", null, useFlatConfig);
+                });
+            }
 
-            assert.strictEqual(exitStatus, 1);
+            // only works on Windows
+            if (os.platform() === "win32") {
+                it(`should load the local config file with Windows slashes glob pattern and configType:${configType}`, async () => {
+                    await cli.execute("lib\\cli*.js", null, useFlatConfig);
+                });
+            }
         });
-    });
 
-    describe("when given a config file and a directory of files", () => {
-        it("should load and execute without error", async () => {
-            const configPath = getFixturePath("configurations", "semi-error.json");
-            const filePath = getFixturePath("formatters");
-            const code = `--config ${configPath} ${filePath}`;
+        describe("Formatters", () => {
 
-            const exitStatus = await cli.execute(code);
+            describe("when given a valid built-in formatter name", () => {
+                it(`should execute without any errors with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("passing.js");
+                    const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+                    const exit = await cli.execute(`${flag} -f checkstyle ${filePath}`, null, useFlatConfig);
 
-            assert.strictEqual(exitStatus, 0);
-        });
-    });
+                    assert.strictEqual(exit, 0);
+                });
+            });
 
-    describe("when given a config with environment set to browser", () => {
-        it("should execute without any errors", async () => {
-            const configPath = getFixturePath("configurations", "env-browser.json");
-            const filePath = getFixturePath("globals-browser.js");
-            const code = `--config ${configPath} ${filePath}`;
+            describe("when given a valid built-in formatter name that uses rules meta.", () => {
+
+                const originalCwd = process.cwd;
+
+                beforeEach(() => {
+                    process.cwd = () => getFixturePath();
+                });
+
+                afterEach(() => {
+                    process.cwd = originalCwd;
+                });
+
+                it(`should execute without any errors with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("passing.js");
+                    const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+                    const exit = await cli.execute(`--no-ignore -f json-with-metadata ${filePath} ${flag}`, null, useFlatConfig);
+
+                    assert.strictEqual(exit, 0);
+
+                    /*
+                     * Note: There is a behavior difference between eslintrc and flat config
+                     * when using formatters. For eslintrc, rulesMeta always contains every
+                     * rule that was loaded during the last run; for flat config, rulesMeta
+                     * only contains meta data for the rules that triggered messages in the
+                     * results. (Flat config uses ESLint#getRulesMetaForResults().)
+                     */
+
+                    // Check metadata.
+                    const { metadata } = JSON.parse(log.info.args[0][0]);
+                    const expectedMetadata = {
+                        cwd: process.cwd(),
+                        rulesMeta: useFlatConfig ? {} : Array.from(BuiltinRules).reduce((obj, [ruleId, rule]) => {
+                            obj[ruleId] = rule.meta;
+                            return obj;
+                        }, {})
+                    };
+
+                    assert.deepStrictEqual(metadata, expectedMetadata);
+                });
+            });
 
-            const exit = await cli.execute(code);
+            describe("when given an invalid built-in formatter name", () => {
+                it(`should execute with error: with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("passing.js");
+                    const exit = await cli.execute(`-f fakeformatter ${filePath}`);
 
-            assert.strictEqual(exit, 0);
-        });
-    });
+                    assert.strictEqual(exit, 2);
+                });
+            });
 
-    describe("when given a config with environment set to Node.js", () => {
-        it("should execute without any errors", async () => {
-            const configPath = getFixturePath("configurations", "env-node.json");
-            const filePath = getFixturePath("globals-node.js");
-            const code = `--config ${configPath} ${filePath}`;
+            describe("when given a valid formatter path", () => {
+                it(`should execute without any errors with configType:${configType}`, async () => {
+                    const formatterPath = getFixturePath("formatters", "simple.js");
+                    const filePath = getFixturePath("passing.js");
+                    const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
 
-            const exit = await cli.execute(code);
+                    assert.strictEqual(exit, 0);
+                });
+            });
 
-            assert.strictEqual(exit, 0);
-        });
-    });
+            describe("when given an invalid formatter path", () => {
+                it(`should execute with error with configType:${configType}`, async () => {
+                    const formatterPath = getFixturePath("formatters", "file-does-not-exist.js");
+                    const filePath = getFixturePath("passing.js");
+                    const exit = await cli.execute(`-f ${formatterPath} ${filePath}`, null, useFlatConfig);
 
-    describe("when given a config with environment set to Nashorn", () => {
-        it("should execute without any errors", async () => {
-            const configPath = getFixturePath("configurations", "env-nashorn.json");
-            const filePath = getFixturePath("globals-nashorn.js");
-            const code = `--config ${configPath} ${filePath}`;
+                    assert.strictEqual(exit, 2);
+                });
+            });
 
-            const exit = await cli.execute(code);
+            describe("when given an async formatter path", () => {
+                it(`should execute without any errors with configType:${configType}`, async () => {
+                    const formatterPath = getFixturePath("formatters", "async.js");
+                    const filePath = getFixturePath("passing.js");
+                    const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
 
-            assert.strictEqual(exit, 0);
+                    assert.strictEqual(log.info.getCall(0).args[0], "from async formatter");
+                    assert.strictEqual(exit, 0);
+                });
+            });
         });
-    });
 
-    describe("when given a config with environment set to WebExtensions", () => {
-        it("should execute without any errors", async () => {
-            const configPath = getFixturePath("configurations", "env-webextensions.json");
-            const filePath = getFixturePath("globals-webextensions.js");
-            const code = `--config ${configPath} ${filePath}`;
+        describe("Exit Codes", () => {
 
-            const exit = await cli.execute(code);
+            const originalCwd = process.cwd;
 
-            assert.strictEqual(exit, 0);
-        });
-    });
+            beforeEach(() => {
+                process.cwd = () => getFixturePath();
+            });
 
-    describe("when given a valid built-in formatter name", () => {
-        it("should execute without any errors", async () => {
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`-f checkstyle ${filePath}`);
+            afterEach(() => {
+                process.cwd = originalCwd;
+            });
 
-            assert.strictEqual(exit, 0);
-        });
-    });
+            describe("when executing a file with a lint error", () => {
 
-    describe("when given a valid built-in formatter name that uses rules meta.", () => {
-        it("should execute without any errors", async () => {
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`-f json-with-metadata ${filePath} --no-eslintrc`);
+                it(`should exit with error with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("undef.js");
+                    const code = `--no-ignore --rule no-undef:2 ${filePath}`;
 
-            assert.strictEqual(exit, 0);
+                    const exit = await cli.execute(code, null, useFlatConfig);
 
-            // Check metadata.
-            const { metadata } = JSON.parse(log.info.args[0][0]);
-            const expectedMetadata = {
-                cwd: process.cwd(),
-                rulesMeta: Array.from(BuiltinRules).reduce((obj, [ruleId, rule]) => {
-                    obj[ruleId] = rule.meta;
-                    return obj;
-                }, {})
-            };
+                    assert.strictEqual(exit, 1);
+                });
+            });
 
-            assert.deepStrictEqual(metadata, expectedMetadata);
-        });
-    });
+            describe("when using --fix-type without --fix or --fix-dry-run", () => {
+                it(`should exit with error with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("passing.js");
+                    const code = `--fix-type suggestion ${filePath}`;
 
-    describe("when given an invalid built-in formatter name", () => {
-        it("should execute with error", async () => {
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`-f fakeformatter ${filePath}`);
+                    const exit = await cli.execute(code, null, useFlatConfig);
 
-            assert.strictEqual(exit, 2);
-        });
-    });
+                    assert.strictEqual(exit, 2);
+                });
+            });
 
-    describe("when given a valid formatter path", () => {
-        it("should execute without any errors", async () => {
-            const formatterPath = getFixturePath("formatters", "simple.js");
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
+            describe("when executing a file with a syntax error", () => {
+                it(`should exit with error with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("syntax-error.js");
+                    const exit = await cli.execute(`--no-ignore ${filePath}`, null, useFlatConfig);
+
+                    assert.strictEqual(exit, 1);
+                });
+            });
 
-            assert.strictEqual(exit, 0);
         });
-    });
 
-    describe("when given an invalid formatter path", () => {
-        it("should execute with error", async () => {
-            const formatterPath = getFixturePath("formatters", "file-does-not-exist.js");
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
+        describe("when calling execute more than once", () => {
 
-            assert.strictEqual(exit, 2);
-        });
-    });
+            const originalCwd = process.cwd;
 
-    describe("when given an async formatter path", () => {
-        it("should execute without any errors", async () => {
-            const formatterPath = getFixturePath("formatters", "async.js");
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
+            beforeEach(() => {
+                process.cwd = () => getFixturePath();
+            });
 
-            assert.strictEqual(log.info.getCall(0).args[0], "from async formatter");
-            assert.strictEqual(exit, 0);
-        });
-    });
+            afterEach(() => {
+                process.cwd = originalCwd;
+            });
 
-    describe("when executing a file with a lint error", () => {
-        it("should exit with error", async () => {
-            const filePath = getFixturePath("undef.js");
-            const code = `--no-ignore --rule no-undef:2 ${filePath}`;
+            it(`should not print the results from previous execution with configType:${configType}`, async () => {
+                const filePath = getFixturePath("missing-semicolon.js");
+                const passingPath = getFixturePath("passing.js");
 
-            const exit = await cli.execute(code);
+                await cli.execute(`--no-ignore --rule semi:2 ${filePath}`, null, useFlatConfig);
 
-            assert.strictEqual(exit, 1);
-        });
-    });
+                assert.isTrue(log.info.called, "Log should have been called.");
 
-    describe("when using --fix-type without --fix or --fix-dry-run", () => {
-        it("should exit with error", async () => {
-            const filePath = getFixturePath("passing.js");
-            const code = `--fix-type suggestion ${filePath}`;
+                log.info.resetHistory();
 
-            const exit = await cli.execute(code);
+                await cli.execute(`--no-ignore --rule semi:2 ${passingPath}`, null, useFlatConfig);
+                assert.isTrue(log.info.notCalled);
 
-            assert.strictEqual(exit, 2);
+            });
         });
-    });
 
-    describe("when executing a file with a syntax error", () => {
-        it("should exit with error", async () => {
-            const filePath = getFixturePath("syntax-error.js");
-            const exit = await cli.execute(`--no-ignore ${filePath}`);
-
-            assert.strictEqual(exit, 1);
+        describe("when executing with version flag", () => {
+            it(`should print out current version with configType:${configType}`, async () => {
+                assert.strictEqual(await cli.execute("-v", null, useFlatConfig), 0);
+                assert.strictEqual(log.info.callCount, 1);
+            });
         });
-    });
 
-    describe("when calling execute more than once", () => {
-        it("should not print the results from previous execution", async () => {
-            const filePath = getFixturePath("missing-semicolon.js");
-            const passingPath = getFixturePath("passing.js");
+        describe("when executing with env-info flag", () => {
 
-            await cli.execute(`--no-ignore --rule semi:2 ${filePath}`);
+            it(`should print out environment information with configType:${configType}`, async () => {
+                assert.strictEqual(await cli.execute("--env-info", null, useFlatConfig), 0);
+                assert.strictEqual(log.info.callCount, 1);
+            });
 
-            assert.isTrue(log.info.called, "Log should have been called.");
+            describe("With error condition", () => {
 
-            log.info.resetHistory();
+                beforeEach(() => {
+                    RuntimeInfo.environment = sinon.stub().throws("There was an error!");
+                });
 
-            await cli.execute(`--no-ignore --rule semi:2 ${passingPath}`);
-            assert.isTrue(log.info.notCalled);
+                afterEach(() => {
+                    RuntimeInfo.environment = sinon.stub();
+                });
 
-        });
-    });
+                it(`should print error message and return error code with configType:${configType}`, async () => {
+
+                    assert.strictEqual(await cli.execute("--env-info", null, useFlatConfig), 2);
+                    assert.strictEqual(log.error.callCount, 1);
+                });
+            });
 
-    describe("when executing with version flag", () => {
-        it("should print out current version", async () => {
-            assert.strictEqual(await cli.execute("-v"), 0);
-            assert.strictEqual(log.info.callCount, 1);
         });
-    });
 
-    describe("when executing with env-info flag", () => {
-        it("should print out environment information", async () => {
-            assert.strictEqual(await cli.execute("--env-info"), 0);
-            assert.strictEqual(log.info.callCount, 1);
+        describe("when executing with help flag", () => {
+            it(`should print out help with configType:${configType}`, async () => {
+                assert.strictEqual(await cli.execute("-h", null, useFlatConfig), 0);
+                assert.strictEqual(log.info.callCount, 1);
+            });
         });
 
-        it("should print error message and return error code", async () => {
-            RuntimeInfo.environment.throws("There was an error!");
+        describe("when executing a file with a shebang", () => {
+            it(`should execute without error with configType:${configType}`, async () => {
+                const filePath = getFixturePath("shebang.js");
+                const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+                const exit = await cli.execute(`${flag} --no-ignore ${filePath}`, null, useFlatConfig);
 
-            assert.strictEqual(await cli.execute("--env-info"), 2);
-            assert.strictEqual(log.error.callCount, 1);
+                assert.strictEqual(exit, 0);
+            });
         });
-    });
 
-    describe("when executing without no-error-on-unmatched-pattern flag", () => {
-        it("should throw an error on unmatched glob pattern", async () => {
-            const filePath = getFixturePath("unmatched-patterns");
-            const globPattern = "*.js3";
+        describe("FixtureDir Dependent Tests", () => {
 
-            await stdAssert.rejects(async () => {
-                await cli.execute(`"${filePath}/${globPattern}"`);
-            }, new Error(`No files matching '${filePath}/${globPattern}' were found.`));
-        });
+            const originalCwd = process.cwd;
 
-        it("should throw an error on unmatched --ext", async () => {
-            const filePath = getFixturePath("unmatched-patterns");
-            const extension = ".js3";
+            beforeEach(() => {
+                process.cwd = () => getFixturePath();
+            });
 
-            await stdAssert.rejects(async () => {
-                await cli.execute(`--ext ${extension} ${filePath}`);
-            }, `No files matching '${filePath}' were found`);
-        });
-    });
+            afterEach(() => {
+                process.cwd = originalCwd;
+            });
 
-    describe("when executing with no-error-on-unmatched-pattern flag", () => {
-        it("should not throw an error on unmatched node glob syntax patterns", async () => {
-            const filePath = getFixturePath("unmatched-patterns");
-            const exit = await cli.execute(`--no-error-on-unmatched-pattern "${filePath}/*.js3"`);
+            describe("when executing with global flag", () => {
 
-            assert.strictEqual(exit, 0);
-        });
+                it(`should default defined variables to read-only with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("undef.js");
+                    const exit = await cli.execute(`--global baz,bat --no-ignore --rule no-global-assign:2 ${filePath}`, null, useFlatConfig);
 
-        it("should not throw an error on unmatched --ext", async () => {
-            const filePath = getFixturePath("unmatched-patterns");
-            const exit = await cli.execute(`--no-error-on-unmatched-pattern --ext .js3 ${filePath}`);
+                    assert.isTrue(log.info.calledOnce);
+                    assert.strictEqual(exit, 1);
+                });
 
-            assert.strictEqual(exit, 0);
-        });
-    });
+                it(`should allow defining writable global variables with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("undef.js");
+                    const exit = await cli.execute(`--global baz:false,bat:true --no-ignore ${filePath}`, null, useFlatConfig);
 
-    describe("when executing with no-error-on-unmatched-pattern flag and multiple patterns", () => {
-        it("should not throw an error on multiple unmatched node glob syntax patterns", async () => {
-            const filePath = getFixturePath("unmatched-patterns");
-            const exit = await cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js4`);
+                    assert.isTrue(log.info.notCalled);
+                    assert.strictEqual(exit, 0);
+                });
 
-            assert.strictEqual(exit, 0);
-        });
+                it(`should allow defining variables with multiple flags with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("undef.js");
+                    const exit = await cli.execute(`--global baz --global bat:true --no-ignore ${filePath}`);
 
-        it("should still throw an error on when a matched pattern has lint errors", async () => {
-            const filePath = getFixturePath("unmatched-patterns");
-            const exit = await cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js`);
+                    assert.isTrue(log.info.notCalled);
+                    assert.strictEqual(exit, 0);
+                });
+            });
 
-            assert.strictEqual(exit, 1);
-        });
-    });
 
-    describe("when executing with no-error-on-unmatched-pattern flag and multiple --ext arguments", () => {
-        it("should not throw an error on multiple unmatched --ext arguments", async () => {
-            const filePath = getFixturePath("unmatched-patterns");
-            const exit = await cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js4 ${filePath}`);
+            describe("when supplied with rule flag and severity level set to error", () => {
 
-            assert.strictEqual(exit, 0);
-        });
 
-        it("should still throw an error on when a matched pattern has lint errors", async () => {
-            const filePath = getFixturePath("unmatched-patterns");
-            const exit = await cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js ${filePath}`);
+                it(`should exit with an error status (2) with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("single-quoted.js");
+                    const code = `--no-ignore --rule 'quotes: [2, double]' ${filePath}`;
+                    const exitStatus = await cli.execute(code, null, useFlatConfig);
 
-            assert.strictEqual(exit, 1);
-        });
-    });
+                    assert.strictEqual(exitStatus, 1);
+                });
+            });
 
-    describe("when executing with help flag", () => {
-        it("should print out help", async () => {
-            assert.strictEqual(await cli.execute("-h"), 0);
-            assert.strictEqual(log.info.callCount, 1);
-        });
-    });
+            describe("when the quiet option is enabled", () => {
 
-    describe("when given a directory with eslint excluded files in the directory", () => {
-        it("should throw an error and not process any files", async () => {
-            const ignorePath = getFixturePath(".eslintignore");
-            const filePath = getFixturePath("cli");
+                it(`should only print error with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("single-quoted.js");
+                    const cliArgs = `--no-ignore --quiet  -f compact --rule 'quotes: [2, double]' --rule 'no-unused-vars: 1' ${filePath}`;
 
-            await stdAssert.rejects(async () => {
-                await cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
-            }, new Error(`All files matched by '${filePath}' are ignored.`));
-        });
-    });
+                    await cli.execute(cliArgs, null, useFlatConfig);
 
-    describe("when given a file in excluded files list", () => {
-        it("should not process the file", async () => {
-            const ignorePath = getFixturePath(".eslintignore");
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
+                    sinon.assert.calledOnce(log.info);
 
-            // a warning about the ignored file
-            assert.isTrue(log.info.called);
-            assert.strictEqual(exit, 0);
-        });
+                    const formattedOutput = log.info.firstCall.args[0];
 
-        it("should process the file when forced", async () => {
-            const ignorePath = getFixturePath(".eslintignore");
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`--ignore-path ${ignorePath} --no-ignore ${filePath}`);
+                    assert.include(formattedOutput, "Error");
+                    assert.notInclude(formattedOutput, "Warning");
+                });
 
-            // no warnings
-            assert.isFalse(log.info.called);
-            assert.strictEqual(exit, 0);
-        });
-    });
+                it(`should print nothing if there are no errors with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("single-quoted.js");
+                    const cliArgs = `--quiet  -f compact --rule 'quotes: [1, double]' --rule 'no-unused-vars: 1' ${filePath}`;
 
-    describe("when given a pattern to ignore", () => {
-        it("should not process any files", async () => {
-            const ignoredFile = getFixturePath("cli/syntax-error.js");
-            const filePath = getFixturePath("cli/passing.js");
-            const exit = await cli.execute(`--ignore-pattern cli/ ${ignoredFile} ${filePath}`);
+                    await cli.execute(cliArgs, null, useFlatConfig);
 
-            // warnings about the ignored files
-            assert.isTrue(log.info.called);
-            assert.strictEqual(exit, 0);
-        });
-    });
+                    sinon.assert.notCalled(log.info);
+                });
+            });
 
-    describe("when given patterns to ignore", () => {
-        it("should not process any matching files", async () => {
-            const ignorePaths = ["a", "b"];
 
-            const cmd = ignorePaths.map(ignorePath => `--ignore-pattern ${ignorePath}`).concat(".").join(" ");
+            describe("no-error-on-unmatched-pattern flag", () => {
 
-            const opts = {
-                overrideConfig: {
-                    ignorePatterns: ignorePaths
-                }
-            };
+                describe("when executing without no-error-on-unmatched-pattern flag", () => {
+                    it(`should throw an error on unmatched glob pattern with configType:${configType}`, async () => {
+                        let filePath = getFixturePath("unmatched-patterns");
+                        const globPattern = "unmatched*.js";
 
-            await verifyESLintOpts(cmd, opts);
-        });
-    });
+                        if (useFlatConfig) {
+                            filePath = filePath.replace(/\\/gu, "/");
+                        }
 
-    describe("when executing a file with a shebang", () => {
-        it("should execute without error", async () => {
-            const filePath = getFixturePath("shebang.js");
-            const exit = await cli.execute(`--no-ignore ${filePath}`);
+                        await stdAssert.rejects(async () => {
+                            await cli.execute(`"${filePath}/${globPattern}"`, null, useFlatConfig);
+                        }, new Error(`No files matching '${filePath}/${globPattern}' were found.`));
+                    });
 
-            assert.strictEqual(exit, 0);
-        });
-    });
+                });
 
-    describe("when loading a custom rule", () => {
-        it("should return an error when rule isn't found", async () => {
-            const rulesPath = getFixturePath("rules", "wrong");
-            const configPath = getFixturePath("rules", "eslint.json");
-            const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
-            const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
+                describe("when executing with no-error-on-unmatched-pattern flag", () => {
+                    it(`should not throw an error on unmatched node glob syntax patterns with configType:${configType}`, async () => {
+                        const filePath = getFixturePath("unmatched-patterns");
+                        const exit = await cli.execute(`--no-error-on-unmatched-pattern "${filePath}/unmatched*.js"`, null, useFlatConfig);
 
-            await stdAssert.rejects(async () => {
-                const exit = await cli.execute(code);
+                        assert.strictEqual(exit, 0);
+                    });
+                });
 
-                assert.strictEqual(exit, 2);
-            }, /Error while loading rule 'custom-rule': Boom!/u);
-        });
+                describe("when executing with no-error-on-unmatched-pattern flag and multiple patterns", () => {
+                    it(`should not throw an error on multiple unmatched node glob syntax patterns with configType:${configType}`, async () => {
+                        const filePath = getFixturePath("unmatched-patterns/js3");
+                        const exit = await cli.execute(`--no-error-on-unmatched-pattern ${filePath}/unmatched1*.js ${filePath}/unmatched2*.js`, null, useFlatConfig);
 
-        it("should return a warning when rule is matched", async () => {
-            const rulesPath = getFixturePath("rules");
-            const configPath = getFixturePath("rules", "eslint.json");
-            const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
-            const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
+                        assert.strictEqual(exit, 0);
+                    });
 
-            await cli.execute(code);
+                    it(`should still throw an error on when a matched pattern has lint errors with configType:${configType}`, async () => {
+                        const filePath = getFixturePath("unmatched-patterns");
+                        const exit = await cli.execute(`--no-ignore --no-error-on-unmatched-pattern ${filePath}/unmatched1*.js ${filePath}/failing.js`, null, useFlatConfig);
 
-            assert.isTrue(log.info.calledOnce);
-            assert.isTrue(log.info.neverCalledWith(""));
-        });
+                        assert.strictEqual(exit, 1);
+                    });
+                });
 
-        it("should return warnings from multiple rules in different directories", async () => {
-            const rulesPath = getFixturePath("rules", "dir1");
-            const rulesPath2 = getFixturePath("rules", "dir2");
-            const configPath = getFixturePath("rules", "multi-rulesdirs.json");
-            const filePath = getFixturePath("rules", "test-multi-rulesdirs.js");
-            const code = `--rulesdir ${rulesPath} --rulesdir ${rulesPath2} --config ${configPath} --no-ignore ${filePath}`;
-            const exit = await cli.execute(code);
-
-            const call = log.info.getCall(0);
-
-            assert.isTrue(log.info.calledOnce);
-            assert.isTrue(call.args[0].indexOf("String!") > -1);
-            assert.isTrue(call.args[0].indexOf("Literal!") > -1);
-            assert.isTrue(call.args[0].indexOf("2 problems") > -1);
-            assert.isTrue(log.info.neverCalledWith(""));
-            assert.strictEqual(exit, 1);
-        });
+            });
 
+            describe("Parser Options", () => {
 
-    });
+                describe("when given parser options", () => {
+                    it(`should exit with error if parser options are invalid with configType:${configType}`, async () => {
+                        const filePath = getFixturePath("passing.js");
+                        const exit = await cli.execute(`--no-ignore --parser-options test111 ${filePath}`, null, useFlatConfig);
 
-    describe("when executing with no-eslintrc flag", () => {
-        it("should ignore a local config file", async () => {
-            const filePath = getFixturePath("eslintrc", "quotes.js");
-            const exit = await cli.execute(`--no-eslintrc --no-ignore ${filePath}`);
+                        assert.strictEqual(exit, 2);
+                    });
 
-            assert.isTrue(log.info.notCalled);
-            assert.strictEqual(exit, 0);
-        });
-    });
+                    it(`should exit with no error if parser is valid with configType:${configType}`, async () => {
+                        const filePath = getFixturePath("passing.js");
+                        const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`, null, useFlatConfig);
 
-    describe("when executing without no-eslintrc flag", () => {
-        it("should load a local config file", async () => {
-            const filePath = getFixturePath("eslintrc", "quotes.js");
-            const exit = await cli.execute(`--no-ignore ${filePath}`);
+                        assert.strictEqual(exit, 0);
+                    });
 
-            assert.isTrue(log.info.calledOnce);
-            assert.strictEqual(exit, 1);
-        });
-    });
+                    it(`should exit with an error on ecmaVersion 7 feature in ecmaVersion 6 with configType:${configType}`, async () => {
+                        const filePath = getFixturePath("passing-es7.js");
+                        const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`, null, useFlatConfig);
 
-    describe("when executing without env flag", () => {
-        it("should not define environment-specific globals", async () => {
-            const files = [
-                getFixturePath("globals-browser.js"),
-                getFixturePath("globals-node.js")
-            ];
+                        assert.strictEqual(exit, 1);
+                    });
 
-            await cli.execute(`--no-eslintrc --config ./conf/eslint-recommended.js --no-ignore ${files.join(" ")}`);
+                    it(`should exit with no error on ecmaVersion 7 feature in ecmaVersion 7 with configType:${configType}`, async () => {
+                        const filePath = getFixturePath("passing-es7.js");
+                        const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:7 ${filePath}`, null, useFlatConfig);
 
-            assert.strictEqual(log.info.args[0][0].split("\n").length, 10);
-        });
-    });
+                        assert.strictEqual(exit, 0);
+                    });
 
-    describe("when executing with global flag", () => {
-        it("should default defined variables to read-only", async () => {
-            const filePath = getFixturePath("undef.js");
-            const exit = await cli.execute(`--global baz,bat --no-ignore --rule no-global-assign:2 ${filePath}`);
+                    it(`should exit with no error on ecmaVersion 7 feature with config ecmaVersion 6 and command line ecmaVersion 7 with configType:${configType}`, async () => {
+                        const configPath = useFlatConfig
+                            ? getFixturePath("configurations", "es6.js")
+                            : getFixturePath("configurations", "es6.json");
+                        const filePath = getFixturePath("passing-es7.js");
+                        const exit = await cli.execute(`--no-ignore --config ${configPath} --parser-options=ecmaVersion:7 ${filePath}`, null, useFlatConfig);
 
-            assert.isTrue(log.info.calledOnce);
-            assert.strictEqual(exit, 1);
-        });
+                        assert.strictEqual(exit, 0);
+                    });
+                });
+            });
 
-        it("should allow defining writable global variables", async () => {
-            const filePath = getFixturePath("undef.js");
-            const exit = await cli.execute(`--global baz:false,bat:true --no-ignore ${filePath}`);
+            describe("when given the max-warnings flag", () => {
 
-            assert.isTrue(log.info.notCalled);
-            assert.strictEqual(exit, 0);
-        });
+                let filePath, configFilePath;
 
-        it("should allow defining variables with multiple flags", async () => {
-            const filePath = getFixturePath("undef.js");
-            const exit = await cli.execute(`--global baz --global bat:true --no-ignore ${filePath}`);
+                before(() => {
+                    filePath = getFixturePath("max-warnings/six-warnings.js");
+                    configFilePath = getFixturePath(useFlatConfig ? "max-warnings/eslint.config.js" : "max-warnings/.eslintrc");
+                });
 
-            assert.isTrue(log.info.notCalled);
-            assert.strictEqual(exit, 0);
-        });
-    });
+                it(`should not change exit code if warning count under threshold with configType:${configType}`, async () => {
+                    const exitCode = await cli.execute(`--no-ignore --max-warnings 10 ${filePath} -c ${configFilePath}`, null, useFlatConfig);
 
-    describe("when supplied with rule flag and severity level set to error", () => {
-        it("should exit with an error status (2)", async () => {
-            const filePath = getFixturePath("single-quoted.js");
-            const code = `--no-ignore --rule 'quotes: [2, double]' ${filePath}`;
-            const exitStatus = await cli.execute(code);
+                    assert.strictEqual(exitCode, 0);
+                });
 
-            assert.strictEqual(exitStatus, 1);
-        });
-    });
+                it(`should exit with exit code 1 if warning count exceeds threshold with configType:${configType}`, async () => {
+                    const exitCode = await cli.execute(`--no-ignore --max-warnings 5 ${filePath} -c ${configFilePath}`, null, useFlatConfig);
 
-    describe("when the quiet option is enabled", () => {
+                    assert.strictEqual(exitCode, 1);
+                    assert.ok(log.error.calledOnce);
+                    assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings");
+                });
 
-        it("should only print error", async () => {
-            const filePath = getFixturePath("single-quoted.js");
-            const cliArgs = `--no-ignore --quiet  -f compact --rule 'quotes: [2, double]' --rule 'no-unused-vars: 1' ${filePath}`;
+                it(`should exit with exit code 1 without printing warnings if the quiet option is enabled and warning count exceeds threshold with configType:${configType}`, async () => {
+                    const exitCode = await cli.execute(`--no-ignore --quiet --max-warnings 5 ${filePath} -c ${configFilePath}`, null, useFlatConfig);
 
-            await cli.execute(cliArgs);
+                    assert.strictEqual(exitCode, 1);
+                    assert.ok(log.error.calledOnce);
+                    assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings");
+                    assert.ok(log.info.notCalled); // didn't print warnings
+                });
 
-            sinon.assert.calledOnce(log.info);
+                it(`should not change exit code if warning count equals threshold with configType:${configType}`, async () => {
+                    const exitCode = await cli.execute(`--no-ignore --max-warnings 6 ${filePath} -c ${configFilePath}`, null, useFlatConfig);
 
-            const formattedOutput = log.info.firstCall.args[0];
+                    assert.strictEqual(exitCode, 0);
+                });
 
-            assert.include(formattedOutput, "Error");
-            assert.notInclude(formattedOutput, "Warning");
-        });
+                it(`should not change exit code if flag is not specified and there are warnings with configType:${configType}`, async () => {
+                    const exitCode = await cli.execute(`-c ${configFilePath} ${filePath}`, null, useFlatConfig);
 
-        it("should print nothing if there are no errors", async () => {
-            const filePath = getFixturePath("single-quoted.js");
-            const cliArgs = `--quiet  -f compact --rule 'quotes: [1, double]' --rule 'no-unused-vars: 1' ${filePath}`;
+                    assert.strictEqual(exitCode, 0);
+                });
+            });
 
-            await cli.execute(cliArgs);
+            describe("when given the exit-on-fatal-error flag", () => {
+                it(`should not change exit code if no fatal errors are reported with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error.js");
+                    const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`, null, useFlatConfig);
 
-            sinon.assert.notCalled(log.info);
-        });
-    });
+                    assert.strictEqual(exitCode, 0);
+                });
 
-    describe("when supplied with report output file path", () => {
-        afterEach(() => {
-            sh.rm("-rf", "tests/output");
-        });
+                it(`should exit with exit code 1 if no fatal errors are found, but rule violations are found with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error-rule-violation.js");
+                    const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`, null, useFlatConfig);
 
-        it("should write the file and create dirs if they don't exist", async () => {
-            const filePath = getFixturePath("single-quoted.js");
-            const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
+                    assert.strictEqual(exitCode, 1);
+                });
 
-            await cli.execute(code);
+                it(`should exit with exit code 2 if fatal error is found with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("exit-on-fatal-error", "fatal-error.js");
+                    const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`, null, useFlatConfig);
 
-            assert.include(fs.readFileSync("tests/output/eslint-output.txt", "utf8"), filePath);
-            assert.isTrue(log.info.notCalled);
-        });
+                    assert.strictEqual(exitCode, 2);
+                });
 
-        it("should return an error if the path is a directory", async () => {
-            const filePath = getFixturePath("single-quoted.js");
-            const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output ${filePath}`;
+                it(`should exit with exit code 2 if fatal error is found in any file with configType:${configType}`, async () => {
+                    const filePath = getFixturePath("exit-on-fatal-error");
+                    const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`, null, useFlatConfig);
 
-            fs.mkdirSync("tests/output");
+                    assert.strictEqual(exitCode, 2);
+                });
 
-            const exit = await cli.execute(code);
 
-            assert.strictEqual(exit, 2);
-            assert.isTrue(log.info.notCalled);
-            assert.isTrue(log.error.calledOnce);
-        });
+            });
 
-        it("should return an error if the path could not be written to", async () => {
-            const filePath = getFixturePath("single-quoted.js");
-            const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
 
-            fs.writeFileSync("tests/output", "foo");
+            describe("Ignores", () => {
+
+                describe("when given a directory with eslint excluded files in the directory", () => {
+                    it(`should throw an error and not process any files with configType:${configType}`, async () => {
+                        const ignorePath = getFixturePath(".eslintignore");
+                        const filePath = getFixturePath("cli");
+                        const expectedMessage = useFlatConfig
+                            ? `All files matched by '${filePath.replace(/\\/gu, "/")}/**/*.js' are ignored.`
+                            : `All files matched by '${filePath}' are ignored.`;
+
+                        await stdAssert.rejects(async () => {
+                            await cli.execute(`--ignore-path ${ignorePath} ${filePath}`, null, useFlatConfig);
+                        }, new Error(expectedMessage));
+                    });
+                });
+
+                describe("when given a file in excluded files list", () => {
+                    it(`should not process the file with configType:${configType}`, async () => {
+                        const ignorePath = getFixturePath(".eslintignore");
+                        const filePath = getFixturePath("passing.js");
+                        const exit = await cli.execute(`--ignore-path ${ignorePath} ${filePath}`, null, useFlatConfig);
+
+                        // a warning about the ignored file
+                        assert.isTrue(log.info.called);
+                        assert.strictEqual(exit, 0);
+                    });
+
+                    it(`should process the file when forced with configType:${configType}`, async () => {
+                        const ignorePath = getFixturePath(".eslintignore");
+                        const filePath = getFixturePath("passing.js");
+                        const exit = await cli.execute(`--ignore-path ${ignorePath} --no-ignore ${filePath}`, null, useFlatConfig);
+
+                        // no warnings
+                        assert.isFalse(log.info.called);
+                        assert.strictEqual(exit, 0);
+                    });
+                });
+
+                describe("when given a pattern to ignore", () => {
+                    it(`should not process any files with configType:${configType}`, async () => {
+                        const ignoredFile = getFixturePath("cli/syntax-error.js");
+                        const filePath = getFixturePath("cli/passing.js");
+                        const exit = await cli.execute(`--ignore-pattern cli/ ${ignoredFile} ${filePath}`, null, useFlatConfig);
+
+                        // warnings about the ignored files
+                        assert.isTrue(log.info.called);
+                        assert.strictEqual(exit, 0);
+                    });
+                });
 
-            const exit = await cli.execute(code);
+            });
 
-            assert.strictEqual(exit, 2);
-            assert.isTrue(log.info.notCalled);
-            assert.isTrue(log.error.calledOnce);
         });
-    });
 
-    describe("when supplied with a plugin", () => {
-        it("should pass plugins to ESLint", async () => {
-            const examplePluginName = "eslint-plugin-example";
 
-            await verifyESLintOpts(`--no-ignore --plugin ${examplePluginName} foo.js`, {
-                overrideConfig: {
-                    plugins: [examplePluginName]
-                }
-            });
-        });
+        describe("when given a parser name", () => {
 
-    });
+            it(`should exit with a fatal error if parser is invalid with configType:${configType}`, async () => {
+                const filePath = getFixturePath("passing.js");
 
-    describe("when supplied with a plugin-loading path", () => {
-        it("should pass the option to ESLint", async () => {
-            const examplePluginDirPath = "foo/bar";
+                await stdAssert.rejects(async () => await cli.execute(`--no-ignore --parser test111 ${filePath}`, null, useFlatConfig), "Cannot find module 'test111'");
+            });
+
+            it(`should exit with no error if parser is valid with configType:${configType}`, async () => {
+                const filePath = getFixturePath("passing.js");
+                const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+                const exit = await cli.execute(`${flag} --no-ignore --parser espree ${filePath}`, null, useFlatConfig);
 
-            await verifyESLintOpts(`--resolve-plugins-relative-to ${examplePluginDirPath} foo.js`, {
-                resolvePluginsRelativeTo: examplePluginDirPath
+                assert.strictEqual(exit, 0);
             });
+
         });
-    });
 
-    describe("when given an parser name", () => {
-        it("should exit with a fatal error if parser is invalid", async () => {
-            const filePath = getFixturePath("passing.js");
+        describe("when supplied with report output file path", () => {
+            afterEach(() => {
+                sh.rm("-rf", "tests/output");
+            });
 
-            await stdAssert.rejects(async () => await cli.execute(`--no-ignore --parser test111 ${filePath}`), "Cannot find module 'test111'");
-        });
+            it(`should write the file and create dirs if they don't exist with configType:${configType}`, async () => {
+                const filePath = getFixturePath("single-quoted.js");
+                const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
 
-        it("should exit with no error if parser is valid", async () => {
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`--no-ignore --parser espree ${filePath}`);
+                await cli.execute(code, null, useFlatConfig);
 
-            assert.strictEqual(exit, 0);
-        });
-    });
+                assert.include(fs.readFileSync("tests/output/eslint-output.txt", "utf8"), filePath);
+                assert.isTrue(log.info.notCalled);
+            });
 
-    describe("when given parser options", () => {
-        it("should exit with error if parser options are invalid", async () => {
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`--no-ignore --parser-options test111 ${filePath}`);
+            it(`should return an error if the path is a directory with configType:${configType}`, async () => {
+                const filePath = getFixturePath("single-quoted.js");
+                const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output ${filePath}`;
 
-            assert.strictEqual(exit, 2);
-        });
+                fs.mkdirSync("tests/output");
 
-        it("should exit with no error if parser is valid", async () => {
-            const filePath = getFixturePath("passing.js");
-            const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`);
+                const exit = await cli.execute(code, null, useFlatConfig);
 
-            assert.strictEqual(exit, 0);
-        });
+                assert.strictEqual(exit, 2);
+                assert.isTrue(log.info.notCalled);
+                assert.isTrue(log.error.calledOnce);
+            });
 
-        it("should exit with an error on ecmaVersion 7 feature in ecmaVersion 6", async () => {
-            const filePath = getFixturePath("passing-es7.js");
-            const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`);
+            it(`should return an error if the path could not be written to with configType:${configType}`, async () => {
+                const filePath = getFixturePath("single-quoted.js");
+                const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
 
-            assert.strictEqual(exit, 1);
-        });
+                fs.writeFileSync("tests/output", "foo");
 
-        it("should exit with no error on ecmaVersion 7 feature in ecmaVersion 7", async () => {
-            const filePath = getFixturePath("passing-es7.js");
-            const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:7 ${filePath}`);
+                const exit = await cli.execute(code, null, useFlatConfig);
 
-            assert.strictEqual(exit, 0);
+                assert.strictEqual(exit, 2);
+                assert.isTrue(log.info.notCalled);
+                assert.isTrue(log.error.calledOnce);
+            });
         });
 
-        it("should exit with no error on ecmaVersion 7 feature with config ecmaVersion 6 and command line ecmaVersion 7", async () => {
-            const configPath = getFixturePath("configurations", "es6.json");
-            const filePath = getFixturePath("passing-es7.js");
-            const exit = await cli.execute(`--no-ignore --config ${configPath} --parser-options=ecmaVersion:7 ${filePath}`);
+        describe("when passed --no-inline-config", () => {
+            let localCLI;
 
-            assert.strictEqual(exit, 0);
-        });
-    });
+            afterEach(() => {
+                sinon.verifyAndRestore();
+            });
 
-    describe("when given the max-warnings flag", () => {
-        it("should not change exit code if warning count under threshold", async () => {
-            const filePath = getFixturePath("max-warnings");
-            const exitCode = await cli.execute(`--no-ignore --max-warnings 10 ${filePath}`);
+            it(`should pass allowInlineConfig:false to ESLint when --no-inline-config is used with configType:${configType}`, async () => {
+
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: false }));
+
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintFiles").returns([{
+                    filePath: "./foo.js",
+                    output: "bar",
+                    messages: [
+                        {
+                            severity: 2,
+                            message: "Fake message"
+                        }
+                    ],
+                    errorCount: 1,
+                    warningCount: 0
+                }]);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.outputFixes = sinon.stub();
+
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
+                    "./shared/logging": log
+                });
+
+                await localCLI.execute("--no-inline-config .", null, useFlatConfig);
+            });
 
-            assert.strictEqual(exitCode, 0);
-        });
+            it(`should not error and allowInlineConfig should be true by default with configType:${configType}`, async () => {
 
-        it("should exit with exit code 1 if warning count exceeds threshold", async () => {
-            const filePath = getFixturePath("max-warnings");
-            const exitCode = await cli.execute(`--no-ignore --max-warnings 5 ${filePath}`);
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: true }));
 
-            assert.strictEqual(exitCode, 1);
-            assert.ok(log.error.calledOnce);
-            assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings");
-        });
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.outputFixes = sinon.stub();
 
-        it("should exit with exit code 1 without printing warnings if the quiet option is enabled and warning count exceeds threshold", async () => {
-            const filePath = getFixturePath("max-warnings");
-            const exitCode = await cli.execute(`--no-ignore --quiet --max-warnings 5 ${filePath}`);
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
+                    "./shared/logging": log
+                });
 
-            assert.strictEqual(exitCode, 1);
-            assert.ok(log.error.calledOnce);
-            assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings");
-            assert.ok(log.info.notCalled); // didn't print warnings
-        });
+                const exitCode = await localCLI.execute(".", null, useFlatConfig);
 
-        it("should not change exit code if warning count equals threshold", async () => {
-            const filePath = getFixturePath("max-warnings");
-            const exitCode = await cli.execute(`--no-ignore --max-warnings 6 ${filePath}`);
+                assert.strictEqual(exitCode, 0);
+
+            });
 
-            assert.strictEqual(exitCode, 0);
         });
 
-        it("should not change exit code if flag is not specified and there are warnings", async () => {
-            const filePath = getFixturePath("max-warnings");
-            const exitCode = await cli.execute(filePath);
+        describe("when passed --fix", () => {
+            let localCLI;
 
-            assert.strictEqual(exitCode, 0);
-        });
-    });
+            afterEach(() => {
+                sinon.verifyAndRestore();
+            });
 
-    describe("when given the exit-on-fatal-error flag", () => {
-        it("should not change exit code if no fatal errors are reported", async () => {
-            const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error.js");
-            const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+            it(`should pass fix:true to ESLint when executing on files with configType:${configType}`, async () => {
 
-            assert.strictEqual(exitCode, 0);
-        });
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
 
-        it("should exit with exit code 1 if no fatal errors are found, but rule violations are found", async () => {
-            const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error-rule-violation.js");
-            const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.outputFixes = sinon.mock().once();
 
-            assert.strictEqual(exitCode, 1);
-        });
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
+                    "./shared/logging": log
+                });
 
-        it("should exit with exit code 2 if fatal error is found", async () => {
-            const filePath = getFixturePath("exit-on-fatal-error", "fatal-error.js");
-            const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+                const exitCode = await localCLI.execute("--fix .", null, useFlatConfig);
 
-            assert.strictEqual(exitCode, 2);
-        });
+                assert.strictEqual(exitCode, 0);
 
-        it("should exit with exit code 2 if fatal error is found in any file", async () => {
-            const filePath = getFixturePath("exit-on-fatal-error");
-            const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+            });
 
-            assert.strictEqual(exitCode, 2);
-        });
 
+            it(`should rewrite files when in fix mode with configType:${configType}`, async () => {
 
-    });
+                const report = [{
+                    filePath: "./foo.js",
+                    output: "bar",
+                    messages: [
+                        {
+                            severity: 2,
+                            message: "Fake message"
+                        }
+                    ],
+                    errorCount: 1,
+                    warningCount: 0
+                }];
 
-    describe("when passed --no-inline-config", () => {
-        let localCLI;
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
 
-        afterEach(() => {
-            sinon.verifyAndRestore();
-        });
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
 
-        it("should pass allowInlineConfig:false to ESLint when --no-inline-config is used", async () => {
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: false }));
+                    "./shared/logging": log
+                });
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintFiles").returns([{
-                filePath: "./foo.js",
-                output: "bar",
-                messages: [
-                    {
-                        severity: 2,
-                        message: "Fake message"
-                    }
-                ],
-                errorCount: 1,
-                warningCount: 0
-            }]);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.outputFixes = sinon.stub();
+                const exitCode = await localCLI.execute("--fix .", null, useFlatConfig);
+
+                assert.strictEqual(exitCode, 1);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
             });
 
-            await localCLI.execute("--no-inline-config .");
-        });
+            it(`should provide fix predicate and rewrite files when in fix mode and quiet mode with configType:${configType}`, async () => {
 
-        it("should not error and allowInlineConfig should be true by default", async () => {
+                const report = [{
+                    filePath: "./foo.js",
+                    output: "bar",
+                    messages: [
+                        {
+                            severity: 1,
+                            message: "Fake message"
+                        }
+                    ],
+                    errorCount: 0,
+                    warningCount: 1
+                }];
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: true }));
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.outputFixes = sinon.stub();
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.getErrorResults = sinon.stub().returns([]);
+                fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
-            });
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
 
-            const exitCode = await localCLI.execute(".");
+                    "./shared/logging": log
+                });
 
-            assert.strictEqual(exitCode, 0);
+                const exitCode = await localCLI.execute("--fix --quiet .", null, useFlatConfig);
 
-        });
+                assert.strictEqual(exitCode, 0);
 
-    });
+            });
 
-    describe("when passed --fix", () => {
-        let localCLI;
+            it(`should not call ESLint and return 2 when executing on text with configType:${configType}`, async () => {
 
-        afterEach(() => {
-            sinon.verifyAndRestore();
-        });
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().never();
 
-        it("should pass fix:true to ESLint when executing on files", async () => {
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+                    "./shared/logging": log
+                });
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.outputFixes = sinon.mock().once();
+                const exitCode = await localCLI.execute("--fix .", "foo = bar;", null, useFlatConfig);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
+                assert.strictEqual(exitCode, 2);
             });
 
-            const exitCode = await localCLI.execute("--fix .");
+        });
 
-            assert.strictEqual(exitCode, 0);
+        describe("when passed --fix-dry-run", () => {
+            let localCLI;
 
-        });
+            afterEach(() => {
+                sinon.verifyAndRestore();
+            });
 
+            it(`should pass fix:true to ESLint when executing on files with configType:${configType}`, async () => {
 
-        it("should rewrite files when in fix mode", async () => {
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
 
-            const report = [{
-                filePath: "./foo.js",
-                output: "bar",
-                messages: [
-                    {
-                        severity: 2,
-                        message: "Fake message"
-                    }
-                ],
-                errorCount: 1,
-                warningCount: 0
-            }];
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.outputFixes = sinon.mock().never();
+
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+                    "./shared/logging": log
+                });
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
+                const exitCode = await localCLI.execute("--fix-dry-run .", null, useFlatConfig);
+
+                assert.strictEqual(exitCode, 0);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
             });
 
-            const exitCode = await localCLI.execute("--fix .");
+            it(`should pass fixTypes to ESLint when --fix-type is passed with configType:${configType}`, async () => {
 
-            assert.strictEqual(exitCode, 1);
+                const expectedESLintOptions = {
+                    fix: true,
+                    fixTypes: ["suggestion"]
+                };
 
-        });
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match(expectedESLintOptions));
 
-        it("should provide fix predicate and rewrite files when in fix mode and quiet mode", async () => {
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.outputFixes = sinon.stub();
 
-            const report = [{
-                filePath: "./foo.js",
-                output: "bar",
-                messages: [
-                    {
-                        severity: 1,
-                        message: "Fake message"
-                    }
-                ],
-                errorCount: 0,
-                warningCount: 1
-            }];
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
+                    "./shared/logging": log
+                });
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.getErrorResults = sinon.stub().returns([]);
-            fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
+                const exitCode = await localCLI.execute("--fix-dry-run --fix-type suggestion .", null, useFlatConfig);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
+                assert.strictEqual(exitCode, 0);
             });
 
-            const exitCode = await localCLI.execute("--fix --quiet .");
+            it(`should not rewrite files when in fix-dry-run mode with configType:${configType}`, async () => {
 
-            assert.strictEqual(exitCode, 0);
+                const report = [{
+                    filePath: "./foo.js",
+                    output: "bar",
+                    messages: [
+                        {
+                            severity: 2,
+                            message: "Fake message"
+                        }
+                    ],
+                    errorCount: 1,
+                    warningCount: 0
+                }];
 
-        });
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.outputFixes = sinon.mock().never();
+
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
 
-        it("should not call ESLint and return 2 when executing on text", async () => {
+                    "./shared/logging": log
+                });
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().never();
+                const exitCode = await localCLI.execute("--fix-dry-run .", null, useFlatConfig);
+
+                assert.strictEqual(exitCode, 1);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
             });
 
-            const exitCode = await localCLI.execute("--fix .", "foo = bar;");
+            it(`should provide fix predicate when in fix-dry-run mode and quiet mode with configType:${configType}`, async () => {
 
-            assert.strictEqual(exitCode, 2);
-        });
+                const report = [{
+                    filePath: "./foo.js",
+                    output: "bar",
+                    messages: [
+                        {
+                            severity: 1,
+                            message: "Fake message"
+                        }
+                    ],
+                    errorCount: 0,
+                    warningCount: 1
+                }];
 
-    });
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
 
-    describe("when passed --fix-dry-run", () => {
-        let localCLI;
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.getErrorResults = sinon.stub().returns([]);
+                fakeESLint.outputFixes = sinon.mock().never();
 
-        afterEach(() => {
-            sinon.verifyAndRestore();
-        });
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
 
-        it("should pass fix:true to ESLint when executing on files", async () => {
+                    "./shared/logging": log
+                });
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+                const exitCode = await localCLI.execute("--fix-dry-run --quiet .", null, useFlatConfig);
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.outputFixes = sinon.mock().never();
+                assert.strictEqual(exitCode, 0);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
             });
 
-            const exitCode = await localCLI.execute("--fix-dry-run .");
+            it(`should allow executing on text with configType:${configType}`, async () => {
 
-            assert.strictEqual(exitCode, 0);
+                const report = [{
+                    filePath: "./foo.js",
+                    output: "bar",
+                    messages: [
+                        {
+                            severity: 2,
+                            message: "Fake message"
+                        }
+                    ],
+                    errorCount: 1,
+                    warningCount: 0
+                }];
 
-        });
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
 
-        it("should pass fixTypes to ESLint when --fix-type is passed", async () => {
+                Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+                sinon.stub(fakeESLint.prototype, "lintText").returns(report);
+                sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+                fakeESLint.outputFixes = sinon.mock().never();
 
-            const expectedESLintOptions = {
-                fix: true,
-                fixTypes: ["suggestion"]
-            };
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match(expectedESLintOptions));
+                    "./shared/logging": log
+                });
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.outputFixes = sinon.stub();
+                const exitCode = await localCLI.execute("--fix-dry-run .", "foo = bar;", useFlatConfig);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
+                assert.strictEqual(exitCode, 1);
             });
 
-            const exitCode = await localCLI.execute("--fix-dry-run --fix-type suggestion .");
+            it(`should not call ESLint and return 2 when used with --fix with configType:${configType}`, async () => {
+
+                // create a fake ESLint class to test with
+                const fakeESLint = sinon.mock().never();
+
+                localCLI = proxyquire("../../lib/cli", {
+                    "./eslint": { ESLint: fakeESLint },
+                    "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
+
+                    "./shared/logging": log
+                });
 
-            assert.strictEqual(exitCode, 0);
+                const exitCode = await localCLI.execute("--fix --fix-dry-run .", "foo = bar;", useFlatConfig);
+
+                assert.strictEqual(exitCode, 2);
+            });
         });
 
-        it("should not rewrite files when in fix-dry-run mode", async () => {
+        describe("when passing --print-config", () => {
+            it(`should print out the configuration with configType:${configType}`, async () => {
+                const filePath = getFixturePath("xxxx");
 
-            const report = [{
-                filePath: "./foo.js",
-                output: "bar",
-                messages: [
-                    {
-                        severity: 2,
-                        message: "Fake message"
-                    }
-                ],
-                errorCount: 1,
-                warningCount: 0
-            }];
+                const exitCode = await cli.execute(`--print-config ${filePath}`, null, useFlatConfig);
+
+                assert.isTrue(log.info.calledOnce);
+                assert.strictEqual(exitCode, 0);
+            });
+
+            it(`should error if any positional file arguments are passed with configType:${configType}`, async () => {
+                const filePath1 = getFixturePath("files", "bar.js");
+                const filePath2 = getFixturePath("files", "foo.js");
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+                const exitCode = await cli.execute(`--print-config ${filePath1} ${filePath2}`, null, useFlatConfig);
+
+                assert.isTrue(log.info.notCalled);
+                assert.isTrue(log.error.calledOnce);
+                assert.strictEqual(exitCode, 2);
+            });
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.outputFixes = sinon.mock().never();
+            it(`should error out when executing on text with configType:${configType}`, async () => {
+                const exitCode = await cli.execute("--print-config=myFile.js", "foo = bar;", useFlatConfig);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
+                assert.isTrue(log.info.notCalled);
+                assert.isTrue(log.error.calledOnce);
+                assert.strictEqual(exitCode, 2);
             });
+        });
+
+        // ---------
+    });
 
-            const exitCode = await localCLI.execute("--fix-dry-run .");
 
-            assert.strictEqual(exitCode, 1);
+    describe("when given a config file", () => {
+        it("should load the specified config file", async () => {
+            const configPath = getFixturePath(".eslintrc");
+            const filePath = getFixturePath("passing.js");
 
+            await cli.execute(`--config ${configPath} ${filePath}`);
         });
+    });
 
-        it("should provide fix predicate when in fix-dry-run mode and quiet mode", async () => {
 
-            const report = [{
-                filePath: "./foo.js",
-                output: "bar",
-                messages: [
-                    {
-                        severity: 1,
-                        message: "Fake message"
-                    }
-                ],
-                errorCount: 0,
-                warningCount: 1
-            }];
+    describe("eslintrc Only", () => {
+
+        describe("Environments", () => {
+
+            describe("when given a config with environment set to browser", () => {
+                it("should execute without any errors", async () => {
+                    const configPath = getFixturePath("configurations", "env-browser.json");
+                    const filePath = getFixturePath("globals-browser.js");
+                    const code = `--config ${configPath} ${filePath}`;
+
+                    const exit = await cli.execute(code);
+
+                    assert.strictEqual(exit, 0);
+                });
+            });
+
+            describe("when given a config with environment set to Node.js", () => {
+                it("should execute without any errors", async () => {
+                    const configPath = getFixturePath("configurations", "env-node.json");
+                    const filePath = getFixturePath("globals-node.js");
+                    const code = `--config ${configPath} ${filePath}`;
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
+                    const exit = await cli.execute(code);
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.getErrorResults = sinon.stub().returns([]);
-            fakeESLint.outputFixes = sinon.mock().never();
+                    assert.strictEqual(exit, 0);
+                });
+            });
+
+            describe("when given a config with environment set to Nashorn", () => {
+                it("should execute without any errors", async () => {
+                    const configPath = getFixturePath("configurations", "env-nashorn.json");
+                    const filePath = getFixturePath("globals-nashorn.js");
+                    const code = `--config ${configPath} ${filePath}`;
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
+                    const exit = await cli.execute(code);
+
+                    assert.strictEqual(exit, 0);
+                });
             });
 
-            const exitCode = await localCLI.execute("--fix-dry-run --quiet .");
+            describe("when given a config with environment set to WebExtensions", () => {
+                it("should execute without any errors", async () => {
+                    const configPath = getFixturePath("configurations", "env-webextensions.json");
+                    const filePath = getFixturePath("globals-webextensions.js");
+                    const code = `--config ${configPath} ${filePath}`;
 
-            assert.strictEqual(exitCode, 0);
+                    const exit = await cli.execute(code);
 
+                    assert.strictEqual(exit, 0);
+                });
+            });
         });
 
-        it("should allow executing on text", async () => {
+        describe("when loading a custom rule", () => {
+            it("should return an error when rule isn't found", async () => {
+                const rulesPath = getFixturePath("rules", "wrong");
+                const configPath = getFixturePath("rules", "eslint.json");
+                const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
+                const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
 
-            const report = [{
-                filePath: "./foo.js",
-                output: "bar",
-                messages: [
-                    {
-                        severity: 2,
-                        message: "Fake message"
-                    }
-                ],
-                errorCount: 1,
-                warningCount: 0
-            }];
+                await stdAssert.rejects(async () => {
+                    const exit = await cli.execute(code);
+
+                    assert.strictEqual(exit, 2);
+                }, /Error while loading rule 'custom-rule': Boom!/u);
+            });
+
+            it("should return a warning when rule is matched", async () => {
+                const rulesPath = getFixturePath("rules");
+                const configPath = getFixturePath("rules", "eslint.json");
+                const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
+                const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+                await cli.execute(code);
 
-            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
-            sinon.stub(fakeESLint.prototype, "lintText").returns(report);
-            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
-            fakeESLint.outputFixes = sinon.mock().never();
+                assert.isTrue(log.info.calledOnce);
+                assert.isTrue(log.info.neverCalledWith(""));
+            });
+
+            it("should return warnings from multiple rules in different directories", async () => {
+                const rulesPath = getFixturePath("rules", "dir1");
+                const rulesPath2 = getFixturePath("rules", "dir2");
+                const configPath = getFixturePath("rules", "multi-rulesdirs.json");
+                const filePath = getFixturePath("rules", "test-multi-rulesdirs.js");
+                const code = `--rulesdir ${rulesPath} --rulesdir ${rulesPath2} --config ${configPath} --no-ignore ${filePath}`;
+                const exit = await cli.execute(code);
+
+                const call = log.info.getCall(0);
 
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
+                assert.isTrue(log.info.calledOnce);
+                assert.isTrue(call.args[0].includes("String!"));
+                assert.isTrue(call.args[0].includes("Literal!"));
+                assert.isTrue(call.args[0].includes("2 problems"));
+                assert.isTrue(log.info.neverCalledWith(""));
+                assert.strictEqual(exit, 1);
             });
 
-            const exitCode = await localCLI.execute("--fix-dry-run .", "foo = bar;");
 
-            assert.strictEqual(exitCode, 1);
         });
 
-        it("should not call ESLint and return 2 when used with --fix", async () => {
+        describe("when executing with no-eslintrc flag", () => {
+            it("should ignore a local config file", async () => {
+                const filePath = getFixturePath("eslintrc", "quotes.js");
+                const exit = await cli.execute(`--no-eslintrc --no-ignore ${filePath}`);
 
-            // create a fake ESLint class to test with
-            const fakeESLint = sinon.mock().never();
-
-            localCLI = proxyquire("../../lib/cli", {
-                "./eslint": { ESLint: fakeESLint },
-                "./shared/logging": log
+                assert.isTrue(log.info.notCalled);
+                assert.strictEqual(exit, 0);
             });
+        });
 
-            const exitCode = await localCLI.execute("--fix --fix-dry-run .", "foo = bar;");
+        describe("when executing without no-eslintrc flag", () => {
+            it("should load a local config file", async () => {
+                const filePath = getFixturePath("eslintrc", "quotes.js");
+                const exit = await cli.execute(`--no-ignore ${filePath}`);
 
-            assert.strictEqual(exitCode, 2);
+                assert.isTrue(log.info.calledOnce);
+                assert.strictEqual(exit, 1);
+            });
         });
-    });
 
-    describe("when passing --print-config", () => {
-        it("should print out the configuration", async () => {
-            const filePath = getFixturePath("xxxx");
+        describe("when executing without env flag", () => {
+            it("should not define environment-specific globals", async () => {
+                const files = [
+                    getFixturePath("globals-browser.js"),
+                    getFixturePath("globals-node.js")
+                ];
 
-            const exitCode = await cli.execute(`--print-config ${filePath}`);
+                await cli.execute(`--no-eslintrc --config ./conf/eslint-recommended.js --no-ignore ${files.join(" ")}`);
 
-            assert.isTrue(log.info.calledOnce);
-            assert.strictEqual(exitCode, 0);
+                assert.strictEqual(log.info.args[0][0].split("\n").length, 10);
+            });
         });
 
-        it("should error if any positional file arguments are passed", async () => {
-            const filePath1 = getFixturePath("files", "bar.js");
-            const filePath2 = getFixturePath("files", "foo.js");
 
-            const exitCode = await cli.execute(`--print-config ${filePath1} ${filePath2}`);
+        describe("when supplied with a plugin", () => {
+            it("should pass plugins to ESLint", async () => {
+                const examplePluginName = "eslint-plugin-example";
+
+                await verifyESLintOpts(`--no-ignore --plugin ${examplePluginName} foo.js`, {
+                    overrideConfig: {
+                        plugins: [examplePluginName]
+                    }
+                });
+            });
 
-            assert.isTrue(log.info.notCalled);
-            assert.isTrue(log.error.calledOnce);
-            assert.strictEqual(exitCode, 2);
         });
 
-        it("should error out when executing on text", async () => {
-            const exitCode = await cli.execute("--print-config=myFile.js", "foo = bar;");
+        describe("when supplied with a plugin-loading path", () => {
+            it("should pass the option to ESLint", async () => {
+                const examplePluginDirPath = "foo/bar";
 
-            assert.isTrue(log.info.notCalled);
-            assert.isTrue(log.error.calledOnce);
-            assert.strictEqual(exitCode, 2);
+                await verifyESLintOpts(`--resolve-plugins-relative-to ${examplePluginDirPath} foo.js`, {
+                    resolvePluginsRelativeTo: examplePluginDirPath
+                });
+            });
         });
+
+
     });
 
+
 });