Fix unit test Error using Jest in React JS - javascript

I'm creating a unit test on some code in React. But there is some action that didn't seem to work.
Let say I have a testing.js containing at the begenning:
const images = require.context('../../../media/promotions', true);
This is the unit test i'm trying ( testing.test.js ) :
import React from 'react';
import { shallow } from 'enzyme';
import { Testing } from '../../src/components/Testing';
let wrapper, instance;
beforeAll(() => {
wrapper = shallow(
<Testing />
);
instance = wrapper.instance();
});
describe('Testing', () => {
it('renders without crashing', () => {
expect(wrapper).toMatchSnapshot();
});
})
But the application crushes and this is the error that I get :
TypeError: require.context is not a function

The solution is to change the library:
import requireContext from 'require-context.macro';
And then require them this way:
const images = requireContext('../../../media/promotions', true);

Related

How to reset redux store after each test using #testing-library/react in Next.js?

I'm trying to get #testing-framework/react integrated into my Next.js workflow. To do that, I created a test-utils.js file as suggested in the documentation, where I re-export the render method with all my providers:
import React from 'react';
import { render } from '#testing-library/react';
import { ChakraProvider, ColorModeProvider } from '#chakra-ui/react';
import { Provider as ReduxStore } from 'react-redux';
import { useStore } from './lib/init-store';
import theme from './lib/theme';
const providersWrapper = ({ children }) => {
// As pageProps.initialReduxState is undefined in _app.js
const store = useStore(undefined);
return (
<ReduxStore store={store}>
<ChakraProvider resetCSS theme={theme}>
<ColorModeProvider
options={{
useSystemColorMode: true,
}}>
{children}
</ColorModeProvider>
</ChakraProvider>
</ReduxStore>
);
};
const customRender = (ui, options) =>
render(ui, { wrapper: providersWrapper, ...options });
// re-export everything
export * from '#testing-library/react';
// override render method
export { customRender as render };
On the other hand, I have a Counter component and its tests:
import React from 'react';
import { render, fireEvent, act, cleanup } from '../../test-utils';
import Counter from './index';
describe('Counter works properly', () => {
test('it should increment count when +1 button is clicked', async () => {
await act(async () => {
const { findByText } = render(<Counter />);
const initialCount = await findByText('0');
expect(initialCount).toBeInTheDocument();
const incrementButton = await findByText('+');
fireEvent.click(incrementButton);
const incrementedCount = await findByText('1');
expect(incrementedCount).toBeInTheDocument();
cleanup();
});
});
test('it should decrement count when -1 button is clicked', async () => {
await act(async () => {
const { findByText } = render(<Counter />);
const initialCount = await findByText('0');
expect(initialCount).toBeInTheDocument();
const decrementButton = await findByText('-');
fireEvent.click(decrementButton);
const decrementedCount = await findByText('-1');
expect(decrementedCount).toBeInTheDocument();
cleanup();
});
});
});
The jest setup works perfectly, but the second test, can't find a 0 text, because the state of the first test persists. I've confirmed this by swapping them resulting in the same: The first test passes, but the second fails.
This is weird, since the Testing Library documentation explicitly says that cleanup is called after each test automatically and by default (https://testing-library.com/docs/react-testing-library/setup/?fbclid=IwAR0CgDKrHalIhEUAEuP5S355uVYkTScMBATSIMgMPFcOz4ntsNCqgRA3Jyc#skipping-auto-cleanup).
So I'm a little bit lost here, I even tried to pull the celanup function out of render in both tests, and adding a cleanup() at the end of each test, having no different result.
Because of that, I thing that testing library is not the problem, instead, the redux store is not resetting after each test, causing the second test to read the state of the first. But I can't 100% prove it, and even if I could, I don't know how i'd reset it manually, since cleanup is supposed to happen automatically.
If you are curious, you can read the code of the whole project in this repo: https://github.com/AmetAlvirde/testing-library-redux-next-question/
I really hope you can help me, since being unable to test my code is something I really don't want to live with.
Thank you so much in advance.

Can we mock a function inside a node module component?

I have a checkbox component coming as a node module to my app,
CHECKBOX Component:
import React from 'react';
import uuidv4 from 'uuid/dist/v4';
export default ({inputProps}) => {
let id = uuidv4();
return (
<input
type="checkbox"
{...inputProps}
id={id}
/>
);
};
In my App.js, I'm using CheckBox Component
import React from 'react';
import Checkbox from '#checkbox'; // path from the node module
export default () => {
return (
<Checkbox
{...{
inputProps: {
checked: false,
onChange: () => {}
}
}}
/>
)
};
Test file:
import {mount} from 'enzyme';
describe('test App', () => {
it('should render the component', async () => {
const component = mount(<App />);
expect(component).toBeDefined();
expect(component.html()).toMatchSnapshot();
});
});
These are the sample components I've added
I don't want to mock the entire Checkbox component coz I want to test the checkbox behavior.
Is there any way that I can mock the uuid function in Checkbox component since it's generating a new UUID every single time I update the snapshot without any actual component changes.
I tried mocking the UUID function
jest.mock('uuid/dist/v4', () => {
return () => 'test id';
});
This mocks any of the usages in my app but not the function inside the Checkbox component or any other node module.
please ignore if any imports missed
I'm able to run the tests successfully but I want to find out a way to ignore the UUID generation in snapshots files.
You probably shouldn't import from package/dist/, try
import { v4: uuidv4 } from 'uuid';
and to mock, try using this:
jest.mock("uuid", () => {
return {
v4: () => 'test id'
}
});
See also a playground (it works): https://repl.it/#kiprasmel/jest-playground

How to snapshot test a component with nested component?

I'm testing a component with a nested component inside which use redux. I'm using shallow test for the component.
This is my test:
describe("Header", () =>
void it("renders correctly", () => {
const renderer = new ShallowRenderer()
const tree = renderer.render(<Header />)
expect(tree).toMatchSnapshot();
})
The snapshot output is:
exports[`Header renders correctly 1`] = `
<mockConstructor
render={[Function]}
/>
`;
Is this correct? Shouldn't a snapshot show my component?
Try using shallow from the enzyme package:
import { shallow } from 'enzyme';
import Header from './Header';
describe('Header', () => {
it('should render', () => {
const wrapper = shallow(<Header />);
expect(wrapper).toMatchSnapshot();
});
});
I changed my code as you say and the snapshot output for your snippet is:
exports[`Header renders correctly 1`] = `ShallowWrapper {}`;
Looking information about this output i found Jest/Enzyme ShallowWrapper is empty when creating Snapshot
Basically i have to use enzyme-to-json, so i changed my code to:
import { shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
...
describe("Header", () =>
void it("renders correctly", () => {
const tree = shallow(<Header />)
expect(toJson(tree)).toMatchSnapshot()
})
)
In the github site for enzyme-to-json there is a example that show as my test
import React, {Component} from 'react';
import {shallow} from 'enzyme';
import toJson from 'enzyme-to-json';
it('renders correctly', () => {
const wrapper = shallow(
<MyComponent className="my-component">
<strong>Hello World!</strong>
</MyComponent>
);
expect(toJson(wrapper)).toMatchSnapshot();
});
But the snapshot is:
exports[`Header renders correctly 1`] = `
<mockConstructor
render={[Function]}
/>
`;

Best practice to test propTypes with jest + enzyme + react-redux?

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

shallow rendering could not find component

hi everyone I am testing my react application using jest. While testing a component I found that a test breaks unexpectedly throwing error as
Method “props” is only meant to be run on a single node. 0 found instead.
test file
import React from 'react';
import {shallow} from 'enzyme';
import {AddLibraryItem} from '../../components/AddLibraryItem';
import libraryItems from '../fixtures/libraryItems';
let addLibraryItem, history, wrapper;
beforeEach(() => {
addLibraryItem = jest.fn();
history = {push: jest.fn()};
wrapper = shallow(<AddLibraryItem addLibraryItem={addLibraryItem} history={history}/>);
})
test('should execute on submit button successfully', () => {
console.log(wrapper);
wrapper.find('LibraryItemForm').prop('onSubmit')(libraryItems[0]);
expect(addLibraryItem).toHaveBeenLastCalledWith(libraryItems[0]);
expect(history.push).toHaveBeenLastCalledWith("/");
});
Component
import React from 'react';
import {connect} from 'react-redux';
import LibraryItemForm from './LibraryItemForm';
import {addLibraryItem} from '../actions/libraryA';
export class AddLibraryItem extends React.Component {
onSubmit = (libraryItem) => {
this.props.addLibraryItem(libraryItem);
this.props.history.push('/');
}
render () {
return (
<div>
<LibraryItemForm onSubmit={this.onSubmit} />
</div>
);
}
}
const mapDispatchToProps = (dispatch) => {
return {
addLibraryItem: (libraryItem) => dispatch(addLibraryItem(libraryItem))
}
}
const ConnectedAddLibraryItem = connect(undefined, mapDispatchToProps)(AddLibraryItem);
export default ConnectedAddLibraryItem;
The piece of test was earlier working very fine and test of 'LibraryItemForm' is also working fine and also rendering perfectly.
I am not getting what is wrong with it.
Is there any fix of it?
You probably forgot to dive():
wrapper.find(LibraryItemForm).dive().prop('onSubmit')(libraryItems[0]);
Enzyme documentation here.

Categories

Resources