From e5edfe9c739570de3f7cc838ca8f86368fccc687 Mon Sep 17 00:00:00 2001
From: Adam Brown <adampsbrown@gmail.com>
Date: Tue, 9 Nov 2021 08:49:09 +0000
Subject: [PATCH] adding dedicated message menu robot and adding sanity check
 for developer mode flows

---
 .../vector/app/ui/UiAllScreensSanityTest.kt   | 23 +++++++-
 .../im/vector/app/ui/robot/ElementRobot.kt    |  6 ++
 .../vector/app/ui/robot/MessageMenuRobot.kt   | 59 +++++++++++++++++++
 .../im/vector/app/ui/robot/RoomDetailRobot.kt | 58 +++++++++---------
 .../im/vector/app/ui/robot/RoomListRobot.kt   | 20 +++++--
 .../robot/settings/SettingsAdvancedRobot.kt   | 28 +++++----
 .../app/ui/robot/settings/SettingsRobot.kt    | 10 +++-
 7 files changed, 153 insertions(+), 51 deletions(-)
 create mode 100644 vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt

diff --git a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt
index d80f11e975..e3917919bb 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt
@@ -19,8 +19,11 @@ package im.vector.app.ui
 import androidx.test.ext.junit.rules.ActivityScenarioRule
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
+import im.vector.app.R
 import im.vector.app.features.MainActivity
+import im.vector.app.getString
 import im.vector.app.ui.robot.ElementRobot
+import im.vector.app.ui.robot.withDeveloperMode
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -69,13 +72,30 @@ class UiAllScreensSanityTest {
             createNewRoom {
                 crawl()
                 createRoom {
-                    postMessage("Hello world!")
+                    val message = "Hello world!"
+                    postMessage(message)
                     crawl()
+                    crawlMessage(message)
                     openSettings { crawl() }
                 }
             }
         }
 
+        elementRobot.withDeveloperMode {
+            settings {
+                advancedSettings { crawlDeveloperOptions() }
+            }
+            roomList {
+                openRoom(getString(R.string.room_displayname_empty_room)) {
+                    val message = "Test view source"
+                    postMessage(message)
+                    openMessageMenu(message) {
+                        viewSource()
+                    }
+                }
+            }
+        }
+
         elementRobot.roomList {
             verifyCreatedRoom()
         }
@@ -89,3 +109,4 @@ class UiAllScreensSanityTest {
         elementRobot.signout(expectSignOutWarning = false)
     }
 }
+
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt
index e904ce1c80..a3bc5b26fc 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt
@@ -141,3 +141,9 @@ class ElementRobot {
 }
 
 private fun Boolean.toWarningType() = if (this) "shown" else "skipped"
+
+fun ElementRobot.withDeveloperMode(block: ElementRobot.() -> Unit) {
+    settings { toggleDeveloperMode() }
+    block()
+    settings { toggleDeveloperMode() }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt
new file mode 100644
index 0000000000..0948ecb30d
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.ui.robot
+
+import androidx.test.espresso.Espresso
+import com.adevinta.android.barista.interaction.BaristaClickInteractions
+import com.adevinta.android.barista.interaction.BaristaListInteractions
+import im.vector.app.R
+
+class MessageMenuRobot(
+        var autoClosed: Boolean = false
+) {
+
+    fun viewSource() {
+        BaristaClickInteractions.clickOn(R.string.view_source)
+        // wait for library
+        Thread.sleep(1000)
+        Espresso.pressBack()
+        autoClosed = true
+    }
+
+    fun editHistory() {
+        BaristaClickInteractions.clickOn(R.string.message_view_edit_history)
+        Espresso.pressBack()
+        autoClosed = true
+    }
+
+    fun addQuickReaction(quickReaction: String) {
+        BaristaClickInteractions.clickOn(quickReaction)
+        autoClosed = true
+    }
+
+    fun addReactionFromEmojiPicker() {
+        BaristaClickInteractions.clickOn(R.string.message_add_reaction)
+        // Wait for emoji to load, it's async now
+        Thread.sleep(2000)
+        BaristaListInteractions.clickListItem(R.id.emojiRecyclerView, 4)
+        autoClosed = true
+    }
+
+    fun edit() {
+        BaristaClickInteractions.clickOn(R.string.edit)
+        autoClosed = true
+    }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt
index c77fcbfe35..f2978aa35f 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt
@@ -17,7 +17,7 @@
 package im.vector.app.ui.robot
 
 import androidx.recyclerview.widget.RecyclerView
-import androidx.test.espresso.Espresso
+import androidx.test.espresso.Espresso.onView
 import androidx.test.espresso.Espresso.pressBack
 import androidx.test.espresso.action.ViewActions
 import androidx.test.espresso.contrib.RecyclerViewActions
@@ -27,11 +27,11 @@ import com.adevinta.android.barista.interaction.BaristaClickInteractions
 import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
 import com.adevinta.android.barista.interaction.BaristaClickInteractions.longClickOn
 import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo
-import com.adevinta.android.barista.interaction.BaristaListInteractions.clickListItem
 import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.clickMenu
 import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.openMenu
 import im.vector.app.R
 import im.vector.app.espresso.tools.waitUntilViewVisible
+import im.vector.app.features.reactions.data.EmojiDataSource
 import im.vector.app.waitForView
 import java.lang.Thread.sleep
 
@@ -55,61 +55,57 @@ class RoomDetailRobot {
         pressBack()
         clickMenu(R.id.search)
         pressBack()
-        // Long click on the message
-        longClickOnMessageTest()
     }
 
-    private fun longClickOnMessageTest() {
+    fun crawlMessage(message: String) {
         // Test quick reaction
-        longClickOnMessage()
-        waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
-        // Add quick reaction
-        clickOn("\uD83D\uDC4Dī¸") // 👍
+        val quickReaction = EmojiDataSource.quickEmojis[0] // 👍
+        openMessageMenu(message) {
+            addQuickReaction(quickReaction)
+        }
         waitUntilViewVisible(withId(R.id.composerEditText))
-
         // Open reactions
-        longClickOn("\uD83D\uDC4Dī¸") // 👍
+        longClickOn(quickReaction)
         // wait for bottom sheet
         pressBack()
-
         // Test add reaction
-        longClickOnMessage()
-        waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
-        clickOn(R.string.message_add_reaction)
-        // Filter
-        // TODO clickMenu(R.id.search)
-        // Wait for emoji to load, it's async now
-        sleep(2000)
-        clickListItem(R.id.emojiRecyclerView, 4)
+        openMessageMenu(message) {
+            addReactionFromEmojiPicker()
+        }
         waitUntilViewVisible(withId(R.id.composerEditText))
-
         // Test Edit mode
-        longClickOnMessage()
-        waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
-        clickOn(R.string.edit)
+        openMessageMenu(message) {
+            edit()
+        }
         waitUntilViewVisible(withId(R.id.composerEditText))
         // TODO Cancel action
         writeTo(R.id.composerEditText, "Hello universe!")
         // Wait a bit for the keyboard layout to update
         sleep(30)
+        waitUntilViewVisible(withId(R.id.sendButton))
         clickOn(R.id.sendButton)
         // Wait for the UI to update
         sleep(1000)
         // Open edit history
-        longClickOnMessage("Hello universe! (edited)")
-        waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
-        clickOn(R.string.message_view_edit_history)
-        pressBack()
+        openMessageMenu("Hello universe! (edited)") {
+            editHistory()
+        }
     }
 
-    private fun longClickOnMessage(text: String = "Hello world!") {
-        Espresso.onView(withId(R.id.timelineRecyclerView))
+    fun openMessageMenu(message: String, block: MessageMenuRobot.() -> Unit) {
+        onView(withId(R.id.timelineRecyclerView))
                 .perform(
                         RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
-                                ViewMatchers.hasDescendant(ViewMatchers.withText(text)),
+                                ViewMatchers.hasDescendant(ViewMatchers.withText(message)),
                                 ViewActions.longClick()
                         )
                 )
+        waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
+        val messageMenuRobot = MessageMenuRobot()
+        block(messageMenuRobot)
+        if (!messageMenuRobot.autoClosed) {
+            pressBack()
+        }
     }
 
     fun openSettings(block: RoomSettingsRobot.() -> Unit) {
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt
index bc7d4ac76b..2c6367736d 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt
@@ -18,37 +18,47 @@ package im.vector.app.ui.robot
 
 import androidx.recyclerview.widget.RecyclerView
 import androidx.test.espresso.Espresso
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.Espresso.pressBack
 import androidx.test.espresso.action.ViewActions
 import androidx.test.espresso.contrib.RecyclerViewActions
 import androidx.test.espresso.matcher.ViewMatchers
+import androidx.test.espresso.matcher.ViewMatchers.withText
 import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions
 import com.adevinta.android.barista.interaction.BaristaClickInteractions
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
 import im.vector.app.R
 import im.vector.app.espresso.tools.waitUntilActivityVisible
 import im.vector.app.features.roomdirectory.RoomDirectoryActivity
 
 class RoomListRobot {
 
+    fun openRoom(roomName: String, block: RoomDetailRobot.() -> Unit) {
+        clickOn(roomName)
+        block(RoomDetailRobot())
+        pressBack()
+    }
+
     fun verifyCreatedRoom() {
-        Espresso.onView(ViewMatchers.withId(R.id.roomListView))
+        onView(ViewMatchers.withId(R.id.roomListView))
                 .perform(
                         RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
-                                ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.room_displayname_empty_room)),
+                                ViewMatchers.hasDescendant(withText(R.string.room_displayname_empty_room)),
                                 ViewActions.longClick()
                         )
                 )
-        Espresso.pressBack()
+        pressBack()
     }
 
     fun newRoom(block: NewRoomRobot.() -> Unit) {
-        BaristaClickInteractions.clickOn(R.id.createGroupRoomButton)
+        clickOn(R.id.createGroupRoomButton)
         waitUntilActivityVisible<RoomDirectoryActivity> {
             BaristaVisibilityAssertions.assertDisplayed(R.id.publicRoomsList)
         }
         val newRoomRobot = NewRoomRobot()
         block(newRoomRobot)
         if (!newRoomRobot.createdRoom) {
-            Espresso.pressBack()
+            pressBack()
         }
     }
 }
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt
index ecce51f9bb..4aeb8903dd 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt
@@ -17,8 +17,11 @@
 package im.vector.app.ui.robot.settings
 
 import androidx.test.espresso.Espresso.pressBack
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
 import im.vector.app.R
 import im.vector.app.espresso.tools.clickOnPreference
+import im.vector.app.espresso.tools.waitUntilViewVisible
 
 class SettingsAdvancedRobot {
 
@@ -28,20 +31,19 @@ class SettingsAdvancedRobot {
 
         clickOnPreference(R.string.settings_push_rules)
         pressBack()
+    }
 
-        /* TODO P2 test developer screens
-    // Enable developer mode
-    clickOnSwitchPreference("SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY")
+    fun toggleDeveloperMode() {
+        clickOn(R.string.settings_developer_mode_summary)
+    }
 
-    clickOnPreference(R.string.settings_account_data)
-    clickOn("m.push_rules")
-    pressBack()
-    pressBack()
-    clickOnPreference(R.string.settings_key_requests)
-    pressBack()
-
-    // Disable developer mode
-    clickOnSwitchPreference("SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY")
-     */
+    fun crawlDeveloperOptions() {
+        clickOnPreference(R.string.settings_account_data)
+        waitUntilViewVisible(withText("m.push_rules"))
+        clickOn("m.push_rules")
+        pressBack()
+        pressBack()
+        clickOnPreference(R.string.settings_key_requests)
+        pressBack()
     }
 }
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt
index 3f37d9daf1..a9c053f6c3 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt
@@ -21,6 +21,12 @@ import im.vector.app.clickOnAndGoBack
 
 class SettingsRobot {
 
+    fun toggleDeveloperMode() {
+        advancedSettings {
+            toggleDeveloperMode()
+        }
+    }
+
     fun general(block: SettingsGeneralRobot.() -> Unit) {
         clickOnAndGoBack(R.string.settings_general_title) { block(SettingsGeneralRobot()) }
     }
@@ -50,7 +56,9 @@ class SettingsRobot {
     }
 
     fun advancedSettings(block: SettingsAdvancedRobot.() -> Unit) {
-        clickOnAndGoBack(R.string.settings_advanced_settings) { block(SettingsAdvancedRobot()) }
+        clickOnAndGoBack(R.string.settings_advanced_settings) {
+            block(SettingsAdvancedRobot())
+        }
     }
 
     fun helpAndAbout(block: SettingsHelpRobot.() -> Unit) {