diff --git a/bin/check.js b/bin/check.js index 0d243c1..4685e80 100644 --- a/bin/check.js +++ b/bin/check.js @@ -1,12 +1,2 @@ #!/usr/bin/env node - -try { - require("../lib/checker").check(process.argv[2]); -} catch (e) { - if (e.name === "ConflictRules") { - console.log(e.message); - process.exitCode = 1; - } else { - throw e; - } -} +require("../lib/checker").check(process.argv.slice(2)); diff --git a/tools/__snapshots__/checker.test.ts.snap b/tools/__snapshots__/checker.test.ts.snap index 43d1c4d..02bbcee 100644 --- a/tools/__snapshots__/checker.test.ts.snap +++ b/tools/__snapshots__/checker.test.ts.snap @@ -1,35 +1,63 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should show success message for conflict rules that is disabled 1`] = `"No conflict rule detected in /fixtures/tslint.false.json"`; +exports[`should be able to check multiple config files 1`] = ` +"[error] Conflict rule(s) detected in /fixtures/tslint.all.json: +[error] align +[error] arrow-parens +[error] eofline +[error] import-spacing +[error] indent +[error] linebreak-style +[error] max-line-length +[error] new-parens +[error] newline-per-chained-call +[error] no-consecutive-blank-lines +[error] no-irregular-whitespace +[error] no-trailing-whitespace +[error] number-literal-format +[error] object-literal-key-quotes +[error] one-line +[error] quotemark +[error] semicolon +[error] space-before-function-paren +[error] space-within-parens +[error] trailing-comma +[error] typedef-whitespace +[error] whitespace +[log] No conflict rule detected in /fixtures/tslint.empty.json +[error] Unexpected number in JSON at position 1 in /fixtures/tslint.error.json" +`; + +exports[`should show success message for conflict rules that is disabled 1`] = `"[log] No conflict rule detected in /fixtures/tslint.false.json"`; -exports[`should show success message for non-conflict rules 1`] = `"No conflict rule detected in /fixtures/tslint.empty.json"`; +exports[`should show success message for non-conflict rules 1`] = `"[log] No conflict rule detected in /fixtures/tslint.empty.json"`; + +exports[`should show usage if there is no filePath 1`] = `"[log] Usage: tslint-config-prettier-check ..."`; exports[`should throw conflict rules 1`] = ` -"Conflict rule(s) detected in /fixtures/tslint.all.json: -align -arrow-parens -eofline -import-spacing -indent -linebreak-style -max-line-length -new-parens -newline-per-chained-call -no-consecutive-blank-lines -no-irregular-whitespace -no-trailing-whitespace -number-literal-format -object-literal-key-quotes -one-line -quotemark -semicolon -space-before-function-paren -space-within-parens -trailing-comma -typedef-whitespace -whitespace" +"[error] Conflict rule(s) detected in /fixtures/tslint.all.json: +[error] align +[error] arrow-parens +[error] eofline +[error] import-spacing +[error] indent +[error] linebreak-style +[error] max-line-length +[error] new-parens +[error] newline-per-chained-call +[error] no-consecutive-blank-lines +[error] no-irregular-whitespace +[error] no-trailing-whitespace +[error] number-literal-format +[error] object-literal-key-quotes +[error] one-line +[error] quotemark +[error] semicolon +[error] space-before-function-paren +[error] space-within-parens +[error] trailing-comma +[error] typedef-whitespace +[error] whitespace" `; -exports[`should throw error if input is not a string 1`] = `"Usage: tslint-config-prettier-check "`; - -exports[`should throw parsing error for invalid config 1`] = `"Unexpected number in JSON at position 1 in /fixtures/tslint.error.json"`; +exports[`should throw parsing error for invalid config 1`] = `"[error] Unexpected number in JSON at position 1 in /fixtures/tslint.error.json"`; diff --git a/tools/checker.test.ts b/tools/checker.test.ts index 3f9af5d..1249058 100644 --- a/tools/checker.test.ts +++ b/tools/checker.test.ts @@ -2,39 +2,82 @@ import * as path from "path"; import { check } from "./checker"; expect.addSnapshotSerializer({ - print: (value: string, serializer) => serializer(value.replace(process.cwd(), "")), - test: (value) => typeof value === "string" && value.indexOf(process.cwd()) !== -1, + print: (value: string, serializer) => + serializer(value.replace(process.cwd(), "")), + test: (value) => + typeof value === "string" && value.indexOf(process.cwd()) !== -1, }); -const mockedConsoleLog = jest.spyOn(console, "log"); +const messages: string[] = []; + +mockConsole("log"); +mockConsole("error"); beforeEach(() => { - mockedConsoleLog.mockReset(); + messages.splice(0, messages.length); + process.exitCode = 0; +}); + +afterAll(() => { + process.exitCode = 0; }); it("should throw conflict rules", () => { - expect(() => checkFixture("all")).toThrowErrorMatchingSnapshot(); + checkFixture("all"); + expect(getMessage()).toMatchSnapshot(); + expect(process.exitCode).toBe(1); }); it("should throw parsing error for invalid config", () => { - expect(() => checkFixture("error")).toThrowErrorMatchingSnapshot(); + checkFixture("error"); + expect(getMessage()).toMatchSnapshot(); + expect(process.exitCode).toBe(1); }); it("should show success message for non-conflict rules", () => { checkFixture("empty"); - expect(mockedConsoleLog.mock.calls[0][0]).toMatchSnapshot(); + expect(getMessage()).toMatchSnapshot(); + expect(process.exitCode).toBe(0); }); it("should show success message for conflict rules that is disabled", () => { checkFixture("false"); - expect(mockedConsoleLog.mock.calls[0][0]).toMatchSnapshot(); + expect(getMessage()).toMatchSnapshot(); + expect(process.exitCode).toBe(0); +}); + +it("should show usage if there is no filePath", () => { + checkFixture(); + expect(getMessage()).toMatchSnapshot(); + expect(process.exitCode).toBe(0); }); -it("should throw error if input is not a string", () => { - expect(() => check(undefined!)).toThrowErrorMatchingSnapshot(); +it("should be able to check multiple config files", () => { + checkFixture("all", "empty", "error"); + expect(getMessage()).toMatchSnapshot(); + expect(process.exitCode).toBe(1); }); -function checkFixture(id: string) { - const filePath = path.resolve(__dirname, `../fixtures/tslint.${id}.json`); - return check(filePath); +function mockConsole(id: keyof typeof console) { + const mockedConsoleLog = jest + .spyOn(console, id) + .mockImplementation((message: string) => + messages.push( + message + .split("\n") + .map((x) => `[${id}] ${x}`) + .join("\n"), + ), + ); +} + +function getMessage() { + return messages.join("\n"); +} + +function checkFixture(...ids: string[]) { + const filePaths = ids.map((id) => + path.resolve(__dirname, `../fixtures/tslint.${id}.json`), + ); + return check(filePaths); } diff --git a/tools/checker.ts b/tools/checker.ts index 7541c84..8e7e3d6 100644 --- a/tools/checker.ts +++ b/tools/checker.ts @@ -4,32 +4,49 @@ import { Configuration, Linter } from "tslint"; // tslint:disable-next-line:no-var-requires const tslintConfigPrettier = require("..") as Configuration.RawConfigFile; -export const check = (configFilePath: string) => { - if (typeof configFilePath !== "string") { - throw new Error("Usage: tslint-config-prettier-check "); +export const check = (configFilePaths: string[]) => { + if (configFilePaths.length === 0) { + // tslint:disable-next-line:no-console + console.log("Usage: tslint-config-prettier-check ..."); + return; } - const { rules, jsRules } = Linter.loadConfigurationFromPath(configFilePath); - - const conflictRules: string[] = []; - - Object.keys(tslintConfigPrettier.rules!).forEach((conflictRuleName) => { - if (isConflict(conflictRuleName, rules) || isConflict(conflictRuleName, jsRules)) { - conflictRules.push(conflictRuleName); + configFilePaths.forEach((configFilePath) => { + try { + const conflictRules = getConflictRules(configFilePath); + if (conflictRules.length === 0) { + // tslint:disable-next-line:no-console + console.log(`No conflict rule detected in ${configFilePath}`); + } else { + // tslint:disable-next-line:no-console + console.error( + `Conflict rule(s) detected in ${configFilePath}:\n${conflictRules + .map((conflictRule) => ` ${conflictRule}`) + .join("\n")}`, + ); + process.exitCode = 1; + } + } catch (error) { + // tslint:disable-next-line:no-console + console.error(error.message); + process.exitCode = 1; } }); - - if (conflictRules.length !== 0) { - const error = new Error(`Conflict rule(s) detected in ${configFilePath}:\n${conflictRules.join("\n")}`); - error.name = "ConflictRules"; - throw error; - } - - // tslint:disable-next-line:no-console - console.log(`No conflict rule detected in ${configFilePath}`); }; -function isConflict(conflictRuleName: string, rules: Configuration.IConfigurationFile["rules"]) { +function getConflictRules(configFilePath: string) { + const { rules, jsRules } = Linter.loadConfigurationFromPath(configFilePath); + return Object.keys(tslintConfigPrettier.rules!).filter( + (conflictRuleName) => + isConflict(conflictRuleName, rules) || + isConflict(conflictRuleName, jsRules), + ); +} + +function isConflict( + conflictRuleName: string, + rules: Configuration.IConfigurationFile["rules"], +) { return ( rules.has(conflictRuleName) && rules.get(conflictRuleName)!.ruleSeverity !== "off"