Fixed forward and reply tests.

This commit is contained in:
Denys Zelenchuk 2022-09-05 17:45:19 +02:00
parent 0d39be4d18
commit bd1c625d01
17 changed files with 140 additions and 88 deletions

Binary file not shown.

View File

@ -36,8 +36,9 @@ import me.proton.fusion.utils.StringUtils.stringFromResource
*/ */
class ContactsRobot : Fusion { class ContactsRobot : Fusion {
private fun openAddContactsMenu() { private fun openAddContactsMenu(): ContactsRobot {
view.withId(R.id.fab_contacts_add_menu).click() view.withId(R.id.fab_contacts_add_menu).click()
return this
} }
fun addContact(): AddContactRobot { fun addContact(): AddContactRobot {

View File

@ -25,39 +25,40 @@ import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until import androidx.test.uiautomator.Until
import me.proton.core.test.android.instrumented.utils.Shell import me.proton.core.test.android.instrumented.utils.Shell
import me.proton.fusion.Fusion
open class DeviceRobot { open class DeviceRobot: Fusion {
fun clickHomeButton(): DeviceRobot { fun clickHomeButton(): DeviceRobot {
device.pressHome() uiDevice.pressHome()
return this return this
} }
fun clickRecentAppsButton(): DeviceRobot { fun clickRecentAppsButton(): DeviceRobot {
device.pressRecentApps() uiDevice.pressRecentApps()
return this return this
} }
fun clickRecentAppView(): DeviceRobot { fun clickRecentAppView(): DeviceRobot {
val recentAppSelector = UiSelector().resourceId("com.google.android.apps.nexuslauncher:id/overview_panel") val recentAppSelector = UiSelector().resourceId("com.google.android.apps.nexuslauncher:id/overview_panel")
device.findObject(recentAppSelector).waitForExists(5000) uiDevice.findObject(recentAppSelector).waitForExists(5000)
device.findObject(recentAppSelector).click() uiDevice.findObject(recentAppSelector).click()
return this return this
} }
fun expandNotifications(): DeviceRobot { fun expandNotifications(): DeviceRobot {
device.openNotification() uiDevice.openNotification()
return this return this
} }
fun clickNotificationByText(text: String): DeviceRobot { fun clickNotificationByText(text: String): DeviceRobot {
device.wait(Until.findObject(By.text(text)), TIMEOUT_5S).click() uiDevice.wait(Until.findObject(By.text(text)), TIMEOUT_5S).click()
return this return this
} }
fun clickShareDialogJustOnceButton(): DeviceRobot { fun clickShareDialogJustOnceButton(): DeviceRobot {
device.wait(Until.findObject(By.textContains("ProtonMail")), TIMEOUT_30S)?.click() byObject.containsText("Proton Mail").withTimeout(TIMEOUT_30S).click()
device.wait(Until.findObject(By.res("android:id/button_once")), TIMEOUT_30S).click() byObject.withResName("android:id/button_once").withTimeout(TIMEOUT_30S).click()
return this return this
} }
@ -70,6 +71,6 @@ open class DeviceRobot {
private const val TIMEOUT_5S = 5000L private const val TIMEOUT_5S = 5000L
private const val TIMEOUT_30S = 30_000L private const val TIMEOUT_30S = 30_000L
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) private val uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
} }
} }

View File

@ -22,15 +22,20 @@ package ch.protonmail.android.uitests.robots.mailbox
import android.widget.ImageView import android.widget.ImageView
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso import androidx.test.espresso.Espresso
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.ViewAction
import androidx.test.espresso.ViewInteraction import androidx.test.espresso.ViewInteraction
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition
import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withId
import ch.protonmail.android.R import ch.protonmail.android.R
import ch.protonmail.android.uitests.robots.mailbox.MailboxMatchers.withFirstInstanceMessageSubject import ch.protonmail.android.uitests.robots.mailbox.MailboxMatchers.withFirstInstanceMessageSubject
import ch.protonmail.android.uitests.robots.mailbox.MailboxMatchers.withMessageSubject
import ch.protonmail.android.uitests.robots.mailbox.MailboxMatchers.withMessageSubjectAndFlag import ch.protonmail.android.uitests.robots.mailbox.MailboxMatchers.withMessageSubjectAndFlag
import ch.protonmail.android.uitests.robots.mailbox.MailboxMatchers.withMessageSubjectAndRecipient import ch.protonmail.android.uitests.robots.mailbox.MailboxMatchers.withMessageSubjectAndRecipient
import ch.protonmail.android.uitests.robots.mailbox.composer.ComposerRobot import ch.protonmail.android.uitests.robots.mailbox.composer.ComposerRobot
@ -39,9 +44,12 @@ import ch.protonmail.android.uitests.robots.mailbox.messagedetail.MessageRobot
import ch.protonmail.android.uitests.robots.mailbox.search.SearchRobot import ch.protonmail.android.uitests.robots.mailbox.search.SearchRobot
import ch.protonmail.android.uitests.robots.menu.MenuRobot import ch.protonmail.android.uitests.robots.menu.MenuRobot
import ch.protonmail.android.uitests.testsHelper.StringUtils import ch.protonmail.android.uitests.testsHelper.StringUtils
import ch.protonmail.android.uitests.testsHelper.UICustomViewActions.TIMEOUT_15S
import ch.protonmail.android.uitests.testsHelper.UICustomViewActions.TIMEOUT_30S
import ch.protonmail.android.uitests.testsHelper.UICustomViewActions.TIMEOUT_60S import ch.protonmail.android.uitests.testsHelper.UICustomViewActions.TIMEOUT_60S
import ch.protonmail.android.uitests.testsHelper.UICustomViewActions.saveMessageSubject import ch.protonmail.android.uitests.testsHelper.UICustomViewActions.saveMessageSubject
import ch.protonmail.android.uitests.testsHelper.waitForCondition import ch.protonmail.android.uitests.testsHelper.waitForCondition
import com.google.android.material.snackbar.SnackbarContentLayout
import me.proton.fusion.Fusion import me.proton.fusion.Fusion
import okhttp3.internal.wait import okhttp3.internal.wait
@ -65,11 +73,16 @@ interface MailboxRobotInterface : Fusion {
return Any() return Any()
} }
fun deleteMessageWithSwipe(subject: String): Any {
recyclerView.onHolderItem(withMessageSubject(subject)).swipeRight()
return Any()
}
fun deleteMessageWithSwipe(position: Int): Any { fun deleteMessageWithSwipe(position: Int): Any {
saveMessageSubjectAtPosition(messagesRecyclerViewId, position, (::SetDeleteWithSwipeMessage)())
recyclerView recyclerView
.withId(messagesRecyclerViewId) .withId(messagesRecyclerViewId)
.onItemAtPosition(position) .onItemAtPosition(position)
.withTimeout(TIMEOUT_15S)
.swipeRight() .swipeRight()
return Any() return Any()
} }
@ -145,10 +158,9 @@ interface MailboxRobotInterface : Fusion {
view.withId(messageTitleTextViewId).withText(draftSubject).checkIsDisplayed() view.withId(messageTitleTextViewId).withText(draftSubject).checkIsDisplayed()
} }
fun messageMovedToTrash(subject: String, date: String) { fun messageMovedToTrash(subject: String) {
val messageMovedToTrash = StringUtils.quantityStringFromResource(R.plurals.action_move_to_trash, 1) view.withText(R.string.swipe_action_trash).waitForDisplayed().checkIsDisplayed()
view.withText(messageMovedToTrash).checkIsDisplayed() view.withId(R.id.subject_text_view).withText(subject).waitUntilGone().checkDoesNotExist()
view.withId(R.id.subject_text_view).withText(subject).checkDoesNotExist()
} }
fun messageDeleted(subject: String) { fun messageDeleted(subject: String) {
@ -157,7 +169,7 @@ interface MailboxRobotInterface : Fusion {
fun multipleMessagesMovedToTrash(subjectMessageOne: String, subjectMessageTwo: String) { fun multipleMessagesMovedToTrash(subjectMessageOne: String, subjectMessageTwo: String) {
val messagesMovedToTrash = StringUtils.quantityStringFromResource(R.plurals.action_move_to_trash, 2) val messagesMovedToTrash = StringUtils.quantityStringFromResource(R.plurals.action_move_to_trash, 2)
view.withText(messagesMovedToTrash).checkIsDisplayed() view.withText(messagesMovedToTrash).waitForDisplayed().checkIsDisplayed()
view.withId(R.id.subject_text_view).withText(subjectMessageOne).checkDoesNotExist() view.withId(R.id.subject_text_view).withText(subjectMessageOne).checkDoesNotExist()
view.withId(R.id.subject_text_view).withText(subjectMessageTwo).checkDoesNotExist() view.withId(R.id.subject_text_view).withText(subjectMessageTwo).checkDoesNotExist()
} }
@ -168,9 +180,9 @@ interface MailboxRobotInterface : Fusion {
} }
fun messageWithSubjectExists(subject: String) { fun messageWithSubjectExists(subject: String) {
view.withText(subject).waitForDisplayed()
recyclerView recyclerView
.withId(messagesRecyclerViewId) .withId(messagesRecyclerViewId)
.withTimeout(TIMEOUT_30S)
.scrollToHolder(withFirstInstanceMessageSubject(subject)) .scrollToHolder(withFirstInstanceMessageSubject(subject))
} }
@ -189,6 +201,7 @@ interface MailboxRobotInterface : Fusion {
fun messageWithSubjectHasForwardedFlag(subject: String) { fun messageWithSubjectHasForwardedFlag(subject: String) {
recyclerView recyclerView
.withId(messagesRecyclerViewId) .withId(messagesRecyclerViewId)
.withTimeout(TIMEOUT_30S)
.scrollToHolder(withMessageSubjectAndFlag(subject, R.id.forward_image_view)) .scrollToHolder(withMessageSubjectAndFlag(subject, R.id.forward_image_view))
} }

View File

@ -154,6 +154,7 @@ class ComposerRobot : Fusion {
.setExpirationInDays(days) .setExpirationInDays(days)
.attachments() .attachments()
.addImageCaptureAttachment(logoDrawable) .addImageCaptureAttachment(logoDrawable)
.navigateUpToComposer()
.send() .send()
fun sendMessageEOAndExpiryTimeWithAttachmentAndConfirmation( fun sendMessageEOAndExpiryTimeWithAttachmentAndConfirmation(
@ -171,6 +172,7 @@ class ComposerRobot : Fusion {
.setExpirationInDays(days) .setExpirationInDays(days)
.attachments() .attachments()
.addImageCaptureAttachment(logoDrawable) .addImageCaptureAttachment(logoDrawable)
.navigateUpToComposer()
.sendWithNotSupportedExpiryConfirmation() .sendWithNotSupportedExpiryConfirmation()
.sendAnyway() .sendAnyway()
@ -178,27 +180,28 @@ class ComposerRobot : Fusion {
composeMessage(to, subject, body) composeMessage(to, subject, body)
.attachments() .attachments()
.addImageCaptureAttachment(logoDrawable) .addImageCaptureAttachment(logoDrawable)
.navigateUpToComposer()
.send() .send()
fun sendMessageWithFileAttachment(to: String, subject: String, body: String): InboxRobot = fun sendMessageWithFileAttachment(to: String, subject: String, body: String): InboxRobot =
composeMessage(to, subject, body) composeMessage(to, subject, body)
.attachments() .attachments()
.addFileAttachment(logoDrawable) .addFileAttachment(logoDrawable)
.goBackToComposer() .navigateUpToComposer()
.send() .send()
fun sendMessageTwoImageCaptureAttachments(to: String, subject: String, body: String): InboxRobot = fun sendMessageTwoImageCaptureAttachments(to: String, subject: String, body: String): InboxRobot =
composeMessage(to, subject, body) composeMessage(to, subject, body)
.attachments() .attachments()
.addTwoImageCaptureAttachments(logoDrawable, welcomeDrawable) .addTwoImageCaptureAttachments(logoDrawable, driveDrawable)
.send() .send()
fun addAndRemoveAttachmentAndSend(to: String, subject: String, body: String): InboxRobot = fun addAndRemoveAttachmentAndSend(to: String, subject: String, body: String): InboxRobot =
composeMessage(to, subject, body) composeMessage(to, subject, body)
.attachments() .attachments()
.addFileAttachment(logoDrawable) .addFileAttachment(logoDrawable)
.removeLastAttachment() .removeAttachmentAtPosition(0)
.goBackToComposer() .navigateUpToComposer()
.send() .send()
fun draftToSubjectBody(to: String, messageSubject: String, body: String): ComposerRobot = fun draftToSubjectBody(to: String, messageSubject: String, body: String): ComposerRobot =
@ -218,6 +221,7 @@ class ComposerRobot : Fusion {
return draftToSubjectBody(to, messageSubject, body) return draftToSubjectBody(to, messageSubject, body)
.attachments() .attachments()
.addImageCaptureAttachment(logoDrawable) .addImageCaptureAttachment(logoDrawable)
.navigateUpToComposer()
} }
fun editBodyAndReply(newBody: String): MessageRobot = fun editBodyAndReply(newBody: String): MessageRobot =
@ -349,7 +353,7 @@ class ComposerRobot : Fusion {
} }
private fun waitForConditionAndSend() { private fun waitForConditionAndSend() {
view.withId(sendMessageId).waitForEnabled().checkEnabled().click() view.withId(sendMessageId).waitForEnabled().checkIsEnabled().click()
} }
/** /**
@ -359,7 +363,6 @@ class ComposerRobot : Fusion {
fun sendAnyway(): InboxRobot { fun sendAnyway(): InboxRobot {
view.withId(ok).click() view.withId(ok).click()
// view.withText(R.string.message_sent).inRoot(rootView.withNotCurrentActivityDecorView())
return InboxRobot() return InboxRobot()
} }
} }
@ -391,8 +394,8 @@ class ComposerRobot : Fusion {
const val sendMessageId = R.id.send_button const val sendMessageId = R.id.send_button
const val messageBodyId = R.id.composer_message_body_edit_text const val messageBodyId = R.id.composer_message_body_edit_text
const val subjectId = R.id.composer_subject_edit_text const val subjectId = R.id.composer_subject_edit_text
const val logoDrawable = R.drawable.ic_launcher_foreground const val logoDrawable = R.drawable.ic_logo_proton
const val welcomeDrawable = R.drawable.welcome const val driveDrawable = R.drawable.ic_logo_drive
const val addressSpinnerId = R.id.composer_from_spinner const val addressSpinnerId = R.id.composer_from_spinner
const val toRecipientsId = R.id.composer_to_recipient_view const val toRecipientsId = R.id.composer_to_recipient_view
const val ok = R.id.ok const val ok = R.id.ok

View File

@ -19,8 +19,10 @@
package ch.protonmail.android.uitests.robots.mailbox.composer package ch.protonmail.android.uitests.robots.mailbox.composer
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.appcompat.widget.AppCompatImageButton
import ch.protonmail.android.R import ch.protonmail.android.R
import ch.protonmail.android.uitests.testsHelper.MockAddAttachmentIntent import ch.protonmail.android.uitests.testsHelper.MockAddAttachmentIntent
import ch.protonmail.android.uitests.testsHelper.TestData
import me.proton.fusion.Fusion import me.proton.fusion.Fusion
/** /**
@ -28,7 +30,7 @@ import me.proton.fusion.Fusion
*/ */
open class MessageAttachmentsRobot : Fusion { open class MessageAttachmentsRobot : Fusion {
fun addImageCaptureAttachment(@IdRes drawable: Int): ComposerRobot = fun addImageCaptureAttachment(@IdRes drawable: Int): MessageAttachmentsRobot =
mockCameraImageCapture(drawable) mockCameraImageCapture(drawable)
fun addTwoImageCaptureAttachments( fun addTwoImageCaptureAttachments(
@ -36,35 +38,54 @@ open class MessageAttachmentsRobot : Fusion {
@IdRes secondDrawable: Int @IdRes secondDrawable: Int
): ComposerRobot = ): ComposerRobot =
mockCameraImageCapture(firstDrawable) mockCameraImageCapture(firstDrawable)
.attachments()
.mockCameraImageCapture(secondDrawable) .mockCameraImageCapture(secondDrawable)
.navigateUpToComposer()
fun addFileAttachment(@IdRes drawable: Int): MessageAttachmentsRobot { fun addFileAttachment(@IdRes drawable: Int): MessageAttachmentsRobot {
intent.init()
mockFileAttachment(drawable) mockFileAttachment(drawable)
intent.release()
return this return this
} }
fun removeLastAttachment(): MessageAttachmentsRobot { fun removeAttachmentAtPosition(position: Int): MessageAttachmentsRobot =
waitForLoadingToBeNotVisible().removeAttachment(position)
private fun removeAttachment(position: Int): MessageAttachmentsRobot {
listView
.onListItem()
.inAdapterView(view.withId(R.id.attachment_list))
.atPosition(position)
.onChild(view.withId(R.id.remove)).click()
return this return this
} }
fun goBackToComposer(): ComposerRobot { private fun waitForLoadingToBeNotVisible(): MessageAttachmentsRobot {
view.withText(R.string.sync_attachments).waitForNotDisplayed()
return this
}
fun navigateUpToComposer(): ComposerRobot {
view.instanceOf(AppCompatImageButton::class.java).hasParent(view.withId(R.id.toolbar)).click()
return ComposerRobot() return ComposerRobot()
} }
private fun mockCameraImageCapture(@IdRes drawableId: Int): ComposerRobot { private fun mockCameraImageCapture(@IdRes drawableId: Int): MessageAttachmentsRobot {
view.withId(takePhotoIconId).checkIsDisplayed() intent.init()
view.withId(takePhotoIconId).waitForDisplayed()
MockAddAttachmentIntent.mockCameraImageCapture(takePhotoIconId, drawableId) MockAddAttachmentIntent.mockCameraImageCapture(takePhotoIconId, drawableId)
return ComposerRobot() intent.release()
return this
} }
private fun mockFileAttachment(@IdRes drawable: Int): ComposerRobot { private fun mockFileAttachment(@IdRes drawable: Int): ComposerRobot {
view.withId(addAttachmentIconId).checkIsDisplayed() view.withId(addAttachmentIconId).checkIsDisplayed()
MockAddAttachmentIntent.mockChooseAttachment(addAttachmentIconId, drawable) MockAddAttachmentIntent.mockChooseAttachment(addAttachmentIconId, TestData.pngFile)
return ComposerRobot() return ComposerRobot()
} }
companion object { companion object {
private const val takePhotoIconId = R.id.take_photo private const val takePhotoIconId = R.id.take_photo
private const val addAttachmentIconId = R.id.attach_file private const val addAttachmentIconId = R.id.attach_file
} }

View File

@ -39,6 +39,7 @@ import ch.protonmail.android.uitests.robots.mailbox.trash.TrashRobot
import ch.protonmail.android.uitests.testsHelper.StringUtils import ch.protonmail.android.uitests.testsHelper.StringUtils
import ch.protonmail.android.uitests.testsHelper.TestData.pgpEncryptedTextDecrypted import ch.protonmail.android.uitests.testsHelper.TestData.pgpEncryptedTextDecrypted
import ch.protonmail.android.uitests.testsHelper.TestData.pgpSignedTextDecrypted import ch.protonmail.android.uitests.testsHelper.TestData.pgpSignedTextDecrypted
import ch.protonmail.android.uitests.testsHelper.UICustomViewActions.TIMEOUT_30S
import me.proton.fusion.Fusion import me.proton.fusion.Fusion
import org.hamcrest.CoreMatchers.`is` import org.hamcrest.CoreMatchers.`is`
@ -80,13 +81,12 @@ class MessageRobot : Fusion {
} }
fun openActionSheet(): MessageActionSheet { fun openActionSheet(): MessageActionSheet {
view.withId(R.id.messageWebViewContainer).checkIsDisplayed() view.withId(R.id.messageWebViewContainer).withTimeout(TIMEOUT_30S).waitForDisplayed()
view.withId(R.id.moreActionImageButton).click() view.withId(R.id.moreActionImageButton).click()
return MessageActionSheet() return MessageActionSheet()
} }
fun navigateUpToSearch(): SearchRobot { fun navigateUpToSearch(): SearchRobot {
view.withId(R.id.messageWebViewContainer).checkIsDisplayed()
view.instanceOf(AppCompatImageButton::class.java).hasParent(view.withId(R.id.toolbar)).click() view.instanceOf(AppCompatImageButton::class.java).hasParent(view.withId(R.id.toolbar)).click()
return SearchRobot() return SearchRobot()
} }
@ -268,18 +268,20 @@ class MessageRobot : Fusion {
} }
fun messageContainsAttachment() { fun messageContainsAttachment() {
view.withId(R.id.attachmentsView).checkIsDisplayed() view.withId(R.id.attachmentsView).waitForDisplayed().checkIsDisplayed()
} }
fun messageContainsOneAttachment() { fun messageContainsOneAttachment() {
val oneAttachmentString = StringUtils.quantityStringFromResource(R.plurals.attachments_number, 1) val oneAttachmentString = String.format(StringUtils.quantityStringFromResource(R.plurals.attachments_number, 1), 1)
view.withId(R.id.attachments_text_view).containsText(oneAttachmentString).checkIsDisplayed() view
view.withId(R.id.attachment_name_text_view).checkIsDisplayed() .withId(R.id.attachments_text_view)
.containsText(oneAttachmentString)
.waitForDisplayed()
.checkIsDisplayed()
} }
fun messageContainsTwoAttachments() { fun messageContainsTwoAttachments() {
val twoAttachmentString = StringUtils.quantityStringFromResource(R.plurals.attachments_number, 2) val twoAttachmentString = String.format(StringUtils.quantityStringFromResource(R.plurals.attachments_number, 2), 2)
.replace("%d", "2")
view.withId(R.id.attachments_text_view).containsText(twoAttachmentString).checkIsDisplayed() view.withId(R.id.attachments_text_view).containsText(twoAttachmentString).checkIsDisplayed()
} }

View File

@ -27,6 +27,7 @@ import ch.protonmail.android.uitests.robots.mailbox.composer.ComposerRobot
import ch.protonmail.android.uitests.robots.mailbox.inbox.InboxRobot import ch.protonmail.android.uitests.robots.mailbox.inbox.InboxRobot
import ch.protonmail.android.uitests.robots.mailbox.messagedetail.MessageRobot import ch.protonmail.android.uitests.robots.mailbox.messagedetail.MessageRobot
import ch.protonmail.android.uitests.testsHelper.TestData import ch.protonmail.android.uitests.testsHelper.TestData
import ch.protonmail.android.uitests.testsHelper.UICustomViewActions.TIMEOUT_15S
import me.proton.fusion.Fusion import me.proton.fusion.Fusion
/** /**
@ -65,7 +66,7 @@ class SearchRobot : Fusion {
fun clickSearchedMessageBySubjectPart(subject: String): MessageRobot { fun clickSearchedMessageBySubjectPart(subject: String): MessageRobot {
recyclerView recyclerView
.withId(messagesRecyclerViewId) .withId(messagesRecyclerViewId)
// .waitUntilPopulated() .withTimeout(TIMEOUT_15S)
.onHolderItem(withMessageSubjectContaining(subject)) .onHolderItem(withMessageSubjectContaining(subject))
.click() .click()
return MessageRobot() return MessageRobot()

View File

@ -43,6 +43,11 @@ class SentRobot : MailboxRobotInterface, Fusion {
return SelectionStateRobot() return SelectionStateRobot()
} }
override fun deleteMessageWithSwipe(subject: String): SentRobot {
super.deleteMessageWithSwipe(subject)
return this
}
override fun deleteMessageWithSwipe(position: Int): SentRobot { override fun deleteMessageWithSwipe(position: Int): SentRobot {
super.deleteMessageWithSwipe(position) super.deleteMessageWithSwipe(position)
return this return this

View File

@ -40,7 +40,10 @@ open class SpamRobot : MailboxRobotInterface, Fusion {
} }
fun moreOptions(): SpamRobot { fun moreOptions(): SpamRobot {
view.instanceOf(AppCompatImageView::class.java).hasParent(view.instanceOf(ActionMenuView::class.java)).click() view
.instanceOf(AppCompatImageView::class.java)
.hasParent(view.instanceOf(ActionMenuView::class.java))
.click()
return this return this
} }
} }

View File

@ -43,12 +43,13 @@ import ch.protonmail.android.uitests.testsHelper.TestUser.onePassUser
import ch.protonmail.android.uitests.testsHelper.annotations.SmokeTest import ch.protonmail.android.uitests.testsHelper.annotations.SmokeTest
import ch.protonmail.android.uitests.testsHelper.annotations.TestId import ch.protonmail.android.uitests.testsHelper.annotations.TestId
import me.proton.core.test.android.instrumented.utils.FileUtils import me.proton.core.test.android.instrumented.utils.FileUtils
import me.proton.fusion.Fusion
import org.hamcrest.CoreMatchers.not import org.hamcrest.CoreMatchers.not
import org.junit.experimental.categories.Category import org.junit.experimental.categories.Category
import kotlin.test.BeforeTest import kotlin.test.BeforeTest
import kotlin.test.Test import kotlin.test.Test
class AttachmentsTests : BaseTest() { class AttachmentsTests : BaseTest(), Fusion {
private val loginRobot = LoginMailRobot() private val loginRobot = LoginMailRobot()
private val composeRobot = ComposerRobot() private val composeRobot = ComposerRobot()
@ -62,8 +63,6 @@ class AttachmentsTests : BaseTest() {
super.setUp() super.setUp()
subject = TestData.messageSubject subject = TestData.messageSubject
body = TestData.messageBody body = TestData.messageBody
intending(not(isInternal()))
.respondWith(Instrumentation.ActivityResult(Activity.RESULT_OK, null))
} }
@TestId("53707") @TestId("53707")
@ -72,7 +71,6 @@ class AttachmentsTests : BaseTest() {
val messageSubject = "One inline image and one attachment" val messageSubject = "One inline image and one attachment"
loginRobot loginRobot
.loginOnePassUser() .loginOnePassUser()
.searchBar() .searchBar()
.searchMessageText(messageSubject) .searchMessageText(messageSubject)
.clickSearchedMessageBySubject(messageSubject) .clickSearchedMessageBySubject(messageSubject)
@ -86,7 +84,6 @@ class AttachmentsTests : BaseTest() {
val to = internalEmailTrustedKeys.email val to = internalEmailTrustedKeys.email
loginRobot loginRobot
.loginOnePassUser() .loginOnePassUser()
.mailboxLayoutShown() .mailboxLayoutShown()
deviceRobot deviceRobot
@ -307,7 +304,7 @@ class AttachmentsTests : BaseTest() {
.sent() .sent()
.clickMessageBySubject(subject) .clickMessageBySubject(subject)
.expandAttachments() .expandAttachments()
.verify { messageContainsOneAttachment() } .verify { messageContainsTwoAttachments() }
} }
@TestId("1485") @TestId("1485")

View File

@ -19,6 +19,7 @@
package ch.protonmail.android.uitests.tests.composer package ch.protonmail.android.uitests.tests.composer
import ch.protonmail.android.uitests.robots.login.LoginMailRobot import ch.protonmail.android.uitests.robots.login.LoginMailRobot
import ch.protonmail.android.uitests.robots.mailbox.sent.SentRobot
import ch.protonmail.android.uitests.tests.BaseTest import ch.protonmail.android.uitests.tests.BaseTest
import ch.protonmail.android.uitests.testsHelper.TestData import ch.protonmail.android.uitests.testsHelper.TestData
import ch.protonmail.android.uitests.testsHelper.TestData.fwSubject import ch.protonmail.android.uitests.testsHelper.TestData.fwSubject
@ -34,6 +35,7 @@ import kotlin.test.Test
class ForwardMessageTests : BaseTest() { class ForwardMessageTests : BaseTest() {
private val loginRobot = LoginMailRobot() private val loginRobot = LoginMailRobot()
private val sentRobot = SentRobot()
private lateinit var subject: String private lateinit var subject: String
private lateinit var body: String private lateinit var body: String
@ -60,13 +62,14 @@ class ForwardMessageTests : BaseTest() {
.forwardMessage(to, body) .forwardMessage(to, body)
.navigateUpToSent() .navigateUpToSent()
.refreshMessageList() .refreshMessageList()
.verify { .verify { messageWithSubjectExists(fwSubject(subject)) }
messageWithSubjectExists(fwSubject(subject)) sentRobot
messageWithSubjectHasForwardedFlag(subject) .refreshMessageList()
} .verify { messageWithSubjectHasForwardedFlag(subject) }
} }
@TestId("1950") @TestId("1950")
@Category(SmokeTest::class)
@Test @Test
fun forwardMessageWithAttachment() { fun forwardMessageWithAttachment() {
val to = internalEmailTrustedKeys.email val to = internalEmailTrustedKeys.email
@ -83,7 +86,6 @@ class ForwardMessageTests : BaseTest() {
.navigateUpToSent() .navigateUpToSent()
.refreshMessageList() .refreshMessageList()
.clickMessageBySubject(fwSubject(subject)) .clickMessageBySubject(fwSubject(subject))
.expandAttachments()
.verify { messageContainsOneAttachment() } .verify { messageContainsOneAttachment() }
} }
@ -107,7 +109,6 @@ class ForwardMessageTests : BaseTest() {
.sent() .sent()
.refreshMessageList() .refreshMessageList()
.clickMessageBySubject(updatedSubject(subject)) .clickMessageBySubject(updatedSubject(subject))
.expandAttachments()
.verify { messageContainsOneAttachment() } .verify { messageContainsOneAttachment() }
} }
@ -126,12 +127,11 @@ class ForwardMessageTests : BaseTest() {
.openActionSheet() .openActionSheet()
.forward() .forward()
.attachments() .attachments()
.removeLastAttachment() .removeAttachmentAtPosition(1)
.goBackToComposer() .navigateUpToComposer()
.forwardMessage(to, body) .forwardMessage(to, body)
.navigateUpToSent() .navigateUpToSent()
.clickMessageBySubject(fwSubject(subject)) .clickMessageBySubject(fwSubject(subject))
.expandAttachments()
.verify { messageContainsOneAttachment() } .verify { messageContainsOneAttachment() }
} }
@ -152,7 +152,6 @@ class ForwardMessageTests : BaseTest() {
.forwardMessage(to, body) .forwardMessage(to, body)
.navigateUpToSent() .navigateUpToSent()
.clickMessageBySubject(fwSubject(subject)) .clickMessageBySubject(fwSubject(subject))
.expandAttachments()
.verify { messageContainsOneAttachment() } .verify { messageContainsOneAttachment() }
} }
} }

View File

@ -19,6 +19,7 @@
package ch.protonmail.android.uitests.tests.composer package ch.protonmail.android.uitests.tests.composer
import ch.protonmail.android.uitests.robots.login.LoginMailRobot import ch.protonmail.android.uitests.robots.login.LoginMailRobot
import ch.protonmail.android.uitests.robots.mailbox.sent.SentRobot
import ch.protonmail.android.uitests.tests.BaseTest import ch.protonmail.android.uitests.tests.BaseTest
import ch.protonmail.android.uitests.testsHelper.TestData import ch.protonmail.android.uitests.testsHelper.TestData
import ch.protonmail.android.uitests.testsHelper.TestData.reSubject import ch.protonmail.android.uitests.testsHelper.TestData.reSubject
@ -32,6 +33,7 @@ import kotlin.test.Test
class ReplyToMessageTests : BaseTest() { class ReplyToMessageTests : BaseTest() {
private val loginRobot = LoginMailRobot() private val loginRobot = LoginMailRobot()
private val sentRobot = SentRobot()
private lateinit var subject: String private lateinit var subject: String
private lateinit var body: String private lateinit var body: String
@ -58,12 +60,11 @@ class ReplyToMessageTests : BaseTest() {
.editBodyAndReply("Reply") .editBodyAndReply("Reply")
.navigateUpToSent() .navigateUpToSent()
.refreshMessageList() .refreshMessageList()
.verify { .verify { messageWithSubjectExists(reSubject(subject)) }
messageWithSubjectExists(reSubject(subject))
}
} }
@TestId("1946") @TestId("1946")
@Category(SmokeTest::class)
@Test @Test
fun replyMessageWithAttachment() { fun replyMessageWithAttachment() {
val to = internalEmailTrustedKeys.email val to = internalEmailTrustedKeys.email
@ -78,7 +79,8 @@ class ReplyToMessageTests : BaseTest() {
.reply() .reply()
.editBodyAndReply("Robot Reply With Attachment") .editBodyAndReply("Robot Reply With Attachment")
.navigateUpToSent() .navigateUpToSent()
.verify { messageWithSubjectExists(TestData.reSubject(subject)) } .refreshMessageList()
.verify { messageWithSubjectExists(reSubject(subject)) }
} }
@TestId("21093") @TestId("21093")
@ -96,9 +98,10 @@ class ReplyToMessageTests : BaseTest() {
.replyAll() .replyAll()
.editBodyAndReply("Robot ReplyAll") .editBodyAndReply("Robot ReplyAll")
.navigateUpToSent() .navigateUpToSent()
.verify { .refreshMessageList()
messageWithSubjectExists(TestData.reSubject(subject)) .verify { messageWithSubjectExists(reSubject(subject)) }
messageWithSubjectHasRepliedAllFlag(subject) sentRobot
} .refreshMessageList()
.verify { messageWithSubjectHasRepliedAllFlag(subject) }
} }
} }

View File

@ -20,6 +20,7 @@ package ch.protonmail.android.uitests.tests.composer
import ch.protonmail.android.uitests.robots.login.LoginMailRobot import ch.protonmail.android.uitests.robots.login.LoginMailRobot
import ch.protonmail.android.uitests.tests.BaseTest import ch.protonmail.android.uitests.tests.BaseTest
import ch.protonmail.android.uitests.tests.suites.RegressionSuite
import ch.protonmail.android.uitests.testsHelper.TestData import ch.protonmail.android.uitests.testsHelper.TestData
import ch.protonmail.android.uitests.testsHelper.TestData.editedPassword import ch.protonmail.android.uitests.testsHelper.TestData.editedPassword
import ch.protonmail.android.uitests.testsHelper.TestData.editedPasswordHint import ch.protonmail.android.uitests.testsHelper.TestData.editedPasswordHint

View File

@ -176,7 +176,7 @@ class DraftsTests : BaseTest() {
.clickDraftBySubject(subject) .clickDraftBySubject(subject)
.attachments() .attachments()
.addFileAttachment(welcomeDrawable) .addFileAttachment(welcomeDrawable)
.goBackToComposer() .navigateUpToComposer()
.confirmDraftSavingFromDrafts() .confirmDraftSavingFromDrafts()
.refreshMessageList() .refreshMessageList()
.clickMessageBySubject(subject) .clickMessageBySubject(subject)
@ -267,7 +267,7 @@ class DraftsTests : BaseTest() {
.clickDraftBySubject(subject) .clickDraftBySubject(subject)
.attachments() .attachments()
.addFileAttachment(welcomeDrawable) .addFileAttachment(welcomeDrawable)
.goBackToComposer() .navigateUpToComposer()
.draftSubjectBody(subjectEditOne, bodyEditOne) .draftSubjectBody(subjectEditOne, bodyEditOne)
.clickUpButton() .clickUpButton()
.confirmDraftSavingFromDrafts() .confirmDraftSavingFromDrafts()
@ -306,15 +306,15 @@ class DraftsTests : BaseTest() {
.refreshMessageList() .refreshMessageList()
.clickDraftBySubject(fwSubject(subject)) .clickDraftBySubject(fwSubject(subject))
.attachments() .attachments()
.removeLastAttachment() .removeAttachmentAtPosition(0)
.goBackToComposer() .navigateUpToComposer()
.clickUpButton() .clickUpButton()
.confirmDraftSavingFromDrafts() .confirmDraftSavingFromDrafts()
.refreshMessageList() .refreshMessageList()
.clickDraftBySubject(fwSubject(subject)) .clickDraftBySubject(fwSubject(subject))
.attachments() .attachments()
.addFileAttachment(welcomeDrawable) .addFileAttachment(welcomeDrawable)
.goBackToComposer() .navigateUpToComposer()
.updateSubject(subject) .updateSubject(subject)
.send() .send()
.menuDrawer() .menuDrawer()

View File

@ -24,6 +24,7 @@ import ch.protonmail.android.uitests.robots.mailbox.MailboxRobotInterface.Compan
import ch.protonmail.android.uitests.robots.mailbox.MailboxRobotInterface.Companion.deletedMessageSubject import ch.protonmail.android.uitests.robots.mailbox.MailboxRobotInterface.Companion.deletedMessageSubject
import ch.protonmail.android.uitests.robots.mailbox.MailboxRobotInterface.Companion.swipeLeftMessageSubject import ch.protonmail.android.uitests.robots.mailbox.MailboxRobotInterface.Companion.swipeLeftMessageSubject
import ch.protonmail.android.uitests.tests.BaseTest import ch.protonmail.android.uitests.tests.BaseTest
import ch.protonmail.android.uitests.testsHelper.TestData
import ch.protonmail.android.uitests.testsHelper.TestUser.onePassUser import ch.protonmail.android.uitests.testsHelper.TestUser.onePassUser
import ch.protonmail.android.uitests.testsHelper.TestUser.twoPassUser import ch.protonmail.android.uitests.testsHelper.TestUser.twoPassUser
import ch.protonmail.android.uitests.testsHelper.annotations.SmokeTest import ch.protonmail.android.uitests.testsHelper.annotations.SmokeTest
@ -39,13 +40,18 @@ class SwipeGesturesTests : BaseTest() {
@Category(SmokeTest::class) @Category(SmokeTest::class)
@Test @Test
fun deleteMessageWithSwipe() { fun deleteMessageWithSwipe() {
val subject = TestData.messageSubject
val body = TestData.messageBody
loginRobot loginRobot
.loginOnePassUser() .loginOnePassUser()
.compose()
.sendMessage(twoPassUser.email, subject, body)
.menuDrawer() .menuDrawer()
.sent() .sent()
.deleteMessageWithSwipe(1) .refreshMessageList()
.deleteMessageWithSwipe(0)
.verify { .verify {
messageMovedToTrash(deletedMessageSubject, deletedMessageDate) messageMovedToTrash(subject)
} }
} }

View File

@ -28,24 +28,20 @@ import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.provider.MediaStore import android.provider.MediaStore
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.matcher.IntentMatchers
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.intent.IntentCallback import androidx.test.runner.intent.IntentCallback
import androidx.test.runner.intent.IntentMonitorRegistry import androidx.test.runner.intent.IntentMonitorRegistry
import me.proton.core.test.android.instrumented.Robot import me.proton.fusion.Fusion
import org.jetbrains.annotations.Contract import org.jetbrains.annotations.Contract
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.IOException import java.io.IOException
import java.util.ArrayList import java.util.ArrayList
object MockAddAttachmentIntent : Robot { object MockAddAttachmentIntent : Fusion {
private fun createImage(@IdRes resourceId: Int) { private fun createImage(assetsFilename: String) {
val icon = BitmapFactory.decodeResource( val icon = BitmapFactory
InstrumentationRegistry.getInstrumentation().targetContext.resources, .decodeStream(InstrumentationRegistry.getInstrumentation().context.assets.open(assetsFilename))
resourceId
)
val file = File(InstrumentationRegistry.getInstrumentation() val file = File(InstrumentationRegistry.getInstrumentation()
.targetContext.externalCacheDir, "pickImageResult.jpeg") .targetContext.externalCacheDir, "pickImageResult.jpeg")
try { try {
@ -72,16 +68,16 @@ object MockAddAttachmentIntent : Robot {
return ActivityResult(Activity.RESULT_OK, resultData) return ActivityResult(Activity.RESULT_OK, resultData)
} }
fun mockChooseAttachment(@IdRes objectId: Int, @IdRes imageResourceId: Int) { fun mockChooseAttachment(@IdRes objectId: Int, assetsFilename: String) {
createImage(imageResourceId) createImage(assetsFilename)
val result = pickImageResult() val result = pickImageResult()
Intents.intending(IntentMatchers.hasAction(Intent.ACTION_GET_CONTENT)).respondWith(result) intent.hasAction(Intent.ACTION_CHOOSER).respondWith(result)
view.withId(objectId).click() view.withId(objectId).click()
} }
fun mockCameraImageCapture(@IdRes objectId: Int, @IdRes imageResourceId: Int) { fun mockCameraImageCapture(@IdRes objectId: Int, @IdRes imageResourceId: Int) {
val result = ActivityResult(Activity.RESULT_OK, null) val result = ActivityResult(Activity.RESULT_OK, null)
Intents.intending(IntentMatchers.hasAction(MediaStore.ACTION_IMAGE_CAPTURE)).respondWith(result) intent.hasAction(MediaStore.ACTION_IMAGE_CAPTURE).respondWith(result)
val cameraCallback = intentCallback(imageResourceId) val cameraCallback = intentCallback(imageResourceId)
IntentMonitorRegistry.getInstance().addIntentCallback(cameraCallback) IntentMonitorRegistry.getInstance().addIntentCallback(cameraCallback)
view.withId(objectId).click() view.withId(objectId).click()