@elastic-suite/gally-admin-components
Version:
Components package for gally admin BO
414 lines (389 loc) • 12.4 kB
text/typescript
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
)
})
})
})