assert true if method has been called using avajs - javascript

I am trying to create a unit test using react,ava, etc..I am having issue creating a simple unit test to check if a method was called. My test should pass if the method has been called. However when i check the code coverage I get a message saying "function not covered". Below is the code I am using to test it.
import test from 'ava';
import React from 'react';
import { Cart } from 'components/Cart/CartDisplay';
import { shallow } from 'enzyme';
let props;
test.beforeEach(() => {
props = {
popError: () => {},
message: '',
count: 2,
displayCart:() => {},
onClose:() => {}
};
});
test('renders okay?', (t) => {
shallow(
<Cart {...props} />
);
t.pass('yes');
});
test('Cart Displayed okay?', (t) => {
props.displayCart();
t.pass('yes');
});
What am I doing wrong?

After a couple of tries, I was able to figure it out:
import test from 'ava';
import React from 'react';
import { Cart } from 'components/Cart/CartDisplay';
import { shallow,mount } from 'enzyme';
import sinon from 'sinon';
import {expect} from 'chai';
let props;
test.beforeEach(() => {
props = {
popError: () => {},
message: '',
count: 2,
displayCart:() => {},
onClose:() => {}
};
});
test('Cart Display called?', t => {
sinon.spy(Cart.prototype, 'cartDisplay');
const wrapper = mount(<BannerMessage />);
expect(Cart.prototype.componentDidMount.calledOnce).to.equal(true);
})

Related

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());
});
});

React + Redux : Test failing with jest

I wonder why the test is failing when I use it with redux hooks:
The code is working finem but the tests are failing for some reason. I am unable to test if the component is being rendered or not.
Component:
import React, { useEffect, useState } from 'react';
import { fetchAllApis } from '../../../redux/actions/marketplace/marketplaceActions';
import { useDispatch, useSelector, connect } from 'react-redux';
import ApiCard from '../ApiCard/ApiCard';
import Spinner from '../../../components/Extras/Spinner/Spinner';
const ApiSection = ({ apiList, error, loading, categories }) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchAllApis({ page, category: categories }));
}, [dispatch, categories]);
const renderApiCards = () => {
return apiList.map((each) => (
<ApiCard key={each.apiId} info={each} data-test="ApiCard" />
));
};
if (loading) {
return <Spinner data-test="Spinner" />;
}
if (error) {
return <h1 data-test="Error">Error while fetching</h1>;
}
return (
<div className="ApiSection" data-test="ApiSection">
<div className="ApiSection__cards">{renderApiCards()}</div>
</div>
);
};
const mapStateToProps = ({ marketplaceApiState }) => {
const { apiList, error, loading } = marketplaceApiState;
return {
error,
loading,
apiList: Object.values(apiList),
};
};
export default connect(mapStateToProps)(ApiSection);
Here is the test for the above component:
Test:
import React from 'react';
import { mount } from 'enzyme';
import ApiListSection from './ApiListSection';
import { findByTestAttr, createTestStore } from '../../../../testUtils';
import { Provider } from 'react-redux';
const setup = (props = {}) => {
let initialState = {
marketPlaceState: {
apiList: {
a: { apiId: 'a', name: 'name', description: 'desc', categories: 'cat'}
},
},
};
const store = createTestStore(initialState);
const wrapper = mount(
<Provider store={store}>
<ApiListSection {...props} />
</Provider>
);
return wrapper;
};
describe('ApiListSection Component', () => {
let component;
beforeEach(() => {
component = setup();
});
// assertions
it('Should render without failing', () => {
const apiSection = findByTestAttr(component, 'ApiSection');
expect(apiSection.length).toBe(1); // <===== FAILING HERE !!!!!
});
});
I would really appreciate the help, thanks in advance

Mocking simple internal function using Jest for use in rendered React component

I have a simple React application with the following App.js, App.test.js, and utils.js files:
App.js
import React from 'react';
import { randomNameGenerator } from './utils.js';
import './App.css';
function App() {
return (
<div>
{randomNameGenerator()}
</div>
);
}
export default App;
App.test.js
import React from 'react';
import { render } from '#testing-library/react';
import '#testing-library/jest-dom/extend-expect'
import App from './App';
it('allows Jest method mocking', () => {
const { getByText } = render(<App />);
expect(getByText("Craig")).toBeInTheDocument()
});
utils.js
export function randomNameGenerator() {
return Math.floor((Math.random() * 2) + 1) == 1 ? 'Steve' : 'Bill';
}
This is a simple example, but what I'm trying to accomplish is a Jest mock of the randomNameGenerator() function to only return "Craig" for that specific Jest test.
I've followed a wide variety of tutorials/guides, but can't find anything that works - the closest (by "feel") that I've gotten was this (in App.test.js), which had no effect:
jest.doMock('./utils', () => {
const originalUtils = jest.requireActual('./utils');
return {
__esModule: true,
...originalUtils,
randomNameGenerator: jest.fn(() => {
console.log('## Returning mocked typing duration!');
return 'Craig';
}),
};
})
The way it fails is expected:
Unable to find an element with the text: Craig. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
<body>
<div>
<div>
Steve
</div>
</div>
</body>
6 | it('allows Jest method mocking', () => {
7 | const { getByText } = render(<App />);
> 8 | expect(getByText("Craig")).toBeInTheDocument()
| ^
9 | });
You can mock the module by calling jest.mock, and then import it, then inside your tests you call mockImplementation to setup the right return value.
import React from 'react';
import { render } from '#testing-library/react';
import '#testing-library/jest-dom/extend-expect'
import App from './App';
import { randomNameGenerator } from "./utils";
jest.mock('./utils.js', () => ({
randomNameGenerator: jest.fn()
}));
describe('test', () => {
it('allows Jest method mocking 1', () => {
randomNameGenerator.mockImplementation(() => "Craig");
const { getByText } = render(<App />);
expect(getByText("Craig")).toBeInTheDocument()
});
it('allows Jest method mocking 2', () => {
randomNameGenerator.mockImplementation(() => "Not Craig");
const { getByText } = render(<App />);
expect(getByText("Not Craig")).toBeInTheDocument()
});
});

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