[babel 8] Type checking preset-typescript options (#12460)

* refactor: extract option normalization in preset-typescript

* breaking: type checking preset-typescript options

* chore: bundle preset-typescript into a single lib

* test: disable Babel 7 test on Babel 8 breaking change test

* workaround Jest 24 error snapshot dedent issue

* skip Babel 8 test when the Breaking ENV is not available

* chore: update test snapshot

* Update packages/babel-preset-typescript/test/normalize-options.spec.js

Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>

* update test fixtures

Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
Huáng Jùnliàng 2021-01-07 14:58:58 -05:00 committed by GitHub
parent 866a742bf7
commit ff52acee79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 171 additions and 21 deletions

View File

@ -361,6 +361,7 @@ function copyDts(packages) {
const libBundles = [
"packages/babel-parser",
"packages/babel-plugin-proposal-optional-chaining",
"packages/babel-preset-typescript",
"packages/babel-helper-member-expression-to-functions",
].map(src => ({
src,

View File

@ -1,35 +1,19 @@
import { declare } from "@babel/helper-plugin-utils";
import transformTypeScript from "@babel/plugin-transform-typescript";
import { OptionValidator } from "@babel/helper-validator-option";
const v = new OptionValidator("@babel/preset-typescript");
import normalizeOptions from "./normalize-options.js";
export default declare((api, opts) => {
api.assertVersion(7);
const {
allExtensions,
allowDeclareFields,
allowNamespaces,
isTSX,
jsxPragma,
jsxPragmaFrag,
onlyRemoveTypeImports,
} = opts;
const jsxPragmaFrag = v.validateStringOption(
"jsxPragmaFrag",
opts.jsxPragmaFrag,
"React.Fragment",
);
const allExtensions = v.validateBooleanOption(
"allExtensions",
opts.allExtensions,
false,
);
const isTSX = v.validateBooleanOption("isTSX", opts.isTSX, false);
if (isTSX) {
v.invariant(allExtensions, "isTSX:true requires allExtensions:true");
}
} = normalizeOptions(opts);
const pluginOptions = isTSX => ({
allowDeclareFields,

View File

@ -0,0 +1,72 @@
import { OptionValidator } from "@babel/helper-validator-option";
const v = new OptionValidator("@babel/preset-typescript");
export default function normalizeOptions(options = {}) {
let {
allowDeclareFields,
allowNamespaces,
jsxPragma,
onlyRemoveTypeImports,
} = options;
if (process.env.BABEL_8_BREAKING) {
const TopLevelOptions = {
allowDeclareFields: "allowDeclareFields",
allExtensions: "allExtensions",
allowNamespaces: "allowNamespaces",
isTSX: "isTSX",
jsxPragma: "jsxPragma",
jsxPragmaFrag: "jsxPragmaFrag",
onlyRemoveTypeImports: "onlyRemoveTypeImports",
};
v.validateTopLevelOptions(options, TopLevelOptions);
allowDeclareFields = v.validateBooleanOption(
TopLevelOptions.allowDeclareFields,
options.allowDeclareFields,
true,
);
allowNamespaces = v.validateBooleanOption(
TopLevelOptions.allowNamespaces,
options.allowNamespaces,
true,
);
jsxPragma = v.validateStringOption(
TopLevelOptions.jsxPragma,
options.jsxPragma,
"React",
);
onlyRemoveTypeImports = v.validateBooleanOption(
TopLevelOptions.onlyRemoveTypeImports,
options.onlyRemoveTypeImports,
true,
);
}
const jsxPragmaFrag = v.validateStringOption(
"jsxPragmaFrag",
options.jsxPragmaFrag,
"React.Fragment",
);
const allExtensions = v.validateBooleanOption(
"allExtensions",
options.allExtensions,
false,
);
const isTSX = v.validateBooleanOption("isTSX", options.isTSX, false);
if (isTSX) {
v.invariant(allExtensions, "isTSX:true requires allExtensions:true");
}
return {
allExtensions,
allowDeclareFields,
allowNamespaces,
isTSX,
jsxPragma,
jsxPragmaFrag,
onlyRemoveTypeImports,
};
}

View File

@ -0,0 +1,93 @@
import normalizeOptions from "../src/normalize-options";
describe("normalize options", () => {
(process.env.BABEL_8_BREAKING ? describe : describe.skip)("Babel 8", () => {
it("should throw on unknown options", () => {
expect(() => normalizeOptions({ allowNamespace: true })).toThrowError(
"@babel/preset-typescript: 'allowNamespace' is not a valid top-level option.\n- Did you mean 'allowNamespaces'?",
);
});
it.each([
"allowDeclareFields",
"allExtensions",
"allowNamespaces",
"isTSX",
"onlyRemoveTypeImports",
])("should throw when `%p` is not a boolean", optionName => {
expect(() => normalizeOptions({ [optionName]: 0 })).toThrow(
`@babel/preset-typescript: '${optionName}' option must be a boolean.`,
);
});
it.each(["jsxPragma", "jsxPragmaFrag"])(
"should throw when `%p` is not a string",
optionName => {
expect(() => normalizeOptions({ [optionName]: 0 })).toThrow(
`@babel/preset-typescript: '${optionName}' option must be a string.`,
);
},
);
it("should not throw when options is not defined", () => {
expect(() => normalizeOptions()).not.toThrowError();
});
it("default values", () => {
expect(normalizeOptions({})).toMatchInlineSnapshot(`
Object {
"allExtensions": false,
"allowDeclareFields": true,
"allowNamespaces": true,
"isTSX": false,
"jsxPragma": "React",
"jsxPragmaFrag": "React.Fragment",
"onlyRemoveTypeImports": true,
}
`);
});
});
(process.env.BABEL_8_BREAKING ? describe.skip : describe)("Babel 7", () => {
it("should not throw on unknown options", () => {
expect(() =>
normalizeOptions({ allowNamespace: true }),
).not.toThrowError();
});
it.each(["allowDeclareFields", "allowNamespaces", "onlyRemoveTypeImports"])(
"should not throw when `%p` is not a boolean",
optionName => {
expect(() => normalizeOptions({ [optionName]: 0 })).not.toThrowError();
},
);
it.each(["jsxPragma"])(
"should throw when `%p` is not a string",
optionName => {
expect(() => normalizeOptions({ [optionName]: 0 })).not.toThrowError();
},
);
it.each(["allExtensions", "isTSX"])(
"should throw when `%p` is not a boolean",
optionName => {
expect(() => normalizeOptions({ [optionName]: 0 })).toThrow(
`@babel/preset-typescript: '${optionName}' option must be a boolean.`,
);
},
);
it.each(["jsxPragmaFrag"])(
"should throw when `%p` is not a string",
optionName => {
expect(() => normalizeOptions({ [optionName]: 0 })).toThrow(
`@babel/preset-typescript: '${optionName}' option must be a string.`,
);
},
);
it("default values", () => {
expect(normalizeOptions({})).toMatchInlineSnapshot(`
Object {
"allExtensions": false,
"allowDeclareFields": undefined,
"allowNamespaces": undefined,
"isTSX": false,
"jsxPragma": undefined,
"jsxPragmaFrag": "React.Fragment",
"onlyRemoveTypeImports": undefined,
}
`);
});
});
});