Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,3 @@
coverage/
node_modules/
src/**/*.js

# https://github.com/JoshuaKGoldberg/tslint-to-eslint-config/issues/9
.eslintrc.json
10 changes: 9 additions & 1 deletion src/cli/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { EOL } from "os";
import { promisify } from "util";

import { convertConfig } from "../convertConfig";
import { createNewConfiguration } from "../creation/createNewConfiguration";
import { findTslintRules } from "../input/findTslintRules";
import { TSLintToESLintSettings } from "../types";
import { runCli } from "./runCli";
Expand All @@ -23,7 +24,14 @@ const fileExists = (filePath: string) => Promise.resolve(fs.existsSync(filePath)

const runtime = {
convertConfig: (settings: TSLintToESLintSettings) =>
convertConfig(settings, logger, ruleFinder, fileExists),
convertConfig({
createNewConfiguration: configConversionResults =>
createNewConfiguration(configConversionResults, fs.promises.writeFile),
fileExists,
logger,
ruleFinder,
settings,
}),
logger,
ruleFinder,
};
Expand Down
78 changes: 42 additions & 36 deletions src/convertConfig.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,72 @@ import { createStubLogger } from "./stubs";
import { convertConfig } from "./convertConfig";
import { ResultStatus } from "./types";

const defaultRequest = {
settings: {},
logger: createStubLogger(),
ruleFinder: jest.fn().mockReturnValue(Promise.resolve(new Error())),
fileExists: jest.fn().mockReturnValue(Promise.resolve(true)),
createNewConfiguration: jest.fn().mockReturnValue(Promise.resolve()),
};

describe("convertConfig", () => {
it("complains when the provided config file does not exist", async () => {
// Arrange
const settings = {
config: "./stub/tslint.json",
const request = {
...defaultRequest,
fileExists: jest.fn().mockReturnValue(Promise.resolve(false)),
};
const logger = createStubLogger();
const ruleFinder = jest.fn().mockReturnValue(Promise.resolve(new Error()));
const fileExists = jest.fn().mockReturnValue(Promise.resolve(false));

// Act
const result = await convertConfig(settings, logger, ruleFinder, fileExists);
const result = await convertConfig(request);

// Assert
expect(result).toEqual({
complaint: `${settings.config} does not seem to exist.`,
complaint: `./tslint.json does not seem to exist.`,
status: ResultStatus.ConfigurationError,
});
});

it("searches for settings.config when settings.config is provided", async () => {
// Arrange
const settings = {
config: "./stub/tslint.json",
const request = {
...defaultRequest,
settings: {
config: "./stub/tslint.json",
},
};
const logger = createStubLogger();
const ruleFinder = jest.fn().mockReturnValue(Promise.resolve(new Error()));
const fileExists = jest.fn().mockReturnValue(Promise.resolve(true));

// Act
await convertConfig(settings, logger, ruleFinder, fileExists);
await convertConfig(request);

// Assert
expect(ruleFinder).toHaveBeenLastCalledWith(settings.config);
expect(request.ruleFinder).toHaveBeenLastCalledWith(request.settings.config);
});

it("searches for ./tslint.json by default when no settings.config is provided", async () => {
// Arrange
const settings = {};
const logger = createStubLogger();
const ruleFinder = jest.fn().mockReturnValue(Promise.resolve(new Error()));
const fileExists = jest.fn().mockReturnValue(Promise.resolve(true));
const request = {
...defaultRequest,
settings: {},
};

// Act
await convertConfig(settings, logger, ruleFinder, fileExists);
await convertConfig(request);

// Assert
expect(ruleFinder).toHaveBeenLastCalledWith("./tslint.json");
expect(request.ruleFinder).toHaveBeenLastCalledWith("./tslint.json");
});

it("returns a failure result when ruleFinder returns an error", async () => {
// Arrange
const settings = {};
const logger = createStubLogger();
const error = new Error("oh no");
const ruleFinder = jest.fn().mockReturnValue(Promise.resolve(error));
const fileExists = jest.fn().mockReturnValue(Promise.resolve(true));
const request = {
...defaultRequest,
ruleFinder: jest.fn().mockReturnValue(Promise.resolve(error)),
};

// Act
const result = await convertConfig(settings, logger, ruleFinder, fileExists);
const result = await convertConfig(request);

// Assert
expect(result).toEqual({
Expand All @@ -72,20 +78,20 @@ describe("convertConfig", () => {

it("creates a new configuration when ruleFinder returns rules", async () => {
// Arrange
const settings = {};
const logger = createStubLogger();
const ruleFinder = jest.fn().mockReturnValue({
rules: {
"sample-rule": {
ruleArguments: ["one", "two"],
ruleName: "sample-rule",
const request = {
...defaultRequest,
ruleFinder: jest.fn().mockReturnValue({
rules: {
"sample-rule": {
ruleArguments: ["one", "two"],
ruleName: "sample-rule",
},
},
},
});
const fileExists = jest.fn().mockReturnValue(Promise.resolve(true));
}),
};

// Act
const result = await convertConfig(settings, logger, ruleFinder, fileExists);
const result = await convertConfig(request);

// Assert
expect(result).toEqual({
Expand Down
28 changes: 19 additions & 9 deletions src/convertConfig.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
import { createNewConfiguration } from "./creation/createNewConfiguration";
import { FoundTSLintRules } from "./input/findTslintRules";
import { ProcessLogger } from "./logger";
import { reportConversionResults } from "./reportConversionResults";
import { convertRules } from "./rules/convertRules";
import { convertRules, ConfigConversionResults } from "./rules/convertRules";
import { converters } from "./rules/converters";
import { TSLintToESLintSettings, TSLintToESLintResult, ResultStatus } from "./types";

export type RuleFinder = (config: string) => Promise<FoundTSLintRules | Error>;
export type CreateNewConfiguration = (conversionResults: ConfigConversionResults) => Promise<void>;

export type FileExists = (filePath: string) => Promise<boolean>;

export const convertConfig = async (
settings: TSLintToESLintSettings,
logger: ProcessLogger,
ruleFinder: RuleFinder,
fileExists: FileExists,
): Promise<TSLintToESLintResult> => {
export type RuleFinder = (config: string) => Promise<FoundTSLintRules | Error>;

export type ConvertConfigRequest = {
createNewConfiguration: CreateNewConfiguration;
fileExists: FileExists;
logger: ProcessLogger;
ruleFinder: RuleFinder;
settings: TSLintToESLintSettings;
};

export const convertConfig = async ({
createNewConfiguration,
fileExists,
logger,
ruleFinder,
settings,
}: ConvertConfigRequest): Promise<TSLintToESLintResult> => {
const { config = "./tslint.json" } = settings;
if (!(await fileExists(config))) {
return {
Expand Down
68 changes: 68 additions & 0 deletions src/creation/createNewConfiguration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { emptyConversionResults } from "../stubs";
import { createNewConfiguration } from "./createNewConfiguration";
import { ConfigConversionResults } from "../rules/convertRules";

describe("createNewConfiguration", () => {
it("writes only formatted rules when there are no missing rules", async () => {
// Arrange
const conversionResults: ConfigConversionResults = {
...emptyConversionResults,
converted: new Map(),
};
const writeFile = jest.fn().mockReturnValue(Promise.resolve());

// Act
await createNewConfiguration(conversionResults, writeFile);

// Assert
expect(writeFile).toHaveBeenLastCalledWith(
".eslintrc.json",
JSON.stringify({ rules: {} }, undefined, 4),
);
});

it("includes typescript-eslint plugin settings when there are missing rules", async () => {
// Arrange
const conversionResults: ConfigConversionResults = {
...emptyConversionResults,
converted: new Map(),
missing: [
{
ruleArguments: [],
ruleName: "tslint-rule-one",
ruleSeverity: "error",
},
],
};
const writeFile = jest.fn().mockReturnValue(Promise.resolve());

// Act
await createNewConfiguration(conversionResults, writeFile);

// Assert
expect(writeFile).toHaveBeenLastCalledWith(
".eslintrc.json",
JSON.stringify(
{
plugins: ["@typescript-eslint/tslint"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "tsconfig.json",
},
rules: {
"@typescript-eslint/tslint/config": [
"error",
{
rules: {
"tslint-rule-one": true,
},
},
],
},
},
undefined,
4,
),
);
});
});
11 changes: 7 additions & 4 deletions src/creation/createNewConfiguration.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import * as fs from "fs";

import { ConfigConversionResults } from "../rules/convertRules";
import { formatConvertedRules } from "./formatConvertedRules";

export const createNewConfiguration = async (conversionResults: ConfigConversionResults) => {
export type WriteFile = (filePath: string, contents: string) => Promise<void>;

export const createNewConfiguration = async (
conversionResults: ConfigConversionResults,
writeFile: WriteFile,
) => {
const output = {
...(conversionResults.missing.length && {
plugins: ["@typescript-eslint/tslint"],
Expand All @@ -15,5 +18,5 @@ export const createNewConfiguration = async (conversionResults: ConfigConversion
rules: formatConvertedRules(conversionResults),
};

await fs.promises.writeFile(".eslintrc.json", JSON.stringify(output, undefined, 4));
await writeFile(".eslintrc.json", JSON.stringify(output, undefined, 4));
};