Skip to content

Commit 5f057eb

Browse files
add testing and make code more easily testable
1 parent e12c502 commit 5f057eb

6 files changed

Lines changed: 74 additions & 30 deletions

File tree

src/collectFileNames.test.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,31 @@
1-
import path from "node:path";
21
import { describe, expect, it } from "vitest";
32

43
import { collectFileNames } from "./collectFileNames.js";
54

65
describe("collectFileNames", () => {
76
it("should collect files with wildcard when collection succeeds", async () => {
8-
const cwd = path.resolve(import.meta.dirname, "..");
9-
const fileNames = await collectFileNames(
10-
path.resolve(import.meta.dirname),
11-
["*"],
12-
);
13-
expect(fileNames).toContain(`${cwd}/src/collectFileNames.test.ts`);
7+
const cwd = process.cwd();
8+
const res = await collectFileNames(cwd, ["src/*"]);
9+
expect(res?.fileNames).toContain(`${cwd}/src/collectFileNames.test.ts`);
10+
});
11+
12+
it("should return undefined if includes is empty array", async () => {
13+
const cwd = process.cwd();
14+
const res = await collectFileNames(cwd, []);
15+
expect(res).toBeUndefined();
1416
});
1517

1618
it("should return error if node_modules are implicitly included", async () => {
17-
const cwd = path.resolve(import.meta.dirname, "..");
18-
const fileNames = await collectFileNames(cwd, ["*"]);
19-
expect(fileNames).toEqual(
19+
const cwd = process.cwd();
20+
const res = await collectFileNames(cwd, ["*"]);
21+
expect(res?.error).toEqual(
2022
`At least one path including node_modules was included implicitly: '${cwd}/node_modules'. Either adjust TypeStat's included files to not include node_modules (recommended) or explicitly include node_modules/ (not recommended).`,
2123
);
2224
});
2325

2426
it("should NOT return error if node_modules are explicitly included", async () => {
25-
const cwd = path.resolve(import.meta.dirname, "..");
26-
const fileNames = await collectFileNames(cwd, ["node_modules"]);
27-
expect(fileNames?.length).toBeGreaterThan(0);
27+
const cwd = process.cwd();
28+
const res = await collectFileNames(cwd, ["node_modules"]);
29+
expect(res?.fileNames.length).toBeGreaterThan(0);
2830
});
2931
});

src/collectFileNames.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import { glob } from "node:fs/promises";
22
import path from "node:path";
33

4+
export interface CollectFileNamesResult {
5+
error?: string;
6+
fileNames: readonly string[];
7+
}
8+
49
export const collectFileNames = async (
510
cwd: string,
611
include: readonly string[] | undefined,
7-
): Promise<readonly string[] | string | undefined> => {
8-
if (include === undefined) {
12+
): Promise<CollectFileNamesResult | undefined> => {
13+
if (!include?.length) {
914
return undefined;
1015
}
1116

@@ -16,10 +21,13 @@ export const collectFileNames = async (
1621
);
1722

1823
if (implicitNodeModulesInclude) {
19-
return `At least one path including node_modules was included implicitly: '${implicitNodeModulesInclude}'. Either adjust TypeStat's included files to not include node_modules (recommended) or explicitly include node_modules/ (not recommended).`;
24+
return {
25+
error: `At least one path including node_modules was included implicitly: '${implicitNodeModulesInclude}'. Either adjust TypeStat's included files to not include node_modules (recommended) or explicitly include node_modules/ (not recommended).`,
26+
fileNames: [],
27+
};
2028
}
2129

22-
return fileNames;
30+
return { fileNames };
2331
};
2432

2533
const collectFileNamesFromGlobs = async (
@@ -36,9 +44,9 @@ const collectFileNamesFromGlobs = async (
3644
const implicitNodeModulesIncluded = (
3745
fileGlobs: readonly string[],
3846
fileNames: readonly string[],
39-
): boolean => {
40-
return (
41-
!fileGlobs.some((glob) => glob.includes("node_modules")) &&
42-
fileNames.some((fileName) => fileName.includes("node_modules"))
43-
);
47+
): string | undefined => {
48+
if (fileGlobs.some((glob) => glob.includes("node_modules"))) {
49+
return undefined;
50+
}
51+
return fileNames.find((fileName) => fileName.includes("node_modules"));
4452
};

src/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,14 @@ export const typeStat = async (
9191

9292
for (let i = 0; i < allPendingOptions.length; i += 1) {
9393
// Collect all files to be run on this option iteration from the include glob(s)
94-
const fileNames = await collectFileNames(cwd, allPendingOptions[i].include);
95-
if (typeof fileNames !== "object") {
94+
const fileNamesRes = await collectFileNames(
95+
cwd,
96+
allPendingOptions[i].include,
97+
);
98+
if (!fileNamesRes || fileNamesRes.error) {
9699
return {
97100
error: new Error(
98-
`Could not run options object ${i + 1}: ${fileNames ?? `No files included by the 'include' setting were found.`}`,
101+
`Could not run options object ${i + 1}: ${fileNamesRes?.error ?? `No files included by the 'include' setting were found.`}`,
99102
),
100103
status: ResultStatus.Failed,
101104
};
@@ -116,7 +119,7 @@ export const typeStat = async (
116119
await runMutations({
117120
mutationsProvider: createTypeStatProvider({
118121
...allPendingOptions[i],
119-
fileNames,
122+
fileNames: fileNamesRes.fileNames,
120123
}),
121124
});
122125
} catch (error) {
File renamed without changes.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { describe, expect, it } from "vitest";
2+
3+
import { getFixImportExtensionsMutations } from "./index.js";
4+
5+
describe("getFixImportExtensionsMutations", () => {
6+
it("should collect list of tsconfig files", () => {
7+
const mutations = getFixImportExtensionsMutations(
8+
process.cwd() + "/src/mutators/builtIn/fixImportExtensions/index.ts",
9+
"./README",
10+
1,
11+
);
12+
expect(mutations).toMatchInlineSnapshot(`
13+
{
14+
"insertion": ".md",
15+
"range": {
16+
"begin": 0,
17+
},
18+
"type": "text-insert",
19+
}
20+
`);
21+
});
22+
});

src/mutators/builtIn/fixImportExtensions/index.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,20 @@ const visitExportOrImportDeclaration = (
5050
return undefined;
5151
}
5252

53-
// Try each path that the import could resolve to
54-
const basePath = path.join(
55-
path.dirname(request.sourceFile.fileName),
53+
return getFixImportExtensionsMutations(
54+
request.sourceFile.fileName,
5655
node.moduleSpecifier.text,
56+
node.moduleSpecifier.end,
5757
);
58+
};
59+
60+
export const getFixImportExtensionsMutations = (
61+
sourceFileName: string,
62+
moduleSpecifier: string,
63+
end: number,
64+
): TextInsertMutation | undefined => {
65+
// Try each path that the import could resolve to
66+
const basePath = path.join(path.dirname(sourceFileName), moduleSpecifier);
5867

5968
for (const filePath of [basePath, path.join(basePath, "index")]) {
6069
// If no files exist under that path, ignore this possibility
@@ -75,7 +84,7 @@ const visitExportOrImportDeclaration = (
7584
return {
7685
insertion: "." + path.basename(mostLikely).split(".").slice(1).join("."),
7786
range: {
78-
begin: node.moduleSpecifier.end - 1,
87+
begin: end - 1,
7988
},
8089
type: "text-insert",
8190
};

0 commit comments

Comments
 (0)