35
loading...
This website collects cookies to deliver better user experience
import {renderHook} from '@testing-library/react-hooks';
import useFetch from '.';
describe('UseFetch hook', () => {
it('should exist', () => {
const {result} = renderHook(() => useFetch());
expect(result.current).toBeDefined();
});
});
const useFetch = () => {
return {};
};
export default useFetch;
it('should return an "idle" status when no url is given to it', () => {
const {result} = renderHook(() => useFetch());
expect(result.current.status).toEqual(IDLE_STATUS);
});
NOTE: As you can see I’m jumping some refactoring steps on the way (which you can read about in more details on my previous article) - I’ve create a inner state for the status and also exported some status constants, but if I were to follow the strict TDD manner, I would just return a hard-coded status from the hook which would satisfy the test above as well
import {useState} from 'react';
export const IDLE_STATUS = 'idle';
export const FETCHING_STATUS = 'fetching';
export const FETCHED_STATUS = 'fetched';
const useFetch = ({url} = {}) => {
const [status, setStatus] = useState(IDLE_STATUS);
return {
status,
};
};
export default useFetch;
it('should first go into an "idle" status and then "fetching" and then "fetched" when initiated with a URL', () => {
const {result} = renderHook(() => useFetch({url: mockUrl}));
expect(result.all.length).toEqual(3);
expect(result.all[0].status).toEqual(IDLE_STATUS);
expect(result.all[1].status).toEqual(FETCHING_STATUS);
expect(result.all[2].status).toEqual(FETCHED_STATUS);
});
const useFetch = ({url} = {}) => {
const [status, setStatus] = useState(IDLE_STATUS);
useEffect(() => {
setStatus(FETCHING_STATUS);
setStatus(FETCHED_STATUS);
}, [url]);
return {
status,
};
};
const useFetch = ({url} = {}) => {
const [status, setStatus] = useState(IDLE_STATUS);
useEffect(() => {
if (!url) return;
setStatus(FETCHING_STATUS);
setStatus(FETCHED_STATUS);
}, [url]);
return {
status,
};
};
const mockUrl = 'https://api.instantwebtools.net/v1/passenger';
const mockResponse = {greeting: 'hello there'};
const server = setupServer(
rest.get(mockUrl, (req, res, ctx) => {
return res(ctx.json(mockResponse));
})
);
describe('UseFetch hook', () => {
beforeAll(() => server.listen());
afterAll(() => server.close());
...
});
useEffect(() => {
if (!url) return;
const fetchUrl = async () => {
setStatus(FETCHING_STATUS);
const response = await fetch(url);
const data = await response.json();
setStatus(FETCHED_STATUS);
};
fetchUrl();
}, [url]);
it('should first go into an "idle" status and then "fetching" and then "fetched" when initiated with a URL', async () => {
const {result, waitForNextUpdate} = renderHook(() => useFetch({url: mockUrl}));
await waitForNextUpdate();
expect(result.all.length).toEqual(3);
expect(result.all[0].status).toEqual(IDLE_STATUS);
expect(result.all[1].status).toEqual(FETCHING_STATUS);
expect(result.all[2].status).toEqual(FETCHED_STATUS);
});
it('should return the data from the server', async () => {
const {result, waitForNextUpdate} = renderHook(() => useFetch({url: mockUrl}));
await waitForNextUpdate();
expect(result.current.data).toMatchSnapshot();
});
const useFetch = ({url} = {}) => {
const [status, setStatus] = useState(IDLE_STATUS);
const [data, setData] = useState(null);
useEffect(() => {
if (!url) return;
const fetchUrl = async () => {
setStatus(FETCHING_STATUS);
const response = await fetch(url);
const data = await response.json();
setData(data);
setStatus(FETCHED_STATUS);
};
fetchUrl();
}, [url]);
return {
status,
data,
};
};
it('should first go into an "idle" status and then "fetching" and then "fetched" when initiated with a URL', async () => {
const {result, waitForNextUpdate} = renderHook(() => useFetch({url: mockUrl}));
await waitForNextUpdate();
expect(result.all.length).toEqual(4);
expect(result.all[0].status).toEqual(IDLE_STATUS);
expect(result.all[1].status).toEqual(FETCHING_STATUS);
expect(result.all[3].status).toEqual(FETCHED_STATUS);
});
it('should first go into an "idle" status and then "fetching" and then "fetched" when initiated with a URL', async () => {
const {result, waitForNextUpdate} = renderHook(() => useFetch({url: mockUrl}));
await waitForNextUpdate();
expect(result.all.length).toEqual(3);
expect(result.all[0].status).toEqual(IDLE_STATUS);
expect(result.all[1].status).toEqual(FETCHING_STATUS);
expect(result.all[2].status).toEqual(FETCHED_STATUS);
});
import {useEffect, useReducer} from 'react';
export const IDLE_STATUS = 'idle';
export const FETCHING_STATUS = 'fetching';
export const FETCHED_STATUS = 'fetched';
const FETCHING_ACTION = 'fetchingAction';
const FETCHED_ACTION = 'fetchedAction';
const IDLE_ACTION = 'idleAction';
const initialState = {
status: IDLE_STATUS,
data: null,
};
const useReducerHandler = (state, action) => {
switch (action.type) {
case FETCHING_ACTION:
return {...initialState, status: FETCHING_STATUS};
case FETCHED_ACTION:
return {...initialState, status: FETCHED_STATUS, data: action.payload};
case IDLE_ACTION:
return {...initialState, status: IDLE_STATUS, data: null};
default:
return state;
}
};
const useFetch = ({url} = {}) => {
const [state, dispatch] = useReducer(useReducerHandler, initialState);
useEffect(() => {
if (!url) return;
const fetchUrl = async () => {
dispatch({type: FETCHING_ACTION});
const response = await fetch(url);
const data = await response.json();
dispatch({type: FETCHED_ACTION, payload: data});
};
fetchUrl();
}, [url]);
return state;
};
export default useFetch;
import {renderHook} from '@testing-library/react-hooks';
import {rest} from 'msw';
import {setupServer} from 'msw/node';
import useFetch, {FETCHED_STATUS, FETCHING_STATUS, IDLE_STATUS} from '.';
const mockUrl = 'https://api.instantwebtools.net/v1/passenger';
const mockResponse = {greeting: 'hello there'};
const server = setupServer(
rest.get(mockUrl, (req, res, ctx) => {
return res(ctx.json(mockResponse));
})
);
describe('UseFetch hook', () => {
beforeAll(() => server.listen());
afterAll(() => server.close());
it('should exist', () => {
const {result} = renderHook(() => useFetch());
expect(result.current).toBeDefined();
});
it('should return an "idle" status when no url is given to it', () => {
const {result} = renderHook(() => useFetch());
expect(result.current.status).toEqual(IDLE_STATUS);
});
it('should first go into an "idle" status and then "fetching" and then "fetched" when initiated with a URL', async () => {
const {result, waitForNextUpdate} = renderHook(() => useFetch({url: mockUrl}));
await waitForNextUpdate();
expect(result.all.length).toEqual(3);
expect(result.all[0].status).toEqual(IDLE_STATUS);
expect(result.all[1].status).toEqual(FETCHING_STATUS);
expect(result.all[2].status).toEqual(FETCHED_STATUS);
});
it('should return the data from the server', async () => {
const {result, waitForNextUpdate} = renderHook(() => useFetch({url: mockUrl}));
await waitForNextUpdate();
expect(result.current.data).toMatchSnapshot();
});
});