React app Jest unit test failing with Microsoft application insights react plugin - javascript

I'm trying to use the Microsoft's Application Insights JavaScript SDK React Plugin in my React application, and although it's working successfully, I'm having trouble getting my Jest and Enzyme unit test to pass with it.
I've set up my unit test like the following:
import React from 'react';
import {act} from 'react-dom/test-utils';
import ReactDOM from 'react-dom';
import App from '../App.view';
jest.mock('#microsoft/applicationinsights-react-js', () => ({
ReactPlugin: Object,
}));
jest.mock('#microsoft/applicationinsights-web', () => ({
ApplicationInsights: Object,
loadAppInsights: () => ({}),
}));
describe('App View', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
act(() => {
ReactDOM.render(<App />, div);
});
ReactDOM.unmountComponentAtNode(div);
});
});
With my application insights service as:
import {ApplicationInsights} from '#microsoft/applicationinsights-web';
import {ReactPlugin, withAITracking} from '#microsoft/applicationinsights-react-js';
import {createBrowserHistory} from 'history';
// Set up AppInsights connection
const browserHistory = createBrowserHistory({basename: ''});
const reactPlugin = new ReactPlugin();
const ai = new ApplicationInsights({
config: {
instrumentationKey:
process.env.REACT_APP_APPINSIGHTS_KEY || 'xxxxxxxxxxx-xxxxxxxxxx-xxxxxxx-xxxxx',
extensions: [reactPlugin],
extensionConfig: {
[reactPlugin.identifier]: {history: browserHistory},
},
},
});
ai.loadAppInsights();
export default Component => withAITracking(reactPlugin, Component);
export const appInsights = ai.appInsights;
When I run my tests, I keep getting the error, TypeError: ai.loadAppInsights is not a function
Since I'm using jest mocking for the application insights modules, I've tried to mock this method as well in several ways, but with no luck. Any ideas on what I'm missing here? I'm also unable to find any good documentation on how to properly integrate application insights into a React application, which includes proper unit testing.
Thanks in advance!

Related

Jest : TypeError : Cannod read property 'fn' of undefined

I have a header component which has to be tested using jest. The header component takes in three props setIsDark(function), setMode(function), isDark(boolean). I thought of writing a simple test but it gives me this error : Cannot read property 'fn' of undefined.
This is my test file tests/header.js
import React from "react";
import { render } from "#testing-library/react";
import Header from "../header";
import jest from "jest-mock";
test("temp", () => {
expect(true).toBe(true);
});
test("header renders some text", () => {
const setIsDark = jest.fn();
const setMode = jest.fn();
const isDark = true;
const { debug } = render(
<Header setMode={setMode} isDark={isDark} setIsDark={setIsDark} />,
);
debug();
});
Edit : Without using jest mock im getting TypeError: instace.getTotalLength is not a function
Can somebody point out what am i doing wrong here. Thanks in advance.
Well you're importing the jest-mock library instead of jest.
If you have jest installed correctly in your project you don't have to import it inside your test so if you remove
import jest from "jest-mock"; you can use jest.fn() without any errors.

How to ignore generated Relay query files in Jest tests using create-react-app?

I created a React app using create-react-app and added Relay. I want to test my components with Jest, but the Relay compiler generates files that Jest reads as test files. I can't ignore the files because I'm using create-react-app.
For example a test might look like:
// src/components/MyComponent/__tests__/MyComponent.test.js
import React from 'react';
import graphql from 'babel-plugin-relay/macro';
import { QueryRenderer } from 'react-relay';
import renderer from 'react-test-renderer';
import { MockPayloadGenerator, createMockEnvironment } from 'relay-test-utils';
import MyComponent from '../MyComponent';
const query = graphql`
query MyComponentQuery #relay_test_operation {
myComponent: node(id: "test-id") {
...MyComponent_myComponent
}
}
`;
const rootRender = ({ props }) => <MyComponent myComponent={props.myComponent} />;
it('renders without crashing', () => {
const environment = createMockEnvironment();
const component = renderer.create(
<QueryRenderer
environment={environment}
query={query}
variables={{}}
render={rootRender}
/>
);
environment.mock.resolveMostRecentOperation((operation) =>
MockPayloadGenerator.generate(operation));
expect(component.toJSON()).toMatchSnapshot();
});
relay-compiler will generate a file src/components/MyComponent/__tests__/__generated__/MyComponentQuery.graphql.js for the query.
When running the tests, I get:
FAIL src/components/MyComponent/__tests__/__generated__/MyComponentQuery.graphql.js
● Test suite failed to run
Your test suite must contain at least one test.
How do I get Jest to ignore the generated query files? Is there a way to do this without ejecting from create-react-app?
Try to add this to your package.json
...,
"jest": {
"testPathIgnorePatterns": [
".graphql.js"
]
},
...

Redux Container Unit Testing - Unable to access props for wrapped component

Following the React v6 upgrade, my existing test cases for the component are failing.
Here is my component container code TodoContainer.jsx:
import { connect } from 'react-redux';
import Todo from './Todo';
import { initialLoadExecuted } from '../../actions/LoadActions';
const mapStateToProps = state => ({
isCollapsed: true,
pinnedTiles: false,
});
const mapDispatchToProps = dispatch => ({
dispatchInitialLoadExecuted: (tiles) => {
dispatch(initialLoadExecuted(tiles));
},
});
export default connect(mapStateToProps, mapDispatchToProps)(Todo);
Here is my test code TodoContainer.test.jsx:
import React from 'react';
import configureStore from 'redux-mock-store';
import {Provider} from 'react-redux';
import TodoContainer from '../../../../src/todo-component/components/Todo/TodoContainer';
import { initialLoadExecuted } from '../../../../src/todo-component/actions/LoadActions';
const mockStore = configureStore();
let store;
describe('Todo Container', () => {
beforeEach(() => {
store = mockStore({
});
it('maps state props correctly', () => {
const wrapper = shallow(<TodoContainer store={store}/>);
wrapper.prop('dispatchInitialLoadExecuted')('Test String);
// Expect statements
});
});
The error i am getting is :
Invariant Violation: Passing redux store in props has been removed and does not do anything. To use a custom Redux store for specific components, create a custom React context with React.createContext(), and pass the context object to React-Redux's Provider and specific components like: . You may also pass a {context : MyContext} option to connect.
Is there a way to to pass store through provider while accessing the props, the same way?
It appears that react-redux v6.0.0 now supports the new Context API added to React v 16.4.0 (and also requires that verson of react now).
I was able to resolve the issue and keep the mockStore pattern by installing react-redux#5.1.1 and react#16.3.0 (before they introduced the Context API).
Further testing: I can use react#16.7.0 as long as I use react-redux#5.1.1
There's an ongoing discussion on the react-redux github issues tab: https://github.com/reduxjs/react-redux/issues/1161
Not a long term solution as I'd be stuck at this version of React, but it does pass the test and I was able to get my 100% code coverage.

Vue-test-utils wrapper undefined

I have the following test suite in Jest for a component. I have successfully written unit tests for several other components that follow a similar structure:
import { createLocalVue, mount } from '#vue/test-utils'
import Vuex from 'vuex'
import storeMock from '#mocks/store'
import RequestProposalsContainer from '#/components/RequestProposals/RequestProposalsContainer'
describe('ProviderComparison component', () => {
let localVue, store, wrapper, storeSetup
beforeEach(() => {
localVue = createLocalVue()
localVue.use(Vuex)
storeSetup = storeMock()
store = new Vuex.Store(storeSetup)
/* wrapper is undefined and I'm not sure why */
wrapper = mount(RequestProposalsContainer, {
localVue,
store
})
})
it('renders correct structure', () => {
/* undefined */
console.log('wrapper: ', wrapper)
})
})
By inspection, the component being mounted, the store, and localVue instance are well-defined.
I was in a similar situation where the wrapper would come back undefined.
While testing, you have to give the component everything it needs to render.
It was (as #Adam Freymiller has already alluded to) that all the required values (props, store values, etc) were not set in the test, so the component would error out, much like how it would in a real life scenario.

Unable to set context when rendering child components

I'm trying to test a custom Material-ui React component with Enzyme but getting the following error:
ERROR: 'Warning: Failed context type: Required context 'muiTheme' was not specified in 'ChildComponent'.
What I've tried is to set a context according to this. The component that I want to reach and test is a child component.
const root = shallow(<RootComponent />, {context: {muiTheme}, childContextTypes: {muiTheme: React.PropTypes.object}})
const child = root.find(ChildComponent)
child.render() // <--- this line is throwing the error
update: this is related
I'm not sure this is the solution but it's one step closer to the goal.
const root = mount(<RootComponent />, {
context: {muiTheme},
childContextTypes: {muiTheme: React.PropTypes.object}
})
const child = root.find(ChildComponent)
Notice, I use mount instead of shallow. The issue is with this I can't use child.find({prop: 'value'}) any longer - return 0 items...
You need to provide the <muiThemeProvider> component.
Here is an example on how to do :
import React from 'react';
import { mount } from 'enzyme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Input from './Input';
describe('<Input />', () => {
const mountWithTheme = (node) => mount(<MuiThemeProvider>{node}</MuiThemeProvider>);
it('calls componentDidMount', () => {
sinon.spy(Input.prototype, 'componentDidMount');
mountWithTheme(<Input />);
expect(Input.prototype.componentDidMount.calledOnce).to.equal(true);
});
});

Categories