import { useController, useSuspense } from '@data-client/react'; import { CacheProvider } from '@data-client/react'; import { CoolerArticleResource, CoolerArticle, User } from '__tests__/new'; import nock from 'nock'; import { makeRenderDataClient } from '../../../test'; import hookifyResource from '../hookifyResource'; const CoolerArticleHookResource = hookifyResource( CoolerArticleResource, () => ({}), ); function onError(e: any) { e.preventDefault(); } beforeEach(() => { if (typeof addEventListener === 'function') addEventListener('error', onError); }); afterEach(() => { if (typeof removeEventListener === 'function') removeEventListener('error', onError); }); describe('hookifyResource()', () => { beforeAll(() => { nock(/.*/) .persist() .defaultReplyHeaders({ 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json', }) .options(/.*/) .reply(200); }); afterAll(() => { nock.cleanAll(); }); describe('HookableResource endpoints', () => { const id = 5; const idHtml = 6; const idNoContent = 7; const payload = { id, title: 'happy', author: User.fromJS({ id: 5 }), }; const putResponseBody = { id, title: 'happy', completed: true, }; const patchPayload = { title: 'happy', }; const patchResponseBody = { id, title: 'happy', completed: false, }; let renderDataClient: ReturnType; let errorSpy: jest.SpyInstance; beforeAll(() => { errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); }); afterAll(() => { errorSpy.mockRestore(); }); beforeEach(() => { renderDataClient = makeRenderDataClient(CacheProvider); nock(/.*/) .defaultReplyHeaders({ 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json', }) .get(`/article-cooler/${payload.id}`) .reply(200, payload) .get(`/article-cooler`) .reply(200, [payload]) .get(`/article-cooler/${idHtml}`) .reply(200, 'this is html') .get(`/article-cooler/${idNoContent}`) .reply(204, '') .post('/article-cooler') .reply((uri, requestBody) => [ 201, requestBody, { 'content-type': 'application/json' }, ]) .put('/article-cooler/5') .reply((uri, requestBody) => { let body = requestBody as any; if (typeof requestBody === 'string') { body = JSON.parse(requestBody); } for (const key of Object.keys(CoolerArticle.fromJS({}))) { if (key !== 'id' && !(key in body)) { return [400, {}, { 'content-type': 'application/json' }]; } } return [200, putResponseBody, { 'content-type': 'application/json' }]; }) .patch('/article-cooler/5') .reply(() => [ 200, patchResponseBody, { 'content-type': 'application/json' }, ]) .intercept('/article-cooler/5', 'DELETE') .reply(200, {}); }); it('useDetail', async () => { const { result, waitForNextUpdate } = renderDataClient(() => useSuspense(CoolerArticleHookResource.useGet(), { id: payload.id }), ); await waitForNextUpdate(); expect(result.current).toBeDefined(); expect(result.current.title).toBe(payload.title); }); it('useList', async () => { const { result, waitForNextUpdate } = renderDataClient(() => useSuspense(CoolerArticleHookResource.useGetList()), ); await waitForNextUpdate(); expect(result.current).toBeDefined(); }); it('useCreate', async () => { const { result } = renderDataClient(() => ({ endpoint: CoolerArticleHookResource.useCreate(), fetch: useController().fetch, })); const payload2 = { id: 20, content: 'better task' }; const article = await result.current.fetch( result.current.endpoint, payload2, ); // @ts-expect-error () => result.current.fetch(result.current.endpoint, {}, payload2); expect(article).toMatchObject(payload2); }); it('useDelete', async () => { const { result } = renderDataClient(() => ({ endpoint: CoolerArticleHookResource.useDelete(), fetch: useController().fetch, })); const res = await result.current.fetch(result.current.endpoint, { id: payload.id, }); expect(res).toEqual(CoolerArticle.fromJS({ id: 5 })); }); it('useUpdate', async () => { const { result } = renderDataClient(() => ({ endpoint: CoolerArticleHookResource.useUpdate(), fetch: useController().fetch, })); const res = await result.current.fetch( result.current.endpoint, { id: payload.id }, { ...CoolerArticle.fromJS(payload), }, ); expect(res).toEqual( result.current.endpoint.schema.fromJS(putResponseBody), ); }); it('usePartialUpdate', async () => { const { result } = renderDataClient(() => ({ endpoint: CoolerArticleHookResource.usePartialUpdate(), fetch: useController().fetch, })); const res = await result.current.fetch( result.current.endpoint, { id }, patchPayload, ); expect(res).toEqual( result.current.endpoint.schema.fromJS(patchResponseBody), ); }); it('should use useFetchInit if defined (in endpoint method)', async () => { const useFetchInit = jest.fn(() => ({})); const FetchResource = hookifyResource( CoolerArticleResource, useFetchInit, ); const articleDetail = FetchResource.useGet(); expect(articleDetail).toBeDefined(); expect(useFetchInit.mock.calls.length).toBeGreaterThan(0); }); }); });