React testing mock variable in functional component - javascript

Please help.
I cannot run test because in my util langProvider is package that drops tests.
I have to mock langProvider function or strings variable.
How I can do that?
import React, { ReactElement, useState } from 'react';
import langProvider from 'utils/langProvider';
import { HeaderStyled, DropDownStyled } from './styled';
import './style.scss';
function Header(props: any): ReactElement {
const [state, setState] = useState({
isDropDownOpened: false,
isDrawerOpened: false,
});
const strings = langProvider(props.language, 'components.header');
return (
<HeaderStyled className="header">
...
</HeaderStyled>
);
}
const mapStateToProps = (state: any) => ({
language: state.language,
});
export default connect(mapStateToProps)(Header);
My test file
import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import Header from './index';
configure({ adapter: new Adapter() });
describe('<Header />', () => {
const wrapper = shallow(<Header />);
it('My test', () => {
expect('').toEqual('Header');
});
});

not sure, but you can try to insert in your test file before describe function, something like that:
jest.mock("utils/langProvider", () => ({langProvider: ()=> []}));

Related

Testing React/Jest component with Window.onload

I'm testing a functional component that uses Window.onload to stay on a certain page. Example of the code
function SignUpForm(props) {
const history = useHistory();
const {setOnPage } = props;
window.onload = setOnPage("/registrarse")
My test is:
import React from 'react'
import Enzyme from "enzyme";
import { screen, render } from '#testing-library/react'
import SignInScreen from './SignInScreen'
import Adapter from "enzyme-adapter-react-16"
const { shallow } = Enzyme;
Enzyme.configure({ adapter: new Adapter() })
describe('Test for login in form', () => {
test("renders correctly", () => {
shallow(<SignInScreen/>);
});
});
The error is in the line of Window.onload, I have not been able to find any solution that can help me.
setOnPage is not a function

Cannot shallow render a component using IntlProvider

I have the following component, using Flow:
//#flow
import React, { type Node } from 'react';
import { useIntl } from 'react-intl';
type Props = { balance: Object };
const AvailableDiscount = ({ balance }: Props): Node => {
const { formatMessage, locale } = useIntl();
return (
<div>
{formatMessage({ id: 'XAM_DISCOUNT_DETAILS' })}: {balance.value}
</>
);
};
And while testing it, I seem to have a problem when trying it so mount it with shallow, using Enzyme:
// #flow
import { mount, shallow } from 'enzyme';
import React from 'react';
import { IntlProvider } from 'react-intl';
import balance from '../../../utils/testHelpers/testData/customerBalance';
import AvailableDiscount from './AvailableDiscount';
describe('AvailableDiscount', () => {
it('renders correctly', () => {
const component = <AvailableDiscount balance={balance} />;
const wrappingOptions = {
wrappingComponent: IntlProvider,
wrappingComponentProps: {
locale: 'en',
defaultLocale: 'en',
messages: {},
},
};
const mountedComponent = mount(component, wrappingOptions); // <-- This works
const shallowComponent = shallow(component, wrappingOptions); // <-- This does NOT work
});
});
It tells me that the component does not seem to be wrapped in the provider.
While this seems to work for mount, shallow keeps giving me this error. Why could this be?

How to mock useLocation correctly?

I have a component that uses useLocation hook to get the path from the URL.
const { pathname } = useLocation();
useEffect(() => { }, [pathname]);
While I am trying to mock the location using ,
import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '#testing-library/react';
import { shallow } from 'enzyme';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => ({
pathname: 'https://URL/'
})
}));
describe('<ExampleComponent />', () => {
it('should render correctly', () => {
shallow(<ExampleComponent />);
});
});
I am getting this error while I run the test,
TypeError: Cannot read property 'location' of undefined
Try mocking the useLocation as jest.fn().mockImplementation
jest.mock('react-router', () => ({
...jest.requireActual("react-router") as {},
useLocation: jest.fn().mockImplementation(() => {
return { pathname: "/testroute" };
})
}));
Below is how I have done this in my tests. * Note I am using typescript
import routeData from 'react-router';
describe('Login Page UnitTests', () => {
const useLocation = jest.spyOn(routeData, 'useLocation');
beforeEach(() => {
useLocation.mockReturnValue({ search: 'testQueryParameters'} as any);
});
// Add unit tests
}
Ensure that you clear the mock to avoid issue with data in subsequent tests
The correct way to mock useLocation is below:
import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '#testing-library/react';
import { MemoryRouter} from 'react-router-dom';
import { shallow } from 'enzyme';
const renderComponent = () => {
return (
<MemoryRouter
initialEntries={["/one", "/two", { pathname: 'https://URL/' }]}
initialIndex={1}>
<ExampleComponent />
</MemoryRouter>
);
}
describe('<ExampleComponent />', () => {
it('should render correctly', () => {
shallow(renderComponent());
});
});

"TypeError: dispatch is not a function" when using useReducer/useContext and React-Testing-Library

I'm having issues testing my components that use dispatch via useReducer with React-testing-library.
I created a less complex example to try to boil down what is going on and that is still having the same dispatch is not a function problem. When I run my tests, I am getting this error:
11 | data-testid="jared-test-button"
12 | onClick={() => {
> 13 | dispatch({ type: 'SWITCH' })
| ^
14 | }}
15 | >
16 | Click Me
Also, if I do a console.log(typeof dispatch) inside RandomButton, and I click on the button the output says function.
Here is the test in question.
import React from 'react'
import RandomButton from '../RandomButton'
import { render, fireEvent } from '#testing-library/react'
describe('Button Render', () => {
it('click button', () => {
const { getByTestId, queryByText } = render(<RandomButton />)
expect(getByTestId('jared-test-button')).toBeInTheDocument()
fireEvent.click(getByTestId('jared-test-button'))
expect(queryByText('My name is frog')).toBeInTheDocument()
})
})
Here is my relevant code:
RandomButton.js
import React, { useContext } from 'react'
import MyContext from 'contexts/MyContext'
const RandomButton = () => {
const { dispatch } = useContext(MyContext)
return (
<div>
<Button
data-testid="jared-test-button"
onClick={() => {
dispatch({ type: 'SWITCH' })
}}
>
Click Me
</Button>
</div>
)
}
export default RandomButton
MyApp.js
import React, { useReducer } from 'react'
import {myreducer} from './MyFunctions'
import MyContext from 'contexts/MyContext'
import RandomButton from './RandomButton'
const initialState = {
blue: false,
}
const [{ blue },dispatch] = useReducer(myreducer, initialState)
return (
<MyContext.Provider value={{ dispatch }}>
<div>
{blue && <div>My name is frog</div>}
<RandomButton />
</div>
</MyContext.Provider>
)
export default MyApp
MyFunctions.js
export const myreducer = (state, action) => {
switch (action.type) {
case 'SWITCH':
return { ...state, blue: !state.blue }
default:
return state
}
}
MyContext.js
import React from 'react'
const MyContext = React.createContext({})
export default MyContext
It is probably something stupid that I am missing, but after reading the docs and looking at other examples online I'm not seeing the solution.
I've not tested redux hooks with react-testing-library, but I do know you'll have to provide a wrapper to the render function that provides the Provider with dispatch function.
Here's an example I use to test components connected to a redux store:
testUtils.js
import React from 'react';
import { createStore } from 'redux';
import { render } from '#testing-library/react';
import { Provider } from 'react-redux';
import reducer from '../reducers';
// https://testing-library.com/docs/example-react-redux
export const renderWithRedux = (
ui,
{ initialState, store = createStore(reducer, initialState) } = {},
options,
) => ({
...render(<Provider store={store}>{ui}</Provider>, options),
store,
});
So, based upon what you've shared I think the wrapper you'd want would look something like this:
import React from 'react';
import MyContext from 'contexts/MyContext';
// export so you can test that it was called with specific arguments
export dispatchMock = jest.fn();
export ProviderWrapper = ({ children }) => (
// place your mock dispatch function in the provider
<MyContext.Provider value={{ dispatch: dispatchMock }}>
{children}
</MyContext.Provider>
);
and in your test:
import React from 'react';
import RandomButton from '../RandomButton';
import { render, fireEvent } from '#testing-library/react';
import { ProviderWrapper, dispatchMock } from './testUtils';
describe('Button Render', () => {
it('click button', () => {
const { getByTestId, queryByText } = render(
<RandomButton />,
{ wrapper: ProviderWrapper }, // Specify your wrapper here
);
expect(getByTestId('jared-test-button')).toBeInTheDocument();
fireEvent.click(getByTestId('jared-test-button'));
// expect(queryByText('My name is frog')).toBeInTheDocument(); // won't work since this text is part of the parent component
// If you wanted to test that the dispatch was called correctly
expect(dispatchMock).toHaveBeenCalledWith({ type: 'SWITCH' });
})
})
Like I said, I've not had to specifically test redux hooks but I believe this should get you to a good place.

Testing for a 'null' component return value in React with Jest and Enzyme

As the title states I'm trying to test for a null return value on a react component.
I have tried the solution here, but code coverage is saying we haven't properly tested for line 7: return null. What am I missing here?
Component:
import React from 'react';
import { func, bool } from 'prop-types';
import CloudyAlert from '../../assets/alert_cloud.svg';
const Alert = props => {
if (!props.show) {
return null;
}
return (
<div onClick={props.onDismiss} className="alert">
<img src={CloudyAlert} alt="alert to let you know time is up" />
<button>Ok</button>
</div>
);
};
Alert.propTypes = {
onDismiss: func.isRequired,
show: bool
};
export default Alert;
Test:
import React from 'react';
import Enzyme from 'enzyme';
import Alert from '../Alert';
import { mount, shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
describe('Alert', () => {
it('renders when show is true', () => {
let wrapper = mount(<Alert onDismiss={jest.fn()} show />);
it('renders correctly', () => {
expect(toJson(wrapper)).toMatchSnapshot();
});
it('shows alert when start is clicked and time is zero', () => {
expect(wrapper.find('Alert').props().show).toBe(true);
});
it('does not show alert when show is false', () => {
wrapper = shallow(<Alert show={false} />);
expect(wrapper.type()).toEqual(null);
});
});
});
Solved: the relevant test was nested in another 'it' block

Categories