Expo Auth Session breaking Jest tests | Jest encountered an unexpected token - react-native

I'm building an Expo app with jest as my test runner.
After incorporateing expo-auth-session into the project, I get the following error:
FAIL screens/tests/EntriesScreen.test.jsx
● Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
C:\Users\User\repos\BROG-Trip-Journal\node_modules\expo-auth-session\providers\google.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export * from '../build/providers/Google';
^^^^^^
SyntaxError: Unexpected token 'export'
17 | Alert,
18 | } from 'react-native';
> 19 | import * as Google from 'expo-auth-session/providers/google';
| ^
20 | import { useDispatch } from 'react-redux';
21 | import { FontAwesomeIcon } from '#fortawesome/react-native-fontawesome';
22 | import PropTypes from 'prop-types';
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
at Object.<anonymous> (screens/AuthScreen.jsx:19:1)
I'm no stranger to this error on this project. In the past, all I had to do was add the offending module to the transformIngnorePattern so that it would get transpiled by bable. But this time, it's not working.
Here is what my jest.config.js looks like right now:
module.exports = {
preset: 'jest-expo',
moduleDirectories: ['node_modules', 'test-utils'],
setupFiles: ['./node_modules/react-native-gesture-handler/jestSetup.js'],
transform: {
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
},
transformIgnorePatterns: [
'/node_modules/(?!(#react-native|react-native|#fortawesome|expo-app-loading|expo-splash-screen|expo-modules-core|expo-font|expo-asset|expo-constants|expo-sqlite|#react-navigation|expo-location|#expo|expo-status-bar|react-native-keyboard-aware-scroll-view|react-native-iphone-x-helper|expo-auth-session)/).*/',
],
setupFilesAfterEnv: [
'#testing-library/jest-native/extend-expect',
'./jest.setup.js',
],
};
What am I missing?

Related

Error when adding highchartsjs to Vue3 app

I am using Vue 3 and added highchartsjs according to the docs. I am getting this error:
✘ [ERROR] Could not resolve "highcharts"
node_modules/highcharts-vue/dist/highcharts-vue.min.js:1:90:
1 │ ...?module.exports=e(require("highcharts"),require("vue")):"functio...
╵ ~~~~~~~~~~~~
You can mark the path "highcharts" as external to exclude it from the bundle,
which will remove this error. You can also surround this "require" call with a
try/catch block to handle this failure at run-time instead of bundle-time.
I tried excluding it from bundle as suggested but it's not working:
vite.config.js
export default defineConfig({
...
build: {
rollupOptions: {
external: ['highcharts'],
}
},
})
This works:
export default defineConfig({
...
optimizeDeps: {
exclude: ['highcharts'],
}
})
Excluding highcharts via optimizeDeps.exclude would clear the error, but that would defeat your ultimate goal of using highcharts in your project. You'll notice that after using that config, your project still is not able to import highcharts. The error is indicating that your project is missing that dependency.
The solution would be to install highcharts:
npm install -S highcharts
demo

Web3js fails to import in Vue3 composition api project

I've created a brand new project with npm init vite bar -- --template vue. I've done an npm install web3 and I can see my package-lock.json includes this package. My node_modules directory also includes the web3 modules.
So then I added this line to main.js:
import { createApp } from 'vue'
import App from './App.vue'
import Web3 from 'web3' <-- This line
createApp(App).mount('#app')
And I get the following error:
I don't understand what is going on here. I'm fairly new to using npm so I'm not super sure what to Google. The errors are coming from node_modules/web3/lib/index.js, node_modules/web3-core/lib/index.js, node_modules/web3-core-requestmanager/lib/index.js, and finally node_modules/util/util.js. I suspect it has to do with one of these:
I'm using Vue 3
I'm using Vue 3 Composition API
I'm using Vue 3 Composition API SFC <script setup> tag (but I imported it in main.js so I don't think it is this one)
web3js is in Typescript and my Vue3 project is not configured for Typescript
But as I am fairly new to JavaScript and Vue and Web3 I am not sure how to focus my Googling on this error. My background is Python, Go, Terraform. Basically the back end of the back end. Front end JavaScript is new to me.
How do I go about resolving this issue?
Option 1: Polyfill Node globals/modules
Polyfilling the Node globals and modules enables the web3 import to run in the browser:
Install the ESBuild plugins that polyfill Node globals/modules:
npm i -D #esbuild-plugins/node-globals-polyfill
npm i -D #esbuild-plugins/node-modules-polyfill
Configure optimizeDeps.esbuildOptions to use these ESBuild plugins.
Configure define to replace global with globalThis (the browser equivalent).
import { defineConfig } from 'vite'
import GlobalsPolyfills from '#esbuild-plugins/node-globals-polyfill'
import NodeModulesPolyfills from '#esbuild-plugins/node-modules-polyfill'
export default defineConfig({
⋮
optimizeDeps: {
esbuildOptions: {
2️⃣
plugins: [
NodeModulesPolyfills(),
GlobalsPolyfills({
process: true,
buffer: true,
}),
],
3️⃣
define: {
global: 'globalThis',
},
},
},
})
demo 1
Note: The polyfills add considerable size to the build output.
Option 2: Use pre-bundled script
web3 distributes a bundled script at web3/dist/web3.min.js, which can run in the browser without any configuration (listed as "pure js"). You could configure a resolve.alias to pull in that file:
import { defineConfig } from 'vite'
export default defineConfig({
⋮
resolve: {
alias: {
web3: 'web3/dist/web3.min.js',
},
// or
alias: [
{
find: 'web3',
replacement: 'web3/dist/web3.min.js',
},
],
},
})
demo 2
Note: This option produces 469.4 KiB smaller output than Option 1.
You can avoid the Uncaught ReferenceError: process is not defined error by adding this in your vite config
export default defineConfig({
// ...
define: {
'process.env': process.env
}
})
I found the best solution.
The problem is because you lose window.process variable, and process exists only on node, not the browser.
So you should inject it to browser when the app loads.
Add this line to your app:
window.process = {
...window.process,
};

How to resolve a NativeModule.RNLocalize is null error in test?

I'm using the package react-native-localize to provide localization in an app. I've already linked the library and it works fine running on a device.
Issue:
When I test a component that imports react-native-localize. I get the error react-native-localize: NativeModule.RNLocalize is null.
In order to resolve this null error I call jest.mock('react-native-localize'); at the top of the test file. But I still get an error pointing to NativeModule.RNLocalize is null. I've also provided the mock as mentioned in the package README to no avail.
import 'react-native';
import React from 'react';
import App from '../App';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
import * as RNLocalize from 'react-native-localize';
// mocking the module here with jest.mock
jest.mock('react-native-localize');
it('renders correctly', () => {
renderer.create(<App />);
});
Question:
How can you resolve a NativeModule.RNLocalize is null error in test?
Test Stack Trace:
FAIL __tests__/App-test.js
● Test suite failed to run
react-native-localize: NativeModule.RNLocalize is null. To fix this issue try these steps:
• Run `react-native link react-native-localize` in the project root.
• Rebuild and re-run the app.
• If you are using CocoaPods on iOS, run `pod install` in the `ios` directory and then rebuild and re-run the app. You may also need to re-open Xcode to get the new pods.
• Check that the library was linked correctly when you used the link command by running through the manual installation instructions in the README.
* If you are getting this error while unit testing you need to mock the native module. Follow the guide in the README.
If none of these fix the issue, please open an issue on the Github repository: https://github.com/react-native-community/react-native-localize
16 |
17 | import {NavigationContainer} from '#react-navigation/native';
> 18 | import * as RNLocalize from 'react-native-localize';
| ^
19 | import {Icon} from 'native-base';
20 | import {createStackNavigator} from '#react-navigation/stack';
21 | const Stack = createStackNavigator();
at Object.<anonymous> (node_modules/react-native-localize/lib/commonjs/module.js:17:9)
at Object.<anonymous> (node_modules/react-native-localize/lib/commonjs/index.js:3:1)
at Object.<anonymous> (src/modules/AppView.js:18:1)
at Object.<anonymous> (src/modules/AppViewContainer.js:2:1)
at Object.<anonymous> (App.js:23:1)
at Object.<anonymous> (__tests__/App-test.js:7:1)
I fixed this issue in my tests by adding these lines in my jest configuration file
jest.mock("react-native-localize", () => {
return {
getLocales: jest.fn(),
// you can add other functions mock here that you are using
};
});
I found the solution :- paste this code in your jest configuration file (setup.js)
jest.mock("react-native-localize", () => {
getLocales: jest.fn(), // use getLocales if you have used this, else use the one that you have used
// you can add other functions mock here that you are using
};
});

Testing Expo Constant with Jest, Jest encountered an unexpected token

I'm switching a SDK from Expo managed workflow to Expo bare workflow to reduce some of the unnecessary libraries included in Expo. I'm currently using some of the libraries such as Secure-store, Constants and Web browser from Expo instead of using the entire Expo package. I have some tests originally ran in jest, jest-expo and Expo. I removed expo from jest and trying to compile jest with only those three expo libraries above along with #unimodules. The tests files have import statements such as:
import * as SecureStore from 'expo-secure-store';
import * as WebBrowser from 'expo-web-browser';
import Constants from 'expo-constants';
However, when compiling jest, it keeps giving me
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript. >SyntaxError: Unexpected token import at
import Constants from 'expo-constants'; >ScriptTransformer._transformAndBuildScript(node_modules/#jest/transform/build/ScriptTransformer.js:471:17)
Seems like I might have resolved unexpected imports for expo-secure-store since I was getting that error before. I switched from Babel6 to babel7, added a babel.config.js that looks like this:
module.exports = {
presets: [
'#babel/preset-env'
],
env: {
test: {
presets: [['#babel/preset-env']]
}
},
plugins: [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-transform-modules-commonjs"
]
};
And i'm switching from jest-preset: jest-expo to jest-preset: react-native.
Am I doing something wrong here with the workflow? Any help appreciated.
A bit late but I was having this problem and I fixed adding
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|#react-native-community|expo(nent)?|#expo(nent)?/.*|react-navigation|#react-navigation/.*|#unimodules/.*|unimodules|sentry-expo|native-base|#sentry/.*)"
]
following the guide from https://docs.expo.io/guides/testing-with-jest/

SyntaxError: Unexpected identifier - Nonsensical error in React Enzyme testing

I'm developing in React Native and trying to set up jest testing by following the directions at https://airbnb.io/enzyme/docs/guides/react-native.html.
I think I've set everything up correctly. Here's my config:
//setup-tests.js
import "react-native";
import "jest-enzyme";
import Adapter from "enzyme-adapter-react-16";
import Enzyme from "enzyme";
// Set up DOM in node.js environment for Enzyme to mount to
const { JSDOM } = require("jsdom");
const jsdom = new JSDOM("<!doctype html><html><body></body></html>");
const { window } = jsdom;
function copyProps(src, target) {
Object.defineProperties(target, {
...Object.getOwnPropertyDescriptors(src),
...Object.getOwnPropertyDescriptors(target)
});
}
global.window = window;
global.document = window.document;
global.navigator = {
userAgent: "node.js"
};
copyProps(window, global);
// Set up Enzyme to mount to DOM, simulate events, and inspect the DOM in tests.
Enzyme.configure({ adapter: new Adapter() });
/* Ignore some expected warnings
* see: https://jestjs.io/docs/en/tutorial-react.html#snapshot-testing-with-mocks-enzyme-and-react-16
* see https://github.com/Root-App/react-native-mock-render/issues/6
*/
const originalConsoleError = console.error;
console.error = message => {
if (message.startsWith("Warning:")) {
return;
}
originalConsoleError(message);
};
// jest.config.js
module.exports = {
setupFilesAfterEnv: "<rootDir>setup-tests.js"
};
// Test.test.js
import React from "react";
import renderer from "react-test-renderer";
import { mount, ReactWrapper } from "enzyme";
import { Provider } from "react-redux";
import { Text } from "react-native";
import LoginView from '../js/LoginView'
You'll see the top of LoginView in a moment.
You'll notice that I haven't even written any tests in the test file, I'm just trying to get jest running to the point where it can evaluate a test.
Without the import LoginView, jest runs and "fails" because my test suite must contain at least one test. Sounds good.
Adding in the import LoginView, I get this error (which shows the import statements at the top of LoginView:
import Button from './buttons/Button';
^^^^^^
SyntaxError: Unexpected identifier
1 | import React, { Component } from "react";
> 2 | import { Input, Button, Image } from "react-native-elements";
| ^
3 | import { Text, View } from "react-native";
4 | import { connect } from "react-redux";
5 | import F8StyleSheet from "./F8StyleSheet";
at ScriptTransformer._transformAndBuildScript (node_modules/#jest/transform/build/ScriptTransformer.js:471:17)
at ScriptTransformer.transform (node_modules/#jest/transform/build/ScriptTransformer.js:513:25)
at Object.<anonymous> (js/LoginView.js:2:1)
So this doesn't make sense to me for a number of reasons.
LoginView renders fine in the actual app, with no "Unexpected identifier" crashes or warnings or anything
The lower arrows in the error on line 2 point to import, which of course shouldn't be unexpected.
Then there's the upper arrows that indicate a line from react-native-elements, so, I don't know about that.
Now, it does occur to me that the jest.config.js file did require me to use module.exports, and fails/crashes when I tried using export default { setupFiles } (or however I tried to do it, allowing VS Code to update it to ES6 syntax). So maybe that's why it's not liking import.
Even if that's the case, I don't know what the heck to do next.
Update
I put in the code suggested in Brian's answer, and I'm now getting all new errors. Even though the errors suggest fixes, it doesn't seem to help –- I've added the following to my package.json under jest. I'm not sure where Dimensions.js is anyway; plus, I would assume that all this setup I'm doing for React Native in particular would know how to identify the convention of having file.ios.js and file.android.js be equivalent to file.
Here's my "fix" following the instructions, which doesn't help at all.
"moduleFileExtensions": [
"js",
"json",
"jsx",
"ts",
"tsx",
"node",
"ios.js",
"android.js"
]
And here's the new errors.
FAIL tests/Test.test.js
● Test suite failed to run
Cannot find module './Platform' from 'Dimensions.js'
However, Jest was able to find:
'./Platform.android.js'
'./Platform.ios.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
However, Jest was able to find:
'../Utilities/Dimensions.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
However, Jest was able to find:
'buttons/Button.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
However, Jest was able to find:
'../js/LoginView.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:229:17)
at Object.require (node_modules/react-native/Libraries/Utilities/Dimensions.js:14:18)
react-native-elements contains ES6 code.
ES6 code needs to be compiled before it can be run by Jest.
By default Jest doesn't compile anything in node_modules, but react-native has a jest-preset that tells Jest to compile react-native and #react-native-community modules.
To include react-native-elements you will need to tell Jest to compile it as well by adding the following to your Jest config:
transformIgnorePatterns: [
'node_modules/(?!(jest-)?react-native|#react-native-community|react-native-elements)',
]