How test JSX Vue component with Jest - javascript

I've following component (I simplified code) :
const Comp = Vue.component('Comp', {
render (h) {
// Other stuff ...
return (<div>
<div style={style}>
<div style={{ display : 'inline-block' }} />
</div>
</div>)
},
})
export default Comp
I wrote following unit test :
it('should be initialized', () => {
const addEventListener = spyOn(document, 'addEventListener')
const { vm } = shallowMount(Comp)
expect(addEventListener).toHaveBeenCalledWith('dragend', jasmine.any(Function))
expect(addEventListener).toHaveBeenCalledWith('keypress', jasmine.any(Function))
})
When I run unit tests with Jest, I've an error :
ReferenceError: dom is not defined
> 96 | return (<div>
| ^
97 | <div style={style}>
98 | <div style={{ display : 'inline-block' }} />
99 | </div>
My following babel.config.js file :
module.exports = (api) => {
return {
presets : ['#babel/preset-env', '#vue/babel-preset-jsx'],
plugins : [
'#babel/plugin-syntax-jsx',
['#babel/plugin-transform-react-jsx', { pragma : 'dom' }],
[
'module-resolver', {
root : ['./'],
alias : {
'#' : './src',
'~' : './examples',
},
},
],
],
}
}
And my Jest config file :
module.exports = {
coverageReporters : ['html'],
"transform": {
"^.+\\.[t|j]sx?$": "babel-jest"
},
collectCoverageFrom : [
"src/**/*.{js,jsx}"
],
moduleNameMapper : {
"\\.(css|less|sass|scss)$": "<rootDir>/tests/__mocks__/styleMock.js"
},
moduleFileExtensions : ['js', 'jsx']
}
When I build project with rollup, I've no error, only with jest.
Did i miss something ?
UPDATE
My package.json file :
{
"devDependencies": {
"#babel/core": "^7.1.2",
"#babel/plugin-syntax-jsx": "^7.0.0",
"#babel/plugin-transform-react-jsx": "^7.0.0",
"#babel/preset-env": "^7.1.0",
"#rollup/plugin-alias": "^2.2.0",
"#vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
"#vue/babel-preset-jsx": "^1.1.0",
"#vue/test-utils": "^1.0.0-beta.31",
"babel-core": "^7.0.0-bridge.0",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-jest": "^23.6.0",
"babel-loader": "^8.0.4",
"babel-plugin-module-resolver": "^3.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-vue-jsx": "^3.7.0",
"babel-preset-env": "^1.7.0",
"babel-preset-es2015": "^6.24.1",
"codemirror": "^5.48.2",
"css-loader": "^3.2.0",
"docdash": "^1.0.3",
"eslint": "6.1.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jasmine": "^2.10.1",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"file-loader": "^4.2.0",
"html-loader": "^0.5.5",
"husky": "^3.0.8",
"jest": "^23.6.0",
"jquery": "^3.3.1",
"js-beautify": "^1.10.0",
"jsdoc": "^3.5.5",
"jsx-render": "^1.1.1",
"lint-staged": "^9.4.2",
"node-sass": "^4.13.0",
"rollup": "^1.26.4",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-scss": "^1.0.2",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"url-loader": "^2.1.0",
"vue": "^2.6.10",
"vue-template-compiler": "^2.6.11",
"vuex": "^3.1.1",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
},
"scripts": {
"test": "jest",
"build": "rollup -c"
},
"author": "",
"license": "ISC",
"husky": {
"hooks": {
"pre-push": "npm run test",
"pre-commit": "lint-staged"
}
}
}
Maybe it can be useful : my project wasn't created with vue-cli. I use Vue only for two components.

Could you try with the below setup.
Package.json
{
"name": "hello-world",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"test": "jest --watch"
},
"dependencies": {
"core-js": "^3.4.4",
"vue": "^2.6.10"
},
"devDependencies": {
"#babel/plugin-transform-react-jsx": "^7.8.3",
"#vue/cli-plugin-babel": "^4.1.0",
"#vue/cli-plugin-eslint": "^4.1.0",
"#vue/cli-service": "^4.1.0",
"#vue/test-utils": "^1.0.0-beta.31",
"babel-eslint": "^10.0.3",
"babel-jest": "^25.1.0",
"babel-plugin-module-resolver": "^4.0.0",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"jasmine": "^3.5.0",
"jest": "^25.1.0",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"browserslist": [
"> 1%",
"last 2 versions"
],
"jest": {
"moduleFileExtensions": [
"js",
"json",
"vue"
]
}
}
Component
import Vue from "vue";
const Comp = Vue.component("Comp", {
mounted() {
document.addEventListener("click", () => {
});
},
render(h) {
// Other stuff ...
return (
<div>
<div >Hello World!</div>
<input type="text" id="someeid"></input>
<div id="result"></div>
</div>
);
}
});
export default Comp;
babel.config.js
module.exports = api => {
api.cache(false);
return {
presets: ["#babel/preset-env", "#vue/babel-preset-jsx"],
plugins: [
"#babel/plugin-syntax-jsx",
["#babel/plugin-transform-react-jsx", { pragma : 'dom' }],
[
"module-resolver",
{
root: ["./"],
alias: {
"#": "./src",
"~": "./examples"
}
}
]
]
};
};
test file
import { shallowMount } from "#vue/test-utils";
import Comp from "./Comp";
it("should be initialized", () => {
const addEventListener = spyOn(document, "addEventListener");
const { vm } = shallowMount(Comp);
expect(addEventListener).toHaveBeenCalledWith("click", , expect.any(Function));
});
codesandbox Example

Related

How to resolve jest error when attempting to run test suite?

I am receiving the following error when attempting to run a test suite using jest:
● Test suite failed to run
TypeError: Cannot read property '1' of undefined
at Plugin.manipulateOptions (node_modules/babel-plugin-module-resolver/lib/index.js:88:9)
at run.next (<anonymous>)
at transform.next (<anonymous>)
I have attempted to resolve the issue by removing node_modules and reinstalling to no avail.
Here is a copy of my package.json which is placed in the root directory:
{
"name": "obfuscate",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest",
"test:coverage": "jest --coverage",
"test:snapshots": "jest --updateSnapshot",
"test:watch": "jest --watch -o",
"serve": "node -r babel-register node_modules/webpack-dev-server/bin/webpack-dev-server --config config/webpack/environments/serve/index.js",
"build:dev": "node -r babel-register node_modules/webpack/bin/webpack --config config/webpack/environments/dev/index.js",
"build:prod": "node -r babel-register node_modules/webpack/bin/webpack --config config/webpack/environments/prod/index.js",
"start": "npm run build:dev",
"lint:js": "eslint \"src/**/*.js\"",
"lint:styles": "stylelint \"src/**/*.scss\"",
"prepush": "npm run lint:styles && npm run lint:js",
"browsersync": "npx browser-sync start --config bs-config.js",
"bsync": "concurrently \"npm run start \" \"npx browser-sync start --config bs-config.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.2",
"babel-jest": "^22.0.4",
"babel-loader": "^7.1.2",
"babel-plugin-module-resolver": "^2.7.1",
"babel-plugin-syntax-async-functions": "^6.13.0",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators": "^6.24.1",
"babel-plugin-transform-do-expressions": "^6.22.0",
"babel-plugin-transform-export-extensions": "^6.22.0",
"babel-plugin-transform-function-bind": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-react-constant-elements": "^6.23.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.0",
"babel-register": "^6.26.0",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"del-webpack-plugin": "^1.0.6",
"domready": "^1.0.8",
"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.9.1",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.6",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-loader": "^0.5.1",
"husky": "^0.14.3",
"identity-obj-proxy": "^3.0.0",
"img-loader": "^2.0.0",
"jest": "^22.0.4",
"jsdom": "^16.2.0",
"node-sass": "^4.11.0",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"postcss-loader": "^2.0.6",
"react": "^16.8.2",
"react-collapsible": "^2.1.0",
"react-countup": "^4.0.0",
"react-dom": "^16.8.2",
"react-equalizer": "^1.3.0",
"react-router-dom": "^4.3.1",
"react-scroll": "^1.7.8",
"react-slick": "^0.23.1",
"react-spinners": "^0.3.2",
"react-tabs": "^2.1.1",
"react-text-mask": "^5.1.0",
"react-transition-group": "^2.5.0",
"react-widgets": "^4.1.2",
"sass-loader": "^6.0.6",
"sass-resources-loader": "^1.3.5",
"standard-loader": "^6.0.1",
"stylelint": "^8.4.0",
"stylelint-config-standard": "^18.0.0",
"stylelint-webpack-plugin": "^0.9.0",
"uglifyjs-webpack-plugin": "^1.3.0",
"url-loader": "^0.6.1",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.13.1",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^2.0.0",
"webpack-manifest-plugin": "^2.0.0-rc.1",
"webpack-merge": "^4.2.1"
},
"dependencies": {
"#obfuscate/components": "^1.0.125",
"#obfuscate/react-ranger": "^1.0.0",
"axios": "^0.19.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-polyfill": "^6.26.0",
"blazy": "^1.8.2",
"browser-sync": "^2.26.7",
"classlist-polyfill": "^1.2.0",
"concurrently": "^4.1.2",
"core-js": "^3.6.0",
"eslint": "^6.7.2",
"eslint-config-standard": "^14.1.0",
"eslint-loader": "^3.0.3",
"formdata-polyfill": "^3.0.19",
"isomorphic-fetch": "^2.2.1",
"js-match-height": "^1.0.7",
"mobx": "^4.9.2",
"mobx-react": "^5.4.3",
"mobx-react-form": "^1.36.3",
"nodelist-foreach-polyfill": "^1.2.0",
"regenerator-runtime": "^0.13.3",
"scroll-lock": "^2.1.2",
"smoothscroll": "^0.4.0",
"swiper": "^5.2.1",
"url-search-params": "^1.1.0",
"validatorjs": "^3.15.1"
},
"stylelint": {
"extends": "stylelint-config-standard",
"ignoreFiles": [
"src/styles/vendor/**/*.scss"
],
"ignoreProperties": [
"composes"
],
"rules": {
"no-descending-specificity": null,
"max-empty-lines": 4,
"string-quotes": "single",
"function-url-quotes": "always",
"color-hex-length": "long",
"declaration-colon-newline-after": null,
"declaration-block-no-redundant-longhand-properties": null,
"font-family-name-quotes": null,
"number-leading-zero": "never",
"value-list-comma-newline-after": null,
"max-nesting-depth": 4,
"selector-pseudo-element-colon-notation": "single",
"at-rule-name-space-after": null,
"declaration-empty-line-before": null,
"at-rule-empty-line-before": null,
"at-rule-no-unknown": [
true,
{
"ignoreAtRules": [
"function",
"extend",
"if",
"else",
"each",
"mixin",
"include",
"return",
"media",
"at-root",
"debug",
"warn",
"error",
"for",
"content"
]
}
],
"property-no-unknown": [
true,
{
"ignoreProperties": [
"composes"
]
}
]
}
},
"jest": {
"testURL": "http://localhost",
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|html)$": "<rootDir>config/jest/jest.filemock.js",
"\\.(css|scss)$": "identity-obj-proxy"
},
"setupFiles": [
"./config/jest/jest.setup.js"
],
"modulePaths": [
"<rootDir>/src"
],
"collectCoverageFrom": [
"src/**/*.js",
"!src/base.js",
"!src/index-react.js",
"!src/index.js"
],
"transform": {
"^.+\\.js?$": "babel-jest"
},
"verbose": true
},
"standard": {
"globals": [
"jest",
"describe",
"it",
"expect",
"shallow",
"snapshot",
"test",
"enzyme",
"mount",
"after",
"afterEach",
"beforeEach",
"parent",
"fetch"
],
"ignore": [
"node_modules/**",
"*.test.js"
],
"parser": "babel-eslint"
}
}
Here is a copy of the jest.config.js file also placed in the root directory:
module.exports = {
clearMocks: true,
coverageDirectory: "coverage",
testURL: "http://localhost",
};
Here is a copy of my jest.setup.js file which is placed in config/jest:
import { configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
window.matchMedia = window.matchMedia || function () {
return {
matches: false,
addListener: function () { },
removeListener: function () { }
}
}
configure({ adapter: new Adapter() })
Issue resolved. Issue was caused by running the tests by using the "jest" command in the terminal which is different from using the npm test script which also only runs the "jest" command. The difference is the former was using a higher version of Jest which I had installed globally and ended up running into issues whereas the latter used the version of jest that corresponds with the version in the package.json.

React CKeditor Jest error: SyntaxError: Cannot use import statement outside a module

App was created using CreateReactApp with ejecting.
I'm trying to use CKeditor according to this doc CKeditor 5
After few hours it works fine, but much more hours trying to fix error in test finished unsuccessfully!
When I run npm test I got this error:
node_modules/#ckeditor/ckeditor5-editor-classic/src/classiceditor.js:10
import Editor from '#ckeditor/ckeditor5-core/src/editor/editor';
SyntaxError: Cannot use import statement outside a module
1 | import React, { useState, useEffect } from 'react';
2 | import CKEditor from '#ckeditor/ckeditor5-react';
> 3 | import ClassicEditor from '#ckeditor/ckeditor5-editor-classic/src/classiceditor';
my package.json:
{
"private": true,
"dependencies": {
"#babel/core": "7.4.3",
"#ckeditor/ckeditor5-alignment": "^16.0.0",
"#ckeditor/ckeditor5-basic-styles": "^16.0.0",
"#ckeditor/ckeditor5-dev-utils": "^12.0.5",
"#ckeditor/ckeditor5-dev-webpack-plugin": "^8.0.5",
"#ckeditor/ckeditor5-editor-classic": "^16.0.0",
"#ckeditor/ckeditor5-essentials": "^16.0.0",
"#ckeditor/ckeditor5-heading": "^16.0.0",
"#ckeditor/ckeditor5-link": "^16.0.0",
"#ckeditor/ckeditor5-list": "^16.0.0",
"#ckeditor/ckeditor5-paragraph": "^16.0.0",
"#ckeditor/ckeditor5-react": "^2.0.0",
"#ckeditor/ckeditor5-theme-lark": "^16.0.0",
"#svgr/webpack": "4.1.0",
"#typescript-eslint/eslint-plugin": "1.6.0",
"#typescript-eslint/parser": "1.6.0",
"axios": "^0.18.1",
"babel-eslint": "10.0.1",
"babel-jest": "24.7.1",
"babel-loader": "8.0.5",
"babel-plugin-named-asset-import": "^0.3.2",
"babel-preset-react-app": "^8.0.0",
"base64url": "^3.0.1",
"blueimp-load-image": "^2.21.0",
"case-sensitive-paths-webpack-plugin": "2.2.0",
"cleave.js": "^1.4.10",
"css-loader": "2.1.1",
"dotenv": "6.2.0",
"dotenv-expand": "4.2.0",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
"file-loader": "3.0.1",
"fingerprintjs2": "^2.1.0",
"flow-typed": "^2.5.2",
"fs-extra": "7.0.1",
"google-map-react": "^1.1.4",
"history": "^4.9.0",
"html-react-parser": "^0.10.0",
"html-webpack-plugin": "4.0.0-beta.5",
"identity-obj-proxy": "3.0.0",
"is-wsl": "^1.1.0",
"jest": "24.7.1",
"jest-environment-jsdom-fourteen": "0.1.0",
"jest-resolve": "24.7.1",
"jest-watch-typeahead": "0.3.0",
"lint-staged": "^8.1.5",
"mini-css-extract-plugin": "0.5.0",
"moment": "^2.24.0",
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "5.0.1",
"pnp-webpack-plugin": "1.2.1",
"postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0",
"postcss-normalize": "7.0.1",
"postcss-preset-env": "6.6.0",
"postcss-safe-parser": "4.0.1",
"qs": "^6.7.0",
"raw-loader": "^3.1.0",
"rc-slider": "^8.6.9",
"react": "^16.8.6",
"react-app-polyfill": "^1.0.0",
"react-avatar-editor": "^11.0.7",
"react-dates": "^20.2.2",
"react-dev-utils": "^9.0.0",
"react-dom": "^16.8.6",
"react-modal": "^3.8.1",
"react-onclickoutside": "^6.8.0",
"react-places-autocomplete": "^7.2.1",
"react-redux": "^7.0.3",
"react-responsive": "^6.1.2",
"react-router-dom": "^5.0.0",
"react-select": "^2.4.3",
"react-slick": "^0.24.0",
"react-test-renderer": "^16.8.6",
"react-truncate": "^2.4.0",
"react-with-direction": "^1.3.0",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"resolve": "1.10.0",
"sass-loader": "7.1.0",
"semver": "6.0.0",
"slick-carousel": "^1.8.1",
"style-loader": "0.23.1",
"stylelint": "^10.0.1",
"stylelint-config-standard": "^18.3.0",
"terser-webpack-plugin": "1.2.3",
"url-loader": "1.1.2",
"webpack": "4.29.6",
"webpack-dev-server": "3.2.1",
"webpack-manifest-plugin": "2.0.4",
"workbox-webpack-plugin": "4.2.0"
},
"husky": {
"hooks": {
"pre-commit": "npm run test && flow"
}
},
"proxy": "https://getrenty-qa.devopsready.tools",
"scripts": {
"start": "node scripts/start.js",
"precommit": "npm test && lint-staged",
"build": "node scripts/build.js",
"test:lint:js": "eslint src/**/*.{js,jsx}",
"test:lint:scss": "stylelint --config=.stylelintrc \"**/*.scss\"",
"test:lint": "npm run test:lint:js && npm run test:lint:scss",
"test:unit": "node scripts/test.js --env=jsdom",
"test": "npm run test:lint && npm run test:unit",
"test:ci": "node scripts/test.js --env=jsdom --ci --reporters=default --reporters=jest-junit --coverage",
"flow": "flow"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"eslint": "^5.16.0",
"eslint-config-airbnb": "^17.1.0",
"eslint-config-prettier": "^4.2.0",
"eslint-config-react-app": "^4.0.1",
"eslint-loader": "^2.2.1",
"eslint-plugin-flowtype": "^3.11.1",
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.0.1",
"eslint-plugin-react": "^7.14.2",
"eslint-plugin-react-hooks": "^1.6.1",
"flow-bin": "^0.98.0",
"jest-junit": "^7.0.0",
"prettier": "^1.17.0",
"redux-devtools": "^3.5.0",
"redux-devtools-extension": "^2.13.8",
"stylelint-scss": "^3.6.1",
"husky": "^2.1.0"
},
"jest": {
"coverageReporters": [
"text",
"cobertura"
],
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!src/**/*.d.ts"
],
"setupFiles": [
"react-app-polyfill/jsdom"
],
"setupFilesAfterEnv": [
"<rootDir>/src/setupTests.js"
],
"testMatch": [
"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
"<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"
],
"testEnvironment": "jest-environment-jsdom-fourteen",
"transform": {
"^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$",
"^.+\\.module\\.(css|sass|scss)$"
],
"modulePaths": [
"src/"
],
"moduleNameMapper": {
"^react-native$": "react-native-web",
"^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
},
"moduleFileExtensions": [
"web.js",
"js",
"web.ts",
"ts",
"web.tsx",
"tsx",
"json",
"web.jsx",
"jsx",
"node"
],
"watchPlugins": [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname"
]
},
"babel": {
"presets": [
"react-app"
]
}
}
component code:
import React, { useState, useEffect } from 'react';
import CKEditor from '#ckeditor/ckeditor5-react';
import ClassicEditor from '#ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Alignment from '#ckeditor/ckeditor5-alignment/src/alignment';
import Essentials from '#ckeditor/ckeditor5-essentials/src/essentials';
import Bold from '#ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '#ckeditor/ckeditor5-basic-styles/src/italic';
import Paragraph from '#ckeditor/ckeditor5-paragraph/src/paragraph';
import Heading from '#ckeditor/ckeditor5-heading/src/heading';
import Link from '#ckeditor/ckeditor5-link/src/link';
import List from '#ckeditor/ckeditor5-list/src/list';
import styles from './rtf.module.scss';
const editorConfig = {
plugins: [
Essentials,
Alignment,
Bold,
Italic,
Paragraph,
Heading,
Link,
List,
],
toolbar: [
'heading',
'bold',
'italic',
'link',
'bulletedList',
'numberedList',
'alignment',
],
};
type Props = {
initialData?: string,
onSave: Function,
title?: string,
savingStatus?: string,
};
const Editor = ({ initialData, onSave, title, savingStatus }: Props) => {
const [editorData, setData] = useState(initialData || '');
useEffect(() => {
setData(initialData);
}, [initialData]);
const handleChange = (event, editor) => {
const data = editor.getData();
setData(data);
};
const resetEdit = () => {
setData(initialData);
};
const handleSave = () => {
onSave(editorData);
};
return (
<div>
<div className={styles.title_row}>
<h5 className={styles.title}>{title}</h5>
<button
type="button"
className={`button_small ${styles.to_right}`}
onClick={resetEdit}
>
Reset
</button>
<button
type="button"
className="button_green_dark_short"
onClick={handleSave}
>
Save
</button>
</div>
<div className={styles.saving_status}>{savingStatus}</div>
<div className={styles.rtf_wrapper}>
<CKEditor
config={editorConfig}
editor={ClassicEditor}
onChange={handleChange}
data={editorData}
/>
</div>
</div>
);
};
Editor.defaultProps = {
initialData: '',
title: '',
savingStatus: '',
};
export default Editor;
I have tried modify jest.transformIgnorePatterns in package.json but it failed again.
Any advices?????
This is happening because you are using the unbundled version of the ckeditor, jest does not understand es6, so you got to change transformIgnorePatterns so jest can be able to compile the files for you.
This is for a standard jest configuration (e.g jest.config.js) and .babelrc
*If you are using .babelrc try changing it to babel.config.js
In your jest configuration file include this:
{
moduleNameMapper: {
'^~/(.*)': '<rootDir>/src/$1',
'\\.(css|scss)$': '<rootDir>/src/__mocks__/styleMock.js',
},
transformIgnorePatterns: ['/node_modules/(?!#ckeditor)/.+\\.js$']
}
If you are using craco in a react app use it like this:
jest: {
configure(config) {
config.moduleNameMapper = {
'^~/(.*)': '<rootDir>/src/$1',
'\\.(css|scss)$': '<rootDir>/src/__mocks__/styleMock.js',
};
...
config.transformIgnorePatterns = ['/node_modules/(?!#ckeditor)/.+\\.js$'];
return config;
},
},
The ckeditor builded version is buggy right now, I hope they fix it soon enough...

How can I solve " TypeError: Cannot set property '_eventListeners' of undefined" with jest

I have a vue.js application, and I installed Jest using these instruction:
https://vue-test-utils.vuejs.org/guides/testing-single-file-components-with-jest.html.
when I run npm test, I get the error.
● Test suite failed to run
TypeError: Cannot set property '_eventListeners' of undefined
at Window.close (node_modules/jsdom/lib/jsdom/browser/Window.js:475:51)
I have done everything in the docs, and every other thing about the app is fine, except testing. Please, how can I solve this issue?
This is my package.json config file:
{
"name": "vendor",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"test": "jest"
},
"dependencies": {
"babel-polyfill": "^6.26.0",
"vue": "^2.5.22",
"vue-router": "^3.0.2",
"vuetify": "^1.3.0"
},
"devDependencies": {
"vue-server-renderer": "^2.6.6",
"babel-core": "^6.26.3",
"#babel/core": "^7.2.2",
"#babel/preset-env": "^7.3.1",
"#vue/cli-plugin-babel": "^3.4.0",
"#vue/cli-plugin-eslint": "^3.4.0",
"#vue/cli-service": "^3.4.0",
"#vue/server-test-utils": "^1.0.0-beta.29",
"#vue/test-utils": "^1.0.0-beta.29",
"babel-eslint": "^10.0.1",
"babel-jest": "^24.1.0",
"eslint": "^5.8.0",
"eslint-plugin-vue": "^5.0.0",
"gulp-babel": "^8.0.0",
"jest": "^24.1.0",
"jest-serializer-vue": "^2.0.2",
"jsdom": "^13.2.0",
"jsdom-global": "^3.0.2",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"vue-cli-plugin-vuetify": "^0.4.6",
"vue-jest": "^3.0.3",
"vue-template-compiler": "^2.6.5",
"vuetify-loader": "^1.0.5"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"jest": {
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"transform": {
".*\\.(vue)$": "vue-jest",
"^.+\\.js$": "<rootDir>/node_modules/babel-jest"
},
"moduleNameMapper": {
"^#/(.*)$": "<rootDir>/src/$1"
},
"collectCoverage": true,
"collectCoverageFrom": [
"**/*.{js,vue}",
"!**/node_modules/**"
],
"coverageReporters": [
"html",
"text-summary"
],
"snapshotSerializers": [
"jest-serializer-vue"
]
}
}

jest.mock does not mock a module

In my test I do
import SendSMS from 'react-native-sms';
jest.mock('react-native-sms');
describe('_sendSMS', function() {
it('resolves with result sent', async () => {
SendSMS.send.mockImplementation((opts, callback) => {
callback(true, false, false);
});
...
})
});
and I get following error:
TypeError: _reactNativeSms.default.send.mockImplementation is not a function
package.json:
{
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest --verbose",
"flow": "flow",
"clear_jest": "jest --clearCache"
},
"dependencies": {
"axios": "0.16.2",
"prop-types": "^15.6.2",
"react": "16.5.0",
"react-native": "0.57.0",
"react-native-app-link": "0.3.0",
"react-native-appsflyer": "1.1.12",
"react-native-branch": "2.1.0",
"react-native-device-info": "0.11.0",
"react-native-fabric": "0.5.0",
"react-native-fabric-twitterkit": "0.2.0",
"react-native-fbsdk": "0.7.0",
"react-native-google-signin": "0.11.0",
"react-native-navbar": "2.1.0",
"react-native-rating-requestor": "github:yihanseattle/react-native-rating-requestor#ipsy_fork_rating_requestor",
"react-native-simple-store": "1.2.0",
"react-native-sms": "1.5.0",
"react-native-video": "2.0.0",
"react-native-wkwebview-reborn": "1.20.0",
"react-navigation": "1.0.0-beta.11",
"url-parse": "1.1.3"
},
"devDependencies": {
"#babel/core": "^7.1.2",
"#babel/generator": "^7.1.2",
"#babel/plugin-transform-exponentiation-operator": "^7.1.0",
"#babel/plugin-transform-object-assign": "^7.0.0",
"#babel/plugin-transform-react-jsx-source": "^7.0.0",
"#babel/plugin-transform-regenerator": "^7.0.0",
"#babel/plugin-transform-unicode-regex": "^7.0.0",
"#babel/preset-env": "^7.1.0",
"#babel/runtime": "^7.1.2",
"babel-jest": "^23.6.0",
"enzyme": "3.0.0",
"enzyme-adapter-react-16": "1.0.0",
"eslint": "3.19.0",
"eslint-config-rallycoding": "3.2.0",
"eslint-plugin-flowtype": "2.35.0",
"eslint-plugin-react": "6.10.3",
"eslint-plugin-react-native": "2.3.2",
"flow-bin": "0.79.1",
"invariant": "2.2.2",
"jest": "23.6.0",
"metro-react-native-babel-preset": "0.48.0",
"react-dom": "16.0.0-alpha.12",
"react-test-renderer": "16.5.0"
},
"jest": {
"preset": "react-native",
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
}
}
}
.babelrc:
{
"presets": ["module:metro-react-native-babel-preset"]
}
console.log(SendSMS, SendSMS.send) in the test file prints this:
{ send: [Function: send] } function send(options, callback) {var authorized;return regeneratorRuntime.async(function send$(_context) {while (1) {switch (_context.prev = _context.next) {case 0:if (!(
_reactNative.Platform.OS === 'android')) {_context.next = 9;break;}_context.prev = 1;_context.next = 4;return regeneratorRuntime.awrap(
_reactNative.PermissionsAndroid.request(_reactNative.PermissionsAndroid.PERMISSIONS.READ_SMS));case 4:authorized
Any idea why jest.mock does not actually mock the module?
This provides a solution:
const mock = (mockFn: any) => mockFn;
it('resolves with result sent', async () => {
mock(SendSMS.send).mockImplementation((opts, callback) => {
callback(true, false, false);
});
...
})
From here

SyntaxError: Unexpected token

I am trying to configure my application (https://github.com/freeCodeCamp/meeting-for-good) for testing. I am using jest. However, I get an error when I run my test. It looks like path to my AboutDialog component is failing to transpile.
zach#zach-VirtualBox:~/Documents/Code/fcc-for-good/meeting-for-good$ npm run test
> meeting-for-good#1.0.12 test /home/zach/Documents/Code/fcc-for-good/meeting-for-good
> cross-env NODE_ENV=test jest
FAIL __tests__/test.js
● Test suite failed to run
/home/zach/Documents/Code/fcc-for-good/meeting-for-good/client/components/AboutDialog/about-dialog.css:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.AboutDialog {
^
SyntaxError: Unexpected token .
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/ScriptTransformer.js:289:17)
at Object.<anonymous> (client/components/AboutDialog/AboutDialog.js:7:20)
at Object.<anonymous> (__tests__/test.js:2:20)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 8.204s
Ran all test suites.
I am trying to import my AboutDialog component to my test.
import React from 'react';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import cssModules from 'react-css-modules';
import PropTypes from 'prop-types';
import styles from './about-dialog.css';
const inlineStyles = {
modal: { content: { width: '630px', maxWidth: '630px' }, bodyStyle: { paddingTop: 10, fontSize: '25px' } },
};
const AboutDialog = (props) => {
const { cbOpenModal, openModal } = props;
const actions = [
<FlatButton label="close" primary onTouchTap={() => cbOpenModal()} />,
];
return (
<Dialog
contentStyle={inlineStyles.modal.content}
bodyStyle={inlineStyles.modal.bodyStyle}
actions={actions}
modal
styleName="AboutDialog"
open={openModal}
>
<h1 styleName="titleStyle">Meeting for Good</h1>
<h6 styleName="versionStyle">Version {process.env.versionNumber}</h6>
<h4 styleName="descStyle">THE BEST MEETING COORDINATION APP</h4>
<h6>Created by campers from FreeCodeCamp</h6>
<h6> License and GitHub Repository</h6>
</Dialog>
);
};
AboutDialog.propTypes = {
cbOpenModal: PropTypes.func.isRequired,
openModal: PropTypes.bool.isRequired,
};
export default cssModules(AboutDialog, styles);
My test. If I remove the AboutDialog import from my test , the test suite runs.
import React from 'react';
import AboutDialog from '../client/components/AboutDialog/AboutDialog';
import { shallow } from 'enzyme';
describe('Test', () => {
it('should test', () => {
});
});
My .babelrc file.
{
"presets": ["react", "es2015", "stage-1"],
"plugins": [
"transform-decorators-legacy",
"react-hot-loader/babel",
["transform-runtime", { "polyfill": false, "regenerator": true }]
],
"env": {
"development": {
"presets": [
"react-hmre"
]
}
}
}
My package.json
{
"name": "meeting-for-good",
"version": "1.0.12",
"description": "Schedule events with ease!",
"homepage": "https://github.com/FreeCodeCamp/meeting-for-good/#readme",
"main": "index.js",
"scripts": {
"clean": "rimraf build",
"build:server": "babel -d ./build ./server -s",
"build:client": "cross-env NODE_ENV=production babel-node ./tools/build.js",
"build": "npm run clean && npm run copy && npm run build:server && npm run build:client",
"start": " node ./build/app.js",
"copy": "node tools/copy.js",
"serve": "npm run clean && npm run copy && npm run build:server && npm run dev",
"dev": "cross-env NODE_ENV=development node -r dotenv/config ./build/app.js",
"test": "cross-env NODE_ENV=test jest",
"heroku-postbuild": "npm run build",
"postinstall": "node tools/postInstall.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/FreeCodeCamp/meeting-for-good"
},
"author": "Jean Philip de Rogatis <jrogatis#rogatis.eti.br>",
"contributors": [
{
"name": "Aniruddh Agarwal",
"email": "aaniruddh99#gmail.com"
},
{
"name": "Bob Sutton",
"email": "anischyros#gmail.com"
}
],
"license": "MIT",
"bugs": {
"url": "https://github.com/FreeCodeCamp/meeting-for-good/issues"
},
"engines": {
"node": "^8.0.0",
"npm": "^5.0.0"
},
"dependencies": {
"autobind-decorator": "^2.1.0",
"babel-cli": "^6.22.2",
"babel-core": "^6.22.1",
"babel-eslint": "^7.2.1",
"babel-loader": "^7.1.1",
"babel-plugin-react-transform": "^2.0.2",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.22.0",
"babel-preset-react-hmre": "^1.1.1",
"babel-preset-stage-1": "^6.22.0",
"babel-runtime": "^6.25.0",
"bluebird": "^3.5.0",
"body-parser": "^1.17.2",
"chai": "^4.1.0",
"chalk": "^2.0.1",
"chroma-js": "^1.3.3",
"chunk-manifest-webpack2-plugin": "^1.0.1",
"clipboard": "^1.6.1",
"compression": "^1.7.0",
"connect-flash": "^0.1.1",
"connect-mongo": "^1.3.2",
"cookie-parser": "^1.4.3",
"copy-webpack-plugin": "^4.0.1",
"cpy-cli": "^1.0.1",
"cross-env": "^5.0.1",
"css-loader": "^0.28.1",
"cssnano": "^3.10.0",
"dialog-polyfill": "^0.4.6",
"dotenv": "^4.0.0",
"ejs": "^2.5.5",
"email-templates": "^2.5.6",
"es6-promise": "^4.1.1",
"express": "^4.15.3",
"express-session": "^1.15.4",
"express-sessions": "^1.0.6",
"extract-text-webpack-plugin": "^2.1.0",
"fast-json-patch": "^2.0.4",
"favicons-webpack-plugin": "0.0.7",
"file-loader": "^0.11.1",
"google-calendar": "^1.3.2",
"html-loader": "^0.4.4",
"html-webpack-plugin": "^2.29.0",
"image-webpack-loader": "^3.3.1",
"immutable": "^3.8.1",
"isomorphic-fetch": "^2.2.1",
"jstimezonedetect": "^1.0.6",
"lodash": "^4.17.2",
"material-ui": "^0.18.5",
"mocha": "^3.4.2",
"moment": "^2.18.1",
"moment-range": "^3.0.3",
"mongoose": "^4.11.3",
"morgan": "^1.8.2",
"nodemailer": "^4.0.1",
"nodemailer-ses-transport": "^1.5.0",
"nprogress": "^0.2.0",
"offline-plugin": "^4.8.3",
"opbeat": "^4.14.2",
"optimize-css-assets-webpack-plugin": "^2.0.0",
"passport": "^0.3.2",
"passport-facebook": "^2.1.1",
"passport-google-oauth": "^1.0.0",
"passport-oauth2-refresh": "^1.0.0",
"pngquant-bin": "^3.1.1",
"prop-types": "^15.5.10",
"react": "^15.6.0",
"react-addons-update": "^15.5.2",
"react-css-modules": "^4.3.0",
"react-day-picker": "^5.5.1",
"react-dom": "^15.6.0",
"react-ga": "^2.2.0",
"react-hot-loader": "^3.0.0-beta.7",
"react-infinite": "^0.11.0",
"react-input-range": "^1.2.1",
"react-masonry-component": "^5.0.3",
"react-moment-proptypes": "^1.4.0",
"react-notification-system": "^0.2.14",
"react-router": "^3.0.2",
"react-tap-event-plugin": "^2.0.1",
"react-tooltip": "^3.3.0",
"react-transform-hmr": "^1.0.4",
"request": "^2.81.0",
"rimraf": "^2.6.1",
"shelljs": "^0.7.7",
"style-loader": "^0.18.1",
"url-loader": "^0.5.7",
"webpack": "^2.7.0",
"webpack-assets-manifest": "^0.7.0",
"webpack-bundle-analyzer": "^2.8.3",
"webpack-config": "^7.0.0",
"write-file-webpack-plugin": "^4.0.0",
"yargs": "^8.0.1"
},
"devDependencies": {
"babel-jest": "^20.0.3",
"babel-preset-jest": "^20.0.3",
"enzyme": "^2.9.1",
"eslint": "^3.19.0",
"eslint-config-airbnb": "^15.0.0",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.8.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-jsx-a11y": "^5.1.0",
"eslint-plugin-react": "^7.0.1",
"jest": "^20.0.4",
"jest-css-modules": "^1.1.0",
"react-dom": "^15.6.1",
"react-test-renderer": "^15.6.1",
"regenerator-runtime": "^0.10.5",
"webpack-dev-middleware": "^1.11.0",
"webpack-dev-server": "^2.5.1",
"webpack-hot-middleware": "^2.18.2"
},
"jest": {
"transform": {
".*": "<rootDir>/node_modules/babel-jest"
}
}
}
My webpack config for development.
const webpack = require('webpack');
const WriteFilePlugin = require('write-file-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OptimizeCSS = require('optimize-css-assets-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const WebpackAssetsManifest = require('webpack-assets-manifest');
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const cssNano = require('cssnano');
const packageJSON = require('./package.json');
const noVisualization = process.env.ANALYSE_PACK.toString() === 'false';
const lintCode = process.env.LINT_CODE.toString() === 'false';
const VENDOR_LIBS = [
'autobind-decorator',
'bluebird',
'clipboard',
'chroma-js',
'es6-promise',
'fast-json-patch',
'immutable',
'isomorphic-fetch',
'jstimezonedetect',
'lodash',
'material-ui',
'moment',
'moment-range',
'nprogress',
'react',
'react-addons-update',
'react-day-picker',
'react-tap-event-plugin',
'react-dom',
'react-css-modules',
'react-infinite',
'react-input-range',
'react-masonry-component',
'react-notification-system',
'react-router',
];
module.exports = {
context: __dirname,
entry: {
bundle: [
'react-hot-loader/patch',
'webpack-hot-middleware/client?reload=true',
'./client/main.js',
],
vendor: VENDOR_LIBS,
},
output: {
path: path.resolve('./build/client'),
publicPath: '/client/',
filename: '[name].[hash].js',
},
module: {
rules: [
(!lintCode ? {
test: /\.js$/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
emitWarning: true,
},
} : {}),
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(ttf|eot|woff(2)?)(\?[a-z0-9]+)?$/,
use: 'file-loader',
},
{
test: /\.(png|jp?g|gif|svg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1000,
},
},
{
loader: 'image-webpack-loader',
query: {
mozjpeg: {
progressive: true,
},
gifsicle: {
interlaced: false,
},
optipng: {
optimizationLevel: 4,
},
pngquant: {
quality: '75-90',
speed: 3,
},
},
},
],
},
{
test: /\.css$/,
exclude: [/node_modules/, /no-css-modules/],
use: [{
loader: 'style-loader?sourceMap',
},
{
loader: 'css-loader?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
},
],
},
{
test: /\.css$/,
include: [/node_modules/, /no-css-modules/],
use: ExtractTextPlugin.extract({
fallback: 'style-loader?sourceMap',
use: 'css-loader',
}),
},
],
},
plugins: [
(!noVisualization ?
new BundleAnalyzerPlugin({
analyzerMode: 'static',
}) : null),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.GOOGLE_ANALYTICS_ID': JSON.stringify(process.env.GOOGLE_ANALYTICS_ID),
'process.env.GOOGLE_ANALYTICS_DEBUG': JSON.stringify(process.env.GOOGLE_ANALYTICS_DEBUG),
'process.env.versionNumber': JSON.stringify(packageJSON.version),
}),
new ExtractTextPlugin('vendor.css'),
new OptimizeCSS({
assetNameRegExp: /\.optimize\.css$/g,
cssProcessor: cssNano,
cssProcessorOptions: {
discardComments: {
removeAll: true,
},
canPrint: true,
},
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.[hash].js',
minChunks: 'Infinity',
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new WriteFilePlugin({
test: /\.(html|ejs)$/,
}),
new FaviconsWebpackPlugin({
logo: './client/assets/favicons/logo.png',
icons: {
appleStartup: false,
},
background: 'transparent',
persistentCache: true,
inject: true,
}),
new HtmlWebpackPlugin({
title: 'Meeting for Good',
template: 'html-loader!./client/index.html',
filename: '../index.html',
inject: 'body',
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new WebpackAssetsManifest({
writeToDisk: true,
merge: true,
done(manifest) {
console.log(`The manifest has been written to ${manifest.getOutputPath()}`);
},
apply(manifest) {
manifest.set('manifest_version', '2');
manifest.set('start_url', '/?homescreen=1');
manifest.set('version', '1');
manifest.set('default_locale', 'en');
manifest.set('description', 'THE BEST MEETING COORDINATION APP');
manifest.set('display', 'fullscreen');
manifest.set('short_name', 'MeetingFG');
manifest.set('name', 'Meeting For Good');
manifest.set('background_color', '#FBFFFB');
manifest.set('theme_color', '#FBFFFB');
},
}),
].filter(p => p),
resolve: {
extensions: ['.js', '.css'],
},
devtool: 'source-map',
};
I figured it out. I just needed to use jest-css-modules (https://www.npmjs.com/package/jest-css-modules).
So I just have to add to make package.json
"jest": {
"transform": {
".*": "<rootDir>/node_modules/jest-css-modules"
}
}

Categories

Resources