trailheadapps/ebikes-lwc

SyntaxError: Cannot use import statement outside a module

markocir opened this issue ยท 21 comments

Summary

I was trying to runt tests npm run test:ui and it failed with: SyntaxError: Cannot use import statement outside a module.
I have changed ChromeDriver version to latest and run npm install and it did not change the outcome: "chromedriver": "^107.0.3",

Salesforce Org Type

Scratch Org

Steps To Reproduce

  1. Installing E-Bikes using a Scratch Org
  2. npm install
  3. npm run test:ui:compile
  4. npm run test:ui:generate:login
  5. npm run test:ui -> this fails
  6. update chromedriver dependency version to ^107.0.3
  7. npm install
  8. npm run test:ui -> this still fails

Current Behavior

No response

Expected Behavior

No response

Relevant Log Output

image

Code of Conduct

  • I agree to follow this project's Code of Conduct

Thank you for posting this issue. ๐Ÿ™‡๐Ÿผโ€โ™‚๏ธ
We will come back to you shortly.

pozil commented

Hi @markocir. Thanks for reporting this issue but I couldn't reproduce it.
Can you confirm that you're using node v16 or above?
I just updated the dependencies on the repo, just in case.

Hi,
I have node version v16.15.0. Also I am using wsl2 subsystem on windows if that could cause the issue...

pozil commented

Ah yes, I have suspicions on WSL and the Windows file system. It could be that there's an issue with the ways paths are represented vs Unix systems. I'll try to see if I can get my hands on a Windows machine to repro.

I tried to run it in Windows cmd but still the same issue persists.
image

Reporting how I managed to get the test running:

  1. I replaced import with require
    image
  2. I replaced some paths inside pageObjects to show to correct location; for example: ProductTileList was importing Paginator with path: ebikes-lwc/pageObjects/paginator which was not found, and changed to (see image)
    image
pozil commented

Sorry for the delay, I didn't get the chance to run the tests on a Windows machine. I'm glad that you could make it work but fixing code under pageObjects is not future proof because it's auto-generated by the UTAM compiler.

There's definitely an issue with path resolution when working with Windows.
Out of curiosity, are the official JS UTAM recipes working for you?

No problem :)

Yes its working - the offical JS UTAM recipes.

But only in windows command line. On WSL it is not working due to chromedriver

Just adding my 2 cents on the issue:

The error Cannot use import statement outside a module is a SyntaxError. Indeed, the use of the import keyword (which is part of the JS specification) is only allowed in the context of an ES Module. Using the import keyword outside of that context is syntactically invalid. That error is actually thrown by node.js itself when trying to load a file.

Node.js uses some heuristics to determine the module system of a given file. There are a couple of things at play here:

First, we have to look at the root package.json to see what the value of the type property hold. If it's setup to commonjs (or absent), node will use it's legacy CommonJS module format by default for the files that end up with the .js file extension. That's the case for this project as we don't have a type property in the package manifest.

Our tests, which have a .js file extension, will be interpreted by node.js as being authored with the CommonJS module format.

Note: The commonJS module format isn't part of the JS specification and is using a require function that's actually backed into node.js.

So the error is actually what would node.js throw if we were to execute the file directly through it. However, there's a trick in that repo in the WDIO config. We register a helpers script that will use Babel to transpile the content of the test file from ES Modules to CommonJS on the fly while running the test. So even if the test uses import it's actually being transpiled into a require call when passed to the node.js runtime.

My guess is that this helper doesn't resolve correctly on your system. Could you please provide the output of:
console.log(path.resolve(process.cwd(), 'wdioJasmineHelper.js'));

Just to double check if that's the issue you were having. I understood you solve the issue switching to require calls but you shouldn't have to.

I tried to put the console log into wdioJasmineHelper._jasmineRegister() but nothing was printed out so I put it inside the tests and this is what I got, I think its ok?
image

I can successfully run tests with yarn test --spec force-app/test/record-create.spec.js (https://github.com/salesforce/utam-js-recipes)

Yes that looks correct to me.

Can you try npm run test:ui --spec force-app/test/utam/page-explorer.spec.js?
I would also just try to add a dummy console.log('something') statement in the wdioJasmineHelper.js file (in the top-level scope) and see if that prints when you start running the test.

Just adding that I see in the OP that @babel/register is not loaded.

Instead of @wdio/config:utils: Found '@babel/register' package, auto-compiling files with Babel it's showing @wdio/config:utils: Found 'ts-node' package, auto-compiling TypeScript files.

Thanks @muenzpraeger! That's a good catch. It explains why babel doesn't transpile the files and hence why node.js interpret them as being ES Modules. @markocir do you have any changes in your local copy of the repository (such as typescript setup or dependencies)?

I did a quick investigation in the wdio source code. The ts-node message is very specific (see here).

After a quick test I can reproduce the error when adding ts-node to the project (which confirms what @olivier-martin-sf mentioned).

Sorry for late reply.

@olivier-martin-sf No I have not changed anything.

This is the package.json:

{
   "name": "ebikes-lwc",
   "private": true,
   "version": "1.0.0",
   "description": "EBikes Sample App - Lightning Web Components",
   "scripts": {
       "lint": "eslint **/lwc/**/*.js",
       "test": "npm run test:unit",
       "test:unit": "sfdx-lwc-jest --skipApiVersionCheck",
       "test:unit:watch": "sfdx-lwc-jest --watch --skipApiVersionCheck",
       "test:unit:debug": "sfdx-lwc-jest --debug --skipApiVersionCheck",
       "test:unit:coverage": "sfdx-lwc-jest --coverage --skipApiVersionCheck",
       "test:ui": "wdio",
       "test:ui:compile": "utam -c utam.config.js",
       "test:ui:generate:login": "node scripts/generate-login-url.js",
       "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
       "prettier:verify": "prettier --check \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
       "postinstall": "husky install",
       "precommit": "lint-staged"
   },
   "lint-staged": {
       "**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}": [
           "prettier --write"
       ],
       "**/lwc/**/*.js": [
           "eslint"
       ],
       "**/lwc/**": [
           "sfdx-lwc-jest --skipApiVersionCheck -- --bail --findRelatedTests --passWithNoTests"
       ]
   },
   "author": "salesforce.com",
   "license": "CC0-1.0",
   "repository": {
       "type": "git",
       "url": "git+https://github.com/trailheadapps/ebikes-lwc"
   },
   "devDependencies": {
       "@babel/cli": "^7.19.3",
       "@babel/core": "^7.20.2",
       "@babel/preset-env": "^7.20.2",
       "@babel/register": "^7.18.9",
       "@lwc/eslint-plugin-lwc": "^1.5.0",
       "@prettier/plugin-xml": "^2.2.0",
       "@sa11y/jest": "^4.0.1",
       "@salesforce/eslint-config-lwc": "^3.3.3",
       "@salesforce/eslint-plugin-lightning": "^1.0.0",
       "@salesforce/sfdx-lwc-jest": "^1.1.3",
       "@wdio/cli": "^7.25.4",
       "@wdio/jasmine-framework": "^7.25.4",
       "@wdio/local-runner": "^7.25.4",
       "@wdio/spec-reporter": "^7.25.4",
       "chromedriver": "^107.0.3",
       "dotenv": "^16.0.3",
       "eslint": "^8.27.0",
       "eslint-plugin-import": "^2.26.0",
       "eslint-plugin-jest": "^27.1.4",
       "husky": "^8.0.1",
       "lint-staged": "^13.0.3",
       "prettier": "^2.7.1",
       "prettier-plugin-apex": "^1.11.0",
       "salesforce-pageobjects": "^2.2.0",
       "utam": "^1.2.1",
       "wdio-chromedriver-service": "^8.0.0",
       "wdio-utam-service": "^1.2.1"
   },
   "workspaces": [
       "./"
   ],
   "volta": {
       "node": "16.13.2",
       "npm": "8.1.2"
   }
}

How can I test from where ts-node is comming from? Nor bash or cmd recognize ts-node or typescript command.

npm explain ts-node should give you some information about this!

ts-node is not found just typescript. But I think that is ok? Since tests use .ts files.
image

I would try 2 things:

  1. First delete your node_modules folder and try to run npm install && npm test:ui:compile
  2. Disable WDIO auto compile option by adding autoCompileOpts: { autoCompile: false } in the config object that's exported by wdio.conf.js

Thank you everybody!

I discovered that I had node_module in a folder of folder structure: a/b/c/ebikes

When running npm explain ts-node in ebikes folder only ebikes/node_modules folder is evaluated which in fact did not contain ts-node module. When running npm explain ts-node in c folder ts-node was detected.

So I just removed the a/node_modules folder and reinstalled ebikes and now it works.

Thanks again for your help!

pozil commented

Nice, thanks for sharing you investigations. We're glad that you were able to deploy.