-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Added Several Contact Support tests.
#15744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0f69f25
a57a010
d4e294b
68c5a3a
b492893
2539abd
5153c27
77025df
08fd20d
e176a68
7c93b54
11a16e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| package org.wordpress.android.e2e; | ||
|
|
||
| import org.junit.After; | ||
| import org.junit.Before; | ||
| import org.junit.Ignore; | ||
| import org.junit.Test; | ||
| import org.wordpress.android.R; | ||
| import org.wordpress.android.e2e.flows.LoginFlow; | ||
| import org.wordpress.android.e2e.pages.ContactSupportScreen; | ||
| import org.wordpress.android.support.BaseTest; | ||
|
|
||
| import static org.wordpress.android.BuildConfig.E2E_WP_COM_USER_EMAIL; | ||
| import static org.wordpress.android.support.WPSupportUtils.pressBackUntilElementIsDisplayed; | ||
|
|
||
| public class ContactUsTests extends BaseTest { | ||
| @Before | ||
| public void setUp() { | ||
| logoutIfNecessary(); | ||
| } | ||
|
|
||
| @After | ||
| public void tearDown() { | ||
| pressBackUntilElementIsDisplayed(R.id.continue_with_wpcom_button); | ||
| } | ||
|
|
||
| @Test | ||
| public void sendButtonEnabledWhenTextIsEntered() { | ||
| try { | ||
| new LoginFlow() | ||
| .chooseContinueWithWpCom() | ||
| .tapHelp() | ||
| .assertHelpAndSupportScreenLoaded() | ||
| .openContactUs() | ||
| .assertContactSupportScreenLoaded() | ||
| .assertSendButtonDisabled() | ||
| .setMessageText("Hello") | ||
| .assertSendButtonEnabled() | ||
| .setMessageText("") | ||
| .assertSendButtonDisabled(); | ||
| } finally { | ||
| new ContactSupportScreen().goBackAndDeleteUnsentMessageIfNeeded(); | ||
| } | ||
| } | ||
|
|
||
| @Ignore("As long as CI does not use gradle.properties from MobileSecrets") | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As can be seen from the number of commits in this PR starting with Looks different from the same screen on my local Emulator: After blaming the Emulator/Android differences for some time, I realized that CI uses the default Since I automated this test, I decided to keep it for the case if Mobile Secrets will be used on CI.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In case we have this test running in CI are we going to be creating real Zendesk tickets? I'm afraid it can get real noisy.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have this suspicion too. This test is disabled for now, so it's not an urgent matter, but I think we can contact the HE team, and ask them if there's a painless way for them to filter out certain messages, so that they wouldn't be bothered with them.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I agree.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it turns out to be the case that we cannot prevent the creation of real tickets, and idea could be to use the Zendesk APIs to find the tickets created by the UI tests and delete them. |
||
| @Test | ||
| public void messageCanBeSent() { | ||
| String userMessageText = "Please ignore, this is an automated test."; | ||
| String automatedReplyText = "Mobile support will respond as soon as possible, " | ||
| + "generally within 48-96 hours. " | ||
| + "Please reply with your site address (URL) " | ||
| + "and any additional details we should know."; | ||
|
Comment on lines
+49
to
+52
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. So far, I'm not sure if it makes sense to maintain this test (or even to keep it) - I probably firstly need to ask if Zendesk connection is ever planned on CI.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have it connected for WPiOS because it was not possible to even check if the screen had been loaded. From what I can recall it is possible but not desirable. Given it is an identified critical flow I'd ask @jkmassel to weigh in. =)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could also use a less sophisticated check and ensure we get any text in |
||
|
|
||
| try { | ||
| new LoginFlow() | ||
| .chooseContinueWithWpCom() | ||
| .tapHelp() | ||
| .openContactUs() | ||
| .setMessageText(userMessageText) | ||
| .tapSendButton() | ||
| .assertUserMessageDelivered(userMessageText) | ||
| .assertSystemMessageReceived(automatedReplyText); | ||
| } finally { | ||
| new ContactSupportScreen().goBackAndDeleteUnsentMessageIfNeeded(); | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| public void helpCanBeOpenedWhileEnteringEmail() { | ||
| new LoginFlow() | ||
| .chooseContinueWithWpCom() | ||
| .tapHelp() | ||
| .assertHelpAndSupportScreenLoaded(); | ||
| } | ||
|
|
||
| @Test | ||
| public void helpCanBeOpenedWhileEnteringPassword() { | ||
| new LoginFlow() | ||
| .chooseContinueWithWpCom() | ||
| .enterEmailAddress(E2E_WP_COM_USER_EMAIL) | ||
| .tapHelp() | ||
| .assertHelpAndSupportScreenLoaded(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| package org.wordpress.android.e2e.pages; | ||
|
|
||
| import androidx.test.espresso.Espresso; | ||
| import androidx.test.espresso.ViewInteraction; | ||
| import androidx.test.espresso.action.ViewActions; | ||
|
|
||
| import org.wordpress.android.R; | ||
|
|
||
| import static androidx.test.espresso.Espresso.onView; | ||
| import static androidx.test.espresso.assertion.ViewAssertions.matches; | ||
| import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; | ||
| import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; | ||
| import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; | ||
| import static androidx.test.espresso.matcher.ViewMatchers.withId; | ||
| import static androidx.test.espresso.matcher.ViewMatchers.withText; | ||
| import static org.hamcrest.Matchers.allOf; | ||
| import static org.hamcrest.Matchers.anyOf; | ||
| import static org.hamcrest.Matchers.not; | ||
| import static org.wordpress.android.support.WPSupportUtils.populateTextField; | ||
| import static org.wordpress.android.support.WPSupportUtils.sleep; | ||
| import static org.wordpress.android.support.WPSupportUtils.waitForElementToBeDisplayed; | ||
| import static org.wordpress.android.support.WPSupportUtils.waitForElementToBeDisplayedWithoutFailure; | ||
|
|
||
| public class ContactSupportScreen { | ||
| // "Contact Support" screen looks differently depending on | ||
| // "gradle.properties" content (default or from Mobile Secrets). | ||
| // But the elements tree always contains all elements, some are | ||
| // just hidden. Locators below attempt to support both variants. | ||
| static ViewInteraction textInput = onView(allOf( | ||
| isCompletelyDisplayed(), | ||
| anyOf( | ||
| withId(R.id.message_composer_input_text), | ||
| withId(R.id.request_message_field) | ||
| ) | ||
| )); | ||
|
Comment on lines
+29
to
+35
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This translates to: find an element that is both completely displayed and has either In fact, both of these elements are present when the screen is opened, but only one is visible. |
||
| static ViewInteraction sendButton = onView(allOf( | ||
| isCompletelyDisplayed(), | ||
| anyOf( | ||
| withId(R.id.message_composer_send_btn), | ||
| withId(R.id.request_conversations_disabled_menu_ic_send) | ||
| ) | ||
| )); | ||
|
|
||
| // Actions: | ||
| public ContactSupportScreen tapSendButton() { | ||
| sendButton.perform(ViewActions.click()); | ||
| return this; | ||
| } | ||
|
|
||
| public ContactSupportScreen setMessageText(String text) { | ||
| populateTextField(textInput, text); | ||
| // This sleep serves only one purpose: allowing human to notice | ||
| // that text was really entered. Especially matters when watching | ||
| // low-fps test video recordings from CI. | ||
| sleep(); | ||
| return this; | ||
| } | ||
|
|
||
| public HelpAndSupportScreen goBackAndDeleteUnsentMessageIfNeeded() { | ||
| Espresso.pressBack(); | ||
|
|
||
| ViewInteraction unsentMessageAlert = onView( | ||
| withText("Going back will delete your message. " | ||
| + "Are you sure you want to delete it?" | ||
| )); | ||
|
|
||
| if (waitForElementToBeDisplayedWithoutFailure(unsentMessageAlert)) { | ||
| onView(withText("Delete")) | ||
| .perform(ViewActions.click()); | ||
| } | ||
|
|
||
| return new HelpAndSupportScreen(); | ||
| } | ||
|
|
||
| // Assertions: | ||
| public ContactSupportScreen assertContactSupportScreenLoaded() { | ||
| textInput.check(matches(isCompletelyDisplayed())); | ||
| sendButton.check(matches(isCompletelyDisplayed())); | ||
| return this; | ||
| } | ||
|
|
||
| public ContactSupportScreen assertSendButtonDisabled() { | ||
| sendButton.check(matches(not(isEnabled()))); | ||
| return this; | ||
| } | ||
|
|
||
| public ContactSupportScreen assertSendButtonEnabled() { | ||
| sendButton.check(matches(isEnabled())); | ||
| return this; | ||
| } | ||
|
|
||
| public ContactSupportScreen assertUserMessageDelivered(String messageText) { | ||
| ViewInteraction userMessageContainer = onView(allOf( | ||
| withId(R.id.request_user_message_container), | ||
| hasDescendant(allOf( | ||
| withId(R.id.request_user_message_text), | ||
| withText(messageText) | ||
| )), | ||
| hasDescendant(allOf( | ||
| withId(R.id.request_user_message_status), | ||
| withText("Delivered") | ||
| )) | ||
| )); | ||
|
|
||
| waitForElementToBeDisplayed(userMessageContainer); | ||
| userMessageContainer.check(matches(isCompletelyDisplayed())); | ||
| return this; | ||
| } | ||
|
|
||
| public ContactSupportScreen assertSystemMessageReceived(String messageText) { | ||
| ViewInteraction systemResponseBubble = onView(allOf( | ||
| withId(R.id.request_system_message_text), | ||
| withText(messageText))); | ||
|
|
||
| waitForElementToBeDisplayed(systemResponseBubble); | ||
| systemResponseBubble.check(matches(isCompletelyDisplayed())); | ||
| return this; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| package org.wordpress.android.e2e.pages; | ||
|
|
||
| import androidx.test.espresso.ViewInteraction; | ||
| import androidx.test.espresso.action.ViewActions; | ||
|
|
||
| import org.wordpress.android.R; | ||
|
|
||
| import static androidx.test.espresso.Espresso.onView; | ||
| import static androidx.test.espresso.assertion.ViewAssertions.matches; | ||
| import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; | ||
| import static androidx.test.espresso.matcher.ViewMatchers.withText; | ||
| import static androidx.test.espresso.matcher.ViewMatchers.withId; | ||
| import static org.wordpress.android.support.WPSupportUtils.populateTextField; | ||
| import static org.hamcrest.Matchers.anyOf; | ||
| import static org.wordpress.android.support.WPSupportUtils.waitForElementToBeDisplayedWithoutFailure; | ||
|
|
||
|
|
||
| public class HelpAndSupportScreen { | ||
| static ViewInteraction contactUsButton = onView(withId(R.id.contact_us_button)); | ||
| static ViewInteraction faqButton = onView(withId(R.id.faq_button)); | ||
| static ViewInteraction myTicketsButton = onView(withId(R.id.my_tickets_button)); | ||
| static ViewInteraction applicationLogButton = onView(withId(R.id.application_log_button)); | ||
| static ViewInteraction applicationVersionText = onView(withId(R.id.applicationVersion)); | ||
| static ViewInteraction emailAddressText = onView(withId(R.id.contactEmailAddress)); | ||
|
|
||
|
|
||
| public HelpAndSupportScreen assertHelpAndSupportScreenLoaded() { | ||
| contactUsButton.check(matches(isCompletelyDisplayed())); | ||
| faqButton.check(matches(isCompletelyDisplayed())); | ||
| myTicketsButton.check(matches(isCompletelyDisplayed())); | ||
| applicationLogButton.check(matches(isCompletelyDisplayed())); | ||
| applicationVersionText.check(matches(isCompletelyDisplayed())); | ||
| emailAddressText.check(matches(isCompletelyDisplayed())); | ||
| return this; | ||
| } | ||
|
|
||
| public ContactSupportScreen openContactUs() { | ||
| contactUsButton.perform(ViewActions.click()); | ||
| setEmailIfNeeded("WPcomTest@test.com", "TestUser"); | ||
| return new ContactSupportScreen(); | ||
| } | ||
|
|
||
| public void setEmailIfNeeded(String emailAddress, String userName) { | ||
| ViewInteraction emailInput = onView(withId(R.id.support_identity_input_dialog_email_edit_text)); | ||
|
|
||
| if (!waitForElementToBeDisplayedWithoutFailure(emailInput)) { | ||
| return; | ||
| } | ||
|
|
||
| populateTextField(emailInput, emailAddress); | ||
| ViewInteraction nameInput = onView(withId(R.id.support_identity_input_dialog_name_edit_text)); | ||
| populateTextField(nameInput, userName); | ||
|
|
||
| onView(anyOf( | ||
| withText(android.R.string.ok), | ||
| withId(android.R.id.button1) | ||
| )) | ||
|
Comment on lines
+54
to
+57
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the locator for I used something like |
||
| .perform(ViewActions.click()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -475,6 +475,20 @@ public Boolean get() { | |
| return isElementDisplayed(elementID); | ||
| } | ||
|
|
||
| public static boolean waitForElementToBeDisplayedWithoutFailure(final ViewInteraction element) { | ||
| try { | ||
| waitForConditionToBeTrueWithoutFailure(new Supplier<Boolean>() { | ||
| @Override | ||
| public Boolean get() { | ||
| return isElementDisplayed(element); | ||
| } | ||
| }); | ||
| } catch (Exception e) { | ||
| // ignore the failure | ||
| } | ||
| return isElementDisplayed(element); | ||
| } | ||
|
|
||
|
Comment on lines
+478
to
+491
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had to do the same thing in my PR. The only difference was that I made |
||
| public static void waitForConditionToBeTrue(Supplier<Boolean> supplier) { | ||
| if (supplier.get()) { | ||
| return; | ||
|
|
||




There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A kind of local teardown, in order to not slow down
helpCanBeOpenedWhileEnteringEmailandhelpCanBeOpenedWhileEnteringPasswordwhich do not get toContactSupportscreen, so there's no possibility of unsent message.