Import an es6 module in a protractor test file

Viewed 230

I'm trying to import an es6 module in my protractor test files, but I can't get it working (I used the is-docker package 3.0.0 as an example). Here is what I tried:

  1. First I got this error:
Error: Error [ERR_REQUIRE_ESM]: require() of ES Module [...]/node_modules/is-docker/index.js from [...]/e2e/app.e2e-spec.ts not supported.
Instead change the require of index.js in [...]/e2e/app.e2e-spec.ts to a dynamic import() which is available in all CommonJS modules.
  1. I updated my tsconfig used by protractor:
{
  // ...
  "compilerOptions": {
    "module": "esnext",
    "target": "esnext",
    // ...  
  }
}

This resulted in the following error:

SyntaxError: Cannot use import statement outside a module
  1. So I added a package.json in my e2e folder containing the protractor test files:
{
  "type": "module"
}

This resulted in the following error:

E/configParser - Error [ERR_REQUIRE_ESM]: require() of ES Module [...]/e2e/protractor.conf.js from /usr/local/lib/node_modules/protractor/built/configParser.js not supported.
protractor.conf.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename protractor.conf.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in [...]/e2e/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

    at ConfigParser.addFileConfig (/usr/local/lib/node_modules/protractor/built/configParser.js:135:26)
    at Object.initFn [as init] (/usr/local/lib/node_modules/protractor/built/launcher.js:93:22)
    at Object.<anonymous> (/usr/local/lib/node_modules/protractor/built/cli.js:227:10)
    at Object.<anonymous> (/usr/local/lib/node_modules/protractor/bin/protractor:5:1)

I can't follow the error instructions and change the requiring code to use dynamic import(), because the error is inside protractor code:

addFileConfig(filename) {
    // ...
    let filePath = path.resolve(process.cwd(), filename);
    let fileConfig;
    try {
        fileConfig = require(filePath).config;
    }
    // ...
}
1 Answers

Root cause

Start from Angular@13, it removed the support for CommonJS and UMD - Detail

Workaround

As the warning suggested, use the dynamic import() from CJS.

No changes in package.json or tsconfig.json

For ProtractorHarnessEnvironment, replace it with SeleniumWebDriverHarnessEnvironment

async function getSeleniumWebDriverHarnessEnvironment() {
  const lib = await import("@angular/cdk/testing/selenium-webdriver");
  return lib.SeleniumWebDriverHarnessEnvironment;
}

For Angular Material Component Harness, apply the same:

async function getMatTableHarness() {
  const lib = await import("@angular/material/table/testing");
  return lib.MatTableHarness;
}

If above approach doesn't work, try use the following replace import() (as explained by this blog)

const dynamicImport = async (packageName: string) =>
  new Function(`return import('${packageName}')`)();

References

  1. How to import ES6 modules in CommonJS
  2. Difference between ES Modules and CommonJS Modules
  3. Import ES modules in TypeScript project
Related