diff --git a/app/containers/EmojiPicker/EmojiCategory.tsx b/app/containers/EmojiPicker/EmojiCategory.tsx index d2fe39703..1f5e74829 100644 --- a/app/containers/EmojiPicker/EmojiCategory.tsx +++ b/app/containers/EmojiPicker/EmojiCategory.tsx @@ -39,7 +39,7 @@ const EmojiCategory = ({ baseUrl, onEmojiSelected, emojis, width, tabsCount }: I onEmojiSelected(emoji)} - testID={`reaction-picker-${typeof emoji === 'string' ? emoji : emoji.content}`} + testID={`emoji-${typeof emoji === 'string' ? emoji : emoji.content}`} android_ripple={{ color: colors.bannerBackground, borderless: true, radius: emojiSize / 2 }} style={({ pressed }: { pressed: boolean }) => ({ backgroundColor: isIOS && pressed ? colors.bannerBackground : 'transparent' diff --git a/app/containers/EmojiPicker/Footer.tsx b/app/containers/EmojiPicker/Footer.tsx index 0ed26f1fa..7da0304b5 100644 --- a/app/containers/EmojiPicker/Footer.tsx +++ b/app/containers/EmojiPicker/Footer.tsx @@ -15,11 +15,18 @@ const Footer = ({ onSearchPressed, onBackspacePressed }: IFooterProps): React.Re [[styles.footerButtonsContainer, { opacity: pressed ? 0.7 : 1 }]]}> + style={({ pressed }) => [[styles.footerButtonsContainer, { opacity: pressed ? 0.7 : 1 }]]} + testID='emoji-picker-search' + > - [{ opacity: pressed ? 0.7 : 1 }]}> + [{ opacity: pressed ? 0.7 : 1 }]} + testID='emoji-picker-backspace' + > diff --git a/app/containers/EmojiPicker/TabBar.tsx b/app/containers/EmojiPicker/TabBar.tsx index 50326ee30..dbc63ceb9 100644 --- a/app/containers/EmojiPicker/TabBar.tsx +++ b/app/containers/EmojiPicker/TabBar.tsx @@ -16,14 +16,15 @@ const TabBar = ({ activeTab, tabs, goToPage }: ITabBarProps): React.ReactElement goToPage?.(i)} - testID={`reaction-picker-${tab}`} + testID={`emoji-picker-tab-${tab}`} android_ripple={{ color: colors.bannerBackground }} style={({ pressed }: { pressed: boolean }) => [ styles.tab, { backgroundColor: isIOS && pressed ? colors.bannerBackground : 'transparent' } - ]}> + ]} + > diff --git a/app/containers/MessageBox/EmojiSearchbar.tsx b/app/containers/MessageBox/EmojiSearchbar.tsx index 98329bf96..074f1150e 100644 --- a/app/containers/MessageBox/EmojiSearchbar.tsx +++ b/app/containers/MessageBox/EmojiSearchbar.tsx @@ -43,7 +43,7 @@ const Emoji = ({ emoji, baseUrl }: { emoji: IEmoji | string; baseUrl: string }): const ListItem = ({ emoji, onEmojiSelected, baseUrl }: IListItem): React.ReactElement => { const key = typeof emoji === 'string' ? emoji : emoji?.name || emoji?.content; return ( - + onEmojiSelected(emoji)}> @@ -83,7 +83,7 @@ const EmojiSearchBar = React.forwardRef( renderItem={({ item }) => } showsHorizontalScrollIndicator={false} ListEmptyComponent={() => ( - + {I18n.t('No_results_found')} )} @@ -97,6 +97,7 @@ const EmojiSearchBar = React.forwardRef( style={({ pressed }: { pressed: boolean }) => [styles.openEmojiKeyboard, { opacity: pressed ? 0.7 : 1 }]} onPress={openEmoji} hitSlop={BUTTON_HIT_SLOP} + testID='openback-emoji-keyboard' > @@ -115,6 +116,7 @@ const EmojiSearchBar = React.forwardRef( value={searchText} onClearInput={() => handleTextChange('')} iconRight={'search'} + testID='emoji-searchbar-input' /> diff --git a/app/views/RoomView/ReactionPicker.tsx b/app/views/RoomView/ReactionPicker.tsx index 853812a3e..d9fae81dc 100644 --- a/app/views/RoomView/ReactionPicker.tsx +++ b/app/views/RoomView/ReactionPicker.tsx @@ -87,6 +87,7 @@ const ReactionPicker = ({ onEmojiSelected, message, reactionClose }: IReactionPi value={searchText} onClearInput={() => handleTextChange('')} iconRight={'search'} + testID='reaction-picker-searchbar' /> diff --git a/e2e/tests/room/02-room.spec.js b/e2e/tests/room/02-room.spec.js index 2f39cf378..32842bf9a 100644 --- a/e2e/tests/room/02-room.spec.js +++ b/e2e/tests/room/02-room.spec.js @@ -60,9 +60,7 @@ describe('Room screen', () => { }); it('should have open emoji button', async () => { - if (device.getPlatform() === 'android') { - await expect(element(by.id('messagebox-open-emoji'))).toExist(); - } + await expect(element(by.id('messagebox-open-emoji'))).toExist(); }); it('should have message input', async () => { @@ -87,23 +85,77 @@ describe('Room screen', () => { }); it('should show/hide emoji keyboard', async () => { - if (device.getPlatform() === 'android') { - await element(by.id('messagebox-open-emoji')).tap(); - await waitFor(element(by.id('messagebox-keyboard-emoji'))) - .toExist() - .withTimeout(10000); - await expect(element(by.id('messagebox-close-emoji'))).toExist(); - await expect(element(by.id('messagebox-open-emoji'))).toBeNotVisible(); - await element(by.id('messagebox-close-emoji')).tap(); - await waitFor(element(by.id('messagebox-keyboard-emoji'))) - .toBeNotVisible() - .withTimeout(10000); - await expect(element(by.id('messagebox-close-emoji'))).toBeNotVisible(); - await expect(element(by.id('messagebox-open-emoji'))).toExist(); - } + await element(by.id('messagebox-open-emoji')).tap(); + await waitFor(element(by.id('messagebox-keyboard-emoji'))) + .toExist() + .withTimeout(10000); + await expect(element(by.id('messagebox-close-emoji'))).toExist(); + await expect(element(by.id('messagebox-open-emoji'))).toBeNotVisible(); + await element(by.id('messagebox-close-emoji')).tap(); + await waitFor(element(by.id('messagebox-keyboard-emoji'))) + .not.toBeVisible() + .withTimeout(10000); + await expect(element(by.id('messagebox-close-emoji'))).toBeNotVisible(); + await expect(element(by.id('messagebox-open-emoji'))).toExist(); + }); + + it('should clear the emoji', async () => { + await element(by.id('messagebox-open-emoji')).tap(); + await waitFor(element(by.id('messagebox-keyboard-emoji'))) + .toExist() + .withTimeout(10000); + await expect(element(by.id('emoji-picker-tab-emoji'))).toExist(); + await element(by.id('emoji-picker-tab-emoji')).tap(); + await expect(element(by.id('emoji-smiley'))).toExist(); + await element(by.id('emoji-smiley')).tap(); + await waitFor(element(by.id('emoji-picker-backspace'))) + .toExist() + .withTimeout(4000); + await expect(element(by.id('messagebox-input'))).toHaveText('😃'); + await expect(element(by.id('emoji-picker-backspace'))).toExist(); + await element(by.id('emoji-picker-backspace')).tap(); + await expect(element(by.id('messagebox-input'))).toHaveText(''); + await element(by.id('messagebox-close-emoji')).tap(); + await waitFor(element(by.id('messagebox-keyboard-emoji'))) + .not.toBeVisible() + .withTimeout(10000); + }); + + it('should search emojis, go back to EmojiKeyboard and then close the EmojiKeyboard', async () => { + await element(by.id('messagebox-open-emoji')).tap(); + await waitFor(element(by.id('emoji-picker-search'))) + .toExist() + .withTimeout(4000); + await element(by.id('emoji-picker-search')).tap(); + await waitFor(element(by.id('emoji-searchbar-input'))) + .toExist() + .withTimeout(2000); + await element(by.id('emoji-searchbar-input')).typeText('smiley'); + await waitFor(element(by.id('searched-emoji-smiley'))) + .toExist() + .withTimeout(2000); + await element(by.id('searched-emoji-smiley')).tap(); + await expect(element(by.id('messagebox-input'))).toHaveText('😃'); + await element(by.id('emoji-searchbar-input')).clearText(); + await element(by.id('emoji-searchbar-input')).typeText('random-text'); + await waitFor(element(by.id('no-results-found'))) + .toExist() + .withTimeout(2000); + await element(by.id('emoji-searchbar-input')).clearText(); + await expect(element(by.id('openback-emoji-keyboard'))).toExist(); + await element(by.id('openback-emoji-keyboard')).tap(); + await waitFor(element(by.id('emoji-searchbar-input'))) + .not.toBeVisible() + .withTimeout(2000); + await expect(element(by.id('messagebox-close-emoji'))).toExist(); + await element(by.id('messagebox-close-emoji')).tap(); + await waitFor(element(by.id('messagebox-keyboard-emoji'))) + .not.toBeVisible() + .withTimeout(10000); }); it('should show/hide emoji autocomplete', async () => { + await element(by.id('messagebox-input')).clearText(); await element(by.id('messagebox-input')).typeText(':joy'); await sleep(300); await waitFor(element(by.id('messagebox-container'))) @@ -220,10 +272,8 @@ describe('Room screen', () => { await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await element(by[textMatcher]('Permalink')).atIndex(0).tap(); - // TODO: test clipboard }); - it('should copy message', async () => { await element(by[textMatcher](`${data.random}message`)) .atIndex(0) @@ -234,13 +284,10 @@ describe('Room screen', () => { await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await element(by[textMatcher]('Copy')).atIndex(0).tap(); - // TODO: test clipboard }); - it('should star message', async () => { await starMessage('message'); - await sleep(1000); // https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/2324 await element(by[textMatcher](`${data.random}message`)) .atIndex(0) @@ -255,7 +302,6 @@ describe('Room screen', () => { .withTimeout(6000); await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.8); }); - it('should react to message', async () => { await waitFor(element(by[textMatcher](`${data.random}message`))) .toExist() @@ -272,19 +318,41 @@ describe('Room screen', () => { await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); await element(by.id('add-reaction')).tap(); - await waitFor(element(by.id('reaction-picker'))) - .toBeVisible() + await waitFor(element(by.id('emoji-picker-tab-emoji'))) + .toExist() .withTimeout(2000); - await element(by.id('reaction-picker-😃')).tap(); - await waitFor(element(by.id('reaction-picker-grinning'))) + await element(by.id('action-sheet-handle')).swipe('up', 'fast', 1); + await element(by.id('emoji-picker-tab-emoji')).tap(); + await waitFor(element(by.id('emoji-grinning'))) .toExist() .withTimeout(10000); - await element(by.id('reaction-picker-grinning')).tap(); + await element(by.id('emoji-grinning')).tap(); await waitFor(element(by.id('message-reaction-:grinning:'))) .toExist() .withTimeout(60000); }); - + it('should search emojis in the reaction picker and react', async () => { + await element(by[textMatcher](`${data.random}message`)) + .atIndex(0) + .longPress(); + await waitFor(element(by.id('action-sheet'))) + .toExist() + .withTimeout(2000); + await expect(element(by.id('action-sheet-handle'))).toBeVisible(); + await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5); + await element(by.id('add-reaction')).tap(); + await waitFor(element(by.id('reaction-picker-searchbar'))) + .toExist() + .withTimeout(2000); + await element(by.id('reaction-picker-searchbar')).typeText('smile'); + await waitFor(element(by.id('emoji-smile'))) + .toExist() + .withTimeout(4000); + await element(by.id('emoji-smile')).tap(); + await waitFor(element(by.id('message-reaction-:smile:'))) + .toExist() + .withTimeout(60000); + }); it('should react to message with frequently used emoji', async () => { await element(by[textMatcher](`${data.random}message`)) .atIndex(0) @@ -302,36 +370,37 @@ describe('Room screen', () => { .toBeVisible() .withTimeout(60000); }); - it('should show reaction picker on add reaction button pressed and have frequently used emoji, and dismiss review nag', async () => { await element(by.id('message-add-reaction')).tap(); - await waitFor(element(by.id('reaction-picker'))) + await waitFor(element(by.id('action-sheet'))) .toExist() .withTimeout(2000); - await waitFor(element(by.id('reaction-picker-grinning'))) + await expect(element(by.id('action-sheet-handle'))).toBeVisible(); + await element(by.id('action-sheet-handle')).swipe('up', 'fast', 1); + await waitFor(element(by.id('emoji-grinning'))) + .toExist() + .withTimeout(4000); + await waitFor(element(by.id('emoji-picker-tab-emoji'))) .toExist() .withTimeout(2000); - await element(by.id('reaction-picker-😃')).tap(); - await waitFor(element(by.id('reaction-picker-grimacing'))) + await element(by.id('emoji-picker-tab-emoji')).tap(); + await waitFor(element(by.id('emoji-wink'))) .toExist() - .withTimeout(2000); - await element(by.id('reaction-picker-grimacing')).tap(); - await waitFor(element(by.id('message-reaction-:grimacing:'))) + .withTimeout(10000); + await element(by.id('emoji-wink')).tap(); + await waitFor(element(by.id('message-reaction-:wink:'))) .toExist() .withTimeout(60000); }); - it('should remove reaction', async () => { - await element(by.id('message-reaction-:grinning:')).tap(); - await waitFor(element(by.id('message-reaction-:grinning:'))) - .toBeNotVisible() + await element(by.id('message-reaction-:smile:')).tap(); + await waitFor(element(by.id('message-reaction-:smile:'))) + .not.toExist() .withTimeout(60000); }); - it('should ask for review', async () => { await dismissReviewNag(); // TODO: Create a proper test for this elsewhere. }); - it('should edit message', async () => { await mockMessage('edit'); await element(by[textMatcher](`${data.random}edit`)) @@ -352,7 +421,6 @@ describe('Room screen', () => { .toExist() .withTimeout(60000); }); - it('should quote message', async () => { await mockMessage('quote'); await element(by[textMatcher](`${data.random}quote`)) @@ -369,14 +437,11 @@ describe('Room screen', () => { .toExist() .withTimeout(2000); await element(by.id('messagebox-send-message')).tap(); - // TODO: test if quote was sent }); - it('should pin message', async () => { await mockMessage('pin'); await pinMessage('pin'); - await waitFor(element(by[textMatcher](`${data.random}pin`)).atIndex(0)) .toExist() .withTimeout(5000); @@ -396,7 +461,6 @@ describe('Room screen', () => { .withTimeout(2000); await element(by.id('action-sheet-handle')).swipe('down', 'fast', 0.8); }); - it('should delete message', async () => { await mockMessage('delete'); await waitFor(element(by[textMatcher](`${data.random}delete`)).atIndex(0)).toBeVisible(); @@ -412,7 +476,6 @@ describe('Room screen', () => { .toExist() .withTimeout(1000); await element(by[textMatcher]('Delete')).atIndex(0).tap(); - const deleteAlertMessage = 'You will not be able to recover this message!'; await waitFor(element(by[textMatcher](deleteAlertMessage)).atIndex(0)) .toExist()