import React, { useState, useEffect, useContext } from 'react'; import { View, Text } from 'react-native'; import { useTestStoreContext } from 'context/useTestStoreContext.hook'; import { prettyDOM } from '@testing-library/dom'; import {render, act, screen, waitFor, fireEvent} from '@testing-library/react-native'; import { CardContextProvider, CardContext } from 'context/CardContext'; import * as fetchUtil from 'api/fetchUtil'; function CardView() { const [renderCount, setRenderCount] = useState(0); const card = useContext(CardContext); const [cards, setCards] = useState([]); useEffect(() => { setRenderCount(renderCount + 1); const rendered = []; card.state.cards.forEach((cardValue) => { const content = [( { cardValue.card.profile.handle } )]; cardValue.channels.forEach((channelValue) => { content.push({ channelValue.detail.data }); }); rendered.push( { content } ); }); setCards(rendered); }, [card.state]); return ( { cards } ); } function CardTestApp() { return ( ) } const realUseContext = React.useContext; const realFetchWithTimeout = fetchUtil.fetchWithTimeout; const realFetchWithCustomTimeout = fetchUtil.fetchWithCustomTimeout; let fetchMessage; let fetchCards; let fetchDetail; let fetchProfile; let fetchCardChannels; beforeEach(() => { fetchCards = []; fetchDetail = {}; fetchProfile = {}; fetchCardChannels = []; fetchMessage = false; const mockUseContext = jest.fn().mockImplementation((ctx) => { return useTestStoreContext(); }); React.useContext = mockUseContext; const mockFetch = jest.fn().mockImplementation((url, options) => { if (url.startsWith('https://test.org/contact/cards?agent')) { return Promise.resolve({ json: () => Promise.resolve(fetchCards) }); } if (url.startsWith('https://test.org/contact/cards/000a/profile?agent')) { return Promise.resolve({ json: () => Promise.resolve(fetchProfile) }); } if (url.startsWith('https://test.org/contact/cards/000a/detail?agent')) { return Promise.resolve({ json: () => Promise.resolve(fetchDetail) }); } if (url.startsWith('https://test.org/content/channels?contact')) { return Promise.resolve({ json: () => Promise.resolve(fetchCardChannels) }); } if (url.startsWith('https://test.org/profile/message?contact')) { fetchMessage = true; return Promise.resolve({ json: () => Promise.resolve({}) }); } else { return Promise.resolve({ json: () => Promise.resolve([]) }); } }); fetchUtil.fetchWithTimeout = mockFetch; fetchUtil.fetchWithCustomTimeout = mockFetch; }); afterEach(() => { React.useContext = realUseContext; fetchUtil.fetchWithTimeout = realFetchWithTimeout; fetchUtil.fetchWithCustomTimeout = realFetchWithCustomTimeout; }); test('add, update, and remove card', async () => { render() await act(async () => { const card = screen.getByTestId('card').props.card; await card.actions.setSession({ guid: 'abc', server: 'test.org', token: '123' }); await card.actions.setRevision(1); }); await waitFor(async () => { expect(screen.getByTestId('card').props.children).toHaveLength(0); }); fetchCards = [{ id: '000a', revision: 1, data: { detailRevision: 2, profileRevision: 3, notifiedProfile: 4, 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 () => { const card = screen.getByTestId('card').props.card; await card.actions.setRevision(2); }); await waitFor(async () => { expect(screen.getByTestId('card').props.children).toHaveLength(1); expect(screen.getByTestId('000a-handle').props.children).toBe('test1'); expect(fetchMessage).toBe(true); }); fetchCards = [{ id: '000a', revision: 2, data: { detailRevision: 3, profileRevision: 4, notifiedProfile: 4, notifiedArticle: 5, notifiedChannel: 6, notifiedView: 7, }, }]; fetchProfile = { guid: '01ab23', handle: 'test2', }; fetchDetail = { status: 'confirmed', } await act(async () => { const card = screen.getByTestId('card').props.card; await card.actions.setRevision(4); }); await waitFor(async () => { expect(screen.getByTestId('card').props.children).toHaveLength(1); expect(screen.getByTestId('000a-handle').props.children).toBe('test2'); }); fetchCards = [{ id: '000a', revision: 3, }]; await act(async () => { const card = screen.getByTestId('card').props.card; await card.actions.setRevision(4); }); await waitFor(async () => { expect(screen.getByTestId('card').props.children).toHaveLength(1); }); await act(async () => { const card = screen.getByTestId('card').props.card; await card.actions.setRevision(5); }); await waitFor(async () => { expect(screen.getByTestId('card').props.children).toHaveLength(0); }); }); test('add, update, and remove channel', async () => { render() 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 () => { const card = screen.getByTestId('card').props.card; await card.actions.setSession({ guid: 'abc', server: 'test.org', token: '123' }); await card.actions.setRevision(1); }); await waitFor(async () => { expect(screen.getByTestId('000a').props.children).toHaveLength(1); }); fetchCardChannels = [{ id: '01', revision: 1, data: { detailRevision: 1, topicRevision: 1, channelDetail: { dataType: 'superbasic', data: 'testchannel', }, channelSummary: { dataType: 'superbasictopic', data: 'testtopic', }, }, }]; fetchCards = [{ id: '000a', revision: 2, data: { detailRevision: 2, profileRevision: 3, notifiedProfile: 3, notifiedArticle: 5, notifiedChannel: 6, notifiedView: 7, }, }]; await act(async () => { const card = screen.getByTestId('card').props.card; await card.actions.setRevision(2); }); await waitFor(async () => { expect(screen.getByTestId('000a').props.children).toHaveLength(1); }); fetchCards = [{ id: '000a', revision: 2, data: { detailRevision: 2, profileRevision: 3, notifiedProfile: 3, notifiedArticle: 5, notifiedChannel: 7, notifiedView: 7, }, }]; await act(async () => { const card = screen.getByTestId('card').props.card; await card.actions.setRevision(3); }); await waitFor(async () => { expect(screen.getByTestId('000a').props.children).toHaveLength(2); expect(screen.getByTestId('01').props.children).toBe('testchannel'); }); fetchCardChannels = [{ id: '01', revision: 2, data: { detailRevision: 2, topicRevision: 2, channelDetail: { dataType: 'superbasic', data: 'testchannel2', }, channelSummary: { dataType: 'superbasictopic', data: 'testtopic', }, }, }]; fetchCards = [{ id: '000a', revision: 2, data: { detailRevision: 2, profileRevision: 3, notifiedProfile: 3, notifiedArticle: 5, notifiedChannel: 8, notifiedView: 7, }, }]; await act(async () => { const card = screen.getByTestId('card').props.card; await card.actions.setRevision(4); }); await waitFor(async () => { expect(screen.getByTestId('000a').props.children).toHaveLength(2); expect(screen.getByTestId('01').props.children).toBe('testchannel2'); }); fetchCardChannels = [{ id: '01', revision: 3, }]; fetchCards = [{ id: '000a', revision: 3, data: { detailRevision: 2, profileRevision: 3, notifiedProfile: 3, notifiedArticle: 5, notifiedChannel: 9, notifiedView: 7, }, }]; await act(async () => { const card = screen.getByTestId('card').props.card; await card.actions.setRevision(5); }); await waitFor(async () => { expect(screen.getByTestId('000a').props.children).toHaveLength(1); }); });