diff --git a/e2e/chatTest.spec.ts b/e2e/chatTest.spec.ts index 8ec09f92..9a5c7efa 100644 --- a/e2e/chatTest.spec.ts +++ b/e2e/chatTest.spec.ts @@ -11,7 +11,9 @@ import { waitAndTypeText, signIn, forceLogout, - detoxElementCount, + countElements, + sleep, + scrollUpAndFindText, } from './helpers'; describe('Chat', () => { @@ -101,7 +103,7 @@ describe('Chat', () => { await signIn(mentor); await element(by.id('tabs.chats')).tap(); - const unseenDotsAmountBefore = await detoxElementCount( + const unseenDotsAmountBefore = await countElements( by.id('main.buddyList.button.unseenDot'), ); jestExpect(unseenDotsAmountBefore).toBe(2); @@ -112,7 +114,7 @@ describe('Chat', () => { await element(by.id('chat.back.button')).tap(); - const unseenDotsAmountAfter = await detoxElementCount( + const unseenDotsAmountAfter = await countElements( by.id('main.buddyList.button.unseenDot'), ); jestExpect(unseenDotsAmountAfter).toBe(1); @@ -141,4 +143,27 @@ describe('Chat', () => { await element(by.id('chat.back.button')).tap(); await expect(element(by.id('main.tabs.unseenDot'))).toBeVisible(); }); + + it('loads more messages if all newest unread', async () => { + const mentee = accountFixtures.mentees[0]; + await APISignUpMentee(mentee); + const mentor = accountFixtures.mentors[0]; + await APISignUpMentor(mentor); + + const { + sender_id: menteeId, + recipient_id: mentorId, + senderHeaders: menteeHeaders, + } = await APIGetSendInfo(mentee, mentor); + await sendMultiple(menteeId, mentorId, menteeHeaders, 'Hello', 20); + + await signIn(mentor); + await element(by.id('tabs.chats')).tap(); + + // wait for 2 message-polls, so all messages are fetched + await sleep(10); + await element(by.text(mentee.displayName)).tap(); + await expect(element(by.text('Hello 19'))).toBeVisible(); + await scrollUpAndFindText('Hello 0', 'main.buddy.messageList'); + }); }); diff --git a/e2e/helpers.ts b/e2e/helpers.ts index 4f097f3d..86090b40 100644 --- a/e2e/helpers.ts +++ b/e2e/helpers.ts @@ -66,6 +66,18 @@ export async function scrollUpTo(elementId: string, viewId: string) { .scroll(100, 'up', 0.1, 0.2); } +/** + * Scrolls view up until element with text is found + */ +export async function scrollUpAndFindText(text: string, viewId: string) { + await waitFor(element(by.text(text))) + .toBeVisible() + .whileElement(by.id(viewId)) + // Needs to scroll from x=0.1, y=0.2 + // because of the big sticky toolbar + .scroll(100, 'up', 0.1, 0.2); +} + /** * Waits until input is visible and then types given text */ @@ -523,7 +535,7 @@ export async function APIUpdateMentor(mentorName: string, mentor: any) { }); } -export async function detoxElementCount(matcher: NativeMatcher) { +export async function countElements(matcher: NativeMatcher) { try { const attributes = await element(matcher)?.getAttributes(); @@ -536,3 +548,9 @@ export async function detoxElementCount(matcher: NativeMatcher) { return 0; } } + +export async function sleep(seconds: number) { + return new Promise(resolve => { + setTimeout(resolve, seconds * 1000); + }); +} diff --git a/src/Screens/Main/Chat/MessageList/Message.tsx b/src/Screens/Main/Chat/MessageList/Message.tsx index 2470705d..00cebe1a 100644 --- a/src/Screens/Main/Chat/MessageList/Message.tsx +++ b/src/Screens/Main/Chat/MessageList/Message.tsx @@ -20,10 +20,9 @@ const Message = ({ value: message }: MessageProps) => { const bubbleStyle = type === 'Received' ? styles.leftBubble : styles.rightBubble; - const isSeenTemp = - type === 'Received' && !message.isSeen - ? { borderWidth: 2, borderColor: 'red' } - : { borderWidth: 2, borderColor: 'green' }; + // TODO: Visual aid, remove this after review + const isSeenBorder = type === 'Received' && + !message.isSeen && { borderWidth: 2, borderColor: colors.orangeLight }; const addZero = (n: number) => (n < 10 ? `0${n}` : `${n}`); const date = new Date(sentTime); @@ -32,7 +31,7 @@ const Message = ({ value: message }: MessageProps) => { const timeText = `${hours}:${minutes}`; return ( - + {content} diff --git a/src/Screens/Main/Chat/MessageList/index.tsx b/src/Screens/Main/Chat/MessageList/index.tsx index a1ad24c8..44972657 100644 --- a/src/Screens/Main/Chat/MessageList/index.tsx +++ b/src/Screens/Main/Chat/MessageList/index.tsx @@ -94,7 +94,8 @@ export const MessageList = ({ const dispatch = useDispatch(); const getPreviousMessagesIfNotLoading = () => { - if (isLoading) { + console.log('messageList.length', messageList.length); + if (isLoading || messageList.length < messageApi.MAX_MESSAGES_AT_ONCE) { return; } @@ -107,7 +108,7 @@ export const MessageList = ({ }; const handleViewableChanged = ({ changed }: ViewArgs) => { - // TODO: Helper here, decode the changed maybe + // TODO: Decode 'changed' maybe const unSeenMessagesOnScreen = changed .filter(item => item.isViewable) .filter( @@ -130,6 +131,7 @@ export const MessageList = ({ return ( } diff --git a/src/api/messages.ts b/src/api/messages.ts index 46f25683..b4e0d413 100644 --- a/src/api/messages.ts +++ b/src/api/messages.ts @@ -20,6 +20,8 @@ import { isLeft } from 'fp-ts/lib/Either'; type ApiMessage = t.TypeOf; +export const MAX_MESSAGES_AT_ONCE = 10; + const messageType = t.interface({ content: t.string, recipient_id: t.string, @@ -94,23 +96,21 @@ const reduceToMsgRecord = (acc: MessageMapping, message: Message) => ({ }); const createFetchParams = (pollingParams: PollingParams) => { - const maxMessagesAtOnce = 10; - if (pollingParams.type === 'New' && pollingParams.previousMsgId.length > 0) { - return `from_message_id=${pollingParams.previousMsgId}&desc=false&max=${maxMessagesAtOnce}`; + return `from_message_id=${pollingParams.previousMsgId}&desc=false&max=${MAX_MESSAGES_AT_ONCE}`; } if (pollingParams.type === 'InitialMessages') { const userIds = pollingParams.buddyIds.join(','); - return `contact_user_ids=${userIds}&max=${maxMessagesAtOnce}&desc=true`; + return `contact_user_ids=${userIds}&max=${MAX_MESSAGES_AT_ONCE}&desc=true`; } if (pollingParams.type === 'OlderThan') { - return `contact_user_ids=${pollingParams.buddyId}&from_message_id=${pollingParams.messageId}&max=${maxMessagesAtOnce}&desc=true`; + return `contact_user_ids=${pollingParams.buddyId}&from_message_id=${pollingParams.messageId}&max=${MAX_MESSAGES_AT_ONCE}&desc=true`; } - return `max=${maxMessagesAtOnce}&desc=true`; + return `max=${MAX_MESSAGES_AT_ONCE}&desc=true`; }; export type MessageResponse = { diff --git a/src/state/reducers/markSeen.ts b/src/state/reducers/markSeen.ts index 8cd24725..59911dfd 100644 --- a/src/state/reducers/markSeen.ts +++ b/src/state/reducers/markSeen.ts @@ -39,10 +39,6 @@ export const reducer: automaton.Reducer = ( type: 'messages/markSeen', payload: { messages }, })), - // { - // type: 'messages/markSeen', - // payload: { messages }, - // }, ); } diff --git a/src/state/reducers/messages.ts b/src/state/reducers/messages.ts index e47cd0d5..9c649b91 100644 --- a/src/state/reducers/messages.ts +++ b/src/state/reducers/messages.ts @@ -93,15 +93,6 @@ export const reducer: automaton.Reducer = ( const previousMsgId = messageApi.extractMostRecentId(nextMessages); - // TODO: add some e2e-test - // case 1: oldermessage-fetching (for example initial) - // - mentee sends 20 messages to mentor - // - mentor login - // - mentor waits 5 seconds (the poll interval) - // - mentor scrolls up to the converstaion ( all messages have been loaded ) - // - mentor opens chat - // TODO: remove borders of message-bubbles - const newOlderThanParams = messageApi.getParamsForUnreadMessages( newMessages, state.currentParams,