mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 12:39:17 +00:00
testing conversation context for mobile app
This commit is contained in:
parent
eca43835be
commit
50fa8bf9af
@ -109,6 +109,7 @@ export function useCardContext() {
|
|||||||
const { notifiedView, notifiedProfile, notifiedArticle, notifiedChannel } = card.data || {};
|
const { notifiedView, notifiedProfile, notifiedArticle, notifiedChannel } = card.data || {};
|
||||||
const cardRevision = { view: notifiedView, profile: notifiedProfile, artcile: notifiedArticle, channel: notifiedChannel };
|
const cardRevision = { view: notifiedView, profile: notifiedProfile, artcile: notifiedArticle, channel: notifiedChannel };
|
||||||
await syncCard(server, token, guid, entry, cardRevision);
|
await syncCard(server, token, guid, entry, cardRevision);
|
||||||
|
await store.action.clearCardItemOffsync(guid, cardId);
|
||||||
entry.card.offsync = false;
|
entry.card.offsync = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +165,7 @@ export function useCardContext() {
|
|||||||
catch (err) {
|
catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
entry.offsync = true;
|
entry.offsync = true;
|
||||||
|
await store.action.setCardItemOffsync(guid, card.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cards.current.set(card.id, entry);
|
cards.current.set(card.id, entry);
|
||||||
|
@ -24,7 +24,6 @@ export function useConversationContext() {
|
|||||||
const force = useRef(false);
|
const force = useRef(false);
|
||||||
const syncing = useRef(false);
|
const syncing = useRef(false);
|
||||||
const update = useRef(false);
|
const update = useRef(false);
|
||||||
|
|
||||||
const loaded = useRef(false);
|
const loaded = useRef(false);
|
||||||
const conversationId = useRef(null);
|
const conversationId = useRef(null);
|
||||||
const topics = useRef(new Map());
|
const topics = useRef(new Map());
|
||||||
@ -44,7 +43,7 @@ export function useConversationContext() {
|
|||||||
syncing.current = true;
|
syncing.current = true;
|
||||||
update.current = false;
|
update.current = false;
|
||||||
force.current = false;
|
force.current = false;
|
||||||
loadMore.current = false;
|
more.current = false;
|
||||||
|
|
||||||
if (reset.current) {
|
if (reset.current) {
|
||||||
reset.current = false;
|
reset.current = false;
|
||||||
@ -55,44 +54,28 @@ export function useConversationContext() {
|
|||||||
|
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
const { cardId, channelId } = 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);
|
||||||
|
if (channelValue) {
|
||||||
|
const { topicRevision, syncRevision, topicMarker } = channelValue;
|
||||||
|
curRevision = topicRevision;
|
||||||
|
setRevision = syncRevision;
|
||||||
|
marker = topicMarker;
|
||||||
|
updateState({ card: cardValue, channel: channelValue });
|
||||||
|
|
||||||
if (loaded.current) {
|
if (!loaded.current) {
|
||||||
const cardValue = cardId ? card.state.cards.get(cardId) : null;
|
|
||||||
const channelValue = cardId ? cardValue?.get(channelId) : channel.state.channels.get(channelId);
|
|
||||||
if (channelValue) {
|
|
||||||
const { topicRevision, syncRevision, topicMarker } = channelValue;
|
|
||||||
curRevision = topicRevision;
|
|
||||||
setRevision = syncRevision;
|
|
||||||
marker = topicMarker;
|
|
||||||
updateState({ card: cardValue, channel: channelValue });
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log("failed to load conversation");
|
|
||||||
sysncing.current = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loaded.current) {
|
|
||||||
const cardValue = cardId ? card.state.cards.get(cardId) : null;
|
|
||||||
const channelValue = cardId ? cardValue?.get(channelId) : channel.state.channels.get(channelId);
|
|
||||||
if (channelValue) {
|
|
||||||
const { topicRevision, syncRevision, topicMarker } = channelValue;
|
|
||||||
curRevision = topicRevision;
|
|
||||||
setRevision = syncRevision;
|
|
||||||
marker = topicMarker;
|
|
||||||
const topicItems = await getTopicItems(cardId, channelId);
|
const topicItems = await getTopicItems(cardId, channelId);
|
||||||
for (let topic: topicItems) {
|
for (let topic of topicItems) {
|
||||||
topics.current.set(topic.topicId, topic);
|
topics.current.set(topic.topicId, topic);
|
||||||
}
|
}
|
||||||
updateState({ card: cardValue, channel: channelValue, topics: topics.current });
|
updateState({ offsync: false, topics: topics.current });
|
||||||
loaded.current = true;
|
loaded.current = true;
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
console.log("failed to load conversation");
|
else {
|
||||||
syncing.current = false;
|
console.log("failed to load conversation");
|
||||||
return;
|
syncing.current = false;
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -125,7 +108,7 @@ export function useConversationContext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const setTopicDelta(cardId, channelId, entries) => {
|
const setTopicDelta = async (cardId, channelId, entries) => {
|
||||||
for (let entry of entries) {
|
for (let entry of entries) {
|
||||||
if (entry.data) {
|
if (entry.data) {
|
||||||
if (entry.data.detail) {
|
if (entry.data.detail) {
|
||||||
@ -139,6 +122,7 @@ export function useConversationContext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
topics.current.delete(entry.id);
|
||||||
clearTopicItem(entry.id);
|
clearTopicItem(entry.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +141,7 @@ export function useConversationContext() {
|
|||||||
reset.current = true;
|
reset.current = true;
|
||||||
await sync();
|
await sync();
|
||||||
},
|
},
|
||||||
clearConversation: async ()
|
clearConversation: async () => {
|
||||||
conversationId.current = null;
|
conversationId.current = null;
|
||||||
reset.current = true;
|
reset.current = true;
|
||||||
await sync();
|
await sync();
|
||||||
@ -216,14 +200,22 @@ export function useConversationContext() {
|
|||||||
await channel.actions.clearChannelCard(channelId, id);
|
await channel.actions.clearChannelCard(channelId, id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setChannelReadRevision: async (revision) => {
|
||||||
|
const { cardId, channelId } = conversationId.current || {};
|
||||||
|
if (cardId) {
|
||||||
|
await card.actions.setChannelReadRevision(cardId, channelId, revision);
|
||||||
|
}
|
||||||
|
else if (channelId) {
|
||||||
|
await channel.actions.setReadRevision(channelId, revision);
|
||||||
|
}
|
||||||
|
},
|
||||||
addChannelAlert: async () => {
|
addChannelAlert: async () => {
|
||||||
const { cardId, channelId } = conversationId.current || {};
|
const { cardId, channelId } = conversationId.current || {};
|
||||||
if (cardId) {
|
if (cardId) {
|
||||||
return await card.actions.addChannelAlert(cardId, channelId);
|
return await card.actions.addChannelAlert(cardId, channelId);
|
||||||
}
|
}
|
||||||
else if (channelId) {
|
else if (channelId) {
|
||||||
return await channel.actions.addChannelAlert(channelId);
|
return await channel.actions.addChannelAlert(channelId);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setChannelFlag: async () => {
|
setChannelFlag: async () => {
|
||||||
@ -271,7 +263,7 @@ export function useConversationContext() {
|
|||||||
if (cardId) {
|
if (cardId) {
|
||||||
await card.actions.setUnsealedTopicSubject(cardId, channelId, topicId, revision, unsealed);
|
await card.actions.setUnsealedTopicSubject(cardId, channelId, topicId, revision, unsealed);
|
||||||
}
|
}
|
||||||
else {channelId) {
|
else if (channelId) {
|
||||||
await channel.actions.setUnsealedTopicSubject(channelId, topicId, revision, unsealed);
|
await channel.actions.setUnsealedTopicSubject(channelId, topicId, revision, unsealed);
|
||||||
}
|
}
|
||||||
setTopicField(topicId, 'unsaledDetail', unsealed);
|
setTopicField(topicId, 'unsaledDetail', unsealed);
|
||||||
@ -390,8 +382,8 @@ export function useConversationContext() {
|
|||||||
return {
|
return {
|
||||||
topicId: entry.id,
|
topicId: entry.id,
|
||||||
revision: entry.revision,
|
revision: entry.revision,
|
||||||
detailRevision = entry.data?.detailRevision,
|
detailRevision: entry.data?.detailRevision,
|
||||||
detail = entry.data?.topicDetail,
|
detail: entry.data?.topicDetail,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ export function useStoreContext() {
|
|||||||
},
|
},
|
||||||
setCardItem: async (guid, card) => {
|
setCardItem: async (guid, card) => {
|
||||||
const { id, revision, data } = card;
|
const { id, revision, data } = card;
|
||||||
await db.current.executeSql(`INSERT OR REPLACE INTO card_${guid} (card_id, revision, detail_revision, profile_revision, detail, profile, notified_view, notified_profile, notified_article, notified_channel) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`, [id, revision, data.detailRevision, data.profileRevision, encodeObject(data.cardDetail), encodeObject(data.cardProfile), null, null, null, null]);
|
await db.current.executeSql(`INSERT OR REPLACE INTO card_${guid} (card_id, revision, detail_revision, profile_revision, detail, profile, notified_view, notified_profile, notified_article, notified_channel) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`, [card.cardId, card.revision, card.detailRevision, card.profileRevision, encodeObject(card.detail), encodeObject(card.profile), null, null, null, null]);
|
||||||
},
|
},
|
||||||
clearCardItem: async (guid, cardId) => {
|
clearCardItem: async (guid, cardId) => {
|
||||||
await db.current.executeSql(`DELETE FROM card_${guid} WHERE card_id=?`, [cardId]);
|
await db.current.executeSql(`DELETE FROM card_${guid} WHERE card_id=?`, [cardId]);
|
||||||
@ -141,24 +141,6 @@ export function useStoreContext() {
|
|||||||
setCardItemProfile: async (guid, cardId, revision, profile) => {
|
setCardItemProfile: async (guid, cardId, revision, profile) => {
|
||||||
await db.current.executeSql(`UPDATE card_${guid} set profile_revision=?, profile=? where card_id=?`, [revision, encodeObject(profile), cardId]);
|
await db.current.executeSql(`UPDATE card_${guid} set profile_revision=?, profile=? where card_id=?`, [revision, encodeObject(profile), cardId]);
|
||||||
},
|
},
|
||||||
getCardItemStatus: async (guid, cardId) => {
|
|
||||||
const values = await getAppValues(db.current, `SELECT detail, profile, profile_revision, detail_revision, notified_view, notified_article, notified_profile, notified_channel, offsync FROM card_${guid} WHERE card_id=?`, [cardId]);
|
|
||||||
if (!values.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
detail: decodeObject(values[0].detail),
|
|
||||||
profile: decodeObject(values[0].profile),
|
|
||||||
profileRevision: values[0].profile_revision,
|
|
||||||
detailRevision: values[0].detail_revision,
|
|
||||||
notifiedView: values[0].notified_view,
|
|
||||||
notifiedArticle: values[0].notified_article,
|
|
||||||
notifiedProfile: values[0].notified_profile,
|
|
||||||
notifiedChannel: values[0].notified_channel,
|
|
||||||
offsync: values[0].offsync,
|
|
||||||
blocked: values[0].blocked,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getCardItems: async (guid) => {
|
getCardItems: async (guid) => {
|
||||||
const values = await getAppValues(db.current, `SELECT card_id, revision, detail_revision, profile_revision, detail, profile, offsync, blocked, notified_view, notified_profile, notified_article, notified_channel FROM card_${guid}`, []);
|
const values = await getAppValues(db.current, `SELECT card_id, revision, detail_revision, profile_revision, detail, profile, offsync, blocked, notified_view, notified_profile, notified_article, notified_channel FROM card_${guid}`, []);
|
||||||
return values.map(card => ({
|
return values.map(card => ({
|
||||||
|
85
app/mobile/test/Conversation.test.js
Normal file
85
app/mobile/test/Conversation.test.js
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import React, { useState, useEffect, useContext } from 'react';
|
||||||
|
import { View, Text } from 'react-native';
|
||||||
|
import { useTestStoreContext } from './useTestStoreContext.hook';
|
||||||
|
import { prettyDOM } from '@testing-library/dom';
|
||||||
|
import {render, act, screen, waitFor, fireEvent} from '@testing-library/react-native';
|
||||||
|
import { StoreContext } from 'context/StoreContext';
|
||||||
|
import { ConversationContextProvider, ConversationContext } from 'context/ConversationContext';
|
||||||
|
import { CardContextProvider, CardContext } from 'context/CardContext';
|
||||||
|
import { ChannelContextProvider, ChannelContext } from 'context/ChannelContext';
|
||||||
|
import * as fetchUtil from 'api/fetchUtil';
|
||||||
|
|
||||||
|
function ConversationView() {
|
||||||
|
const [renderCount, setRenderCount] = useState(0);
|
||||||
|
const conversation = useContext(ConversationContext);
|
||||||
|
const channel = useContext(ChannelContext);
|
||||||
|
const card = useContext(CardContext);
|
||||||
|
const [topics, setTopics] = useState([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setRenderCount(renderCount + 1);
|
||||||
|
const rendered = [];
|
||||||
|
}, [conversation.state]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View key="conversation" testID="conversation" renderCount={renderCount}
|
||||||
|
card={card} channel={channel} conversation={conversation}>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ConversationTestApp() {
|
||||||
|
return (
|
||||||
|
<ChannelContextProvider>
|
||||||
|
<CardContextProvider>
|
||||||
|
<ConversationContextProvider>
|
||||||
|
<ConversationView />
|
||||||
|
</ConversationContextProvider>
|
||||||
|
</CardContextProvider>
|
||||||
|
</ChannelContextProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const realUseContext = React.useContext;
|
||||||
|
const realFetchWithTimeout = fetchUtil.fetchWithTimeout;
|
||||||
|
const realFetchWithCustomTimeout = fetchUtil.fetchWithCustomTimeout;
|
||||||
|
beforeEach(() => {
|
||||||
|
const mockUseContext = jest.fn().mockImplementation((ctx) => {
|
||||||
|
if (ctx === StoreContext) {
|
||||||
|
return useTestStoreContext();
|
||||||
|
}
|
||||||
|
return realUseContext(ctx);
|
||||||
|
});
|
||||||
|
React.useContext = mockUseContext;
|
||||||
|
|
||||||
|
const mockFetch = jest.fn().mockImplementation((url, options) => {
|
||||||
|
return Promise.resolve({
|
||||||
|
json: () => Promise.resolve([])
|
||||||
|
});
|
||||||
|
});
|
||||||
|
fetchUtil.fetchWithTimeout = mockFetch;
|
||||||
|
fetchUtil.fetchWithCustomTimeout = mockFetch;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
React.useContext = realUseContext;
|
||||||
|
fetchUtil.fetchWithTimeout = realFetchWithTimeout;
|
||||||
|
fetchUtil.fetchWithCustomTimeout = realFetchWithCustomTimeout;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test conversation', 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;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user