import { loadOptions as loadOptionsOrig } from "../lib/index.js"; import path from "path"; import { fileURLToPath } from "url"; const cwd = path.dirname(fileURLToPath(import.meta.url)); function loadOptions(opts) { return loadOptionsOrig({ cwd, ...opts }); } describe("option-manager", () => { it("throws for babel 5 plugin", () => { return expect(() => { loadOptions({ plugins: [({ Plugin }) => new Plugin("object-assign", {})], }); }).toThrow(/Babel 5 plugin is being run with an unsupported Babel/); }); describe("config plugin/preset flattening and overriding", () => { function makePlugin() { const calls = []; const plugin = (api, opts) => { calls.push(opts); return {}; }; return { plugin, calls }; } it("should throw when an option is provided as a preset", () => { expect(() => { loadOptions({ presets: [ "./fixtures/option-manager/babel-preset-bar", { useBuiltIns: "entry" }, ], }); }).toThrowErrorMatchingSnapshot(); }); it("should throw when an option is provided as a plugin", () => { expect(() => { loadOptions({ plugins: [ "./fixtures/option-manager/babel-plugin-foo", { useSpread: true }, ], }); }).toThrowErrorMatchingSnapshot(); }); it("should throw when an option is following a preset", () => { expect(() => { loadOptions({ presets: [ "./fixtures/option-manager/babel-plugin-foo", "./fixtures/option-manager/babel-preset-bar", { useSpread: true }, ], }); }).toThrowErrorMatchingSnapshot(); }); it("should not throw when a preset string followed by valid preset object", () => { const { plugin } = makePlugin(); expect( loadOptions({ presets: [ "@babel/env", { plugins: [[plugin, undefined, "my-plugin"]] }, ], }), ).toBeTruthy(); }); it("should throw if a plugin name is repeated, with information about the repeated plugin", () => { const { calls, plugin } = makePlugin(); expect(() => { loadOptions({ plugins: [ [plugin, undefined, "my-plugin"], [plugin, undefined, "my-plugin"], ], }); }).toThrow( /Duplicate plugin\/preset detected.*Duplicates detected are.*my-plugin.*my-plugin/ms, ); expect(calls).toEqual([]); }); it("throws for null options", () => { const { calls, plugin } = makePlugin(); expect(() => { loadOptions({ plugins: [[plugin, null]], }); }).toThrow(".plugins[0][1] must be an object, false, or undefined"); expect(calls).toEqual([]); }); it("should not throw if a repeated plugin has a different name", () => { const { calls, plugin } = makePlugin(); loadOptions({ plugins: [ [plugin, { arg: 1 }], [plugin, { arg: 2 }, "some-name"], ], }); expect(calls).toEqual([{ arg: 1 }, { arg: 2 }]); }); it("should merge .env[] plugins with parent presets", () => { const { calls: calls1, plugin: plugin1 } = makePlugin(); const { calls: calls2, plugin: plugin2 } = makePlugin(); loadOptions({ envName: "test", plugins: [[plugin1, { arg: 1 }]], env: { test: { plugins: [ [plugin1, { arg: 3 }], [plugin2, { arg: 2 }], ], }, }, }); expect(calls1).toEqual([{ arg: 3 }]); expect(calls2).toEqual([{ arg: 2 }]); }); it("should throw if a preset is repeated", () => { const { calls, plugin: preset } = makePlugin(); expect(() => { loadOptions({ presets: [preset, preset], }); }).toThrow(/Duplicate plugin\/preset detected/); expect(calls).toEqual([]); }); it("should not throw if a repeated preset has a different name", () => { const { calls, plugin: preset } = makePlugin(); loadOptions({ presets: [ [preset, { arg: 1 }], [preset, { arg: 2 }, "some-name"], ], }); expect(calls).toEqual([{ arg: 1 }, { arg: 2 }]); }); it("should merge .env[] presets with parent presets", () => { const { calls: calls1, plugin: preset1 } = makePlugin(); const { calls: calls2, plugin: preset2 } = makePlugin(); loadOptions({ envName: "test", presets: [[preset1, { arg: 1 }]], env: { test: { presets: [ [preset1, { arg: 3 }], [preset2, { arg: 2 }], ], }, }, }); expect(calls1).toEqual([{ arg: 3 }]); expect(calls2).toEqual([{ arg: 2 }]); }); it("should not merge .env[] presets with parent presets when passPerPreset", () => { const { calls: calls1, plugin: preset1 } = makePlugin(); const { calls: calls2, plugin: preset2 } = makePlugin(); loadOptions({ envName: "test", passPerPreset: true, presets: [[preset1, { arg: 1 }]], env: { test: { presets: [ [preset1, { arg: 3 }], [preset2, { arg: 2 }], ], }, }, }); expect(calls1).toEqual([{ arg: 1 }, { arg: 3 }]); expect(calls2).toEqual([{ arg: 2 }]); }); }); describe("mergeOptions", () => { it("throws for removed babel 5 options", () => { return expect(() => { loadOptions({ randomOption: true, }); }).toThrow(/Unknown option: .randomOption/); }); it("throws for removed babel 5 options", () => { return expect(() => { loadOptions({ auxiliaryComment: true, blacklist: true, }); }).toThrow( // eslint-disable-next-line max-len /Using removed Babel 5 option: .auxiliaryComment - Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`/, ); }); it("throws for resolved but erroring preset", () => { return expect(() => { loadOptions({ presets: [path.join(cwd, "fixtures/option-manager/not-a-preset")], }); }).toThrow( /While processing: .*option-manager(?:\/|\\\\)not-a-preset\.js/, ); }); }); describe("presets", function () { it.each([ "es5_function", "es5_object", "es2015_default_function", "es2015_default_object", ])("%p should work", name => { const options = loadOptions({ presets: [path.join(cwd, "fixtures/option-manager/presets", name)], }); expect(Array.isArray(options.plugins)).toBe(true); expect(options.plugins).toHaveLength(1); expect(options.presets).toHaveLength(0); }); it.each([ ["es2015_named", /Must export a default export when using ES6 modules/], ["es2015_invalid", /Unsupported format: string/], ["es5_invalid", /Unsupported format: string/], ])("%p should throw %p", (name, msg) => { expect(() => loadOptions({ presets: [path.join(cwd, "fixtures/option-manager/presets", name)], }), ).toThrow(msg); }); }); });