text: import * as babel from "@babel/core";
  import { fileURLToPath } from "url";
  import path from "path";
  
  import { ImportInjector } from "../lib/index.js";
  
  const cwd = path.dirname(fileURLToPath(import.meta.url));
  
  function test(sourceType, opts, initializer, inputCode, expectedCode) {
    if (typeof opts === "function") {
      expectedCode = inputCode;
      inputCode = initializer;
      initializer = opts;
      opts = null;
    }
    if (expectedCode === undefined) {
      expectedCode = inputCode;
      inputCode = "";
    }
  
    const result = babel.transform(inputCode, {
      cwd,
      sourceType,
      filename: "example" + (sourceType === "module" ? ".mjs" : ".js"),
      babelrc: false,
      configFile: false,
      plugins: [
        function ({ types: t }) {
          return {
            pre(file) {
              file.set("helperGenerator", name =>
                t.memberExpression(
                  t.identifier("babelHelpers"),
                  t.identifier(name),
                ),
              );
            },
            visitor: {
              Program(path) {
                const manager = new ImportInjector(path, opts);
  
                const ref = initializer(manager);
                if (ref) path.pushContainer("body", t.expressionStatement(ref));
              },
            },
          };
        },
      ],
    });
  
    expect(result.code.replace(/\s+/g, " ").trim()).toBe(
      (expectedCode || "").replace(/\s+/g, " ").trim(),
    );
  }
  const testScript = test.bind(undefined, "script");
  const testModule = test.bind(undefined, "module");
  
  describe("@babel/helper-module-imports", () => {
    describe("namespace import", () => {
      const addNamespace = opts => m => m.addNamespace("source", opts);
  
      describe("loading an ES6 module", () => {
        const importedType = "es6";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedType },
              addNamespace(),
              `
                import * as _source from "source";
                _source;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedType },
              addNamespace({ nameHint: "hintedName" }),
              `
                import * as _hintedName from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedType },
              addNamespace(),
              `
                import * as _source from "source";
                _source;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            expect(() => {
              testScript({ importedType }, addNamespace());
            }).toThrow("Cannot import an ES6 module from CommonJS");
          });
        });
      });
  
      describe("loading CommonJS with 'uncompiled'", () => {
        const importedInterop = "uncompiled";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamespace(),
              `
                import _source from "source";
                _source;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamespace(),
              `
                import _source from "source";
                _source;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addNamespace(),
              `
                var _source = require("source");
                _source;
              `,
            );
          });
        });
      });
  
      describe("loading CommonJS with 'compiled'", () => {
        const importedInterop = "compiled";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamespace(),
              `
                import _source from "source";
                _source;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamespace(),
              `
                import * as _source from "source";
                _source;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addNamespace(),
              `
                var _source = require("source");
                _source;
              `,
            );
          });
        });
      });
  
      describe("loading CommonJS with 'babel'", () => {
        const importedInterop = "babel";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamespace(),
              `
                import _source$es6Default from "source";
                var _source = babelHelpers.interopRequireWildcard(_source$es6Default);
                _source;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamespace(),
              `
                import * as _source from "source";
                _source;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addNamespace(),
              `
                var _source = babelHelpers.interopRequireWildcard(require("source"));
                _source;
              `,
            );
          });
        });
      });
    });
  
    describe("default imports", () => {
      const addDefault = opts => m => m.addDefault("source", opts);
  
      describe("loading an ES6 module", () => {
        const importedType = "es6";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedType },
              addDefault(),
              `
                import _default from "source";
                _default;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedType },
              addDefault({ nameHint: "hintedName" }),
              `
                import _hintedName from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedType },
              addDefault(),
              `
                import _default from "source";
                _default;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedType },
              addDefault({ nameHint: "hintedName" }),
              `
                import _hintedName from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            expect(() => {
              testScript({ importedType }, addDefault());
            }).toThrow("Cannot import an ES6 module from CommonJS");
          });
        });
      });
  
      describe("loading CommonJS with 'uncompiled'", () => {
        const importedInterop = "uncompiled";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault(),
              `
                import _default from "source";
                _default;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault({ nameHint: "hintedName" }),
              `
                import _hintedName from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault(),
              `
                import _default from "source";
                _default;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault({ nameHint: "hintedName" }),
              `
                import _hintedName from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addDefault(),
              `
                var _default = require("source");
                _default;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testScript(
              { importedInterop },
              addDefault({ nameHint: "hintedName" }),
              `
                var _hintedName = require("source");
                _hintedName;
              `,
            );
          });
  
          it("should fail to import with force-enabled liveness", () => {
            expect(() => {
              testScript(
                { importedInterop, ensureLiveReference: true },
                addDefault(),
              );
            }).toThrow("No live reference for commonjs default");
          });
        });
      });
  
      describe("loading CommonJS with 'compiled'", () => {
        const importedInterop = "compiled";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault(),
              `
                import _source from "source";
                _source.default;
              `,
            );
          });
  
          it("should import with a force-disabled context", () => {
            testModule(
              { importingInterop, importedInterop, ensureNoContext: true },
              addDefault(),
              `
                import _source from "source";
                0, _source.default;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault(),
              `
                import _default from "source";
                _default;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault({ nameHint: "hintedName" }),
              `
                import _hintedName from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addDefault(),
              `
                var _default = require("source").default;
                _default;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testScript(
              { importedInterop },
              addDefault({ nameHint: "hintedName" }),
              `
                var _hintedName = require("source").default;
                _hintedName;
              `,
            );
          });
  
          it("should import with force-enabled liveness", () => {
            testScript(
              { importedInterop, ensureLiveReference: true },
              addDefault(),
              `
                var _source = require("source");
                _source.default;
              `,
            );
          });
        });
      });
  
      describe("loading CommonJS with 'babel'", () => {
        const importedInterop = "babel";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault(),
              `
                import _source$es6Default from "source";
                var _source = babelHelpers.interopRequireDefault(_source$es6Default).default;
                _source;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault({ nameHint: "hintedName" }),
              `
                import _source$es6Default from "source";
                var _hintedName = babelHelpers.interopRequireDefault(_source$es6Default).default;
                _hintedName;
              `,
            );
          });
  
          it("should import with force-enabled liveness", () => {
            testModule(
              { importingInterop, importedInterop, ensureLiveReference: true },
              addDefault(),
              `
                import _source$es6Default from "source";
                var _source = babelHelpers.interopRequireDefault(_source$es6Default);
                _source.default;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault(),
              `
                import _default from "source";
                _default;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedInterop },
              addDefault({ nameHint: "hintedName" }),
              `
                import _hintedName from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addDefault(),
              `
                var _default = babelHelpers.interopRequireDefault(require("source")).default;
                _default;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testScript(
              { importedInterop },
              addDefault({ nameHint: "hintedName" }),
              `
                var _hintedName = babelHelpers.interopRequireDefault(require("source")).default;
                _hintedName;
              `,
            );
          });
  
          it("should import with force-enabled liveness", () => {
            testScript(
              { importedInterop, ensureLiveReference: true },
              addDefault(),
              `
                var _source = babelHelpers.interopRequireDefault(require("source"));
                _source.default;
              `,
            );
          });
        });
      });
    });
  
    describe("named imports", () => {
      const addNamed = opts => m => m.addNamed("read", "source", opts);
  
      describe("loading an ES6 module", () => {
        const importedType = "es6";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedType },
              addNamed(),
              `
                import { read as _read } from "source";
                _read;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedType },
              addNamed({ nameHint: "hintedName" }),
              `
                import { read as _hintedName } from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedType },
              addNamed(),
              `
                import { read as _read } from "source";
                _read;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedType },
              addNamed({ nameHint: "hintedName" }),
              `
                import { read as _hintedName } from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            expect(() => {
              testScript({ importedType }, addNamed());
            }).toThrow("Cannot import an ES6 module from CommonJS");
          });
        });
      });
  
      describe("loading CommonJS with 'uncompiled'", () => {
        const importedInterop = "uncompiled";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamed(),
              `
                import _source from "source";
                _source.read;
              `,
            );
          });
  
          it("should import with a force-disabled context", () => {
            testModule(
              { importingInterop, importedInterop, ensureNoContext: true },
              addNamed(),
              `
                import _source from "source";
                0, _source.read;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamed(),
              `
                import { read as _read } from "source";
                _read;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamed({ nameHint: "hintedName" }),
              `
                import { read as _hintedName } from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addNamed(),
              `
                var _read = require("source").read;
                _read;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testScript(
              { importedInterop },
              addNamed({ nameHint: "hintedName" }),
              `
                var _hintedName = require("source").read;
                _hintedName;
              `,
            );
          });
  
          it("should import with force-enabled liveness", () => {
            testScript(
              { importedInterop, ensureLiveReference: true },
              addNamed(),
              `
                var _source = require("source");
                _source.read;
              `,
            );
          });
        });
      });
  
      describe("loading CommonJS with 'compiled'", () => {
        const importedInterop = "compiled";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamed(),
              `
                import _source from "source";
                _source.read;
              `,
            );
          });
  
          it("should import with a force-disabled context", () => {
            testModule(
              { importingInterop, importedInterop, ensureNoContext: true },
              addNamed(),
              `
                import _source from "source";
                0, _source.read;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamed(),
              `
                import { read as _read } from "source";
                _read;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamed({ nameHint: "hintedName" }),
              `
                import { read as _hintedName } from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addNamed(),
              `
                var _read = require("source").read;
                _read;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testScript(
              { importedInterop },
              addNamed({ nameHint: "hintedName" }),
              `
                var _hintedName = require("source").read;
                _hintedName;
              `,
            );
          });
  
          it("should import with force-enabled liveness", () => {
            testScript(
              { importedInterop, ensureLiveReference: true },
              addNamed(),
              `
                var _source = require("source");
                _source.read;
              `,
            );
          });
        });
      });
  
      describe("loading CommonJS with 'babel'", () => {
        const importedInterop = "babel";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamed(),
              `
                import _source$es6Default from "source";
                _source$es6Default.read;
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamed(),
              `
                import { read as _read } from "source";
                _read;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testModule(
              { importingInterop, importedInterop },
              addNamed({ nameHint: "hintedName" }),
              `
                import { read as _hintedName } from "source";
                _hintedName;
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addNamed(),
              `
                var _read = require("source").read;
                _read;
              `,
            );
          });
  
          it("should import with a name hint", () => {
            testScript(
              { importedInterop },
              addNamed({ nameHint: "hintedName" }),
              `
                var _hintedName = require("source").read;
                _hintedName;
              `,
            );
          });
  
          it("should import with force-enabled liveness", () => {
            testScript(
              { importedInterop, ensureLiveReference: true },
              addNamed(),
              `
                var _source = require("source");
                _source.read;
              `,
            );
          });
        });
      });
    });
  
    describe("side-effectful imports", () => {
      const addSideEffect = opts => m => m.addSideEffect("source", opts);
  
      describe("loading an ES6 module", () => {
        const importedType = "es6";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedType },
              addSideEffect(),
              `
                import "source";
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedType },
              addSideEffect(),
              `
                import "source";
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            expect(() => {
              testScript({ importedType }, addSideEffect());
            }).toThrow("Cannot import an ES6 module from CommonJS");
          });
        });
      });
  
      describe("loading CommonJS with 'uncompiled'", () => {
        const importedInterop = "uncompiled";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addSideEffect(),
              `
                import "source";
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addSideEffect(),
              `
                import "source";
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addSideEffect(),
              `
                require("source");
              `,
            );
          });
        });
      });
  
      describe("loading CommonJS with 'compiled'", () => {
        const importedInterop = "compiled";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addSideEffect(),
              `
                import "source";
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addSideEffect(),
              `
                import "source";
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addSideEffect(),
              `
                require("source");
              `,
            );
          });
        });
      });
  
      describe("loading CommonJS with 'babel'", () => {
        const importedInterop = "babel";
  
        describe("using Node's interop", () => {
          const importingInterop = "node";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addSideEffect(),
              `
                import "source";
              `,
            );
          });
        });
  
        describe("using Babel's interop", () => {
          const importingInterop = "babel";
  
          it("should import", () => {
            testModule(
              { importingInterop, importedInterop },
              addSideEffect(),
              `
                import "source";
              `,
            );
          });
        });
  
        describe("using a CommonJS loader", () => {
          it("should import", () => {
            testScript(
              { importedInterop },
              addSideEffect(),
              `
                require("source");
              `,
            );
          });
        });
      });
    });
  
    describe("importPosition: after", () => {
      it("works in ES modules", () => {
        testModule(
          { importPosition: "after" },
          m => m.addNamed("read", "source"),
          `
            import f from "foo";
            f();
            import b from "bar";
            b();
          `,
          `
            import f from "foo";
            f();
            import b from "bar";
            import { read as _read } from "source";
            b();
            _read;
          `,
        );
      });
  
      it("is disallowed in CJS modules", () => {
        expect(() =>
          testScript({ importPosition: "after" }, m =>
            m.addNamed("read", "source"),
          ),
        ).toThrow(`"importPosition": "after" is only supported in modules`);
      });
    });
  });
  