trailheadapps / ebikes-lwc

Sample application for Lightning Web Components and Experience Cloud on Salesforce Platform. Retail use case. Get inspired and learn best practices.
https://developer.salesforce.com
Creative Commons Zero v1.0 Universal
780 stars 1.16k forks source link

SyntaxError: Cannot use import statement outside a module #465

Closed markocir closed 1 year ago

markocir commented 1 year ago

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

github-actions[bot] commented 1 year ago

Thank you for posting this issue. 🙇🏼‍♂️
We will come back to you shortly.

pozil commented 1 year ago

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.

markocir commented 1 year ago

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

pozil commented 1 year ago

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.

markocir commented 1 year ago

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

markocir commented 1 year ago

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 1 year ago

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?

markocir commented 1 year ago

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

olivier-martin-sf commented 1 year ago

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.

markocir commented 1 year ago

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)

olivier-martin-sf commented 1 year ago

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.

muenzpraeger commented 1 year ago

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.

olivier-martin-sf commented 1 year ago

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)?

muenzpraeger commented 1 year ago

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).

markocir commented 1 year ago

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"
    }
}
markocir commented 1 year ago

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

olivier-martin-sf commented 1 year ago

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

markocir commented 1 year ago

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

olivier-martin-sf commented 1 year ago

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
markocir commented 1 year ago

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 1 year ago

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