diff --git a/__tests__/fixtures/options.ts b/__tests__/fixtures/options.ts new file mode 100644 index 00000000..921ec6e0 --- /dev/null +++ b/__tests__/fixtures/options.ts @@ -0,0 +1,32 @@ +import * as ts from "typescript"; + +import { setTypescriptModule } from "../../src/tsproxy"; +import { IOptions } from "../../src/ioptions"; + +setTypescriptModule(ts); + +export function makeOptions(cacheDir: string, cwd: string): IOptions { + return { + include: ["*.ts+(|x)", "**/*.ts+(|x)"], + exclude: ["*.d.ts", "**/*.d.ts"], + check: false, + verbosity: 5, + clean: false, + cacheRoot: cacheDir, + cwd, + abortOnError: false, + rollupCommonJSResolveHack: false, + typescript: ts, + objectHashIgnoreUnknownHack: false, + tsconfigOverride: null, + useTsconfigDeclarationDir: false, + tsconfigDefaults: null, + sourceMapCallback: (id: string, map: string): void => { + console.log(id + map); + }, + transformers: [(ls: ts.LanguageService) => { + console.log(ls); + return {}; + }], + }; +} diff --git a/__tests__/get-options-overrides.spec.ts b/__tests__/get-options-overrides.spec.ts index ec2c6725..cdc141e5 100644 --- a/__tests__/get-options-overrides.spec.ts +++ b/__tests__/get-options-overrides.spec.ts @@ -4,13 +4,10 @@ import * as ts from "typescript"; import { normalizePath as normalize } from "@rollup/pluginutils"; import { remove } from "fs-extra"; +import { makeOptions } from "./fixtures/options"; import { makeStubbedContext } from "./fixtures/context"; -import { setTypescriptModule } from "../src/tsproxy"; -import { IOptions } from "../src/ioptions"; import { getOptionsOverrides, createFilter } from "../src/get-options-overrides"; -setTypescriptModule(ts); - const local = (x: string) => normalize(path.resolve(__dirname, x)); const cacheDir = local("__temp/get-options-overrides"); @@ -19,29 +16,7 @@ const filtPath = (relPath: string) => normalize(`${process.cwd()}/${relPath}`); afterAll(() => remove(cacheDir)); -const defaultConfig: IOptions = { - include: ["*.ts+(|x)", "**/*.ts+(|x)"], - exclude: ["*.d.ts", "**/*.d.ts"], - check: false, - verbosity: 5, - clean: false, - cacheRoot: cacheDir, - cwd: local(""), - abortOnError: false, - rollupCommonJSResolveHack: false, - typescript: ts, - objectHashIgnoreUnknownHack: false, - tsconfigOverride: null, - useTsconfigDeclarationDir: false, - tsconfigDefaults: null, - sourceMapCallback: (id: string, map: string): void => { - console.log(id + map); - }, - transformers: [(ls: ts.LanguageService) => { - console.log(ls); - return {}; - }], -}; +const defaultConfig = makeOptions(cacheDir, local("")); const forcedOptions: ts.CompilerOptions = { allowNonTsExtensions: true, diff --git a/__tests__/integration/errors.spec.ts b/__tests__/integration/errors.spec.ts index 14b8bd9c..e6cb2aa8 100644 --- a/__tests__/integration/errors.spec.ts +++ b/__tests__/integration/errors.spec.ts @@ -30,13 +30,6 @@ async function genBundle(relInput: string, extraOpts?: RPT2Options, onwarn?: Moc }); } -test("integration - tsconfig errors", async () => { - // TODO: move to parse-tsconfig unit tests? - await expect(genBundle("semantic.ts", { - tsconfig: "non-existent-tsconfig", - })).rejects.toThrow("rpt2: failed to open 'non-existent-tsconfig'"); -}); - test("integration - semantic error", async () => { await expect(genBundle("semantic.ts")).rejects.toThrow("Type 'string' is not assignable to type 'number'."); }); diff --git a/__tests__/parse-tsconfig.spec.ts b/__tests__/parse-tsconfig.spec.ts new file mode 100644 index 00000000..1f2f7754 --- /dev/null +++ b/__tests__/parse-tsconfig.spec.ts @@ -0,0 +1,45 @@ +import { test, expect } from "@jest/globals"; +import * as path from "path"; +import { normalizePath as normalize } from "@rollup/pluginutils"; + +import { makeOptions } from "./fixtures/options"; +import { makeStubbedContext } from "./fixtures/context"; +import { parseTsConfig } from "../src/parse-tsconfig"; + +const local = (x: string) => normalize(path.resolve(__dirname, x)); + +const defaultOpts = makeOptions("", ""); +const stubbedContext = makeStubbedContext({}); + +test("parseTsConfig", () => { + expect(() => parseTsConfig(stubbedContext, defaultOpts)).not.toThrow(); +}); + +test("parseTsConfig - tsconfig errors", () => { + const data = { error: "" }; + + // should not throw when the tsconfig is buggy, but should still print an error (below) + expect(() => parseTsConfig(makeStubbedContext(data), { + ...defaultOpts, + tsconfigOverride: { + include: "should-be-an-array", + }, + })).not.toThrow(); + expect(data.error).toMatch("Compiler option 'include' requires a value of type Array"); +}); + +test("parseTsConfig - failed to open", () => { + expect(() => parseTsConfig(stubbedContext, { + ...defaultOpts, + tsconfig: "non-existent-tsconfig", + })).toThrow("rpt2: failed to open 'non-existent-tsconfig'"); +}); + +test("parseTsConfig - failed to parse", () => { + const notTsConfigPath = local("fixtures/options.ts"); // a TS file should fail to parse + + expect(() => parseTsConfig(stubbedContext, { + ...defaultOpts, + tsconfig: notTsConfigPath, + })).toThrow(`rpt2: failed to parse '${notTsConfigPath}'`); +}); diff --git a/src/parse-tsconfig.ts b/src/parse-tsconfig.ts index b24a0bb9..45380ce9 100644 --- a/src/parse-tsconfig.ts +++ b/src/parse-tsconfig.ts @@ -23,10 +23,7 @@ export function parseTsConfig(context: IContext, pluginOptions: IOptions) let pretty = true; if (fileName) { - const text = tsModule.sys.readFile(fileName); - if (text === undefined) - throw new Error(`rpt2: failed to read '${fileName}'`); - + const text = tsModule.sys.readFile(fileName)!; // readFile only returns undefined when the file doesn't exist, which we already checked above const result = tsModule.parseConfigFileTextToJson(fileName, text); pretty = result.config?.pretty ?? pretty;