I have my React components all fleshed out, and I wanted to learn how to test these components properly with Mocha + chai. I have these configurations for my package.json (relevant ones):
"scripts": {
"start": "http-server",
"build": "watchify main.js -t babelify -o bundle.js",
"test": "./node_modules/mocha/bin/mocha --compilers js:babel-core/register test/test*.js"
},
"devDependencies": {
"babel": "^5.6.23",
"babelify": "^6.1.3",
"browserify": "^11.0.0",
"chai": "^3.5.0",
"jsdom": "^9.8.3",
"mocha": "^3.2.0",
"react-addons-test-utils": "^15.4.1"
},
"babel": {
"presets": [
"es2015"
]
}
I have Skill.js:
import React from 'react';
import _ from 'underscore';
export default class Skills extends React.Component {
render() {
return (
<div>
<h1>T E S T</h1>
</div>
)
}
}
along with a test.js in a folder called test:
import React from 'react';
import { expect, assert } from 'chai';
import Skills from '../src/components/Skills.js';
I'm receiving an unexpected token error when I run npm test.
What's the console complaining about? Why is the <div> tag not valid?
I had a similar issue and at first I thought I did not import React from 'react';.
Next I found out that I did not add --require ./test/test_helper.js
And last but then after still not working, it dawned on me that I did not restart node. That fixed it for me.
You need to install babel-preset-es2015 before using it
npm install --save-dev babel-preset-es2015
Related
Background
For a very simple ReactJS project, I wanted to
add ESLint capabilities :
npm install --save-dev eslint-config-react-app eslint#^8.0.0
package.json after installing ESLint :
{
"name": "reactjs-app",
"scripts": {
"dev": "next dev"
},
"dependencies": {
"next": "^12.1.4",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"eslint": "^8.12.0",
"eslint-config-react-app": "7.0.0"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
}
}
In the above package.json, none of the three dependencies next,
react, react-dom, depends on any ESLint package – neither
directly nor indirectly.
So all installed ESLint packages are dependencies of
eslint-config-react-app.
All the files needed for the project are in a zip file
available for download.
To try it out, just download, unpack and run npm install.
1
index.js :
// index.js
import { useState } from 'react';
function HomePage() {
const [showParagraph, setShowParagraph] = useState(true);
const showParagraphHandler = useCallback(() => {
setShowParagraph((prevToggle) => !prevToggle);
}, []);
console.log('App RUNNING');
console.log(showParagraph);
return (
<div className='app'>
<h1>Hi there!</h1>
<button onClick={showParagraphHandler}>A button</button>
</div>
);
}
export default HomePage;
The question
An observant reader will notice that the import for useCallback is
missing.
But autocompletion (in VS Code Ctrl + space)
wrongly suggests to import from
react/cjs/react.development, or from
react/cjs/react.production.min,
instead of from react which would have been more correct.
Why does this happen? – Is there a bug fix?
^ click to enlarge
References
README for eslint-config-react-app
All the project files in a zip file
Suggested solutions for the bug in this question
1
For me, the npm install command took about 5 minutes to complete.
The npm install command downloads and installs all packages in
package.json – including indirect packages.
Running npm run dev from the command line should start the
application in your default web browser.
Why does this happen? – Is there a bug fix?
It seems the reason is that #types/react is a missing dependency in
eslint-config-react-app so the obvious bug fix is to add
#types/react manually to your project by running :
npm install #types/react --save-dev
VS Code's autocompletion through Ctrl + space
now correctly suggests react.
1
Installing #types/react adds "#types/react": "^18.0.0", in your
package.json under "dependencies" :
{
"name": "reactjs-app",
"scripts": {
"dev": "next dev"
},
"dependencies": {
"#types/react": "^18.0.0",
"next": "^12.1.4",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"eslint": "^8.12.0",
"eslint-config-react-app": "7.0.0"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
}
}
1
If it doesn't work, try restarting VS Code.
I'm using sveltekit and I can't use the files api to import html templates. So I decided to import by writing a module that imports the content of the document as a string (described here).
// src/global.d.ts
/// <reference types="#sveltejs/kit" />
declare module '*.html' {
const content: string
export default content
}
So far so good, but now I need to test the code and jest can't interpret the code.
● 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/developer/workspace/src/assets/html/confirm_email.html:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){<!DOCTYPE html>
^
SyntaxError: Unexpected token '<'
I don't understand how jest understands the .d.ts files... How do I get to test the code?
Do you install #babel/plugin-transform-runtime"?
I share my config for jest/svelte-jester..
I have:
jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"],
}
svelte.config.js
import vercel from '#sveltejs/adapter-vercel'
/** #type {import('#sveltejs/kit').Config} */
const config = {
kit: {
adapter: vercel(),
vite: {
define: {
'process.env': process.env,
},
},
},
transform: {
"^.+\\.svelte$": ["svelte-jester", { "preprocess": true }]
}
};
export default config;
babel.config.json
{
"presets": [
["#babel/preset-env", { "modules": "auto" }]
],
"plugins": ["babel-plugin-transform-vite-meta-env","#babel/plugin-transform-runtime"]
}
jest.config.js
export default {
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.svelte$": "svelte-jester",
},
"moduleFileExtensions": ["svelte", "js"],
"testEnvironment": "jsdom",
"setupFilesAfterEnv": ["#testing-library/jest-dom/extend-expect"]
}
and whole package.json
{
"name": "sveltekit",
"version": "0.0.1",
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build",
"package": "svelte-kit package",
"preview": "svelte-kit preview",
"test": "jest src",
"test:watch": "npm run test -- --watch"
},
"devDependencies": {
"#babel/core": "^7.16.12",
"#babel/plugin-transform-modules-commonjs": "^7.16.8",
"#babel/plugin-transform-runtime": "^7.17.0",
"#babel/preset-env": "^7.16.11",
"#supabase/supabase-js": "^1.29.1",
"#sveltejs/adapter-auto": "^1.0.0-next.7",
"#sveltejs/kit": "^1.0.0-next.215",
"#sveltejs/svelte-virtual-list": "^3.0.1",
"#testing-library/svelte": "^3.0.3",
"autoprefixer": "^10.4.1",
"babel-jest": "^27.4.6",
"babel-plugin-transform-vite-meta-env": "^1.0.3",
"jest": "^27.4.7",
"postcss-load-config": "^3.1.1",
"prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.5.1",
"svelte": "^3.44.0",
"svelte-jester": "^2.1.5",
"svelte-lazy": "^1.0.12",
"tailwindcss": "^3.0.8",
"ts-jest": "^27.1.3"
},
"type": "module",
"dependencies": {
"#fontsource/fira-mono": "^4.5.0",
"#lukeed/uuid": "^2.0.0",
"#testing-library/jest-dom": "^5.16.1",
"cookie": "^0.4.1",
"svelte-lazy-image": "^0.2.0",
"swiper": "^8.0.3"
},
"testEnvironment": "jsdom"
}
I hope it will help you.I had a lot of troubles too with setting up jest..
1.Import html as string
I solved the problem using another approach...
I'm using a resource of vite to import the html file as an asset, as can be seen here in the documentation
import confirm_email_template from '../../../assets/html/confirm_email.html?raw'
2.Test using Jest
For production it works perfectly, but for unit testing the code breaks because Jest can't import the asset as a module.
So the second part of the problem was fixed (I don't know if this is the best practice) using asset mocks.
// jest.config.cjs
{
⋮
moduleNameMapper: {
⋮
'([a-zA-Z_ ]+\\.html)\\?raw$': '<rootDir>/__mocks/$1.cjs'
}
⋮
}
To make it work, I created the following folder structure:
__mocks
|
confirm_email.html.cjs
another_asset_mocked.html.cjs
The confirm_email.html.cjs looks like this:
// __mocks/confirm_email.html.cjs
module.exports = '<html>content<html>'
I know when you have a bare React app, you config webpack to use babel and then jest is using the babel configuration to compile the modules.
Now I have an app created with create-react-app. With a package.json as follows:
{
"name": "it does not matter",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-redux": "^7.2.0",
"react-redux-loading": "^1.0.1",
"react-router-dom": "^5.1.2",
"react-scripts": "1.1.1",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
With things being like that I wrote the simplest possible test, that passes as green:
import React from "react";
import ReactDOM from "react-dom";
it("renders LoggedUser without crashing", () => {
const div = document.createElement("div");
const name = "::name::";
const avatarURL = "::avatarURL::";
const loggedUser = { name, avatarURL };
ReactDOM.render(<LoggedUser loggedUser={loggedUser} />, div);
});
Now I follow the create react app docs to add the React testing library:
https://create-react-app.dev/docs/running-tests/#option-2-react-testing-library
I follow the steps but when running the test it complaints:
import React from "react";
import { render } from "#testing-library/react";
import { LoggedUser } from "../components/LoggedUser";
it("renders LoggedUser without crashing", () => {
const name = "::name::";
const avatarURL = "::avatarURL::";
const loggedUser = { name, avatarURL };
render(<LoggedUser loggedUser={loggedUser} />);
});
import ArrayFrom from "./polyfills/array.from.mjs";
^^^^^^^^^
SyntaxError: Unexpected identifier
In my package I have only added the dependencies:
"devDependencies": {
"#testing-library/jest-dom": "^5.5.0",
"#testing-library/react": "^10.0.4"
}
And as the docs suggested created a src/setupTests.js file
// react-testing-library renders your components to document.body,
// this adds jest-dom's custom assertions
import '#testing-library/jest-dom/extend-expect';
I have tried many things (a .babelrc file with and without a jest.config file...) but I was unable to make the test pass, when fixing one problem another one appeared...
Maybe sb is familiar with this problem and its possible solutions.
Cheers!
Well, in the end what I was trying to do was very twisted because I didn't know very well the webpack-babel-jest delegation when using the create-react-app boilerplate...
So I made another app from scratch and it did work, so I just updated in my real app the "react-scripts": "3.x.x" to make it work.
I apologize for all this hassle, anyway digging in the boilerplate was quite educational.
Thank you anyway!
I have cloned a demo . after installing koa,koa-router etc, I got an error. Here is my index.ts file
import Koa from "koa"
import Router from "koa-router"
import logger from "koa-logger"
import json from "koa-json"
const app = new Koa()
const router = new Router()
router.get("/",async(ctx: any,next: any)=>{
ctx.body = {
meg:"Hello world"
}
await next
})
app.use(logger())
app.use(json())
app.use(router.routes()).use(router.allowedMethods())
app.listen(3000,()=>console.log("app is running at 3000"))
Here is my package.json
{
"name": "babel-typescript-sample",
"version": "0.7.2",
"license": "MIT",
"scripts": {
"type-check": "tsc --noEmit",
"type-check:watch": "npm run type-check -- --watch",
"build": "npm run build:types && npm run build:js",
"build:types": "tsc --emitDeclarationOnly",
"build:js": "babel src --out-dir lib --extensions \".ts,.tsx\" --source-maps inline"
},
"devDependencies": {
"#babel/cli": "^7.8.3",
"#babel/core": "^7.8.3",
"#babel/plugin-proposal-class-properties": "^7.8.3",
"#babel/preset-env": "^7.8.3",
"#babel/preset-typescript": "^7.8.3",
"#types/koa": "^2.11.3",
"typescript": "^3.7.5"
},
"dependencies": {
"koa": "^2.11.0",
"koa-bodyparser": "^4.3.0",
"koa-json": "^2.0.2",
"koa-logger": "^3.2.1",
"koa-router": "^8.0.8"
}
}
my file structure loos like:
/-------
-lib
-index.js
-index.d.ts
-node_modules
-src
-index.ts
Actually,before this ,when I run npm run build,I got error src/index.ts:2:20 - error TS2307: Cannot find module 'koa-router'. I write koa-router.d.ts myself, but I don't think it's a great idea, How do you guys resolve?
You have a few options:
Install koa-router typings with npm install --save-dev #types/koa-router.
Set moduleResolution inside tsconfig.json to node. See this for differences. Note that this option only works if the dependency has typings included. In this case, it does not, so first option would be more correct.
Edit paths (points to directory) or types (points to .d.ts) inside tsconfig.json to point to your typings. Yes, writing your typings ("by hand") for existing dependency is generally considered a bad idea, since it could update and therefore break your typings. If a dependency does not have typings, you can contribute to it by generating it using JSDoc, if it uses JavaScript.
New to using jest and running into immediate test failure on an existing create-react-native-app project when trying to run npm test even though the code appears to work fine when run in the android studio AVD. Error in question looks like
➜ npm test
> spicex_react_native#0.1.0 test /path/to/project
> jest
PASS __tests__/example-test.js
FAIL ./App.test.js
● Test suite failed to run
/home/me/path/to/project/node_modules/tcomb-form-native/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import t from "./lib";
^
SyntaxError: Unexpected identifier
> 1 | import { PropTypes } from 'prop-types';
2 | import React from 'react';
3 | import { Alert, Button, ScrollView, StyleSheet, Text, View } from 'react-native';
4 | import Spinner from 'react-native-loading-spinner-overlay';
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:316:17)
at Object.<anonymous> (app/containers/path/to/some/component.js:1:1290)
Test Suites: 1 failed
Examining the component denoted by the component.js file in the android AVD, the screen renders without any errors or warnings. And the project's package.json looks like
{
"name": "spicex_react_native",
"version": "0.1.0",
"private": true,
"devDependencies": {
"eslint": "^5.3.0",
"eslint-config-standard": "^11.0.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-promise": "^3.8.0",
"eslint-plugin-react": "^7.10.0",
"eslint-plugin-react-redux": "^2.3.0",
"eslint-plugin-standard": "^3.1.0",
"jest-expo": "~27.0.0",
"react-native-scripts": "^1.14.1",
"react-test-renderer": "16.3.1"
},
"main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
"scripts": {
"start": "react-native-scripts start",
"eject": "react-native-scripts eject",
"android": "react-native-scripts android",
"ios": "react-native-scripts ios",
"test": "jest"
},
"jest": {
"preset": "jest-expo"
},
Was not totally sure how could debug properly from just the docs (https://jestjs.io/docs/en/tutorial-react-native.html#setup). If anyone knows what could be going on here, advice or suggestions would be appreciated.