My Code:
printOrder() {
setTimeout(() => {
window.print();
}, 0);
}
render() {
const { orderDetails, messageTexts, preferences, isLoading, imagePath, featureFlags } = this.props;
const error = get(orderDetails, 'errorCode', '');
return (
<Layout disableWhiteBG><span className={cx('printOrder')}><button className={cx('printOrders')} onClick={e => this.printOrder(e)}><Icon iconType="svg" width="45px" height="45px" viewBox="0 0 45 45" name="print" /></button></span>}
</span>
</Layout>);
}
My test cases
const printOrder = sinon.spy();
const TokenProvider = {
get: TokenProviderGetStub,
logout: TokenProviderLogoutStub,
};
const Cookie = {
load: CookieLoadStub,
};
const Constants = {
...constants,
classic_yoda_combination: true,
};
const User = {
isUserLoggedIn: isUserLoggedInStub,
};
const OrderDetailsScreen = proxyquireStrict('./OrderDetails.jsx', {
'yoda-site-components/lib/helpers/TokenProvider/TokenProvider': TokenProvider,
'yoda-core-components/lib/helpers/Cookies/Cookies': Cookie,
'yoda-site-components/lib/helpers/User/User': User,
'yoda-site-components/lib/components/Layout/Layout': reactStubWithChild('Layout'),
'../../../components/OrderDetails/OrderDetails': reactStubWithChild('OrderDetails'),
'../../../common/redirect': redirectStub,
'../../../common/constant': Constants,
'react-router': {
browserHistory: {
push: pushStub,
},
},
});
describe('Test cases for print Order', () => {
describe('printOrders in DesktopScreen', () => {
before(() => {
wrapper = shallow(
<OrderDetailsScreen {...props} />,
);
wrapper.find('.printOrders').simulate('click');
});
after(() => {
wrapper.unmount();
printOrder.reset();
});
it('Should call the printOrder button', () => {
expect(printOrder.calledOnce).to.be.true;
});
});
describe('printOrders in MobileScreen', () => {
before(() => {
wrapper = shallow(
<OrderDetailsScreen {...props} deviceType={{ isDesktop: false, isMobile: true }} />,
);
wrapper.find('.printOrders').simulate('click');
});
after(() => {
wrapper.unmount();
printOrder.reset();
});
it('Should call the printOrder button', () => {
expect(printOrder.calledOnce).to.be.true;
});
});
});
My question is how do I spy window.print with sinon?
Related
I have this function inside a helper:
export const useDAMProductImages = (imageId: string) => {
const {
app: { baseImgDomain },
} = getConfig();
const response: MutableRefObject<string[]> = useRef([]);
useEffect(() => {
const getProductImages = async (imageId: string) => {
try {
const url = new URL(FETCH_URL);
const res = await fetchJsonp(url.href, {
jsonpCallbackFunction: 'callback',
});
const jsonData = await res.json();
response.current = jsonData;
} catch (error) {
response.current = ['error'];
}
};
if (imageId) {
getProductImages(imageId);
}
}, [imageId]);
return response.current;
};
In test file:
import .....
jest.mock('fetch-jsonp', () =>
jest.fn().mockImplementation(() =>
Promise.resolve({
status: 200,
json: () => Promise.resolve({ set: { a: 'b' } }),
}),
),
);
describe('useDAMProductImages', () => {
beforeEach(() => {
jest.clearAllMocks();
cleanup();
});
it('should return empty array', async () => {
const { result: hook } = renderHook(() => useDAMProductImages('a'), {});
expect(hook.current).toMatchObject({ set: { a: 'b' } });
});
});
The problem is that hook.current is an empty array. Seems that useEffect is never called. Can someone explain to me what I'm doing wrong and how I should write the test? Thank you in advance
I am writing tests for my component using react testing library and I am using nested describe blocks for separating tests
const dummyData1 = Array.from({ length: 10 }).map((obj, i) => ({title: "Test" + i,
value: "Test" + i,
key: "Test" + i,
}));
describe("Custom Select", () => {
describe("Single", () => {
afterAll(() => {
cleanup();
});
const loadMore = jest.fn();
const onChange = jest.fn();
loadMore.mockResolvedValueOnce(dummyData2);
const { queryByTestId, getByText, getAllByText, container } = render(
<MultiSelect
data={[{ title: "Test", key: "Test", value: "Test" }, ...dummyData1]}
value="Test"
loadMoreData={loadMore}
onChange={onChange}
/>
);
const selectWrapper = queryByTestId("multi-select-wrapper");
it("Renders successfully -- Single", () => {
expect(selectWrapper).toBeTruthy();
});
it("Value rendered -- Single", () => {
expect(getByText("Test")).toBeInTheDocument();
});
it("Options rendered -- Single", async () => {
act(() => {
fireEvent.click(selectWrapper);
});
const elements = getAllByText("Test");
expect(elements).toHaveLength(1);
});
it("Load More called -- Single", async () => {
act(() => {
fireEvent.click(selectWrapper);
});
const menuEl = container.querySelector(".multi-select-menu");
act(() => {
fireEvent.scroll(menuEl, { target: { scrollY: 700 } });
});
await waitFor(
() => {
expect(loadMore).toBeCalled();
},
{ timeout: 500 }
);
});
it("onChange called -- Single", async () => {
act(() => {
fireEvent.click(selectWrapper);
});
const menuItem = getByText("Test0");
act(() => {
fireEvent.click(menuItem);
});
await waitFor(
() => {
expect(onChange).toHaveBeenCalledWith("Test0");
},
{ timeout: 500 }
);
});
it("Load More called on search -- Single", async () => {
const input = container.querySelector(".multi-select-input");
act(() => {
fireEvent.change(input, { target: { value: "TT" } });
});
await waitFor(
() => {
expect(loadMore).toBeCalledTimes(1);
},
{ timeout: 500 }
);
});
});
describe("Multiple", () => {
beforeAll(() => {
cleanup();
});
const loadMore = jest.fn();
const onChange = jest.fn();
loadMore.mockResolvedValueOnce(dummyData2);
const { queryByTestId, getByText, getAllByText, container } = render(
<MultiSelect
data={[{ title: "Test", key: "Test", value: "Test" }, ...dummyData1]}
value={["Test"]}
loadMoreData={loadMore}
onChange={onChange}
multiple
showCheckboxes
/>
);
const selectWrapper = queryByTestId("multi-select-wrapper");
it("Renders successfully", () => {
expect(selectWrapper).toBeTruthy();
});
it("Value rendered", () => {
expect(getByText("Test")).toBeInTheDocument();
});
});
});
I am getting this error on running the tests. The tests run perfectly if I use them separately. I dont want to render in each test individually but the nested describe is not working
TestingLibraryElementError: Found multiple elements by: [data-testid="multi-select-wrapper"]
I am trying to test a dispatch from 'mapDispatchToProps' defined with a functional component which uses useEffect() hook and the function is called there.
export const MyComponent = (props) => {
useEffect(() => {
// Anything in here is fired on component mount.
props.registerInStore(props.id, false);
return () => {
// Anything in here is fired on component unmount.
props.resetInStore(props.id);
};
}, []);
const handleOnClick = () => {
props.toggle(props.id);
};
return (
<div >
{!props.isOpen ? (
<button
onClick={handleOnClick}>
Open
</button>
) : (
<button
onClick={handleOnClick}>
close
</button>
)}
</div>
);
};
const mapDispatchToProps = (dispatch) => ({
registerInStore(id, isOpen) {
dispatch(registerInStore(id, isOpen));
},
resetInStore(id) {
dispatch(resetInStore(id));
}
});
export default connect(null, mapDispatchToProps)(MyComponent);
In my unit tests with Mocha and enzyme i also want to test the dispatches inside 'mapDispatchToProps', what i did below does not seem to work :
describe('<MyComponent/>', () => {
let store = mockStore({
toggles: [
{
id: 10,
isOpen: true
}
]
}
});
const options = {
context: {store},
childContextTypes: {store: PropTypes.object.isRequired},
lifecycleExperimental: true
};
const setup = (inputProps = {}) => {
const props = {
id: 10,
isOpen: false,
registerInStore: expect.createSpy(),
resetInStore: expect.createSpy(),
toggle: expect.createSpy(),
...inputProps
};
const wrapper = mount(<MyComponent {...props} />, options);
return {
props,
wrapper
};
};
afterEach(() => {
expect.restoreSpies();
});
it('should dispatch', async () => {
const {wrapper}=setup();
await store.dispatch(wrapper.prop('registerInStore')(10,false));
/* i tried the commented way too instead of directly dispatching*/
// wrapper.prop('registerInStore')(10,false);
//await new Promise((resolve) => setTimeout(resolve, 50));
const expectedActions = [{type: 'REGISTER_IN_STORE', id: 10, isOpen: false}];
expect(store.getActions()).toEqual(expectedActions);
});
the store.getActions() is returning an empty array, i am new to React Hooks and testing, what am i doing wrong, any other solutions?.
Thanks in Advance.
worked by removing the spies e.g:-
const setup = (inputProps = {}) => {
const props = {
id: 10,
isOpen: false,
registerInStore:()=>null,
resetInStore: ()=>null,
toggle: ()=>null,
...inputProps
};
const wrapper = mount(<MyComponent {...props} />, options);
return {
props,
wrapper
};
};
I have a inssue, with tdd. I want to call a event byText and i cant do that because i get this error in my component.
TypeError: Cannot read property 'getByText' of undefined
this is my component:
const createSubject = props => {
render(
<AnnoucementItem
{...defaultProps}
{...props}
/>
);
};
and this is my test file:
import React from 'react';
import { render, fireEvent } from 'react-native-testing-library';
import Enzyme, { shallow } from 'enzyme';
import { useDispatch } from 'react-redux';
import i18n from '../../../../src/i18n';
import AnnoucementItem from '../../../../src/screens/Profile/AnnouncementList/AnnouncementItem';
jest.mock('react-redux');
let { onEdit, toggleVisibility, onDelete } = jest.fn();
describe('<AnnoucementItem />', () => {
const defaultProps = {
navigation: {},
item: {
id: 'annoucement id',
user_id: 'id do usuario',
is_published: true,
images: {
0: {
secure_url: genericurl',
},
},
address: {
city: 'Pelotas',
state: 'RS',
number: '990',
street: 'Rua Doutor Francisco Ferreira Veloso',
neighbourhood: 'Py Crespo',
},
values: {
other: '4.32',
total: '4422.33',
},
positive_ratings: '2',
negative_ratings: '1',
onEdit: onEdit,
toggleVisibility: toggleVisibility,
onDelete: onDelete,
},
toggleVisibility: () => {},
onDelete: () => {},
onEdit: () => {},
numberOfLikes: 3,
SwitchOption: {
switchValue: false,
},
userId: () => {},
isFetching: () => {},
shouldUpdate: () => {},
userAnnouncements: () => {},
formVisibility: () => {},
error: () => {},
fetchUserAnnouncements: () => {},
deleteAnnouncement: () => {},
fillFormAnnouncement: () => {},
changeAnnouncementVisibility: () => {},
};
const createSubject = props => {
render(
<AnnoucementItem
{...defaultProps}
{...props}
/>
);
};
describe('AnnoucementItem component', () => {
it('should delete annoucement', () => {
const { getByText, getByTextId } = createSubject();
fireEvent.CallDelete(getByTextId('DeleteButton'), 'deleteAnnouncement');
fireEvent.press(getByText(i18n.t('profile.announcementList.announcementItem.deleteAnnouncementAlert')));
const {
requestDeleteAnnouncement,
successDeleteAnnouncement,
announcementId,
} = jest.fn();
useDispatch.mockReturnValue(
requestDeleteAnnouncement,
successDeleteAnnouncement,
announcementId);
expect(AnnoucementItem.prototype.onDelete.calledOnce).toBe(true);
expect(requestDeleteAnnouncement).toHaveBeenCalledWith({
actionTypes: 'REQUEST_DELETE_ANNOUNCEMENT',
});
expect(successDeleteAnnouncement).toHaveBeenCalledWith({
actionTypes: 'SUCCESS_DELETE_ANNOUNCEMENT',
dispatch: { deletedId: announcementId },
});
});
});
it('should go to edit annoucement', () => {
const { getByText, getByTextId } = createSubject();
fireEvent.CallEdit(getByTextId('EditButton'), 'EditAnnouncement');
fireEvent.press(getByText(i18n.t('profile.announcementList.announcementItem.editAnnouncement')));
const editAnnouncement = jest.fn();
const navigation = { navigate: jest.fn() };
useDispatch.mockReturnValue(editAnnouncement);
expect(editAnnouncement).toHaveBeenCalledWith({
navigation: { navigation },
});
});
it('should count interested peoples in my annoucement', () => {
const { getByText, item } = createSubject();
const interested = getByText(item.positive_ratings + item.negative_ratings);
expect(interested).toBeTruthy();
});
it('should switch visibleAnnoucement', () => {
});
});
the question is, how can i get a element ByText?
In your test update
const createSubject = props => {
render(
<AnnoucementItem
{...defaultProps}
{...props}
/>
);
};
to
const createSubject = props => {
return render(
<AnnoucementItem
{...defaultProps}
{...props}
/>
);
};
Since createSubject is a function you need to return something from that function in order to use its output.
I'm building a web app with React.
On the Home screen, I've the following code.
When running the app, it throws TypeError: unsubFirebaseSnapShot01 is not a function.
browser console error screenshot:
These are the only references to these functions in index.js:
let unsubFirebaseSnapShot01;
let unsubFirebaseSnapShot02;
let unsubFirebaseSnapShot03;
...
class Home extends Component {
...
componentWillUnmount() {
this.mounted = false;
unsubFirebaseSnapShot01();
unsubFirebaseSnapShot02();
unsubFirebaseSnapShot03();
}
checkAll = () => {
this.checkMeetingsSetByMe();
this.checkMeetingsSetForMe();
this.checkNotifications();
};
checkMeetingsSetByMe = () => {
if (!this.mounted) return;
const {
user: { uid },
} = this.props;
this.setState({ screenLoading: true });
unsubFirebaseSnapShot01 = Meetings.where('setBy', '==', uid).onSnapshot(
({ docs }) => {
// setting all the meetingsSetByMe in one place
const meetingsSetByMe = docs.map(item => item.data());
if (this.mounted);
this.setState({ meetingsSetByMe, screenLoading: false });
},
);
};
checkMeetingsSetForMe = () => {
if (!this.mounted) return;
const {
user: { uid },
} = this.props;
this.setState({ screenLoading: true });
unsubFirebaseSnapShot02 = Meetings.where('setWith', '==', uid).onSnapshot(
({ docs }) => {
// setting all the meetingsSetForMe in one place
const meetingsSetForMe = docs.map(item => item.data());
if (this.mounted);
this.setState({ meetingsSetForMe, screenLoading: false });
},
);
};
checkNotifications = () => {
if (!this.mounted) return;
const {
user: { uid },
} = this.props;
this.setState({ screenLoading: true });
unsubFirebaseSnapShot03 = Meetings.where('status', '==', 'unseen')
.where('setWith', '==', uid)
.onSnapshot(({ docs }) => {
const notifications = docs.map(item => item.data());
if (this.mounted);
this.setState({ notifications, screenLoading: false });
});
};
Double checked any typos but cannot see my mistake.
Any help?