import React, { useState, useEffect, useContext } from 'react'; import { prettyDOM } from '@testing-library/dom' import {render, act, screen, waitFor, fireEvent} from '@testing-library/react' import { CardContextProvider, CardContext } from 'context/CardContext'; import * as fetchUtil from 'api/fetchUtil'; let cardContext = null; function CardView() { const [renderCount, setRenderCount] = useState(0); const [cards, setCards] = useState([]); const card = useContext(CardContext); cardContext = card; useEffect(() => { const rendered = [] const entries = Array.from(card.state.cards.values()); entries.forEach(entry => { rendered.push( //@ts-ignore
{ entry.data.cardProfile.name } { entry.data.cardDetail.status } { entry.data.cardDetail.token }
); }); setCards(rendered); setRenderCount(renderCount + 1); }, [card.state]) return ( //@ts-ignore
{ cards }
); } function CardTestApp() { return ( ) } const realFetchWithTimeout = fetchUtil.fetchWithTimeout; const realFetchWithCustomTimeout = fetchUtil.fetchWithCustomTimeout; let statusCards; let statusMessage; let statusDetail; let statusProfile; let fetchCards; let fetchMessage; let fetchDetail; let fetchProfile; beforeEach(() => { statusMessage = 200; fetchMessage = statusCards = 200; fetchCards = []; statusDetail = 200; fetchDetail = {}; statusProfile = 200; fetchProfile = {}; const mockFetch = jest.fn().mockImplementation((url, options) => { const params = url.split('/'); if (params[4]?.split('?')[0] === 'message') { return Promise.resolve({ url: 'getMessage', status: statusMessage, json: () => Promise.resolve(fetchMessage), }); } else if (params[4]?.split('?')[0] === 'detail') { return Promise.resolve({ url: 'getDetail', status: statusDetail, json: () => Promise.resolve(fetchDetail), }); } else if (params[4]?.split('?')[0] === 'profile') { return Promise.resolve({ url: 'getProfile', status: statusProfile, json: () => Promise.resolve(fetchProfile), }); } else if (params[2]?.split('?')[0] === 'cards') { return Promise.resolve({ url: 'getCards', status: statusCards, json: () => Promise.resolve(fetchCards), }); } else { return Promise.resolve({ url: 'endpoint', status: 200, json: () => Promise.resolve([]), }); } }); //@ts-ignore fetchUtil.fetchWithTimeout = mockFetch; //@ts-ignore fetchUtil.fetchWithCustomTimeout = mockFetch; }); afterEach(() => { //@ts-ignore fetchUtil.fetchWithTimeout = realFetchWithTimeout; //@ts-ignore fetchUtil.fetchWithCustomTimeout = realFetchWithCustomTimeout; }); test('resync cards', async() => { render(); await waitFor(async () => { expect(cardContext).not.toBe(null); }); await act(async () => { cardContext.actions.setToken('abc123'); }); statusCards = 500; await act(async () => { cardContext.actions.setRevision(1); }); await waitFor(async () => { //@ts-ignore expect(screen.getByTestId('cards').attributes.offsync.value).toBe('true'); }); statusCards = 200; await act(async () => { cardContext.actions.resync(); }); await waitFor(async () => { //@ts-ignore expect(screen.getByTestId('cards').attributes.offsync.value).toBe('false'); }); act(() => { cardContext.actions.clearToken(); }); }); test('resync contact', async () => { render(); await waitFor(async () => { expect(cardContext).not.toBe(null); }); fetchCards = [{ id: '000a', revision: 1, data: { detailRevision: 2, profileRevision: 3, notifiedProfile: 3, notifiedArticle: 5, notifiedChannel: 6, notifiedView: 7, cardDetail: { status: 'connected', statusUpdate: 136, token: '01ab', }, cardProfile: { guid: '01ab23', handle: 'test1', name: 'tester', imageSet: false, seal: 'abc', version: '1.1.1', node: 'test.org' }, }, }]; await act(async () => { cardContext.actions.setToken('abc123'); cardContext.actions.setRevision(1); }); fetchCards = [{ id: '000a', revision: 2, data: { detailRevision: 2, profileRevision: 3, notifiedProfile: 4, notifiedArticle: 5, notifiedChannel: 6, notifiedView: 7, }, }]; statusMessage = 500; await act(async () => { cardContext.actions.setRevision(2); }); await waitFor(async () => { //@ts-ignore expect(screen.getByTestId('card').attributes.offsync.value).toBe('true'); }); statusMessage = 200; await act(async () => { cardContext.actions.resyncCard('000a'); }); await waitFor(async () => { //@ts-ignore expect(screen.getByTestId('card').attributes.offsync.value).toBe('false'); }); act(() => { cardContext.actions.clearToken(); }); }); test('add, update, remove card', async () => { render(); await waitFor(async () => { expect(cardContext).not.toBe(null); }); await act( async () => { cardContext.actions.setToken('abc123'); }); fetchCards = [{ id: '000a', revision: 1, data: { detailRevision: 2, profileRevision: 3, notifiedProfile: 3, notifiedArticle: 5, notifiedChannel: 6, notifiedView: 7, cardDetail: { status: 'connected', statusUpdate: 136, token: '01ab', }, cardProfile: { guid: '01ab23', handle: 'test1', name: 'tester', imageSet: false, seal: 'abc', version: '1.1.1', node: 'test.org' }, }, }]; await act( async () => { cardContext.actions.setRevision(1); }); await waitFor(async () => { expect(screen.getByTestId('cards').children).toHaveLength(1); expect(screen.getByTestId('name').textContent).toBe('tester'); expect(screen.getByTestId('status').textContent).toBe('connected'); expect(screen.getByTestId('token').textContent).toBe('01ab'); }); fetchCards = [{ id: '000a', revision: 2, data: { detailRevision: 3, profileRevision: 4, notifiedProfile: 3, notifiedArticle: 5, notifiedChannel: 6, notifiedView: 7, }, }]; fetchProfile = { guid: '01ab23', name: 'tested', }; fetchDetail = { status: 'confirmed', }; await act( async () => { cardContext.actions.setRevision(2); }); await waitFor(async () => { expect(screen.getByTestId('name').textContent).toBe('tested'); expect(screen.getByTestId('status').textContent).toBe('confirmed'); }); fetchCards = [{ id: '000a', revision: 3, }]; await act( async () => { cardContext.actions.setRevision(3); }); await waitFor(async () => { expect(screen.getByTestId('cards').children).toHaveLength(0); }); act(() => { cardContext.actions.clearToken(); }); });