testing conversation context in mobile app

This commit is contained in:
Roland Osborne 2023-02-14 21:25:39 -08:00
parent 50fa8bf9af
commit d9157e4c08
6 changed files with 565 additions and 120 deletions

View File

@ -66,7 +66,7 @@ export function useCardContext() {
const card = cards.current.get(cardId);
if (card) {
card[field] = value;
cards.set(cardId, { ...card });
cards.current.set(cardId, { ...card });
updateState({ cards: cards.current });
}
};
@ -134,27 +134,48 @@ export function useCardContext() {
for (let card of delta) {
if (card.data) {
const item = setCardItem(card);
const entry = cards.current.get(card.id) || { card: { cardId: card.id }, channels: new Map() };
const { profileRevision, detailRevision } = entry.card;
if (item.profileRevision !== profileRevision) {
if (item.profile) {
entry.card.profile = item.profile;
}
else {
entry.card.profile = await getCardProfile(server, token, card.id);
}
entry.card.profileRevision = item.profileRevision;
await store.actions.setCardItemProfile(guid, card.id, entry.card.profileRevision, entry.card.profile);
}
if (item.detailRevision !== detailRevision) {
const entry = cards.current.get(card.id) || { channels: new Map() };
if (!entry.card) {
const { cardId, detailRevision, profileRevision } = item;
const entryCard = { cardId, detailRevision, profileRevision };
if (item.detail) {
entry.card.detail = item.detail;
entryCard.detail = item.detail;
}
else {
entry.card.detail = await getCardDetail(server, token, card.id);
entryCard.detail = await getCardDetail(server, token, card.id);
}
if (item.profile) {
entryCard.profile = item.profile;
}
else {
entryCard.profile = await getCardProfile(server, token, card.id);
}
await store.actions.setCardItem(guid, card.id, entryCard);
entry.card = entryCard;
cards.current.set(card.id, entry);
}
else {
const { profileRevision, detailRevision } = entry.card;
if (item.profileRevision !== profileRevision) {
if (item.profile) {
entry.card.profile = item.profile;
}
else {
entry.card.profile = await getCardProfile(server, token, card.id);
}
entry.card.profileRevision = item.profileRevision;
await store.actions.setCardItemProfile(guid, card.id, entry.card.profileRevision, entry.card.profile);
}
if (item.detailRevision !== detailRevision) {
if (item.detail) {
entry.card.detail = item.detail;
}
else {
entry.card.detail = await getCardDetail(server, token, card.id);
}
entry.card.detailRevision = item.detailRevision;
await store.actions.setCardItemDetail(guid, card.id, entry.card.detailRevision, entry.card.detail);
}
entry.card.detailRevision = item.detailRevision;
await store.actions.setCardItemDetail(guid, card.id, entry.card.detailRevision, entry.card.detail);
}
if (entry.card.detail?.status === 'connected' && !entry.card.offsync) {
try {
@ -168,7 +189,7 @@ export function useCardContext() {
await store.action.setCardItemOffsync(guid, card.id);
}
}
cards.current.set(card.id, entry);
cards.current.set(card.id, { ...entry });
}
else {
const entry = cards.current.get(card.id) || { card: {}, channels: new Map() };
@ -223,31 +244,42 @@ export function useCardContext() {
for (let channel of delta) {
if (channel.data) {
const channelItem = setCardChannelItem(channel);
const channelEntry = entry.channels.get(channel.id) || { channelId: channel.id };
const { detailRevision, topicRevision } = channelEntry;
if (channelItem.detailRevision !== detailRevision) {
if (channelItem.detail) {
channelEntry.detail = channelItem.detail;
const channelEntry = entry.channels.get(channel.id);
if (!channelEntry) {
if (!channelItem.detail) {
channelItem.detail = await getContactChannelDetail(cardServer, cardToken, channel.id);
}
else {
channelEntry.detail = await getContactChannelDetail(cardServer, cardToken, channel.id);
if (!channelItem.summary) {
channelItem.summary = await getContactChannelSummary(cardServer, cardToken, channel.id);
}
channelEntry.unsealedDetail = null;
channelEntry.detailRevision = channelItem.detailRevision;
await store.actions.setCardChannelItemDetail(guid, cardId, channel.id, channelItem.detailRevision, channelEntry.detail);
await store.actions.setCardChannelItem(guid, cardId, channelItem);
entry.channels.set(channel.id, { ...channelItem });
}
if (channelItem.topicRevision !== topicRevision) {
if (channelItem.summary) {
channelEntry.summary = channelItem.summary;
else {
if (channelItem.detailRevision !== channelEntry.detailRevision) {
if (channelItem.detail) {
channelEntry.detail = channelItem.detail;
}
else {
channelEntry.detail = await getContactChannelDetail(cardServer, cardToken, channel.id);
}
channelEntry.unsealedDetail = null;
channelEntry.detailRevision = channelItem.detailRevision;
await store.actions.setCardChannelItemDetail(guid, cardId, channel.id, channelEntry.detailRevision, channelEntry.detail);
}
else {
channelEntry.summary = await getContactChannelSummary(cardServer, cardToken, channel.id);
if (channelItem.topicRevision !== channelEntry.topicRevision) {
if (channelItem.summary) {
channelEntry.summary = channelItem.summary;
}
else {
channelEntry.summary = await getContactChannelSummary(cardServer, cardToken, channel.id);
}
channelEntry.unsealedSummary = null;
channelEntry.topicRevision = channelItem.topicRevision;
await store.actions.setCardChannelItemSummary(guid, cardId, channel.id, channelEntry.topicRevision, channelEntry.summary);
}
channelEntry.unsealedSummary = null;
channelEntry.topicRevision = channelItem.topicRevision;
await store.actions.setCardChannelItemSummary(guid, cardId, channel.id, channelItem.topicRevision, channelEntry.summary);
entry.channels.set(channel.id, { ...channelEntry });
}
entry.channels.set(channel.id, channelEntry);
}
else {
await store.actions.clearCardChannelTopicItems(guid, cardId, channel.id);
@ -271,14 +303,12 @@ export function useCardContext() {
cards.current = new Map();
const cardItems = await store.actions.getCardItems(session.guid);
for(card of cardItems) {
cards.current.set(card.cardId, { card, channels: new Map() });
}
const cardChannelItems = await store.actions.getCardChannelItems(session.guid);
for (cardChannel of cardChannelItems) {
const card = cards.current.get(cardChannel.cardId);
if (card) {
card.channels.set(card.channelId, cardChannel);
const entry = { card, channels: new Map() };
const cardChannelItems = await store.actions.getCardChannelItems(session.guid, card.cardId);
for (cardChannel of cardChannelItems) {
entry.channels.set(cardChannel.channelId, cardChannel);
}
cards.current.set(card.cardId, entry);
}
const status = await store.actions.getCardRequestStatus(session.guid);
const revision = await store.actions.getCardRevision(session.guid);
@ -362,27 +392,27 @@ export function useCardContext() {
}
},
removeTopic: async (cardId, channelId, topicId) => {
const { detail, profile } = cards.current.get(cardId) || {};
const { detail, profile } = (cards.current.get(cardId) || {}).card;
const cardToken = `${profile?.guid}.${detail?.token}`;
return await removeContactChannelTopic(profile?.node, cardToken, channelId, topicId);
},
setTopicSubject: async (cardId, channelId, topicId, type, subject) => {
const { detail, profile } = cards.current.get(cardId) || {};
const { detail, profile } = (cards.current.get(cardId) || {}).card;
const cardToken = `${profile?.guid}.${detail?.token}`;
return await setContactChannelTopicSubject(profile?.node, cardToken, channelId, topicId, type, subject);
},
getTopicAssetUrl: (cardId, channelId, topicId, assetId) => {
const { detail, profile } = cards.current.get(cardId) || {};
const { detail, profile } = (cards.current.get(cardId) || {}).card;
const cardToken = `${profile?.guid}.${detail?.token}`;
return getContactChannelTopicAssetUrl(profile?.node, cardToken, channelId, topicId, assetId);
},
getTopics: async (cardId, channelId, revision, count, begin, end) => {
const { detail, profile } = cards.current.get(cardId) || {};
const { detail, profile } = (cards.current.get(cardId) || {}).card;
const cardToken = `${profile?.guid}.${detail?.token}`;
return await getContactChannelTopics(profile?.node, cardToken, channelId);
},
getChannelTopic: async (cardId, channelId, topicId) => {
const { detail, profile } = cards.current.get(cardId) || {};
getTopic: async (cardId, channelId, topicId) => {
const { detail, profile } = (cards.current.get(cardId) || {}).card;
const cardToken = `${profile?.guid}.${detail?.token}`;
return await getContactChannelTopic(profile?.node, cardToken, channelId, topicId);
},
@ -394,22 +424,22 @@ export function useCardContext() {
setChannelReadRevision: async (cardId, channelId, revision) => {
const { guid } = access.current;
await store.actions.setCardChannelItemReadRevision(guid, cardId, channelId, revision);
setCardField(cardId, 'readRevision', revision);
setCardChannelField(cardId, channelId, 'readRevision', revision);
},
setChannelSyncRevision: async (cardId, channelId, revision) => {
const { guid } = access.current;
await store.actions.setCardChannelItemSyncRevision(guid, cardId, channelId, revision);
setCardField(cardId, 'syncRevision', revision);
setCardChannelField(cardId, channelId, 'syncRevision', revision);
},
setChannelTopicMarker: async (cardId, channelId, marker) => {
const { guid } = access.current;
await store.actions.setCardChannelItemTopicMarker(guid, cardId, channelId, marker);
setCardField(cardId, 'topicMarker', marker);
setCardChannelField(cardId, channelId, 'topicMarker', marker);
},
setChannelMarkerAndSync: async (cardId, channelId, marker, revision) => {
const { guid } = access.current;
await store.actions.setCardChannelItemMarkerAndSync(guid, cardId, channelId, marker, revision);
setCardField(cardId, 'topicMarker', marker, 'syncRevision', revision);
setCardChannelField(cardId, channelId, 'topicMarker', marker, 'syncRevision', revision);
},
setCardFlag: async (cardId) => {
const { guid } = acccess.current;
@ -440,20 +470,20 @@ export function useCardContext() {
await store.actions.setCardChannelTopicBlocked(guid, cardId, channelId, topicId, false);
},
addChannelAlert: async (cardId, channelId) => {
const { profile } = cards.current.get(cardId) || {};
const { detail, profile } = (cards.current.get(cardId) || {}).card;
return await addFlag(profile?.node, profile?.guid, channelId);
},
addTopicAlert: async (cardId, channelId, topicId) => {
const { detail, profile } = cards.current.get(cardId) || {};
const { detail, profile } = (cards.current.get(cardId) || {}).card;
return await addFlag(profile?.node, profile?.guid, channelId, topicId);
},
getChannelNotifications: async (cardId, channelId) => {
const { detail, profile } = cards.current.get(cardId) || {};
const { detail, profile } = (cards.current.get(cardId) || {}).card;
const token = `${profile?.guid}.${detail?.token}`;
return await getContactChannelNotifications(profile?.node, token, channelId);
},
setChannelNotifications: async (cardId, channelId, notify) => {
const { detail, profile } = cards.current.get(cardId) || {};
const { detail, profile } = (cards.current.get(cardId) || {}).card;
const token = `${profile?.guid}.${detail?.token}`;
return await setContactChannelNotifications(profile?.node, token, channelId, notify);
},

View File

@ -48,12 +48,12 @@ export function useChannelContext() {
}
const setChannelField = (channelId, field, value, field2, value2) => {
const channel = channels.get(channelId) || {};
const channel = channels.current.get(channelId) || {};
channel[field] = value;
if (field2) {
channel[field2] = value2;
}
channels.set(channelId, { ...channel });
channels.current.set(channelId, { ...channel });
updateState({ channels: channels.current });
};
@ -67,30 +67,31 @@ export function useChannelContext() {
for (let channel of delta) {
if (channel.data) {
const item = setChannelItem(channel);
if (item.detail && item.summary) {
const entry = channels.current.get(channel.id);
if (!entry) {
if (!item.detail) {
item.detail = await getChannelDetail(server, token, channel.id);
}
if (!item.summary) {
item.summary = await getChannelSummary(server, token, channel.id);
}
await store.actions.setChannelItem(guid, item);
channels.current.set(item.channelId, item);
channels.current.set(channel.id, item);
}
else {
const { channelId, detailRevision, topicRevision, detail, summary } = channels.current.get(channel.id) || {}
if (item.detailRevision !== detailRevision) {
item.detailRevision = detailRevision;
item.detail = await getChannelDetail(server, token, channelId);
await store.actions.setChannelItemDetail(guid, channelId, detailRevision, item.detail);
if (item.detailRevision !== entry.detailRevision) {
entry.detail = await getChannelDetail(server, token, channel.id);
entry.unsealedDetail = null;
entry.detailRevision = item.detailRevision;
await store.actions.setChannelItemDetail(guid, channel.id, entry.detailRevision, entry.detail);
}
else {
item.datail = detail;
if (item.topicRevision !== entry.topicRevision) {
entry.summary = await getChannelSummary(server, token, channel.id);
entry.unsealedSummary = null;
entry.topicRevision = item.topicRevision;
await store.actions.setChannelItemSummary(guid, channel.id, entry.topicRevision, entry.summary);
}
if (item.topicRevision !== topicRevision) {
item.topicRevision = topicRevision;
item.summary = await getChannelSummary(server, token, item.channelId);
await store.actions.setChannelItemSummary(guid, channelId, topicRevision, item.summary);
}
else {
item.summary = summary;
}
await store.actions.setChannelItem(guid, item);
channels.current.set(channelId, item);
channels.current.set(channel.id, { ...entry });
}
}
else {
@ -192,7 +193,7 @@ export function useChannelContext() {
const { server, token } = access.current;
getChannelTopicAssetUrl(server, token, channelId, topicId, assetId);
},
getTopics: async (channelId) => {
getTopics: async (channelId, revision, count, begin, end) => {
const { server, token } = access.current;
return await getChannelTopics(server, token, channelId, revision, count, begin, end);
},

View File

@ -33,11 +33,11 @@ export function useConversationContext() {
}
const sync = async () => {
if (!syncing.current && (reset.current || update.current || force.current || more.current)) {
if (!syncing.current && (reset.current || update.current || force.current || more.current)) {
const loadMore = more.current;
const ignoreRevision = force.current;
const conversation = converstaionId.current;
const conversation = conversationId.current;
let curRevision, setRevision, marker;
syncing.current = true;
@ -55,9 +55,11 @@ export function useConversationContext() {
if (conversation) {
const { cardId, channelId } = conversation;
const cardValue = cardId ? card.state.cards.get(cardId) : null;
const channelValue = cardId ? cardValue?.get(channelId) : channel.state.channels.get(channelId);
const channelValue = cardId ? cardValue?.channels.get(channelId) : channel.state.channels.get(channelId);
if (channelValue) {
const { topicRevision, syncRevision, topicMarker } = channelValue;
curRevision = topicRevision;
setRevision = syncRevision;
marker = topicMarker;
@ -78,33 +80,35 @@ export function useConversationContext() {
return;
}
try {
if (!marker) {
const delta = await getTopicDelta(cardId, channelId, null, COUNT, null, null);
await setTopicDelta(cardId, channelId, delta.topics);
setMarkerAndSync(cardId, channelId, topicMarker, topicRevision);
if (ignoreRevision || curRevision !== setRevision) {
try {
if (!marker) {
const delta = await getTopicDelta(cardId, channelId, null, COUNT, null, null);
await setTopicDelta(cardId, channelId, delta.topics);
await setMarkerAndSync(cardId, channelId, delta.marker, curRevision);
}
if (loadMore && marker) {
const delta = await getTopicDelta(cardId, channelId, null, COUNT, null, marker);
await setTopicDelta(cardId, channelId, delta.topics);
await setTopicMarker(cardId, channelId, delta.marker);
}
if (ignoreRevision || curRevision !== setRevision) {
const delta = await getTopicDelta(cardId, channelId, setRevision, null, marker, null);
await setTopicDelta(cardId, channelId, delta.topics);
await setSyncRevision(cardId, channelId, curRevision);
}
}
if (loadMore && marker) {
const delta = await getTopicDelta(cardId, channelId, null, COUNT, null, marker);
await setTopicDelta(cardId, channelId, delta.topics);
setTopicMarker(cardId, channelId, delta.topicMarker);
}
if (ignoreRevision || curTopicRevision.current !== setTopicRevision.current) {
const delta = await getTopicDelta(cardId, channelId, setRevision, null, marker, null);
await setTopicDelta(cardId, channelId, delta.topics);
setSyncRevision(cardid, channelId, delta.topicRevision);
catch(err) {
console.log(err);
updateState({ offysnc: true });
syncing.current = false;
return
}
}
catch(err) {
console.log(err);
updateState({ offysnc: true });
syncing.current = false;
return
}
syncing.current = false;
await sync();
}
syncing.current = false;
await sync();
}
}
@ -354,7 +358,7 @@ export function useConversationContext() {
if (cardId) {
return await card.actions.setChannelSyncRevision(cardId, channelId, revision);
}
return await channel.actions.setSyncRevision(channelid, revision);
return await channel.actions.setSyncRevision(channelId, revision);
}
const setMarkerAndSync = async (cardId, channelId, marker, revision) => {
@ -378,7 +382,7 @@ export function useConversationContext() {
return await channel.actions.getTopic(channelId, topicId);
}
const mapTopicItem = (entry) => {
const mapTopicEntry = (entry) => {
return {
topicId: entry.id,
revision: entry.revision,
@ -392,7 +396,7 @@ export function useConversationContext() {
if (topic) {
topic[field] = value;
}
topics.current.set(topicId, topic);
topics.current.set(topicId, { ...topic });
updateState({ topics: topics.current });
};

View File

@ -296,10 +296,9 @@ export function useStoreContext() {
setCardChannelItemUnsealedSummary: async (guid, cardId, channelId, revision, unsealed) => {
await db.current.executeSql(`UPDATE card_channel_${guid} set unsealed_summary=? where topic_revision=? AND card_id=? AND channel_id=?`, [encodeObject(unsealed), revision, cardId, channelId]);
},
getCardChannelItems: async (guid) => {
const values = await getAppValues(db.current, `SELECT card_id, channel_id, read_revision, sync_revision, revision, blocked, detail_revision, topic_revision, topic_marker, detail, unsealed_detail, summary, unsealed_summary FROM card_channel_${guid}`, []);
getCardChannelItems: async (guid, cardId) => {
const values = await getAppValues(db.current, `SELECT channel_id, read_revision, sync_revision, revision, blocked, detail_revision, topic_revision, topic_marker, detail, unsealed_detail, summary, unsealed_summary FROM card_channel_${guid} where card_id=?`, [cardId]);
return values.map(channel => ({
cardId: channel.card_id,
channelId: channel.channel_id,
revision: channel.revision,
readRevision: channel.read_revision,

View File

@ -19,11 +19,16 @@ function ConversationView() {
useEffect(() => {
setRenderCount(renderCount + 1);
const rendered = [];
conversation.state.topics.forEach((value) => {
rendered.push(<Text key={value.topicId} testID={value.topicId}>{ value.detail.data }</Text>);
});
setTopics(rendered);
}, [conversation.state]);
return (
<View key="conversation" testID="conversation" renderCount={renderCount}
card={card} channel={channel} conversation={conversation}>
{ topics }
</View>
);
}
@ -40,10 +45,20 @@ function ConversationTestApp() {
)
}
let fetchCards;
let fetchChannels;
let fetchCardChannels;
let fetchTopics;
const realUseContext = React.useContext;
const realFetchWithTimeout = fetchUtil.fetchWithTimeout;
const realFetchWithCustomTimeout = fetchUtil.fetchWithCustomTimeout;
beforeEach(() => {
fetchCards = [];
fetchChannels = [];
fetchCardChannels = [];
const mockUseContext = jest.fn().mockImplementation((ctx) => {
if (ctx === StoreContext) {
return useTestStoreContext();
@ -53,9 +68,39 @@ beforeEach(() => {
React.useContext = mockUseContext;
const mockFetch = jest.fn().mockImplementation((url, options) => {
return Promise.resolve({
json: () => Promise.resolve([])
});
if (url.startsWith('https://test.org/content/channels?agent')) {
return Promise.resolve({
json: () => Promise.resolve(fetchChannels)
});
}
else if (url.startsWith('https://test.org/contact/cards?agent')) {
return Promise.resolve({
json: () => Promise.resolve(fetchCards)
});
}
else if (url.startsWith('https://test.org/content/channels?contact')) {
return Promise.resolve({
json: () => Promise.resolve(fetchCardChannels)
});
}
else if (url.startsWith('https://test.org/content/channels/aabb/topics?contact') ||
url.startsWith('https://test.org/content/channels/123/topics?agent')) {
const headers = new Map();
headers.set('topic-marker', 48);
headers.set('topic-revision', 55);
return Promise.resolve({
url: 'getTopics',
status: 200,
headers: headers,
json: () => Promise.resolve(fetchTopics),
});
}
else {
return Promise.resolve({
json: () => Promise.resolve([])
});
}
});
fetchUtil.fetchWithTimeout = mockFetch;
fetchUtil.fetchWithCustomTimeout = mockFetch;
@ -67,7 +112,7 @@ afterEach(() => {
fetchUtil.fetchWithCustomTimeout = realFetchWithCustomTimeout;
});
test('test conversation', async () => {
test('add, update, remove card channel topic', async () => {
render(<ConversationTestApp />)
@ -81,5 +126,362 @@ test('test conversation', async () => {
await card.actions.setRevision(1);
//const conversation = screen.getByTestId('conversation').props.conversation;
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(0);
});
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' },
}
},
];
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',
},
}
}
];
await act(async () => {
const conversation = screen.getByTestId('conversation').props.conversation;
conversation.actions.setConversation('000a', 'aabb');
const channel = screen.getByTestId('conversation').props.channel;
await channel.actions.setRevision(2);
const card = screen.getByTestId('conversation').props.card;
await card.actions.setRevision(2);
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(1);
expect(screen.getByTestId('888').props.children).toBe('contacttopicdata');
});
fetchCards = [{
id: '000a',
revision: 2,
data: {
detailRevision: 2,
profileRevision: 3,
notifiedProfile: 3,
notifiedArticle: 5,
notifiedChannel: 7,
notifiedView: 7,
},
}];
fetchCardChannels = [
{ id: 'aabb', revision: 3, data: {
detailRevision: 3,
topicRevision: 6,
}
},
];
fetchTopics = [
{ id: '888', revision: 6, data: {
detailRevision: 4,
tagRevision: 0,
topicDetail: {
guid: '0123',
dataType: 'topictype',
data: 'contacttopicdata2',
created: 1,
updated: 1,
status: 'confirmed',
transform: 'complete',
},
}
}
];
await act(async () => {
const card = screen.getByTestId('conversation').props.card;
await card.actions.setRevision(3);
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(1);
expect(screen.getByTestId('888').props.children).toBe('contacttopicdata2');
});
fetchCards = [{
id: '000a',
revision: 3,
data: {
detailRevision: 2,
profileRevision: 3,
notifiedProfile: 3,
notifiedArticle: 5,
notifiedChannel: 8,
notifiedView: 7,
},
}];
fetchCardChannels = [
{ id: 'aabb', revision: 4, data: {
detailRevision: 3,
topicRevision: 6,
}
},
];
fetchTopics = [
{ id: '888', revision: 6 }
];
await act(async () => {
const card = screen.getByTestId('conversation').props.card;
await card.actions.setRevision(4);
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(1);
});
fetchCards = [{
id: '000a',
revision: 4,
data: {
detailRevision: 2,
profileRevision: 3,
notifiedProfile: 3,
notifiedArticle: 5,
notifiedChannel: 9,
notifiedView: 7,
},
}];
fetchCardChannels = [
{ id: 'aabb', revision: 5, data: {
detailRevision: 3,
topicRevision: 7,
}
},
];
await act(async () => {
const card = screen.getByTestId('conversation').props.card;
await card.actions.setRevision(5);
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(0);
});
});
test('add, update, remove channel topic', async () => {
render(<ConversationTestApp />)
await act(async () => {
const channel = screen.getByTestId('conversation').props.channel;
await channel.actions.setSession({ guid: 'abc', server: 'test.org', token: '123' });
await channel.actions.setRevision(1);
const card = screen.getByTestId('conversation').props.card;
await card.actions.setSession({ guid: 'abc', server: 'test.org', token: '123' });
await card.actions.setRevision(1);
//const conversation = screen.getByTestId('conversation').props.conversation;
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(0);
});
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' },
}
},
];
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',
},
}
}
];
await act(async () => {
const conversation = screen.getByTestId('conversation').props.conversation;
conversation.actions.setConversation(null, '123');
const channel = screen.getByTestId('conversation').props.channel;
await channel.actions.setRevision(2);
const card = screen.getByTestId('conversation').props.card;
await card.actions.setRevision(2);
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(1);
expect(screen.getByTestId('888').props.children).toBe('contacttopicdata');
});
fetchChannels = [
{ id: '123', revision: 3, data: {
detailRevision: 3,
topicRevision: 6,
}
},
];
fetchTopics = [
{ id: '888', revision: 7, data: {
detailRevision: 5,
tagRevision: 0,
topicDetail: {
guid: '0123',
dataType: 'topictype',
data: 'contacttopicdata2',
created: 1,
updated: 1,
status: 'confirmed',
transform: 'complete',
},
}
}
];
await act(async () => {
const channel = screen.getByTestId('conversation').props.channel;
await channel.actions.setRevision(3);
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(1);
expect(screen.getByTestId('888').props.children).toBe('contacttopicdata2');
});
fetchChannels = [
{ id: '123', revision: 4, data: {
detailRevision: 3,
topicRevision: 6,
}
},
];
fetchTopics = [
{ id: '888', revision: 8 }
];
await act(async () => {
const channel = screen.getByTestId('conversation').props.channel;
await channel.actions.setRevision(4);
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(1);
});
fetchChannels = [
{ id: '123', revision: 5, data: {
detailRevision: 3,
topicRevision: 7,
}
},
];
await act(async () => {
const channel = screen.getByTestId('conversation').props.channel;
await channel.actions.setRevision(5);
});
await waitFor(async () => {
expect(screen.getByTestId('conversation').props.children).toHaveLength(0);
});
});

View File

@ -123,6 +123,8 @@ export function useTestStoreContext() {
},
setChannelItemTopicMarker: async (guid, channelId, marker) => {
},
setChannelItemMarkerAndSync: async (guid, channelId, marker, revision) => {
},
setChannelItemBlocked: async (guid, channelId) => {
},
clearChannelItemBlocked: async (guid, channelId) => {
@ -143,6 +145,7 @@ export function useTestStoreContext() {
},
getChannelTopicItems: async (guid, channelId) => {
return [];
},
setChannelTopicItem: async (guid, channelId, topic) => {
},
@ -158,7 +161,9 @@ export function useTestStoreContext() {
},
setCardChannelItem: async (guid, cardId, channel) => {
cardChannelItems.current.set(`${cardId}:${channel.channelId}`, channel);
const card = cardChannels.current.get(cardId) || new Map();
card.set(channel.channelId, channel);
cardChannels.current.set(cardId, card);
},
clearCardChannelItem: async (guid, cardId, channelId) => {
},
@ -170,6 +175,8 @@ export function useTestStoreContext() {
},
setCardChannelItemTopicMarker: async (guid, cardId, channelId, marker) => {
},
setCardChannelItemMarkerAndSync: async (guid, cardid, channelId, marker, revision) => {
},
setCardChannelItemDetail: async (guid, cardId, channelId, revision, detail) => {
},
setCardChannelItemUnsealedDetail: async (guid, cardId, channelId, revision, unsealed) => {
@ -180,13 +187,15 @@ export function useTestStoreContext() {
},
getCardChannelItemView: async (guid, cardId, channelId) => {
},
getCardChannelItems: async (guid) => {
return Array.from(cardChannels.current.values());
getCardChannelItems: async (guid, cardId) => {
const card = cardChannels.current.get(cardId) || new Map();
return Array.from(card.values());
},
clearCardChannelItems: async (guid, cardId) => {
},
getCardChannelTopicItems: async (guid, cardId, channelId) => {
return [];
},
setCardChannelTopicItem: async (guid, cardId, channelId, topic) => {
},