Jest - Jest encountered an unexpected token. Vanilla JS - javascript

I'm trying to make a complex zip extractor in JavaScript and I decided that unit testing would be very important. That being said, a friend recommended Jest. I couldn't get any of my tests to work so I made a dumb test that made sure the first value of my JS Enum is 0. Jest, however, fails ever time saying that it encountered an unexpected token
I tried a more complex test and simplified it down to this simple test:
enums.js:
const Format = {
UNKNOWN: 0,
ZIP: 1,
TAR_GZIP: 2,
TAR_BZIP: 3,
};
export default Format
enums.test.js
const {Format} = require("../src/enums.js");
test("bad test", () => {
expect(Format.UNKNOWN).toBe(0);
});
The error that is gives me is this:
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:
• 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:
/home/giovanni/WebstormProjects/extract.js/src/enums.js:7
export default Format;
^^^^^^
SyntaxError: Unexpected token export
> 1 | const Format = require("../src/enums.js");
| ^
2 |
3 | test("bad test", () => {
4 | expect(Format.UNKNOWN).toBe(0);
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> (test/enum.test.js:1:1)

Using Bable fixed this. Once I installed Babel with NPM, I added a file .babelrc with the contents:
{
"presets": ["#babel/preset-env"]
}
This worked.

Related

Jest encountered an unexpected token - SyntaxError: Unexpected token 'export'

I'm using jest to test a react TypeScript app.
This is the test I'm running:
import { render, screen } from '#testing-library/react'
import { toBeInTheDocument } from '#testing-library/jest-dom'
import ContextProvider from '../../context/ContextProvider'
import { BrowserRouter } from 'react-router-dom'
import BlogPage from './BlogPage'
describe('BlogPage', () => {
test('Render blog page', () => {
render(
<ContextProvider>
<BrowserRouter>
<BlogPage/>
</BrowserRouter>
</ContextProvider>
)
expect(screen.getByText('In this page you can see some of the last articles I wrote.')).toBeInTheDocument()
})
})
And this is the error I'm getting:
FAIL src/components/blogPage/BlogPage.test.js
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• 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/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/home/German/Desktop/ger/code/projects/my-website/node_modules/react-markdown/index.js:6
export {uriTransformer} from './lib/uri-transformer.js'
^^^^^^
SyntaxError: Unexpected token 'export'
> 1 | import ReactMarkdown from 'react-markdown'
| ^
2 | import Accordion from 'react-bootstrap/Accordion'
3 |
4 | interface Props {
I understand this is because the library I'm using (react-markdown) doesn't have pre-compiled source code. The thing is I followed the docs (https://jestjs.io/docs/tutorial-react-native#transformignorepatterns-customization) and added the react-markdown folder to the transformIgnorePatterns config and I still get the error.
This is my jest.config.ts file:
import type { Config } from '#jest/types'
const config: Config.InitialOptions = {
verbose: true,
transform: {
'^.+\\.ts?$': 'ts-jest'
},
transformIgnorePatterns: [
'node_modules/(?!react-markdown/)'
]
}
export default config
I tried adding <rootDir> like <rootDir>/node_modules/(?!react-markdown/) and It didn't make a difference.
I also tried configuring jest directly from package.json instead of a jest.config file and It didn't make a difference either.
Then I found this question: Jest transformIgnorePatterns not working, which mentions you need to configure Babel.
I created my app with create-react-app so I didn't have Babel on my app. I installed it and created a babel.config.js file inside of which I put:
module.exports = {
"presets": [
"#babel/preset-env"
]
};
But I still get the error...
I'm running out of ideas. Any clue of how could I solve this?
Full code can be found here: https://github.com/coccagerman/my-website
react-markdown is shipped as js, add babel-jest as a transformer in your jest config
transform: {
'^.+\\.ts?$': 'ts-jest',
"^.+\\.(js|jsx)$": "babel-jest"
},

Migrating from Babel to SWC with React

TL;DR
How to translate a node script like this:
"test": "NODE_ENV=test riteway -r #babel/register 'src/**/*.test.js' | tap-nirvana",
to use SWC instead of Babel?
Context
We recently upgraded our Next.js version. Next.js now supports SWC instead of Babel.
The unit tests for React in our project are written with RITEway. The test command is:
"test": "NODE_ENV=test riteway -r #babel/register 'src/**/*.test.js' | tap-nirvana",
It transforms the files with Babel first because otherwise import statements and JSX would cause errors.
During our attempts to migrating to SWC, we had no luck with the CLI. However, we found the #swc-node/register package. It allowed us to transform our command like this:
"test": "riteway -r #swc-node/register src/**/*.test.js | tap-nirvana"
which fixes new syntax like the import statement and a test like this would run:
import { describe } from 'riteway';
describe('my test', async assert => {
assert({
given: 'true',
should: 'be true',
actual: true,
expected: true,
});
});
However, tests for React components like this
import { describe } from 'riteway';
import render from 'riteway/render-component';
import Authentication from './user-authentication-component';
describe('user authentication component', async assert => {
const $ = render(<Authentication />);
assert({
given: 'just rendering',
should: "render 'Authentication'",
actual: $('*:contains("Authentication")').text(),
expected: 'Authentication',
});
});
still throw the following error:
$ yarn test
yarn run v1.22.17
$ riteway -r #swc-node/register src/**/*.test.js | tap-nirvana
/Users/user/dev/learning-flow/node_modules/#swc/core/index.js:135
return bindings.transformSync(isModule ? JSON.stringify(src) : src, isModule, toBuffer(newOptions));
^
Error: error: Expression expected
|
7 | const $ = render(<Authentication />);
| ^
error: Expression expected
|
7 | const $ = render(<Authentication />);
| ^
error: Unexpected token `)`. Expected this, import, async, function, [ for array literal, { for object literal, # for decorator, function, class, null, true, false, number, bigint, string, regexp, ` for template literal, (, or an identifier
|
7 | const $ = render(<Authentication />);
| ^
Caused by:
0: failed to process js file
1: Syntax Error
at Compiler.transformSync
How can we create that command so that it runs with SWC?
After some experimentation I found out that it works if you import React from 'react'; in every file (both the component as well as the test) and change the file extensions to .jsx as described in the docs.
However, this is unsatisfying, as we'd like to use React 17's JSX transform feature to avoid having to import React in every file. Additionally, we'd like to keep all file endings .js.
We tried setting .swcrc without any luck so far.
I'm posting this answer here in case no way to configure .swcrc can be found.
I'll assume your question is only about jest and not about the webpack setup for swc.
I've never used swc myself in jest so this is just a shot in the dark, but I found a package for jest called #swc-node/jest which allows you to use a transformer like:
module.exports = {
transform: {
'^.+\\.(t|j)sx?$': ['#swc-node/jest'],
},
}
Which should allow you to transpile all [jt]sx? imports.
There's also a different one called #swc/jest which seems to do the same thing.
I'd start with trying those.
Your issue is that jest isn't able to parse your code, for example if you were using typescript you'd need something like ts-jest in order to parse your TS for you, I think in this case you need a swc/jest transpiler which should first compile your code and output it to memory, then funnel it to jest to run it.
The alternative is that you could compile the tests before hand using swc, then run jest on the compiled files as a separate step. At least with TS you can do that, first compile everything using tsc and then run jest on the .js output. I'm sure swc should work the same.
As to why the #swc-node/register package you're using isn't working, I have no idea.

Running tests with ES6 import statements node

I'm using node v15.0.1, and jest 26.6.0 on ubuntu 18.04.5.
I have setup a simple test case, and at the top of the file I'm trying to use an ES6 import statement:
import Color from './color.js'
test("Initialized properly after construction", () => {
expect(1 + 1).toBe(2);
});
Additionally, here's the code for color.js:
class Color {
constructor(r, g, b, a) {
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
}
export {
Color
};
When I run jest I get the following error output:
FAIL src/modules/color.test.js
● 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:
• 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:
/home/daniel/Documents/raycaster/src/modules/color.test.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Color from './color.js'
^^^^^^
SyntaxError: Cannot use import statement outside a module
at new Script (node:vm:100:7)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 0.288 s
Ran all test suites.
npm ERR! code 1
Based on the Jest documentation https://jestjs.io/docs/en/ecmascript-modules, I have added the following to my package.json file:
"type": "module",
"jest": {
"testEnvironment": "jest-environment-node",
"transform": {}
}
Despite these configurations it appears that jest is unable to run in an ES6 compliant mode. What configurations would I need to do to enable the import statements?
I found Node v13 / Jest / ES6 — native support for modules without babel or esm
which highlighted the piece that I needed:
In my package.json file, I needed to specify the following:
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
As the reference states,
babel-jest is automatically installed when installing Jest and will automatically transform files if a babel configuration exists in your project. To avoid this behavior, you can explicitly reset the transform configuration option:
<...>
transform: {},
This is exactly what this config does, it disables Babel and prevents import from being transpiled.
The solution is to remove transform: {} and use transform only on purpose.
The mentioned reference section is dedicated to native ES module support in Node. It suggests that transform: {} requires to enable them with:
node --experimental-vm-modules node_modules/.bin/jest
This cannot be recommended for regualr use as ESM support in both Node and Jest is experimental, may cause issues and lack features as Jest already heavily relies on CommonJS modules.
Since you are importing the class as a default export, you need to a default value. For more insight check this out https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export
class Color {
constructor(r, g, b, a) {
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
}
export default Color;

How do I correctly configure mocha tests with ts_transformer_keys?

I can't seem to set the custom transformer for ts-transform-keys with my mocha tests.
I’m using mocha 6.1.4
ts-node 8.3.0 https://www.npmjs.com/package/ts-node
ts-trasnformer-keys 0.3.5 https://github.com/kimamula/ts-transformer-keys
ttypescript 1.5.7 https://github.com/cevek/ttypescript
The ts-node documentation says that you cannot set a custom transformer on the CLI, only programatically. So I'm trying to use ttypescript to get around that restriction.
I've tried the following...
Note: test.ts contains the following
import { keys } from 'ts-transformer-keys';
describe("xyz"), () => {
it("123", (done) => {
keys<CustomInterface>();
});
});
Attempt 1) - Set the ts-node with an environment variable
TS_NODE_COMPILER="ttypescript" mocha test/test.ts --require ts-node/register
Then I have the following in test/tsconfig.json
{
"compilerOptions": {
"plugins": [
{ "transform": "ts-transformer-keys/transformer" }
]
}
}
This results in Uncaught TypeError: ts_transformer_keys_1.keys is not a function which indicates that the custom transformer wasn't used at compile time.
Attempt 2) Following the typescript API example from ts-transformer-keys
I added a mocha.opts file with the following
--file test/transformer-config.js
and a transformer-config.js file with the following
const ts = require('typescript');
const keysTransformer = require('ts-transformer-keys/transformer').default;
const program = ts.createProgram(['test/test.ts'], {
strict: true,
noEmitOnError: true,
target: ts.ScriptTarget.ES5
});
const transformers = {
before: [keysTransformer(program)],
after: []
};
const { emitSkipped, diagnostics } = program.emit(undefined, undefined, undefined, false, transformers);
if (emitSkipped) {
throw new Error(diagnostics.map(diagnostic => diagnostic.messageText).join('\n'));
}
Then I invoke it like this mocha test/test.ts --require ts-node/register
This results in the following error
/Users/jjohnson/Documents/OCS/hmp/git/hmp-server/server/test/ttypescript-register.js:17
throw new Error(diagnostics.map(diagnostic => diagnostic.messageText).join('\n'));
^
Error: [object Object]
[object Object]
[object Object]
at Object.<anonymous> (/Users/jjohnson/Documents/OCS/hmp/git/hmp-server/server/test/ttypescript-register.js:17:9)
at Module._compile (internal/modules/cjs/loader.js:777:30)
...
It feels like in Attempt 1 it wasn't ever calling the code that sets the custom transformer in tsconfig.json or if it was getting called the code was failing silently.
It feels like in Attempt 2 I'm creating a new instance of the typescript program and then that fails for some reason. And even if it succeeded I'm not sure that this is the right way to go about configuring things since the ts.createProgram wants a list of RootNames for the files it will transpile.
Maybe my entire approach is wrong.
All I really want is a way that in my mocha tests I can verify that the expected result type is what the method returned. And I'd like to be able to do this w/out touching too much of the source code.
you should be able to define your required module (see below) and run ts-node programmatically. In this way, you can safely use any customer transformer.
// tsnode.js
const transformer = require('ts-transformer-keys/transformer').default;
require("ts-node").register({
transformers: program => ({
before: [
transformer(program)
]
})
});
then you can run mocha with require
mocha --require './tsnode.js' --watch-extensions ts,tsx "test/**/*.{ts,tsx}
You can tell ts-node which compiler to use in tsconfig.json. This is covered in the ts-node docs. If your using transformers presumably your also using ttypescript compiler. You just need to add this:
"ts-node": {
"compiler": "ttypescript"
}

React Native - unexpected token static propTypes when running assmbleRelease, babel plugin doesnt work

I'm trying to compile a release apk in React Native using either
"react-native run-android --variant=release" or
from ./android:
"./gradelw assmbleRelease"
I keep getting the following error:
> :app:bundleReleaseJsAndAssets
ERROR Failed to compile.
./node_modules/native-base-shoutem-theme/src/StyleProvider.js 10:19
Module parse failed: Unexpected token (10:19)
You may need an appropriate loader to handle this file type.
| */
| export default class StyleProvider extends React.Component {
> static propTypes = {
| children: PropTypes.element.isRequired,
...
I've installed this plugin:
https://babeljs.io/docs/en/next/babel-plugin-proposal-class-properties.html
and added it to my babel.config.js:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
'#babel/plugin-proposal-class-properties'
]
};
I've tried creating also a .babelrc file and setting it up. didn't work.
I tried configurating babel through package.json and also it didn't work.
I've tried doing
"react-native start -- --reset-cache"
but nothing helped. I keep getting the same error.
I know the babel.config.js is being read because if I mess around with it I see that the build fails for other reasons.
but a strange thing is that if I remove the file completely, I still get the original error (missing "static propTypes" thing).
why doesn't the plugin work?
Not sure why this happened, but removing "haul" did the trick.
"npm uninstall --save-dev haul"
and remove the added config in app/build.gradle:
project.ext.react = [
cliPath: "node_modules/haul/bin/cli.js"
]

Categories

Resources