Jest, Apollo Client different implementations - reactjs

Currently I have this working test:
import React from 'react';
import { render } from '#testing-library/react';
import AuditList from '../../../components/Audit';
jest.mock('#apollo/client', () => ({
useLazyQuery: jest.fn().mockReturnValue([
jest.fn(),
{
data: {
someTestingData: 'some Value'
},
loading: false,
error: false
}
])
}));
describe('Audit', () => {
it('should render audit', () => {
const rendered = render(<AuditList />);
const getBytext = rendered.queryByText('my title');
expect(getBytext).toBeTruthy();
});
});
But, I want to test different cases: when ´loading/error´ is true/false.
How can I make specific definitions of the mock for different ´it´?
EDIT: I tried this:
import React from 'react';
import { useLazyQuery } from '#apollo/client';
import { render } from '#testing-library/react';
import AuditList from '../../../components/communications/Audit';
jest.mock('#apollo/client');
describe('Audit', () => {
it('should render audit', () => {
useLazyQuery.mockImplementation(() => [
jest.fn(),
{
data: {
someTestingData: 'some Value'
},
loading: false,
error: false
}
]);
const rendered = render(<AuditList />);
const getBytext = rendered.queryByText('Auditoría');
expect(getBytext).toBeTruthy();
});
});
But I get ´ Cannot read property 'mockImplementation' of undefined ´

Related

Warning: An update to Field inside a test was not wrapped in act(...)

How can I get rid of this warning in me test in JEST? I'm working with a simple component that does a side effect. My test passes, but I'm getting the warning Warning: An update to Hello inside a test was not wrapped in act(...)..
console.error
Warning: An update to Field inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
at Field (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/node_modules/rc-field-form/lib/Field.js:79:34)
at WrapperField (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/node_modules/rc-field-form/lib/Field.js:651:20)
at FormItem (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/node_modules/antd/lib/form/FormItem.js:118:20)
at id (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/src/components/Fields/PasswordField/PasswordField.js:8:11)
at type (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/src/components/FormField/FormField.js:8:11)
at form
at Form (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/node_modules/rc-field-form/lib/Form.js:33:19)
at SizeContextProvider (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/node_modules/antd/lib/config-provider/SizeContext.js:19:23)
at DisabledContextProvider (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/node_modules/antd/lib/config-provider/DisabledContext.js:19:23)
at InternalForm (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/node_modules/antd/lib/form/Form.js:74:27)
at div
at /Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/node_modules/antd/lib/grid/col.js:59:33
at div
at /Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/node_modules/antd/lib/grid/row.js:56:34
at SignIn (/Users/anastasiiaponamareva/Desktop/projects/dashboard-proto-frontend/src/containers/SignIn/SignIn.js:18:17)
at basenameProp (/Users/anastasiiaponamareva/Desktop/projects/packages/react-router/lib/components.tsx:173:13)
at basename (/Users/anastasiiaponamareva/Desktop/projects/packages/react-router-dom/index.tsx:147:3)
at printWarning (node_modules/react-dom/cjs/react-dom.development.js:86:30)
at error (node_modules/react-dom/cjs/react-dom.development.js:60:7)
at warnIfUpdatesNotWrappedWithActDEV (node_modules/react-dom/cjs/react-dom.development.js:27589:9)
at scheduleUpdateOnFiber (node_modules/react-dom/cjs/react-dom.development.js:25508:5)
at Object.enqueueForceUpdate (node_modules/react-dom/cjs/react-dom.development.js:14120:7)
at Field.Object.<anonymous>.Component.forceUpdate (node_modules/react/cjs/react.development.js:373:16)
at Field.reRender (node_modules/rc-field-form/lib/Field.js:612:12)
This is my test. How can I resolve this error in my test ? I'm also don't know if waitForElement is the best way to write this test.:
import renderer from "react-test-renderer";
import * as reduxHooks from "react-redux";
import { BrowserRouter } from "react-router-dom";
import "#testing-library/jest-dom"
import { waitFor } from "#testing-library/react";
import SignIn from "../src/containers/SignIn/SignIn";
import { render, fireEvent, screen } from "../test-utils"
jest.mock("react-redux");
const mockedUseSelectors = jest.spyOn(reduxHooks, "useSelector")
beforeAll(() => {
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
}))
});
});
describe("<Login />", () => {
test("render without crashing", () => {
mockedUseSelectors.mockReturnValue([]);
const tree = renderer
.create(<BrowserRouter><SignIn/></BrowserRouter>)
.toJSON();
expect(tree).toMatchSnapshot();
});
test("Login form should be in the document", async () => {
mockedUseSelectors.mockReturnValue([]);
render(
<BrowserRouter>
<SignIn />
</BrowserRouter>,
{ initialState: { user: "Redux User" } }
)
const email = screen.getByLabelText("Email")
await waitFor(() => {
expect(email).toBeInTheDocument();
})
});
test("should success on login", async () => {
mockedUseSelectors.mockReturnValue([]);
const handleClick = jest.fn();
render(
<BrowserRouter>
<SignIn onClick={handleClick}/>
</BrowserRouter>,
{ initialState: { user: "Redux User" } }
)
const emailInput = screen.getByLabelText("Email");
const passwordInput = screen.getByLabelText("Пароль");
const button = screen.getByRole("button", { name: "Войти" });
fireEvent.change(emailInput, { target: { value: "test#gmail.com" } });
fireEvent.change(passwordInput, { target: { value: "A#8134erjanY" } });
fireEvent.click(button);
// expect(handleClick).toHaveBeenCalledTimes(1)
});
});

Unable to write unit test cases for FHIR client api calls

I hava component Componnent1 and inside the componentDidMount i am having the below code:-
const key1 = sessionStorage.getItem("key1");
FHIR.oauth2
.ready()
.then((client) =>
client.request("<url>/" + key1, {
resolveReferences: [
],
graph: true,
})
)
.then((json) => {
console.log(json);
})
.catch(console.error);
And I am getting this error
● renders as expected
console.error internal/process/next_tick.js:68
TypeError: client.request is not a function
at _fhirclient.default.oauth2.ready.then.client (C:\Users\dbdeb\OneDrive\Desktop\patient-application\src\components\my-health-deatails.component\allergies.component\allergies.js:68:16)
at process._tickCallback (internal/process/next_tick.js:68:7)
and my Test case is like:-
import { Component1} from "../component1"
import React, { Component } from "react";
import { render } from '#testing-library/react';
import '#testing-library/jest-dom/extend-expect'
import FHIR from "fhirclient";
jest.mock('fhirclient', () => ({
oauth2: {
ready: jest.fn(() => Promise.resolve({
client: {
request: jest.fn(() => { return { data: null } })
}
}))
}
}));
test('renders as expected', () => {
FHIR.oauth2.ready.mockResolvedValueOnce({ data: { entry: '' } })
render(<Component1></Component1>)
});

How can I mock useQuery from react-fetching-library?

Hello how can I mock useQuery? I have container component which is responsible for calling an api, and simple ui component to display data for the user. I'm receiving current error
console.error node_modules/#testing-library/react/dist/act-compat.js:52
Error: Error: connect ECONNREFUSED 127.0.0.1:80
Container
import React from 'react';
import { screen, waitForElement, getByText } from '#testing-library/react';
import { useQuery } from 'react-fetching-library';
import { render } from 'tests';
import tags from 'api/mocks/tags-response.json';
import { TrendingTagsContainer } from './TrendingTagsContainer';
jest.mock('react-fetching-library');
describe('TrendingTagsContainer component', () => {
test('should render component with correct title and description', async () => {
const action = jest.fn();
const useQuery = jest.fn(action());
useQuery.mockReturnValue({ loading: false, error: false, query: () => true, payload: { tags } });
console.log(useQuery());
const { getByText } = render(<TrendingTagsContainer />);
await waitForElement(() => screen.getByText('#Testing react'));
expect(screen.getByText('#Testing react')).toBeInTheDocument();
});
});
I think you can simply you mock your react-fetching-library module as following:
import { useQuery } from 'react-fetching-library';
jest.mock('react-fetching-library');
// Everything looks the same I guess

useSelector of Undefined

Hi I am writting unit testing for a component it has redux in it. While testing it , throws an error UseSelector state undefined. UseSelector will be updated once after getting response from the api. Till that its value is undefined. But while unit tetsing it throws error on the first itself . How to overcome this issue.
Test File
import React from 'react';
import { render, fireEvent } from '#testing-library/react';
import { act } from 'react-dom/test-utils';
import '#testing-library/jest-dom/extend-expect';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import LinkApplication from '../index';
import {reducer} from '../../../redux/summary/reducer';
let INITIAL_STATES = {
isFetching: false,
errorMessage: "",
requestExtensionErrorMessage: "",
requestExtensionSuccessMessage: "",
linkApplicationSuccess: "",
linkApplicationFailure: null,
linkLoanSuccessMessage: "",
linkLoanErrorMessage: "",
LinkApplicationErrorMessage:"",
};
function renderWithRedux(
component,
{ INITIAL_STATES, store = createStore(reducer, INITIAL_STATES) } = {},
) {
return {
...render(<Provider store={store}>{component}</Provider>),
};
}
it('sumbits the form', async () => {
const onSubmit = jest.fn();
const { getByText, getByTestId } = renderWithRedux(
<LinkApplication onSubmit={onSubmit} />,
);
const Dob_Input = getByTestId('dob-input');
const Phone_Input = getByTestId('phone-input');
const form = getByTestId('form');
act(() => {
fireEvent.keyPress(Dob_Input, {
target: { value: '1995-09-27' },
});
fireEvent.keyPress(Phone_Input, { target: { value: '9500902621' } });
});
expect(Dob_Input.value).toBe('1995-09-27');
expect(Phone_Input.value).toBe('9500902621');
await act(() => {
fireEvent.submit(form);
});
expect(onSubmit).not.toHaveBeenCalled();
})
Component
const LinkApplication = () => {
const dispatch = useDispatch();
let LinkApplicationErrorMessage = useSelector(
state => state.summary.linkApplicationFailure
);
}
Error
TypeError: Cannot read property 'linkApplicationFailure' of undefined
const dispatch = useDispatch();
let LinkApplicationErrorMessage = useSelector(
state => state.summary.linkApplicationFailure
^
);
Please help me with that.
I think you need to mock react-redux
import * as React from 'react';
import { shallow } from 'enzyme';
jest.mock('react-redux', () => ({
useDispatch: () => {},
useSelector: () => ({
your: 'state',
}),
}));
import Component from './index';
describe('Test component', () => {
it('Should render and match the snapshot', () => {
const wrapper = shallow(<Component />);
});
});

React Apollo Testing is not working. Query data is always coming undefined

I am getting loading state only and data as undefined in testing. I don't know why I am following everything in the given example. Please help.
Testing file. When i am waiting thsi line toexecute await wait(() => getByTestId('edit-category'));. It is giving response data of query as undefined.
Error: TypeError: Cannot read property 'getCategory' of undefined
Line 34 on editConatinerCategory.tsx => category={data!.getCategory!}
import React from 'react';
import gql from 'graphql-tag';
import { cleanup, wait } from 'react-testing-library';
import { customRender } from '../../../test-utils/customRender';
import { EditCategoryContainer } from './Container';
afterEach(() => {
cleanup();
console.error;
});
console.error = jest.fn();
const getCategoryMock = {
request: {
query: gql`
query getCategory($id: Int!) {
getCategory(id: $id) {
id
name
active
position
}
}
`,
variables: {
id: 1
}
},
result: {
data: {
getCategory: {
id: 1,
name: 'category',
active: true,
position: 1
}
}
}
};
describe('create edit category module', () => {
test('Rendering correct', async () => {
const { container, debug, getByTestId } = customRender(<EditCategoryContainer />, [
getCategoryMock
]);
await wait(() => getByTestId('edit-category'));
await wait(() => expect(container).toMatchSnapshot());
//Getting this TypeError: Cannot read property 'getCategory' of undefined. Because i am data as undefined from my query response
});
});
CustomRender.tsx
import React from 'react';
import { render } from 'react-testing-library';
import { MockedProvider, MockedResponse } from 'react-apollo/test-utils';
import { Router, Switch } from 'react-router-dom';
import { createMemoryHistory } from 'history';
export const customRender = (
node: JSX.Element | null,
mocks?: MockedResponse[],
{
route = '/',
history = createMemoryHistory({ initialEntries: [route] })
} = {}
) => {
return {
history,
...render(
<MockedProvider mocks={mocks} addTypename={false}>
<Router history={history}>
<Switch>{node}</Switch>
</Router>
</MockedProvider>
)
};
};
EditCategoryContainer.tsx
import React from 'react';
import { withRouter } from 'react-router';
import { Spin } from 'antd';
import {
AddCategoryComponent,
GetCategoryComponent
} from '../../../generated/graphql';
import { EditCategory } from './Edit';
import { LoadingComponent } from '../../../components/LoadingComponent';
export const EditCategoryContainer = withRouter(({ history, match }) => {
const id: number = parseInt(match.params.id, 10);
return (
<GetCategoryComponent
variables={{
id
}}
>
{({ data, loading: getCategoryLoading }) => {
console.log(getCategoryLoading, 'getCategoryLoading');
if (getCategoryLoading) {
return <LoadingComponent />;
}
if (data && !data.getCategory) {
return <div>Category not found!</div>;
}
console.log(data);
return (
<AddCategoryComponent>
{(addCategory, { loading, error }) => {
return (
<EditCategory
data-testid="edit-category"
category={data!.getCategory!}
loading={loading || getCategoryLoading}
onSubmit={values => {
addCategory({ variables: values }).then(() => {
history.push('/dashboard/categories');
});
}}
/>
);
}}
</AddCategoryComponent>
);
}}
</GetCategoryComponent>
);
});
Edit:
I tried #mikaelrs solution which is passed match. But it is not working. I also tried to pass id:1 as fixed. But it is still giving error.
<GetCategoryComponent
variables={{
id:1
}}
>
...rest of code.
</GetCategoryComponent>
This is not working. My query without veriable is working fine. Mutation is also working fine. I am having only problem with this. When i have to pass like varible like this.
What I do to wait for the loading state of the MockedProvider to pass is to use the wait function from waait. This is actually what Apollo recommends as well.
So in your test you would do:
import React from 'react';
import gql from 'graphql-tag';
import { cleanup } from 'react-testing-library';
import wait from 'waait'
import { customRender } from '../../../test-utils/customRender';
import { EditCategoryContainer } from './Container';
afterEach(() => {
cleanup();
});
const getCategoryMock = {
request: {
query: gql`
query getCategory($id: Int!) {
getCategory(id: $id) {
id
name
active
position
}
}
`,
variables: {
id: 1
}
},
result: {
data: {
getCategory: {
id: 1,
name: 'category',
active: true,
position: 1
}
}
}
};
describe('create edit category module', () => {
test('Rendering correct', async () => {
const { container, debug } = customRender(<EditCategoryContainer />, [
getCategoryMock
]);
await wait(0);
// Your loading state should be false after this, and your component should
// get it's data from apollo for you to do any assertion you would like to
// after this point. To see that the component is rendered with data invoke
// the debug function from react-testing-library after this point
debug();
expect(container).toMatchSnapshot()
});
});
Another solution is to use react-testing-librarys wait function to wait for an element that would be present after the loading state switches to true.
For instance
describe('create edit category module', () => {
test('Rendering correct', async () => {
const { container, debug, queryByText } = customRender(<EditCategoryContainer />, [
getCategoryMock
]);
await wait(()=> queryByText("Some Data"));
// Your loading state should be false after this, and your component should
// get it's data from apollo for you to do any assertion you would like to
// after this point
expect(container).toMatchSnapshot()
});
});
I faced a similar issue. Here is how I resolved my issue.
First, wait for the query to resolve, as recommended by #mikaelrs and the docs:
await new Promise(resolve => setTimeout(resolve, 0));
After doing that, the loading property was false, but data was still undefined. I discovered that my mock result object was missing a property. Once I added that missing property to the mock result, the data was populated as expected.

Resources