I'm new to test driven development, I'm trying to implement my simple testing but jest always finds my dayjs as not a function. Also i'm not using typescrcipt so my problem would be similar to this.
I can't seem to find how to setup my jest environment to recognise it as not default export.
Here's my simple test with failed mocking?:
import React from "react";
import { shallow } from "enzyme";
import MainDashboardApp from "../MainDashboard";
jest.mock("dayjs", () => {
return () => jest.requireActual("dayjs")("2020-01-01T00:00:00.000Z");
});
describe("Inititate main dashboard", () => {
it("renders without crashing", () => {
┊ shallow(<MainDashboardApp />);
});
});
Error:
FAIL src/app/main/apps/dashboards/main/__tests__/dashboard.test.js
● Test suite failed to run
TypeError: dayjs is not a function
9 | import { tableData } from "../helpers";
10 |
> 11 | const defaultStart = dayjs().startOf("month").format("YYYY-MM-DD");
| ^
12 | const defaultEnd = dayjs().endOf("month").format("YYYY-MM-DD");
13 |
14 | function IncidentList({
at Object.<anonymous> (src/app/main/apps/operations/incidents/IncidentList.js:11:22)
at Object.<anonymous> (src/app/main/apps/index.js:1:1)
at Object.<anonymous> (src/app/main/apps/dashboards/main/MainDashboard.js:22:1)
at Object.<anonymous> (src/app/main/apps/dashboards/main/__tests__/dashboard.test.js:3:1)
Failed component (which actually renders in chrome):
import React, { useEffect, useCallback, useState } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import * as incidents from "app/store/ducks/incident.duck";
import MaterialTable, { MTableToolbar } from "material-table";
import { useHistory } from "react-router-dom";
import * as dayjs from "dayjs";
import { DatePicker } from "#material-ui/pickers";
import { tableData } from "../helpers";
const defaultStart = dayjs().startOf("month").format("YYYY-MM-DD");
const defaultEnd = dayjs().endOf("month").format("YYYY-MM-DD");
function IncidentList({
incidentsList,
requestIncidents,
selectedLoc,
startDate,
endDate,
}) {
const history = useHistory();
const [selectedEndDate, handleEndDateChange] = useState(defaultEnd);
const [selectedStartDate, handleStartDateChange] = useState(defaultStart);
// Deps are ok because history constantly updates, and this handleclick does not need
// to be updated as well
const handleClick = useCallback((event, rowData) => {
history.push({
pathname: `/operation/incident-details/${rowData.id}`,
state: { detail: "testing" },
});
}, []);
useEffect(() => {
if (startDate && endDate) {
handleEndDateChange(endDate);
handleStartDateChange(startDate);
}
}, [startDate, endDate]);
MockDate works great for this, no intense mocking code required.
https://www.npmjs.com/package/mockdate
import MockDate from 'mockdate'
import dayjs from 'dayjs'
MockDate.set('2020-01-01')
console.log(dayjs.format())
// >>> 2019-12-31T18:00:00-06:00
Remember to clear the mock after your test with:
MockDate.reset();
Also for your situation you probably want to use DayJS UTC to avoid unexpected date math results
https://day.js.org/docs/en/plugin/utc
Related
Learning JEST and unit testing in Javascript, but have errors when testing. There's an error
Invalid hook call. Hooks can only be called inside of the body of a
function component
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
I believe that the error comes when the use of renderInTestApp.
import * as React from 'react';
import { render, RenderResult, screen } from '#testing-library/react';
import ReactDom from 'react-dom'
import { EntityJiraOverviewCard, isJiraAvailable } from '#roadiehq/backstage-plugin-jira';
import { permissionApiRef } from '#backstage/plugin-permission-react';
import { overviewContent } from './EntityPage';
import { renderWithEffects } from '#backstage/test-utils';
import {
MockPermissionApi,
renderInTestApp,
TestApiProvider,
} from '#backstage/test-utils';
import {
EntityProvider,
starredEntitiesApiRef,
MockStarredEntitiesApi,
} from '#backstage/plugin-catalog-react';
import { EntityLayout } from '#backstage/plugin-catalog';
describe('Developer Portal Plugin', () => {
const jira = {
apiVersion: 'vi',
kind: 'Component',
metadata: {
name: 'TestPlugin',
annotations: {
'jira/project-key': 'DET',
},
},
spec:{
'type': 'service',
'lifecycle' : 'production',
'owner' : 'test',
},
};
const mockedApi = {
listWorkflowRuns: jest.fn().mockResolvedValue([]),
};
const mockPermissionApi = new MockPermissionApi();
describe('jiraContent', () => {
it('Should render Jira View', async () => {
const rendered = await renderInTestApp(
<TestApiProvider
apis={[
[isJiraAvailable, mockedApi],
[starredEntitiesApiRef, new MockStarredEntitiesApi()],
[permissionApiRef, mockPermissionApi],
]}
>
<EntityProvider entity={jira}>
<EntityLayout>
<EntityLayout.Route path="/" title="Overview">
{overviewContent}
</EntityLayout.Route>
</EntityLayout>
</EntityProvider>
</TestApiProvider>,
);
expect(rendered.getByText('TestPlugin')).toBeInTheDocument();
await expect(
rendered.findByText('Devops Engineering Team | software'),
).resolves.toBeInTheDocument();
expect(rendered.getByText('Activity stream')).toBeInTheDocument();
});
});
})
here is my code :
import * as React from 'react';
import { ReactReduxContext } from 'react-redux';
import { getDiagramId } from '#app/wireframes/model';
const HOC = () => {
const storeContext = React.useContext(ReactReduxContext);
const diagram = () => {
const selectedDiagramId = getDiagramId(storeContext.store.getState());
console.log(selectedDiagramId);
};
return (diagram);
};
export default HOC;
ERROR:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component
I get the same error no matter what I did, what could be the reason and solution?
I am working with pern stack and when I try using useEffect or useState, I am getting this error.
so, I used postgres to create database and used express to connect using pool
created a endpoint and tried fetching that in my code
import React, {useEffect , useState} from 'react';
import Table from './Table';
import Nav from './Navi';
import TemplateList from './TemplateList';
import {Tab,Tabs} from 'react-bootstrap';
class Dashboard extends React.Component{
const [tdata,setTdata] = React.useState([]);
info = async () => {
try {
const response = await fetch("http://localhost:8080/dashboard");
const dataServer = await response.json();
React.setTdata(dataServer);
} catch (err) {
console.error(err.message);
}
}
console.log(tdata);
React.useEffect(() => {
info();
}, []);
error
Failed to compile
./src/components/Dashboard.js
Line 7:9: Parsing error: Unexpected token
5 | import {Tab,Tabs} from 'react-bootstrap';
6 | class Dashboard extends React.Component{
> 7 | const [tdata,setTdata] = React.useState([]);
| ^
8 |
9 | info = async () => {
10 | try {
You can't use React hooks in a Class-Based component, change your class into a pure functional component like this:
import React, { useEffect, useState } from "react";
import Table from "./Table";
import Nav from "./Navi";
import TemplateList from "./TemplateList";
import { Tab, Tabs } from "react-bootstrap";
const Dashboard = (props) => {
const [tdata, setTdata] = useState([]);
const info = async () => {
try {
const response = await fetch("http://localhost:8080/dashboard");
const dataServer = await response.json();
setTdata(dataServer);
} catch (err) {
console.error(err.message);
}
};
console.log(tdata);
useEffect(() => {
info();
}, []);
return {
<div>
/* your JSX here */
</div>
};
};
More about hooks here: https://reactjs.org/docs/hooks-intro.html
Wondering if someone can point out what I expect is a stupid mistake.
I have an action for user login.
I'm trying to test this action, I've followed the redux documentation as well as the redux-mock-store documentation however I keep getting an error as follows:
TypeError: Cannot read property 'default' of undefined
4 | import thunkMiddleware from 'redux-thunk'
5 |
> 6 | const middlewares = [thunkMiddleware] // add your middlewares like `redux-thunk`
| ^
7 | const mockStore = configureStore(middlewares)
8 |
9 | describe("userActions", () => {
at Object.thunkMiddleware (actions/user.actions.spec.js:6:22)
My test code is as follows:
import {userActions} from "./user.actions";
import {userConstants} from "../constants/user.constants";
import configureStore from 'redux-mock-store'
import thunkMiddleware from 'redux-thunk'
const middlewares = [thunkMiddleware] // add your middlewares like `redux-thunk`
const mockStore = configureStore(middlewares)
describe("userActions", () => {
describe("login", () => {
it(`should dispatch a ${userConstants.LOGIN_REQUEST}`, () =>{
const store = mockStore({});
return store.dispatch(userActions.login("someuser", "somepassword")).then(() => {
expect(store.getState().loggingIn).toBeTruthy();
});
})
})
});
I've double checked both redux-thunk and redux-mock-store are included in my npm dev dependencies as well as deleteing the node_modules directory and reinstalling them all with npm install.
Can anyone see what's going wrong?
Thanks
EDIT:
It seems i'm doing something fundamentally wrong, I've tried to simplify it almost back to a clean slate to find where the problem is introduced.
Even with this test:
import authentication from "./authentication.reducer";
import { userConstants } from "../constants/user.constants";
describe("authentication reducer", () => {
it("is a passing test", () => {
authentication();
expect("").toEqual("");
});
});
Against this:
function authentication(){
return "test";
}
export default authentication
I'm getting an undefined error:
● authentication reducer › is a passing test
TypeError: Cannot read property 'default' of undefined
6 |
7 | it("is a passing test", () => {
> 8 | authentication();
| ^
9 | expect("").toEqual("");
10 | });
at Object.<anonymous> (reducers/authentication.reducer.spec.js:8:9)
yes, according to that error, seems you have a problem with module dependencies. Take a look at your webpack configuration.
Concerning the redux-mock-store, I suggest you to create a helper for future testing needs:
import configureStore from 'redux-mock-store'
import thunk from 'redux-thunk'
export default function(middlewares = [thunk], data = {}) {
const mockedStore = configureStore(middlewares)
return mockedStore(data)
}
and you will include it in your test cases and use like that:
beforeEach(() => {
store = getMockStore()
})
afterEach(() => {
store.clearActions()
})
If you wont test redux with thunk you can use redux-thunk-tester module for it.
Example:
import React from 'react';
import {createStore, applyMiddleware, combineReducers} from 'redux';
import {asyncThunkWithRequest, reducer} from './example';
import ReduxThunkTester from 'redux-thunk-tester';
import thunk from 'redux-thunk';
const createMockStore = () => {
const reduxThunkTester = new ReduxThunkTester();
const store = createStore(
combineReducers({exampleSimple: reducer}),
applyMiddleware(
reduxThunkTester.createReduxThunkHistoryMiddleware(),
thunk
),
);
return {reduxThunkTester, store};
};
describe('Simple example.', () => {
test('Success request.', async () => {
const {store, reduxThunkTester: {getActionHistoryAsync, getActionHistoryStringifyAsync}} = createMockStore();
store.dispatch(asyncThunkWithRequest());
const actionHistory = await getActionHistoryAsync(); // need to wait async thunk (all inner dispatch)
expect(actionHistory).toEqual([
{type: 'TOGGLE_LOADING', payload: true},
{type: 'SOME_BACKEND_REQUEST', payload: 'success response'},
{type: 'TOGGLE_LOADING', payload: false},
]);
expect(store.getState().exampleSimple).toEqual({
loading: false,
result: 'success response'
});
console.log(await getActionHistoryStringifyAsync({withColor: true}));
});
});
I have tried many solutions I found on google to test if Component.propTypes was set properly at a react component, but none of them worked for me. Even though I get a console warning when running my React application on the browser if the properties are passed incorrectly, when I run jest I can't capture that warning in any way that I tried. Here is my best attempt:
App.js:
export class App extends Component {
constructor(props) {
super(props);
}
render() {
return <div/>;
}
}
App.propTypes = {
images: PropTypes.array.isRequired
};
function mapStateToProps(state) {
const {images} = state;
return {images: images};
}
export default connect(mapStateToProps)(App);
App.test.js:
import React from 'react';
import chai from 'chai';
import chaiEnzyme from 'chai-enzyme';
import {shallow} from 'enzyme';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import sinon from 'sinon'
import {Provider} from 'react-redux';
import App from './App';
const expect = chai.use(chaiEnzyme()).expect
const mockStore = configureStore([thunk]);
const wrap = (initialState, props) => {
return shallow(<Provider store={mockStore(initialState)}><App {...props} /></Provider>)
};
describe('App container', () => {
it('validates properties', () => {
const stub = sinon.stub(console, 'warn');
console.warn.reset();
React.createElement(App, {});
expect(stub.calledOnce).to.equal(true);
expect(stub.calledWithMatch(/Failed prop type/)).to.equal(true);
console.warn.restore();
});
it('renders without crashing', () => {
wrap();
});
it('is react-redux connected', () => {
const wrapper = wrap();
expect(wrapper.find('Connect(App)')).to.have.length(1);
});
it('correctly maps properties', () => {
const wrapper = wrap({images: []});
expect(wrapper.props().images).to.equal([]);
});
});
According to what I've read online on various GitHub issue threads, it seems like a common approach is to make console.warn/console.error throw.
So when you are writing your tests you can do something like
expect(// Render Component //).to.throw();
Hope this helps.
More info: https://github.com/airbnb/enzyme/issues/588