Running the following test for closeDock. The test is passing at the moment but when I check its coverage, it does not change. using Jest and enzyme
closeDock = () => {
this.setState({ isVisible: false, tableMargin: 0 })
}
Any reason ?
Test:
beforeEach(() => wrapper = mount(<MemoryRouter keyLength={0}><HomeTab {...baseProps} /></MemoryRouter>));
it ('Test closeDock method ',() => {
wrapper.find('HomeTab').setState({
isVisible: false,
tableMargin: 0,
});
wrapper.update();
expect(wrapper.instance().closeDock).toEqual()
expect(wrapper.find('HomeTab').state('isVisible')).toBeFalsy();
expect(wrapper.find('HomeTab').state('tableMargin')).toEqual(0);
});
part of my package json related to coverage
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx}"
],
],
"setupFiles": [
"<rootDir>/config/polyfills.js"
],
"testMatch": [
"<rootDir>/src/**/__tests__/**/*.js?(x)",
"<rootDir>/src/**/?(*.)(spec|test).js?(x)"
],
Related
src/services/backend.ts:
export const login = ({ metadataKey }) =>
axiosInstance
.get(`${API.DEFAULT_BROKER}${API.V1_LOGIN_PATH}/${metadataKey}`)
.then(({ data }: any) => data);
export default {
...
login
};
I have a file that imports backend.ts and uses the login function. When I import it using import { login } from "../../services/backend";, it works:
import { login } from "../../services/backend";
...
login({
metadataKey
})
Passing test:
PASS src/redux/epics/authentication-epic.test.ts
✓ authenticationEpic loginEpic (9ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.607s, estimated 2s
Ran all test suites matching /src\/redux\/epics\/authentication-epic.test.ts/i.
However, when I import it using the default export, it is always undefined:
import backend from "../../services/backend";
...
backend.login({
metadataKey
})
Failing test:
FAIL src/redux/epics/authentication-epic.test.ts
✕ authenticationEpic loginEpic (37ms)
● authenticationEpic loginEpic
TypeError: Cannot read property 'login' of undefined
22 |
23 | return from(
> 24 | backend.login({
| ^
25 | metadataKey
26 | })
27 | ).pipe(
I noticed the same issue even with 3rd party libraries. For example, I'm using node-forge, but it was breaking unless I changed
import forge from "node-forge";
to:
import { md } from "node-forge";
Am I missing a setting somewhere? This is the jest section of my package.json:
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,mjs}"
],
"setupFiles": [
"<rootDir>/config/polyfills.js"
],
"testMatch": [
"<rootDir>/src/**/*.{js,jsx,mjs,ts}",
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs,ts}"
],
"globals": {
"window": true
},
"testEnvironment": "jsdom",
"testURL": "http://localhost",
"transform": {
"^.+\\.jsx?$": "<rootDir>/node_modules/babel-jest",
"^.+\\.tsx?$": "ts-jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"
],
"moduleNameMapper": {
"^react-native$": "react-native-web"
},
"moduleFileExtensions": [
"web.js",
"js",
"json",
"web.jsx",
"jsx",
"node",
"mjs",
"ts",
"tsx"
]
}
I am replacing karma with jest and when I created all needed files and settings which you can see below. When I executed npm jest got an 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 found a solution with editing node_modules/* files that don't make sense.
When I tried to switch testEnvironment to 'node' it's looked ok but I think that's not a good solution when it isn't node service project.
/jest.config.js
module.exports = {
coverageReporters: [
"html",
"text",
"cobertura"
],
globals: {
"ts-jest": {
tsConfig: "tsconfig.test.json",
babelConfig: true
}
},
moduleFileExtensions: [
"ts",
"tsx",
"js",
"jsx",
"json",
"node",
"d.ts",
"scss"
],
moduleNameMapper: {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test/mocks/fileMock.js",
"\\.(css|sass|scss)$": "<rootDir>/test/mocks/styleMock.js",
"^worker-loader!": "<rootDir>/test/mocks/workerLoaderMock.js",
"^resize-observer-polyfill$": "<rootDir>/test/mocks/resizeObserverPolyfillMock.js",
"applicationinsights-js": "<rootDir>/test/mocks/appInsightsMock.js"
},
reporters: [
"default",
"jest-junit"
],
setupFiles: [
"<rootDir>/test/mocks/setupJest.js"
],
setupFilesAfterEnv: [
"<rootDir>/test/mocks/matchMedia.js"
],
transform: {
"^.+\\.(js|jsx|ts|tsx|d.ts)$": "ts-jest"
},
testMatch: [
"<rootDir>/test/**/*-test.tsx"
],
timers: "fake"
};
/setupJest.js
global.Intl = require("intl");
global.fetch = require('jest-fetch-mock')
global.AppSettings = {
AUTHORITY_URL: "https://auth.blah.com",
INSTRUMENTATION_KEY: "APP_SETTINGS_KEY",
REALTIME_URL_BASE: "https//:realtime.blah.com"
};
my-test.js
import { Tooltip } from "../../src/components/shared";
import { expect, React, shallow } from "../test-utils";
describe("Tooltip with empty properties", () => {
const component = shallow(<Tooltip tooltipText="" />);
it("should have no text", () => {
expect(component.find("span.tooltip-text").text()).to.have.length(0);
});
it("should have 'tooltip-container' class", () => {
expect(component.hasClass("tooltip-container")).to.be.true;
});
it("should have child with 'tooltip-text' class", () => {
expect(component.childAt(0).hasClass("tooltip-text")).to.be.true;
});
});
describe("Tooltip with set properties", () => {
const expectedClass = "test-class";
const expectedText = "Test tooltip text";
const component = shallow(<Tooltip tooltipText={expectedText} className={expectedClass} />);
it("should have the expected text", () => {
expect(component.find("span.tooltip-text").text()).to.be.equal(expectedText);
});
it("should have the expected classes", () => {
expect(component.hasClass("tooltip-container")).to.be.true;
expect(component.hasClass(expectedClass)).to.be.true;
});
});
I am using JEST and Enzyme. In my eslint file I have added jest as true under env. But I get a lint error for shallow as I have included it globally. Error is- error 'shallow' is not defined no-undef
setupTests.js
//as we are accessing our application with a http://localhost prefix, we need to update our jest configuration
import { shallow, render, mount, configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
// React 16 Enzyme adapter
configure({ adapter: new Adapter() });
// Make Enzyme functions available in all test files without importing
global.shallow = shallow;
global.render = render;
global.mount = mount;
.eslintrc
{
parser: "babel-eslint",
"extends": ["airbnb"],
"env": {
"browser": true,
"jest": true
},
"rules": {
"max-len": [1, 200, 2, {ignoreComments: true}],
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"no-underscore-dangle": [0, { "allow": [] }],
"jsx-a11y/label-has-associated-control": [
"error", {
"required": {
"every": [ "id" ]
}
}
],
"jsx-a11y/label-has-for": [
"error", {
"required": {
"every": [ "id" ]
}
}
]
}
}
app.test.js
import React from 'react';
import { LoginFormComponent } from '../../components';
describe('LoginForm', () => {
const loginform = shallow(<LoginFormComponent />);
it('renders correctly', () => {
expect(loginform).toMatchSnapshot();
});
});
package.json
"scripts": {
"dev": "webpack-dev-server --historyApiFallback true --port 8888 --content-base build/",
"test": "jest",
"lint": "eslint ./src",
"lintfix": "eslint ./src --fix"
},
"jest": {
"verbose": true,
"testURL": "http://localhost/",
"transform": {
"^.+\\.js$": "babel-jest"
},
"setupFiles": [
"./setupTests.js"
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
},
The error comes in my app.test.js where I am trying to use shallow. Do I have to add something in my eslint config for enzyme the way I have made jest as true?
How about add global statement? eslint no-undef docs
/*global someFunction b:true*/
/*eslint no-undef: "error"*/
var a = someFunction();
b = 10;
or set global on .eslintrc (eslint global)
{
"globals": {
"shallow": true,
"render": true,
"mount": true
}
}
Updated .eslintrc
{
parser: "babel-eslint",
"extends": ["airbnb"],
"env": {
"browser": true,
"jest": true
},
"globals": {
"shallow": true
},
"rules": {
"max-len": [1, 200, 2, {ignoreComments: true}],
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"no-underscore-dangle": [0, { "allow": [] }],
"jsx-a11y/label-has-associated-control": [
"error", {
"required": {
"every": [ "id" ]
}
}
],
"jsx-a11y/label-has-for": [
"error", {
"required": {
"every": [ "id" ]
}
}
]
}
}
Since globals are only used in test files the best practise is not to set them globally but only for the test files. That can be done by using overrides property with proper files glob:
overrides: [
{
files: "*.test.js",
globals: {
shallow: true,
render: true,
mount: true,
},
},
],
Full .eslintrc after addition in the snippet.
{
"parser": "babel-eslint",
"extends": ["airbnb"],
"env": {
"browser": true,
"jest": true
},
"rules": {
"max-len": [1, 200, 2, { "ignoreComments": true }],
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"no-underscore-dangle": [0, { "allow": [] }],
"jsx-a11y/label-has-associated-control": [
"error",
{
"required": {
"every": ["id"]
}
}
],
"jsx-a11y/label-has-for": [
"error",
{
"required": {
"every": ["id"]
}
}
]
},
"overrides": [
{
"files": "*.test.js",
"globals": {
"shallow": true,
"render": true,
"mount": true
}
}
]
}
I am testing React, Redux App with Jest.
Jest test works well with a simple function test.
but an action creator test is failing throwing the error message below. It is working creator code. Dispatching this action creator in a component updates the state.
TypeError: (0 , _reserve.saveReserveInfo) is not a function
5 | const id = 'date';
6 | const value = '2018-09-30';
> 7 | const action = saveReserveInfo(id, value);
| ^
8 | expect(action).toEqual({
9 | type: types.SAVE_RESERVE_INFO,
10 | id: 'date',
actionTypes.js
module.exports = {
SAVE_RESERVE_INFO: 'SAVE_RESERVE_INFO',
OPEN_RESERVE: 'OPEN_RESERVE',
};
reserve.action.js
import * as types from '../actionTypes';
export const saveReserveInfo = (id, value) => {
return {
type: types.SAVE_RESERVE_INFO,
id,
value,
};
};
export const openReserve = () => ({
type: types.OPEN_RESERVE,
});
reserve.test.js
import * as types from '../../components/actionTypes';
import { saveReserveInfo } from '../../components/reserve/reserve.action';
test('should create an action to update reserve info', () => {
const id = 'date';
const value = '2018-09-30';
const action = saveReserveInfo(id, value);
expect(action).toEqual({
type: types.SAVE_RESERVE_INFO,
id: 'date',
value: '2018-09-30',
});
});
client/jest.config.js
module.exports = {
displayName: 'client',
setupTestFrameworkScriptFile: require.resolve(
'../test/setup-test-framework.js',
),
modulePaths: ['<rootDir>/src'],
moduleNameMapper: {
'\\.scss||css$': require.resolve('../test/style-mock.js'),
'\\.svg$': require.resolve('../test/svg-file-mock.js')
},
};
jest.config.js
module.exports = {
testMatch: ['**/__test__/**'],
testPathIgnorePatterns: ['/node_modules/'],
coverageDirectory: './coverage',
collectCoverageFrom: [
'**/src/**/*.js',
'!**/__test__/**',
'!**/node_modules/**',
],
coverageThreshold: {
global: {
statements: 18,
branches: 10,
functions: 19,
lines: 18,
},
},
projects: ['./client', './server'],
};
babelrc.js
const isTest = String(process.env.NODE_ENV) === 'test';
module.exports = {
presets: [
[
'env',
{
targets: {
browsers: ['last 2 versions', 'safari >= 7'],
node: 'current',
},
loose: true,
modules: isTest ? 'commonjs' : false,
debug: isTest ? false : true,
},
],
'react',
],
retainLines: true,
plugins: [
[
'transform-runtime',
{
helpers: false,
polyfill: false,
regenerator: true,
moduleName: 'babel-runtime',
},
],
'transform-class-properties',
'transform-object-rest-spread',
'syntax-dynamic-import',
isTest ? 'dynamic-import-node' : null,
].filter(Boolean),
env: {
development: {
plugins: ['react-hot-loader/babel'],
},
},
};
version
jest: 23.5.0,
jest-dom: 1.12.0,
react: 16.4.2,
react-dom: 16.4.2,
react-redux: 5.0.7,
redux: 4.0.0,
Here is the project zip file.
Thank you !!
To answer my question,
here is my working jest config file.
jest.config.js
module.exports = {
testMatch: ['**/__test__/**'],
testPathIgnorePatterns: ['/node_modules/'],
coverageDirectory: './coverage',
collectCoverageFrom: [
'**/src/**/*.js',
'!**/__test__/**',
'!**/node_modules/**',
],
projects: ['./client', './server'],
};
I deleted coverageThreshold.
Testing was failing as there was less than specified threshold.
Jest coverageThreshold
I'm making some test to redux with jest but I got sucked because Auth module appears as undefined.
import { auth as Auth } from 'Services/firebase'
export const signIn = (email, password) => {
console.log(Auth) // It get's undefined
return dispatch => {
dispatch(signInInit())
Auth.signIn(email, password, (user) => {
dispatch(push('/'))
return dispatch(signInSuccess(user))
}, (error) => {
return dispatch(signInError(error))
})
}
}
This is the jest configuration:
"jest": {
"collectCoverage": true,
"coverageDirectory": "<rootDir>/coverage",
"verbose": true,
"coveragePathIgnorePatterns": [
"<rootDir>/node_modules"
],
"modulePaths": [
"<rootDir>/src"
],
"moduleFileExtensions": [
"js"
],
"moduleDirectories": [
"node_modules",
"src"
],
"modulePathIgnorePatterns": [
"<rootDir>/public"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|svg|ttf|woff|woff2)$": "<rootDir>/src/components/__mocks__/fileTransformer.js",
"^Components(.*)$": "<rootDir>/src/components",
"^Data(.*)$": "<rootDir>/src/data",
"^Hocs(.*)$": "<rootDir>/src/hocs",
"^Scenes(.*)$": "<rootDir>/src/scenes",
"^Services(.*)$": "<rootDir>/src/services",
"^Styles(.*)$": "<rootDir>/src/styles"
}
Really can't understand why this is happening, well any clue will be very welcome.