databag/net/web/test/Conversation.test.js

517 lines
12 KiB
JavaScript
Raw Normal View History

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 { ChannelContextProvider, ChannelContext } from 'context/ChannelContext';
import { ConversationContextProvider, ConversationContext } from 'context/ConversationContext';
import * as fetchUtil from 'api/fetchUtil';
let cardContext = null;
let channelContext = null;
let conversationContext = null;
function ConversationView() {
const [renderCount, setRenderCount] = useState(0);
const [topics, setTopics] = useState([]);
const card = useContext(CardContext);
const channel = useContext(ChannelContext);
const conversation = useContext(ConversationContext);
cardContext = card;
channelContext = channel;
conversationContext = conversation;
useEffect(() => {
const rendered = []
const entries = Array.from(conversation.state.topics.values());
entries.forEach(entry => {
rendered.push(
<div key={entry.id} data-testid="topic">
2023-01-10 23:35:57 +00:00
<span data-testid="data">{entry.data.topicDetail.data}</span>
</div>);
});
setTopics(rendered);
setRenderCount(renderCount + 1);
2023-01-10 23:35:57 +00:00
}, [conversation.state])
return (
<div data-testid="topics" count={renderCount} offsync={card.state.offsync.toString()}>
{ topics }
</div>
);
}
function ConversationTestApp() {
return (
<CardContextProvider>
<ChannelContextProvider>
<ConversationContextProvider>
<ConversationView />
</ConversationContextProvider>
</ChannelContextProvider>
</CardContextProvider>
)
}
const realFetchWithTimeout = fetchUtil.fetchWithTimeout;
const realFetchWithCustomTimeout = fetchUtil.fetchWithCustomTimeout;
let beginSet;
2023-01-11 06:49:02 +00:00
let endSet;
let statusCards;
let fetchCards;
let statusChannels;
let fetchChannels;
let statusCardChannels;
let fetchCardChannels;
2023-01-10 23:35:57 +00:00
let statusTopics;
let fetchTopics;
2023-01-11 06:10:05 +00:00
let statusTopic;
let fetchTopic;
beforeEach(() => {
statusCards = 200;
fetchCards = [];
statusChannels = 200;
fetchChannels = [];
statusCardChannels = 200;
fetchCardChannels = [];
2023-01-10 23:35:57 +00:00
statusTopics = 200;
fetchTopics = [];
2023-01-11 06:10:05 +00:00
statusTopic = 200;
fetchTopic = {};
2023-01-11 06:49:02 +00:00
endSet = false;
beginSet = false;
const mockFetch = jest.fn().mockImplementation((url, options) => {
2023-01-18 07:42:22 +00:00
const params = url.split('/');
2023-01-18 07:42:22 +00:00
if (params[2]?.startsWith('channels?agent')) {
return Promise.resolve({
url: 'getChannels',
status: statusChannels,
json: () => Promise.resolve(fetchChannels),
});
}
2023-01-18 07:42:22 +00:00
else if (params[4]?.startsWith('channels?contact')) {
return Promise.resolve({
url: 'getCardChannels',
status: statusCardChannels,
json: () => Promise.resolve(fetchCardChannels),
});
}
else if (params[2]?.split('?')[0] === 'cards') {
return Promise.resolve({
url: 'getCards',
status: statusCards,
json: () => Promise.resolve(fetchCards),
});
}
2023-01-11 06:10:05 +00:00
else if (params[4] === 'topics') {
return Promise.resolve({
url: 'getTopic',
status: statusTopic,
json: () => Promise.resolve(fetchTopic),
});
}
2023-01-10 23:35:57 +00:00
else if (params[6]?.split('?')[0] === 'topics' || params[4]?.split('?')[0] === 'topics') {
2023-01-11 06:49:02 +00:00
if (url.endsWith('end=48')) {
endSet = true;
}
if (url.endsWith('begin=48')) {
beginSet = true;
}
2023-01-11 06:49:02 +00:00
const headers = new Map();
headers.set('topic-marker', 48);
headers.set('topic-revision', 55);
2023-01-10 23:35:57 +00:00
return Promise.resolve({
url: 'getTopics',
status: statusTopics,
2023-01-11 06:49:02 +00:00
headers: headers,
2023-01-10 23:35:57 +00:00
json: () => Promise.resolve(fetchTopics),
});
}
else {
return Promise.resolve({
url: 'endpoint',
status: 200,
2023-01-10 21:16:13 +00:00
headers: new Map(),
2023-01-11 06:10:05 +00:00
json: () => Promise.resolve({}),
});
}
});
fetchUtil.fetchWithTimeout = mockFetch;
fetchUtil.fetchWithCustomTimeout = mockFetch;
});
afterEach(() => {
fetchUtil.fetchWithTimeout = realFetchWithTimeout;
fetchUtil.fetchWithCustomTimeout = realFetchWithCustomTimeout;
});
2023-01-11 06:10:05 +00:00
test('add, update, and remove topic', async() => {
render(<ConversationTestApp />);
await waitFor(async () => {
expect(cardContext).not.toBe(null);
expect(channelContext).not.toBe(null);
expect(conversationContext).not.toBe(null);
});
await act(async () => {
cardContext.actions.setToken('abc123');
channelContext.actions.setToken('abc123');
});
fetchChannels = [
{ id: '123', revision: 2, data: {
detailRevision: 3,
topicRevision: 5,
channelSummary: { guid: '11', dataType: 'superbasictopic', data: 'testdata' },
channelDetail: { dataType: 'superbasic', data: 'testdata' },
}
},
];
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' },
},
}];
fetchCardChannels = [
{ id: 'aabb', revision: 2, data: {
detailRevision: 3,
topicRevision: 5,
channelSummary: { guid: '11', dataType: 'superbasictopic', data: 'testcardtopic' },
channelDetail: { dataType: 'superbasic', data: 'testcardchannel' },
}
},
];
await act(async () => {
cardContext.actions.setRevision(1);
channelContext.actions.setRevision(1);
});
2023-01-10 23:35:57 +00:00
fetchTopics = [
{ id: '888', revision: 5, data: {
detailRevision: 3,
tagRevision: 0,
topicDetail: {
guid: '0123',
dataType: 'topictype',
data: 'contacttopicdata',
created: 1,
updated: 1,
status: 'confirmed',
transform: 'complete',
},
}
}
];
2023-01-10 21:16:13 +00:00
await act(async () => {
conversationContext.actions.setChannel('000a', 'aabb');
});
2023-01-10 23:35:57 +00:00
await waitFor(async () => {
expect(screen.getByTestId('topics').children).toHaveLength(1);
expect(screen.getByTestId('data').textContent).toBe('contacttopicdata');
});
fetchTopics = [
{ id: '888', revision: 5, data: {
detailRevision: 3,
tagRevision: 0,
topicDetail: {
guid: '0123',
dataType: 'topictype',
data: 'agenttopicdata',
created: 1,
updated: 1,
status: 'confirmed',
transform: 'complete',
},
}
}
];
await act(async () => {
conversationContext.actions.setChannel(null, '123');
});
await waitFor(async () => {
expect(screen.getByTestId('topics').children).toHaveLength(1);
expect(screen.getByTestId('data').textContent).toBe('agenttopicdata');
});
2023-01-11 06:10:05 +00:00
fetchChannels = [
{ id: '123', revision: 2, data: {
detailRevision: 3,
topicRevision: 6,
}
},
];
fetchTopics = [
{ id: '888', revision: 5, data: {
detailRevision: 3,
tagRevision: 0,
}
}
];
fetchTopic = { id: '888', revision: 5, data: {
detailRevision: 4,
tagRevision: 0,
topicDetail: {
guid: '0123',
dataType: 'topictype',
data: 'agenttopicdata2',
created: 1,
updated: 1,
status: 'confirmed',
transform: 'complete',
},
}
};
await act(async () => {
channelContext.actions.setRevision(2);
});
await waitFor(async () => {
expect(screen.getByTestId('topics').children).toHaveLength(1);
expect(screen.getByTestId('data').textContent).toBe('agenttopicdata');
});
fetchChannels = [
{ id: '123', revision: 3, data: {
2023-01-11 06:10:05 +00:00
detailRevision: 3,
topicRevision: 7,
}
},
];
fetchTopics = [
{ id: '888', revision: 6, data: {
2023-01-11 06:10:05 +00:00
detailRevision: 4,
tagRevision: 0,
}
}
];
await act(async () => {
channelContext.actions.setRevision(3);
});
await waitFor(async () => {
expect(screen.getByTestId('topics').children).toHaveLength(1);
expect(screen.getByTestId('data').textContent).toBe('agenttopicdata2');
});
fetchChannels = [
{ id: '123', revision: 2, data: {
detailRevision: 3,
topicRevision: 8,
}
},
];
fetchTopics = [
{ id: '888', revision: 6 }
];
await act(async () => {
channelContext.actions.setRevision(4);
});
await waitFor(async () => {
expect(screen.getByTestId('topics').children).toHaveLength(0);
});
act(() => {
cardContext.actions.clearToken();
channelContext.actions.clearToken();
});
});
2023-01-11 06:49:02 +00:00
test('load more', async() => {
render(<ConversationTestApp />);
await waitFor(async () => {
expect(cardContext).not.toBe(null);
expect(channelContext).not.toBe(null);
expect(conversationContext).not.toBe(null);
});
await act(async () => {
cardContext.actions.setToken('abc123');
channelContext.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' },
},
}];
fetchCardChannels = [
{ id: 'aabb', revision: 2, data: {
detailRevision: 3,
topicRevision: 5,
channelSummary: { guid: '11', dataType: 'superbasictopic', data: 'testcardtopic' },
channelDetail: { dataType: 'superbasic', data: 'testcardchannel' },
}
},
];
await act(async () => {
cardContext.actions.setRevision(1);
channelContext.actions.setRevision(1);
});
fetchTopics = [];
for (let i = 0; i < 32; i++) {
fetchTopics.push({ id: i.toString(), revision: 5, data: {
detailRevision: 3,
tagRevision: 0,
topicDetail: {
guid: '0123',
dataType: 'topictype',
data: 'contacttopicdata',
created: 1,
updated: 1,
status: 'confirmed',
transform: 'complete',
},
}});
}
await act(async () => {
await conversationContext.actions.setChannel('000a', 'aabb');
});
await waitFor(async () => {
expect(endSet).toBe(false);
expect(beginSet).toBe(false);
2023-01-11 06:49:02 +00:00
expect(screen.getByTestId('topics').children).toHaveLength(32);
});
fetchTopics = [];
for (let i = 100; i < 111; i++) {
fetchTopics.push({ id: i.toString(), revision: 5, data: {
detailRevision: 3,
tagRevision: 0,
topicDetail: {
guid: '0123',
dataType: 'topictype',
data: 'contacttopicdata',
created: 1,
updated: 1,
status: 'confirmed',
transform: 'complete',
},
}});
}
await act(async () => {
await conversationContext.actions.loadMore();
});
await waitFor(async () => {
expect(endSet).toBe(true);
expect(beginSet).toBe(false);
2023-01-11 06:49:02 +00:00
expect(screen.getByTestId('topics').children).toHaveLength(43);
});
fetchCards = [{
id: '000a',
revision: 2,
data: {
detailRevision: 2,
profileRevision: 3,
notifiedProfile: 3,
notifiedArticle: 5,
notifiedChannel: 7,
notifiedView: 7,
},
}];
fetchCardChannels = [
{ id: 'aabb', revision: 2, data: {
detailRevision: 3,
topicRevision: 6,
channelSummary: { guid: '11', dataType: 'superbasictopic', data: 'testcardtopic' },
channelDetail: { dataType: 'superbasic', data: 'testcardchannel' },
}
},
];
await act(async () => {
cardContext.actions.setRevision(2);
});
await waitFor(async () => {
expect(beginSet).toBe(true);
});
fetchTopics = [{ id: 300, revision: 5, data: {
detailRevision: 3,
tagRevision: 0,
topicDetail: {
guid: '0123',
dataType: 'topictype',
data: 'contacttopicdata',
created: 1,
updated: 1,
status: 'confirmed',
transform: 'complete',
},
}}];
await act(async () => {
conversationContext.actions.resync();
});
await waitFor(async () => {
expect(screen.getByTestId('topics').children).toHaveLength(44);
});
2023-01-11 06:49:02 +00:00
await act(async () => {
await conversationContext.actions.clearChannel();
});
await waitFor(async () => {
expect(screen.getByTestId('topics').children).toHaveLength(0);
});
});