UNPKG

@elastic-suite/gally-admin-components

Version:
414 lines (389 loc) 12.4 kB
import { act, waitFor } from '@testing-library/react' import { AuthError, IError, IHydraMember, LoadStatus, fetchApi, log, resource, } from '@elastic-suite/gally-admin-shared' import Router from 'next/router' import { renderHookWithProviders } from '../utils/tests' import { useApiEditableList, useApiFetch, useApiList, useFetchApi, } from './useApi' interface ITest extends IHydraMember { hello: string } describe('useApi', () => { beforeEach(() => { ;(fetchApi as jest.Mock).mockClear() }) describe('useApiFetch', () => { it('should return the apiFetch function prefilled', async () => { ;(fetchApi as jest.Mock).mockClear() const { result } = renderHookWithProviders(() => useApiFetch()) expect(typeof result.current).toEqual('function') const json = await result.current('/test') expect(json).toEqual({ hello: 'world' }) expect(fetchApi).toHaveBeenCalledWith( 'en', '/test', undefined, undefined, true ) }) it('should call the log function if any error is thrown', async () => { const mock = fetchApi as jest.Mock mock.mockClear() ;(log as jest.Mock).mockClear() mock.mockImplementationOnce(() => Promise.reject(new Error('error'))) const { result } = renderHookWithProviders(() => useApiFetch()) const json = await result.current('/test') expect((json as IError).error.message).toEqual('error') expect(log).toHaveBeenCalled() }) it('should logout the user if an auth error is thrown', async () => { const mock = fetchApi as jest.Mock mock.mockClear() mock.mockImplementationOnce(() => Promise.reject(new AuthError('Unauthorized/Forbidden')) ) const pushSpy = Router.push as jest.Mock pushSpy.mockClear() const { result } = renderHookWithProviders(() => useApiFetch()) const json = await result.current('/test') expect((json as IError).error.message).toEqual('Unauthorized/Forbidden') expect(pushSpy).toHaveBeenCalledWith('/login') }) }) describe('useFetchApi', () => { it('calls and return the api result', async () => { ;(fetchApi as jest.Mock).mockClear() const { result } = renderHookWithProviders(() => useFetchApi('/test')) expect(result.current[0]).toEqual({ status: LoadStatus.LOADING, }) await waitFor(() => expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { hello: 'world' }, }) ) expect(fetchApi).toHaveBeenCalledWith( 'en', '/test', undefined, undefined, true ) }) it('calls and return the api result with options', async () => { ;(fetchApi as jest.Mock).mockClear() const options: RequestInit = { body: 'gqlQuery', } const { result } = renderHookWithProviders(() => useFetchApi('/test', null, options) ) expect(result.current[0]).toEqual({ status: LoadStatus.LOADING, }) await waitFor(() => expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { hello: 'world' }, }) ) expect(fetchApi).toHaveBeenCalledWith( 'en', '/test', null, { body: 'gqlQuery', }, true ) }) it('should update the data in the response', async () => { ;(fetchApi as jest.Mock).mockClear() const { result } = renderHookWithProviders(() => useFetchApi('/test')) await waitFor(() => expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { hello: 'world' }, }) ) act(() => result.current[1]({ hello: 'foo' })) expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { hello: 'foo' }, }) }) it('should update the data in the response (using an update function)', async () => { ;(fetchApi as jest.Mock).mockClear() const { result } = renderHookWithProviders(() => useFetchApi('/test')) await waitFor(() => expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { hello: 'world' }, }) ) act(() => result.current[1]((data: any) => ({ ...data, foo: 'bar' }))) expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { hello: 'world', foo: 'bar' }, }) }) }) describe('useApiList', () => { it('calls and return the list result with pagination disabled', async () => { ;(fetchApi as jest.Mock).mockClear() const { result } = renderHookWithProviders(() => useApiList('/list', false) ) await waitFor(() => expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { hello: 'world' }, }) ) expect(fetchApi).toHaveBeenCalledWith( 'en', '/list', { pagination: false }, undefined, true ) }) it('calls and return the list result with pagination enabled', async () => { ;(fetchApi as jest.Mock).mockClear() const { result } = renderHookWithProviders(() => useApiList('/list')) await waitFor(() => expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { hello: 'world' }, }) ) expect(fetchApi).toHaveBeenCalledWith( 'en', '/list', { pagination: true, pageSize: 50, currentPage: 1 }, undefined, true ) }) it('calls and return the list result with page and filters', async () => { ;(fetchApi as jest.Mock).mockClear() const params = { foo: 'bar' } const { result } = renderHookWithProviders(() => useApiList('/list', 2, undefined, params) ) await waitFor(() => expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { hello: 'world' }, }) ) expect(fetchApi).toHaveBeenCalledWith( 'en', '/list', { pagination: true, pageSize: 50, currentPage: 3, foo: 'bar', }, undefined, true ) }) it('should update the list', async () => { const mock = fetchApi as jest.Mock mock.mockClear() mock.mockImplementationOnce(() => Promise.resolve({ 'hydra:member': [{ id: 0 }] }) ) const { result } = renderHookWithProviders(() => useApiList('/list', false) ) await waitFor(() => expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { 'hydra:member': [{ id: 0 }] }, }) ) act(() => result.current[1]([{ id: 1 } as unknown as IHydraMember])) expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { 'hydra:member': [{ id: 1 }] }, }) }) it('should update the list (using an update function)', async () => { const mock = fetchApi as jest.Mock mock.mockClear() mock.mockImplementationOnce(() => Promise.resolve({ 'hydra:member': [{ id: 0 }] }) ) const { result } = renderHookWithProviders(() => useApiList('/list', false) ) await waitFor(() => expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { 'hydra:member': [{ id: 0 }] }, }) ) act(() => result.current[1]((list) => list.concat([{ id: 1 } as unknown as IHydraMember]) ) ) expect(result.current[0]).toEqual({ status: LoadStatus.SUCCEEDED, data: { 'hydra:member': [{ id: 0 }, { id: 1 }] }, }) }) }) describe('useApiEditableList', () => { it('calls and return the list and the resource operations', async () => { ;(fetchApi as jest.Mock).mockClear() const { result } = renderHookWithProviders(() => useApiEditableList(resource) ) expect(result.current[1]).toMatchObject({ create: expect.any(Function), remove: expect.any(Function), replace: expect.any(Function), update: expect.any(Function), }) await waitFor(() => expect(result.current[0].data['hydra:member'].length).toEqual(2) ) expect(fetchApi).toHaveBeenCalledWith( 'en', resource, { pagination: true, pageSize: 50, currentPage: 1 }, undefined, true ) }) it('should call the API (create)', async () => { const { result } = renderHookWithProviders(() => useApiEditableList<ITest>(resource) ) await waitFor(() => expect(result.current[0].data['hydra:member'].length).toEqual(2) ) ;(fetchApi as jest.Mock).mockClear() await act(() => result.current[1].create({ hello: 'world' })) expect(fetchApi).toHaveBeenCalledWith( 'en', 'https://localhost/metadata', undefined, { body: '{"hello":"world"}', method: 'POST' }, true ) }) it('should call the API (replace)', async () => { const { result } = renderHookWithProviders(() => useApiEditableList<ITest>(resource) ) await waitFor(() => expect(result.current[0].data['hydra:member'].length).toEqual(2) ) ;(fetchApi as jest.Mock).mockClear() await act(() => result.current[1].replace({ id: 1, hello: 'world' })) expect(fetchApi).toHaveBeenCalledWith( 'en', 'https://localhost/metadata/1', undefined, { body: '{"id":1,"hello":"world"}', method: 'PUT' }, true ) }) it('should call the API (update)', async () => { const { result } = renderHookWithProviders(() => useApiEditableList<ITest>(resource) ) await waitFor(() => expect(result.current[0].data['hydra:member'].length).toEqual(2) ) ;(fetchApi as jest.Mock).mockClear() await act(() => result.current[1].update(1, { hello: 'world' })) expect(fetchApi).toHaveBeenCalledWith( 'en', 'https://localhost/metadata/1', undefined, { body: '{"hello":"world"}', headers: { 'Content-Type': 'application/merge-patch+json' }, method: 'PATCH', }, true ) }) it('should call the API (remove))', async () => { const { result } = renderHookWithProviders(() => useApiEditableList<ITest>(resource) ) await waitFor(() => expect(result.current[0].data['hydra:member'].length).toEqual(2) ) ;(fetchApi as jest.Mock).mockClear() await act(() => result.current[1].remove(1)) expect(fetchApi).toHaveBeenCalledWith( 'en', 'https://localhost/metadata/1', undefined, { method: 'DELETE' }, true ) }) it('should call the API (massUpdate)', async () => { const { result } = renderHookWithProviders(() => useApiEditableList<ITest>(resource) ) await waitFor(() => expect(result.current[0].data['hydra:member'].length).toEqual(2) ) ;(fetchApi as jest.Mock).mockClear() await act(() => result.current[1].massUpdate([1], { hello: 'world' })) expect(fetchApi).toHaveBeenCalledWith( 'en', 'https://localhost/metadata/1', undefined, { body: '{"hello":"world"}', headers: { 'Content-Type': 'application/merge-patch+json' }, method: 'PATCH', }, true ) }) it('should call the API (massReplace)', async () => { const { result } = renderHookWithProviders(() => useApiEditableList<ITest>(resource) ) await waitFor(() => expect(result.current[0].data['hydra:member'].length).toEqual(2) ) ;(fetchApi as jest.Mock).mockClear() await act(() => result.current[1].massReplace([1], { id: 1, hello: 'world' }) ) expect(fetchApi).toHaveBeenCalledWith( 'en', 'https://localhost/metadata/1', undefined, { body: '{"id":1,"hello":"world"}', method: 'PUT' }, true ) }) }) })