Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export issue for upgraded version. SyntaxError: Unexpected token 'export' #1835

Closed
Ryan-Boustany opened this issue Oct 3, 2024 · 8 comments

Comments

@Ryan-Boustany
Copy link

Plugin version

v24.5.1

Description

I was running v17 of intl-tel-input library on my repo I needed the latest version of libphonenumber so I updgraded my intl-tel-input to v24. I am now receiving these bugs in my test cases that have something to do with export. Does anyone have any idea why this might be occurring.

Any assistance on this would be greatly appreciated thank you!

Expected behaviour

My tests should be running without an export issue

Actual behaviour

My tests are failing due to an export issue

Initialisation options

I am using these versions in my devDependecies:
"babel": "^6.23.0",
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.6",
"babel-jest": "^23.6.0",
"babel-loader": "^7.1.5",
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-plugin-lodash": "^3.3.4",
"babel-plugin-react-css-modules": "^3.4.2",
"babel-plugin-transform-inline-imports-commonjs": "^1.2.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"@babel/core": "^7.25.2"
"@babel/preset-env": "^7.25.4"

"jest": "^23.6.0",
"jest-enzyme": "^6.1.2",
"jest-html-reporter": "^3.10.2",
"jest-slow-test-reporter": "^1.0.0"
"ts-jest": "^23.0.0",

Screenshot 2024-10-03 at 10 54 32 AM
@Ryan-Boustany Ryan-Boustany changed the title Export issue for upgraded version Export issue for upgraded version. SyntaxError: Unexpected token 'export' Oct 3, 2024
@Ozberg
Copy link

Ozberg commented Oct 3, 2024

I'm getting the same from 24.5.0 (updating from 18.1.6)

@rashadmehtab
Copy link

rashadmehtab commented Oct 3, 2024

You are currently importing intl-tel-input/build/js/utils.js, which is no longer supported. Please switch to one of the following options:

  1. intl-tel-input/build/js/intlTelInputWithUtils.js
  2. import intlTelInput from 'intl-tel-input/intlTelInputWithUtils';

For a detailed explanation on how to import the utilities correctly, please refer to this link: Loading the Utilities Script.

@jackocnr
Copy link
Owner

jackocnr commented Oct 3, 2024

Thanks @rashadmehtab!

@Ryan-Boustany yes, as @rashadmehtab says, the problem is that you have the following line somewhere in your tests/code:

import 'intl-tel-input/build/js/utils';

Which file is that in? And what are you hoping to achieve with this? Utils has now changed so it no longer sets a global, so this approach to loading the utils will no longer work. It's now an ES module, which needs to be loaded in a particular way - again see the readme link that @rashadmehtab kindly shared 🙏🏻

@Ryan-Boustany
Copy link
Author

Ryan-Boustany commented Oct 9, 2024

Ive switch to importing my library to the format stated above.

Screenshot 2024-10-09 at 12 58 23 PM Screenshot 2024-10-09 at 2 05 23 PM Screenshot 2024-10-09 at 2 06 19 PM

When I run my test I see errors that appear like this:

Screenshot 2024-10-09 at 2 03 59 PM

Any suggestions?

@Mr0grog
Copy link
Contributor

Mr0grog commented Oct 9, 2024

@Ryan-Boustany I’ve recently done some contributions in this area, and specifically with Jest. 😃

A few things:

  • Since you’re using the React component, you shouldn’t need import 'intl-tel-input/build/js/utils'. To do the same thing for React, drop that line, and use import IntlTelInput from 'intl-tel-input/reactWithUtils instead of import IntlTelInput from 'react-intl-tel-input' (side note: react-intl-tel-input is a separate library that wraps this one, and hasn’t been updated in a quite a while; React support comes built-in here as of v19.2.0 from January of this year).

  • Once intl-tel-input has loaded, the utils are at window.intlTelInput.utils, not window.intlTelInputUtils.

  • If you are using a bundler (or running in Node.js, as in a Jest test), intl-tel-input may not actually install itself on window or global. You’ll need to grab it from the intl-tel-input import module:

    import IntlTelInputReactComponent, { intlTelInput } from 'intl-tel-input/reactWithUtils';
    // OR, if you aren’t using the React component in your codebase at all:
    // import intlTelInput from 'intl-tel-input/intlTelInputWithUtils';
    
    libphonenumber = intlTelInput.utils;

The above should just work, but the downside is that it comes with the utilities module pre-loaded, which is pretty big!

If you want to load utilities asynchronously later on, making it work in Jest is unfortunately a little complicated (the async utilities script is a proper JS module, and Jest’s module support is still experimental). You’ll need to do two things to get async loading working in Jest:

  1. Run your tests with the --experimental-vm-modules node option. If you use npm run ... or npx jest ... to run your tests, the easiest way to do that is to add a line to your .npmrc file. You can see how we do that for the test here:

    intl-tel-input/.npmrc

    Lines 1 to 3 in 05badca

    # Jest uses the `vm` module, which does not have production ready module support
    # yet. This option lets us use dynamic imports.
    node-options='--experimental-vm-modules'

  2. Tell jest to transform the utils.js file into CommonJS when loading it. You can see how we configure that in this repo:

    transform: {
    // Most of the build outputs in this project use UMD syntax, but the
    // utilities script is a proper ES Module. Unfortunately, Jest cannot treat
    // a file with a `.js` extension as ESM unless the whole project is ESM
    // (Jest does not use Node.js built-in resolution and loading logic), so
    // we have to set up special parsing for that file.
    // See also: https://jestjs.io/docs/next/ecmascript-modules
    "utils.js$": [
    "babel-jest",
    {
    plugins: [
    "@babel/plugin-transform-modules-commonjs",
    "babel-plugin-add-module-exports",
    ],
    },
    ],
    },

    Note you’ll need to install the @babel/plugin-transform-modules-commonjs and babel-plugin-add-module-exports packages.

    You’ll probably also want to make the path that is getting transformed more specific, e.g. "intl-tel-input/build/js/utils.js$" instead of "utils.js$" (I have not tested to make sure that’s exactly right).

Then use the React module that loads async instead of preloading utils: import IntlTelInput from 'intl-tel-input/react'.

To just load the utils module directly if you don’t need the whole library, you can also do the following (pretty sure you’ll need the above Jest fixes for this, though):

import libphonenumber from 'intl-tel-input/utils';

libphonenumber.isValidNumber(...); // or whatever you want to do with it

Be careful to make sure you aren’t loading the utils twice in your bundle if you are doing this alongside the React component, though!


Side note on changes to the package that would make this easier:

@jackocnr Seeing how this affects users of this package in their tests tells me you have a better point than I thought about removing the string option for loadUtilsOnInit/loadUtils(). 😅

Another good way to make this easier for users might be to:

  1. Build 3 versions of utils.js: utils.js (same as today), utils.cjs (using UMD syntax), utils.mjs (same as utils.js). People can reference the .mjs or cjs version in tests and Jest won’t need the fancy transform; it will just do the right thing.

  2. Make loadUtils() use Promise.resolve((r) => r(require(source))) instead of import(source) if dynamic import is not available or if require is defined or something along those lines.

That way folks shouldn’t need any special Jest config for the async loading utils.

@Ryan-Boustany
Copy link
Author

Ryan-Boustany commented Oct 10, 2024

Thanks for the suggestions!

In another file I am importing it as such:

Screenshot 2024-10-10 at 12 10 46 PM

How would I need to change the imports for this file?
@Mr0grog

@Mr0grog
Copy link
Contributor

Mr0grog commented Oct 10, 2024

So, assuming you don’t want to do all the wacky stuff to get async utils working in Jest, you want to import <x> from 'intl-tel-input/<whatever>WithUtils'.

  • If you are using React in your project (not just this file):

    import { intlTelInput } from 'intl-tel-input/reactWithUtils';
    
    const libphonenumber = intlTelInput.utils;
  • If you are not using React in your project:

    import intlTelInput from 'intl-tel-input/intlTelInputWithUtils';
    
    const libphonenumber = intlTelInput.utils;

@Ryan-Boustany
Copy link
Author

Thank you @Mr0grog @jackocnr and @rashadmehtab for the assistance :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants