I want to test api call and data returned which should be displayed inside my functional component. I created List component which performs api call. I would like the returned data to be displayed in the component and I use the useState hook for this. Component looks like this:
const List: FC<{}> = () => { const [data, setData] = useState<number>(); const getData = (): Promise<any> => { return fetch('https://jsonplaceholder.typicode.com/todos/1'); }; React.useEffect(() => { const func = async () => { const data = await getData(); const value = await data.json(); setData(value.title); } func(); }, []) return ( <div> <div id="test">{data}</div> </div> ) }
I wrote one test in which I mocked the fetch method. I check if the fetch method has been called and it actually happens. Unfortunately, I don't know how I could test the value returned from response. When I try console.log I just get null and I'd like to get 'example text'. My guess is that I have to wait for this value returned from Promise. Unfortunately, despite trying with methods act and wait, I don't know how to achieve it. Here is my test:
it('test', async () => { let component; const fakeResponse = 'example text'; const mockFetch = Promise.resolve({json: () => Promise.resolve(fakeResponse)}); const mockedFetch = jest.spyOn(window, 'fetch').mockImplementationOnce(() => mockFetch as any ) await wait( async () => { component = render(<List />); }) const value: Element = component.container.querySelector('#test'); console.log(value.textContent); expect(mockedFetch).toHaveBeenCalledTimes(1); })
I would be really thankful for any suggestions.
Also tried using data-testid="test"
and waitForElement
, but still receiving null value.
updated component deltas:
const List: FC<{}> = () => { - const [data, setData] = useState<number>(); + const [data, setData] = useState<string>('test'); const getData = (): Promise<any> => { return fetch('https://jsonplaceholder.typicode.com/todos/1'); }; React.useEffect(() => { const func = async () => { const data = await getData(); const value = await data.json(); setData(value.title); } func(); }, []) return ( <div> - <div id="test">{data}</div> + <div data-testid="test" id="test">{data}</div> </div> ) }
and updated test:
it('test', async () => { const fakeResponse = 'example text'; const mockFetch = Promise.resolve({json: () => Promise.resolve(fakeResponse)}); const mockedFetch = jest.spyOn(window, 'fetch').mockImplementationOnce(() => mockFetch as any ) const { getByTestId } = render(<List />); expect(getByTestId("test")).toHaveTextContent("test"); const resolvedValue = await waitForElement(() => getByTestId('test')); expect(resolvedValue).toHaveTextContent("example text"); expect(mockedFetch).toHaveBeenCalledTimes(1); })
Here is a working unit testing example:
index.tsx
:
import React, { useState, FC } from 'react'; export const List: FC<{}> = () => { const [data, setData] = useState<number>(); const getData = (): Promise<any> => { return fetch('https://jsonplaceholder.typicode.com/todos/1'); }; React.useEffect(() => { const func = async () => { const data = await getData(); const value = await data.json(); setData(value.title); }; func(); }, []); return ( <div> <div data-testid="test">{data}</div> </div> ); };
index.test.tsx
:
import { List } from './'; import React from 'react'; import '@testing-library/jest-dom/extend-expect'; import { render, waitForElement } from '@testing-library/react'; describe('59892259', () => { let originFetch; beforeEach(() => { originFetch = (global as any).fetch; }); afterEach(() => { (global as any).fetch = originFetch; }); it('should pass', async () => { const fakeResponse = { title: 'example text' }; const mRes = { json: jest.fn().mockResolvedValueOnce(fakeResponse) }; const mockedFetch = jest.fn().mockResolvedValueOnce(mRes as any); (global as any).fetch = mockedFetch; const { getByTestId } = render(<List></List>); const div = await waitForElement(() => getByTestId('test')); expect(div).toHaveTextContent('example text'); expect(mockedFetch).toBeCalledTimes(1); expect(mRes.json).toBeCalledTimes(1); }); });
unit test result:
PASS src/stackoverflow/59892259/index.test.tsx (9.816s) 59892259 ✓ should pass (63ms) -----------|----------|----------|----------|----------|-------------------| File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s | -----------|----------|----------|----------|----------|-------------------| All files | 100 | 100 | 100 | 100 | | index.tsx | 100 | 100 | 100 | 100 | | -----------|----------|----------|----------|----------|-------------------| Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 11.73s, estimated 13s
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With