From c6c0d33f6a25e85581cf37f4c45aefc89905ca01 Mon Sep 17 00:00:00 2001 From: Andre Vasconcelos Date: Mon, 12 Oct 2020 21:07:23 +0900 Subject: [PATCH] MM-29046 Add unit and e2e tests for autocomplete popover (#4855) * WIP: Adding autocomplete E2E tests * Fixing search.e2e tests * Updated testIDs, added 2 test suites, added comments * Added comments to search E2E test * Updating testIDs & reverting changes to common.js * Updating snapshots * Added TM4J ticket numbers * Adding assertion commends to search E2E * Updated testID values --- .../autocomplete/at_mention/at_mention.js | 1 + .../channel_mention/channel_mention.js | 1 + .../date_suggestion/date_suggestion.js | 1 + .../emoji_suggestion.test.js.snap | 1 + .../emoji_suggestion/emoji_suggestion.js | 1 + .../slash_suggestion/slash_suggestion.js | 1 + .../edit_channel_info.test.js.snap | 1 + .../edit_channel_info/edit_channel_info.js | 1 + app/components/search_bar/index.js | 1 + .../channel_search_button.test.js.snap | 1 + .../channel_search_button.js | 1 + .../__snapshots__/channel_title.test.js.snap | 4 ++ .../channel_title/channel_title.js | 1 + .../__snapshots__/edit_post.test.js.snap | 1 + app/screens/edit_post/edit_post.js | 1 + app/screens/search/modifier.js | 5 +- app/screens/search/search.js | 5 ++ .../e2e/test/autocomplete/edit_channel.e2e.js | 27 +++++++++ detox/e2e/test/autocomplete/edit_post.e2e.js | 36 ++++++++++++ detox/e2e/test/autocomplete/post_draft.e2e.js | 57 +++++++++++++++++++ detox/e2e/test/autocomplete/search.e2e.js | 50 ++++++++++++++++ 21 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 detox/e2e/test/autocomplete/edit_channel.e2e.js create mode 100644 detox/e2e/test/autocomplete/edit_post.e2e.js create mode 100644 detox/e2e/test/autocomplete/post_draft.e2e.js create mode 100644 detox/e2e/test/autocomplete/search.e2e.js diff --git a/app/components/autocomplete/at_mention/at_mention.js b/app/components/autocomplete/at_mention/at_mention.js index 1e8aa87d5..a84470f8f 100644 --- a/app/components/autocomplete/at_mention/at_mention.js +++ b/app/components/autocomplete/at_mention/at_mention.js @@ -265,6 +265,7 @@ export default class AtMention extends PureComponent { return ( {Boolean(calendarWidth) && diff --git a/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js b/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js index 4a0e6378c..8c25b2d09 100644 --- a/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js +++ b/app/components/autocomplete/emoji_suggestion/emoji_suggestion.js @@ -226,6 +226,7 @@ export default class EmojiSuggestion extends PureComponent { return ( diff --git a/app/screens/edit_post/__snapshots__/edit_post.test.js.snap b/app/screens/edit_post/__snapshots__/edit_post.test.js.snap index c0d001ee2..6ec441624 100644 --- a/app/screens/edit_post/__snapshots__/edit_post.test.js.snap +++ b/app/screens/edit_post/__snapshots__/edit_post.test.js.snap @@ -65,6 +65,7 @@ exports[`EditPost should match snapshot 1`] = ` }, ] } + testID="edit_post.input" underlineColorAndroid="transparent" /> diff --git a/app/screens/edit_post/edit_post.js b/app/screens/edit_post/edit_post.js index 6c7687ea8..972683fdd 100644 --- a/app/screens/edit_post/edit_post.js +++ b/app/screens/edit_post/edit_post.js @@ -255,6 +255,7 @@ export default class EditPost extends PureComponent { {displayError} - + diff --git a/app/screens/search/search.js b/app/screens/search/search.js index 384922029..26feb8f60 100644 --- a/app/screens/search/search.js +++ b/app/screens/search/search.js @@ -597,6 +597,7 @@ export default class Search extends PureComponent { const sectionsData = [{ value: 'from:', + testID: 'search_from.section', modifier: `from:${intl.formatMessage({id: 'mobile.search.from_modifier_title', defaultMessage: 'username'})}`, description: intl.formatMessage({ id: 'mobile.search.from_modifier_description', @@ -604,6 +605,7 @@ export default class Search extends PureComponent { }), }, { value: 'in:', + testID: 'search_in.section', modifier: `in:${intl.formatMessage({id: 'mobile.search.in_modifier_title', defaultMessage: 'channel-name'})}`, description: intl.formatMessage({ id: 'mobile.search.in_modifier_description', @@ -615,6 +617,7 @@ export default class Search extends PureComponent { if (this.props.enableDateSuggestion) { sectionsData.push({ value: 'on:', + testID: 'search_on.section', modifier: 'on: YYYY-MM-DD', description: intl.formatMessage({ id: 'mobile.search.on_modifier_description', @@ -623,6 +626,7 @@ export default class Search extends PureComponent { }); sectionsData.push({ value: 'after:', + testID: 'search_after.section', modifier: 'after: YYYY-MM-DD', description: intl.formatMessage({ id: 'mobile.search.after_modifier_description', @@ -631,6 +635,7 @@ export default class Search extends PureComponent { }); sectionsData.push({ value: 'before:', + testID: 'search_before.section', modifier: 'before: YYYY-MM-DD', description: intl.formatMessage({ id: 'mobile.search.before_modifier_description', diff --git a/detox/e2e/test/autocomplete/edit_channel.e2e.js b/detox/e2e/test/autocomplete/edit_channel.e2e.js new file mode 100644 index 000000000..5e7418763 --- /dev/null +++ b/detox/e2e/test/autocomplete/edit_channel.e2e.js @@ -0,0 +1,27 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {toChannelScreen} from '@support/ui/screen'; + +import {Setup} from '@support/server_api'; + +describe('Autocomplete', () => { + beforeAll(async () => { + const {user} = await Setup.apiInit(); + await toChannelScreen(user); + }); + + it('MM-T3390 should render autocomplete in channel header edit screen', async () => { + // # Open channel info modal + await element(by.id('channel.title.button')).tap(); + + // # Open edit channel menu + await element(by.text('Edit Channel')).tap(); + + // # Activate at_mention autocomplete + await element(by.id('edit_channel.header.input')).typeText('@'); + + // * Expect autocomplete to render + await expect(element(by.id('autocomplete.at_mention.list'))).toExist(); + }); +}); diff --git a/detox/e2e/test/autocomplete/edit_post.e2e.js b/detox/e2e/test/autocomplete/edit_post.e2e.js new file mode 100644 index 000000000..b78a710e7 --- /dev/null +++ b/detox/e2e/test/autocomplete/edit_post.e2e.js @@ -0,0 +1,36 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {toChannelScreen} from '@support/ui/screen'; + +import {Setup} from '@support/server_api'; + +describe('Autocomplete', () => { + beforeAll(async () => { + const {user} = await Setup.apiInit(); + await toChannelScreen(user); + }); + + it('MM-T3391 should render autocomplete in post edit screen', async () => { + const message = Date.now().toString(); + + // # Type a message + const postInput = await element(by.id('post_input')); + await postInput.tap(); + await postInput.typeText(message); + + // # Tap the send button + await element(by.id('send_button')).tap(); + + // # Open edit screen + await element(by.text(message)).longPress(); + await element(by.text('Edit')).tap(); + + // # Open autocomplete + await expect(element(by.id('autocomplete.at_mention.list'))).not.toExist(); + await element(by.id('edit_post.input')).typeText(' @'); + + // * Expect at_mention autocomplete to render + await expect(element(by.id('autocomplete.at_mention.list'))).toExist(); + }); +}); diff --git a/detox/e2e/test/autocomplete/post_draft.e2e.js b/detox/e2e/test/autocomplete/post_draft.e2e.js new file mode 100644 index 000000000..e5315372b --- /dev/null +++ b/detox/e2e/test/autocomplete/post_draft.e2e.js @@ -0,0 +1,57 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {toChannelScreen} from '@support/ui/screen'; + +import {Setup} from '@support/server_api'; + +describe('Autocomplete', () => { + beforeAll(async () => { + const {user} = await Setup.apiInit(); + await toChannelScreen(user); + }); + + beforeEach(async () => { + await device.reloadReactNative(); + + // # Select post draft + await expect(element(by.id('channel_screen'))).toBeVisible(); + await element(by.id('post_input')).tap(); + }); + + it('MM-T3392_1 should render emoji_suggestion component', async () => { + // # Type ":" to activate emoji suggestions + await expect(element(by.id('autocomplete.emoji_suggestion.list'))).not.toExist(); + await element(by.id('post_input')).typeText(':'); + + // * Expect emoji suggestions to render + await expect(element(by.id('autocomplete.emoji_suggestion.list'))).toExist(); + }); + + it('MM-T3392_2 should render at_mention component', async () => { + // # Type "@" to activate at mention autocomplete + await expect(element(by.id('autocomplete.at_mention.list'))).not.toExist(); + await element(by.id('post_input')).typeText('@'); + + // * Expect at mention autocomplete to render + await expect(element(by.id('autocomplete.at_mention.list'))).toExist(); + }); + + it('MM-T3392_3 should render channel_mention component', async () => { + // # Type "~" to activate channel mention autocomplete + await expect(element(by.id('autocomplete.channel_mention.list'))).not.toExist(); + await element(by.id('post_input')).typeText('~'); + + // * Expect channel mention to render + await expect(element(by.id('autocomplete.channel_mention.list'))).toExist(); + }); + + it('MM-T3392_4 should render slash_suggestion component', async () => { + // # Type "/" to activate slash command suggestions + await expect(element(by.id('autocomplete.slash_suggestion'))).not.toExist(); + await element(by.id('post_input')).typeText('/'); + + // * Expect slash suggestions to render + await expect(element(by.id('autocomplete.slash_suggestion'))).toExist(); + }); +}); diff --git a/detox/e2e/test/autocomplete/search.e2e.js b/detox/e2e/test/autocomplete/search.e2e.js new file mode 100644 index 000000000..70b0a8807 --- /dev/null +++ b/detox/e2e/test/autocomplete/search.e2e.js @@ -0,0 +1,50 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {toChannelScreen} from '@support/ui/screen'; + +import {Setup} from '@support/server_api'; + +describe('Autocomplete', () => { + beforeAll(async () => { + const {user} = await Setup.apiInit(); + await toChannelScreen(user); + }); + + beforeEach(async () => { + await device.reloadReactNative(); + + // # Enter search screen + await element(by.id('channel.search.button')).tap(); + }); + + it('MM-T3393_1 should render at_mention component', async () => { + await expect(element(by.id('autocomplete.at_mention.list'))).not.toExist(); + + // # Tap "from:" modifier + await element(by.id('search_from.section')).tap(); + + // * Expect at mention to render + await expect(element(by.id('autocomplete.at_mention.list'))).toExist(); + }); + + it('MM-T3393_2 should render channel_mention component', async () => { + await expect(element(by.id('autocomplete.channel_mention.list'))).not.toExist(); + + // # Tap "in:" modifier + await element(by.id('search_in.section')).tap(); + + // * Expect channel mention to render + await expect(element(by.id('autocomplete.channel_mention.list'))).toExist(); + }); + + it('MM-T3393_3 should render date_suggestion component', async () => { + await expect(element(by.id('autocomplete.date_suggestion'))).not.toExist(); + + // # Tap "before:" modifier + await element(by.id('search_before.section')).tap(); + + // * Expect date suggestion to render + await expect(element(by.id('autocomplete.date_suggestion'))).toExist(); + }); +});