porting the room flows to the robot pattern

This commit is contained in:
Adam Brown 2021-11-04 16:14:51 +00:00
parent e800c59f57
commit 557609c175
7 changed files with 344 additions and 211 deletions

View File

@ -20,6 +20,6 @@ import android.app.Activity
import im.vector.app.activityIdlingResource import im.vector.app.activityIdlingResource
import im.vector.app.withIdlingResource import im.vector.app.withIdlingResource
inline fun <reified T : Activity> waitUntilActivityVisible(noinline block: (() -> Unit)) { inline fun <reified T : Activity> waitUntilActivityVisible(noinline block: (() -> Unit) = {}) {
withIdlingResource(activityIdlingResource(T::class.java), block) withIdlingResource(activityIdlingResource(T::class.java), block)
} }

View File

@ -30,18 +30,10 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest import androidx.test.filters.LargeTest
import com.adevinta.android.barista.assertion.BaristaListAssertions.assertListItemCount
import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickBack
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaClickInteractions.longClickOn
import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton
import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo
import com.adevinta.android.barista.interaction.BaristaListInteractions.clickListItem
import com.adevinta.android.barista.interaction.BaristaListInteractions.clickListItemChild
import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.clickMenu
import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.openMenu
import im.vector.app.EspressoHelper import im.vector.app.EspressoHelper
import im.vector.app.R import im.vector.app.R
import im.vector.app.SleepViewAction import im.vector.app.SleepViewAction
@ -49,12 +41,9 @@ import im.vector.app.activityIdlingResource
import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.features.MainActivity import im.vector.app.features.MainActivity
import im.vector.app.features.home.HomeActivity import im.vector.app.features.home.HomeActivity
import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.login.LoginActivity import im.vector.app.features.login.LoginActivity
import im.vector.app.features.roomdirectory.RoomDirectoryActivity
import im.vector.app.initialSyncIdlingResource import im.vector.app.initialSyncIdlingResource
import im.vector.app.ui.robot.ElementRobot import im.vector.app.ui.robot.ElementRobot
import im.vector.app.waitForView
import im.vector.app.withIdlingResource import im.vector.app.withIdlingResource
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -117,10 +106,19 @@ class UiAllScreensSanityTest {
verifyInviteFriendsButton() verifyInviteFriendsButton()
} }
// Create Room assertDisplayed(R.id.bottomNavigationView)
// First navigate to the other tab sleep(1000)
clickOn(R.id.bottom_action_rooms)
createRoom() elementRobot.newRoom {
createNewRoom {
crawl()
createRoom {
postMessage("Hello world!")
crawl()
openSettings { crawl() }
}
}
}
assertDisplayed(R.id.bottomNavigationView) assertDisplayed(R.id.bottomNavigationView)
@ -172,193 +170,5 @@ class UiAllScreensSanityTest {
assertDisplayed(R.string.are_you_sure) assertDisplayed(R.string.are_you_sure)
clickOn(R.string.skip) clickOn(R.string.skip)
} }
private fun createRoom() {
clickOn(R.id.createGroupRoomButton)
waitUntilActivityVisible<RoomDirectoryActivity> {
assertDisplayed(R.id.publicRoomsList)
}
clickOn(R.string.create_new_room)
// Room access bottom sheet
clickOn(R.string.room_settings_room_access_private_title)
pressBack()
// Create
assertListItemCount(R.id.createRoomForm, 12)
clickListItemChild(R.id.createRoomForm, 11, R.id.form_submit_button)
waitUntilActivityVisible<RoomDetailActivity> {
assertDisplayed(R.id.roomDetailContainer)
}
clickOn(R.id.attachmentButton)
clickBack()
// Send a message
writeTo(R.id.composerEditText, "Hello world!")
clickOn(R.id.sendButton)
navigateToRoomSettings()
// Long click on the message
longClickOnMessageTest()
// Menu
openMenu()
pressBack()
clickMenu(R.id.voice_call)
pressBack()
clickMenu(R.id.video_call)
pressBack()
clickMenu(R.id.search)
pressBack()
pressBack()
}
private fun longClickOnMessageTest() {
// Test quick reaction
longClickOnMessage()
// Add quick reaction
clickOn("\uD83D\uDC4D") // 👍
sleep(1000)
// Open reactions
longClickOn("\uD83D\uDC4D") // 👍
pressBack()
// Test add reaction
longClickOnMessage()
clickOn(R.string.message_add_reaction)
// Filter
// TODO clickMenu(R.id.search)
// Wait for emoji to load, it's async now
sleep(2_000)
clickListItem(R.id.emojiRecyclerView, 4)
// Test Edit mode
longClickOnMessage()
clickOn(R.string.edit)
// TODO Cancel action
writeTo(R.id.composerEditText, "Hello universe!")
// Wait a bit for the keyboard layout to update
sleep(30)
clickOn(R.id.sendButton)
// Wait for the UI to update
sleep(1000)
// Open edit history
longClickOnMessage("Hello universe! (edited)")
clickOn(R.string.message_view_edit_history)
pressBack()
}
private fun longClickOnMessage(text: String = "Hello world!") {
onView(withId(R.id.timelineRecyclerView))
.perform(
actionOnItem<RecyclerView.ViewHolder>(
hasDescendant(withText(text)),
longClick()
)
)
}
private fun navigateToRoomSettings() {
clickOn(R.id.roomToolbarTitleView)
assertDisplayed(R.id.roomProfileAvatarView)
// Room settings
clickListItem(R.id.matrixProfileRecyclerView, 3)
navigateToRoomParameters()
pressBack()
// Notifications
clickListItem(R.id.matrixProfileRecyclerView, 5)
pressBack()
assertDisplayed(R.id.roomProfileAvatarView)
// People
clickListItem(R.id.matrixProfileRecyclerView, 7)
assertDisplayed(R.id.inviteUsersButton)
navigateToRoomPeople()
// Fab
navigateToInvite()
pressBack()
pressBack()
assertDisplayed(R.id.roomProfileAvatarView)
// Uploads
clickListItem(R.id.matrixProfileRecyclerView, 9)
// File tab
clickOn(R.string.uploads_files_title)
sleep(1000)
pressBack()
assertDisplayed(R.id.roomProfileAvatarView)
// Leave
clickListItem(R.id.matrixProfileRecyclerView, 13)
clickDialogNegativeButton()
// Advanced
// Room addresses
clickListItem(R.id.matrixProfileRecyclerView, 15)
onView(isRoot()).perform(waitForView(withText(R.string.room_alias_published_alias_title)))
pressBack()
// Room permissions
clickListItem(R.id.matrixProfileRecyclerView, 17)
onView(isRoot()).perform(waitForView(withText(R.string.room_permissions_title)))
clickOn(R.string.room_permissions_change_room_avatar)
clickDialogNegativeButton()
// Toggle
clickOn(R.string.show_advanced)
clickOn(R.string.hide_advanced)
pressBack()
// Menu share
// clickMenu(R.id.roomProfileShareAction)
// pressBack()
pressBack()
}
private fun navigateToRoomParameters() {
// Room history readability
clickListItem(R.id.roomSettingsRecyclerView, 4)
pressBack()
// Room access
clickListItem(R.id.roomSettingsRecyclerView, 6)
pressBack()
}
private fun navigateToInvite() {
assertDisplayed(R.id.inviteUsersButton)
clickOn(R.id.inviteUsersButton)
closeSoftKeyboard()
pressBack()
}
private fun navigateToRoomPeople() {
// Open first user
clickListItem(R.id.roomSettingsRecyclerView, 1)
sleep(1000)
assertDisplayed(R.id.memberProfilePowerLevelView)
// Verification
clickListItem(R.id.matrixProfileRecyclerView, 1)
clickBack()
// Role
clickListItem(R.id.matrixProfileRecyclerView, 3)
sleep(1000)
clickDialogNegativeButton()
sleep(1000)
clickBack()
}
} }

View File

@ -0,0 +1,47 @@
/*
* 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.assertion.BaristaListAssertions
import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions
import com.adevinta.android.barista.interaction.BaristaClickInteractions
import com.adevinta.android.barista.interaction.BaristaListInteractions
import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.features.home.room.detail.RoomDetailActivity
class CreateNewRoomRobot(
var createdRoom: Boolean = false
) {
fun createRoom(block: RoomDetailRobot.() -> Unit) {
createdRoom = true
BaristaListAssertions.assertListItemCount(R.id.createRoomForm, 12)
BaristaListInteractions.clickListItemChild(R.id.createRoomForm, 11, R.id.form_submit_button)
waitUntilActivityVisible<RoomDetailActivity>()
Thread.sleep(1000)
BaristaVisibilityAssertions.assertDisplayed(R.id.roomDetailContainer)
block(RoomDetailRobot())
}
fun crawl() {
// Room access bottom sheet
BaristaClickInteractions.clickOn(R.string.room_settings_room_access_private_title)
Espresso.pressBack()
}
}

View File

@ -17,13 +17,14 @@
package im.vector.app.ui.robot package im.vector.app.ui.robot
import androidx.test.espresso.Espresso.pressBack import androidx.test.espresso.Espresso.pressBack
import androidx.test.espresso.action.ViewActions import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaDrawerInteractions.openDrawer import com.adevinta.android.barista.interaction.BaristaDrawerInteractions.openDrawer
import im.vector.app.R import im.vector.app.R
import im.vector.app.activityIdlingResource import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.features.createdirect.CreateDirectRoomActivity import im.vector.app.features.createdirect.CreateDirectRoomActivity
import im.vector.app.withIdlingResource import im.vector.app.features.roomdirectory.RoomDirectoryActivity
import java.lang.Thread.sleep
class ElementRobot { class ElementRobot {
@ -37,10 +38,21 @@ class ElementRobot {
fun newDirectMessage(block: NewDirectMessageRobot.() -> Unit) { fun newDirectMessage(block: NewDirectMessageRobot.() -> Unit) {
clickOn(R.id.bottom_action_people) clickOn(R.id.bottom_action_people)
clickOn(R.id.createChatRoomButton) clickOn(R.id.createChatRoomButton)
ViewActions.closeSoftKeyboard() waitUntilActivityVisible<CreateDirectRoomActivity>()
withIdlingResource(activityIdlingResource(CreateDirectRoomActivity::class.java)) { // close keyboard
sleep(1000)
pressBack()
block(NewDirectMessageRobot()) block(NewDirectMessageRobot())
pressBack()
} }
fun newRoom(block: NewRoomRobot.() -> Unit) {
clickOn(R.id.bottom_action_rooms)
clickOn(R.id.createGroupRoomButton)
sleep(1000)
waitUntilActivityVisible<RoomDirectoryActivity>()
BaristaVisibilityAssertions.assertDisplayed(R.id.publicRoomsList)
block(NewRoomRobot())
pressBack() pressBack()
} }
} }

View File

@ -0,0 +1,33 @@
/*
* 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 im.vector.app.R
class NewRoomRobot {
fun createNewRoom(block: CreateNewRoomRobot.() -> Unit) {
BaristaClickInteractions.clickOn(R.string.create_new_room)
val createNewRoomRobot = CreateNewRoomRobot()
block(createNewRoomRobot)
if (!createNewRoomRobot.createdRoom) {
Espresso.pressBack()
}
}
}

View File

@ -0,0 +1,109 @@
/*
* 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.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers
import com.adevinta.android.barista.interaction.BaristaClickInteractions
import com.adevinta.android.barista.interaction.BaristaEditTextInteractions
import com.adevinta.android.barista.interaction.BaristaListInteractions
import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions
import im.vector.app.R
import im.vector.app.waitForView
class RoomDetailRobot {
fun postMessage(content: String) {
BaristaEditTextInteractions.writeTo(R.id.composerEditText, content)
BaristaClickInteractions.clickOn(R.id.sendButton)
}
fun crawl() {
BaristaClickInteractions.clickOn(R.id.attachmentButton)
BaristaClickInteractions.clickBack()
// Menu
BaristaMenuClickInteractions.openMenu()
Espresso.pressBack()
BaristaMenuClickInteractions.clickMenu(R.id.voice_call)
Espresso.pressBack()
BaristaMenuClickInteractions.clickMenu(R.id.video_call)
Espresso.pressBack()
BaristaMenuClickInteractions.clickMenu(R.id.search)
Espresso.pressBack()
// Long click on the message
longClickOnMessageTest()
}
private fun longClickOnMessageTest() {
// Test quick reaction
longClickOnMessage()
// Add quick reaction
BaristaClickInteractions.clickOn("\uD83D\uDC4D") // 👍
Thread.sleep(1000)
// Open reactions
BaristaClickInteractions.longClickOn("\uD83D\uDC4D") // 👍
Espresso.pressBack()
// Test add reaction
longClickOnMessage()
BaristaClickInteractions.clickOn(R.string.message_add_reaction)
// Filter
// TODO clickMenu(R.id.search)
// Wait for emoji to load, it's async now
Thread.sleep(2000)
BaristaListInteractions.clickListItem(R.id.emojiRecyclerView, 4)
Thread.sleep(2000)
// Test Edit mode
longClickOnMessage()
BaristaClickInteractions.clickOn(R.string.edit)
// TODO Cancel action
BaristaEditTextInteractions.writeTo(R.id.composerEditText, "Hello universe!")
// Wait a bit for the keyboard layout to update
Thread.sleep(30)
BaristaClickInteractions.clickOn(R.id.sendButton)
// Wait for the UI to update
Thread.sleep(1000)
// Open edit history
longClickOnMessage("Hello universe! (edited)")
BaristaClickInteractions.clickOn(R.string.message_view_edit_history)
Espresso.pressBack()
}
private fun longClickOnMessage(text: String = "Hello world!") {
Espresso.onView(ViewMatchers.withId(R.id.timelineRecyclerView))
.perform(
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
ViewMatchers.hasDescendant(ViewMatchers.withText(text)),
ViewActions.longClick()
)
)
}
fun openSettings(block: RoomSettingsRobot.() -> Unit) {
BaristaClickInteractions.clickOn(R.id.roomToolbarTitleView)
waitForView(ViewMatchers.withId(R.id.roomProfileAvatarView))
block(RoomSettingsRobot())
Espresso.pressBack()
}
}

View File

@ -0,0 +1,122 @@
/*
* 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 androidx.test.espresso.action.ViewActions
import androidx.test.espresso.matcher.ViewMatchers
import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions
import com.adevinta.android.barista.interaction.BaristaClickInteractions
import com.adevinta.android.barista.interaction.BaristaDialogInteractions
import com.adevinta.android.barista.interaction.BaristaListInteractions
import im.vector.app.R
import im.vector.app.waitForView
class RoomSettingsRobot {
fun crawl() {
// Room settings
BaristaListInteractions.clickListItem(R.id.matrixProfileRecyclerView, 3)
navigateToRoomParameters()
Espresso.pressBack()
// Notifications
BaristaListInteractions.clickListItem(R.id.matrixProfileRecyclerView, 5)
Espresso.pressBack()
BaristaVisibilityAssertions.assertDisplayed(R.id.roomProfileAvatarView)
// People
BaristaListInteractions.clickListItem(R.id.matrixProfileRecyclerView, 7)
BaristaVisibilityAssertions.assertDisplayed(R.id.inviteUsersButton)
navigateToRoomPeople()
// Fab
navigateToInvite()
Espresso.pressBack()
Espresso.pressBack()
BaristaVisibilityAssertions.assertDisplayed(R.id.roomProfileAvatarView)
// Uploads
BaristaListInteractions.clickListItem(R.id.matrixProfileRecyclerView, 9)
// File tab
BaristaClickInteractions.clickOn(R.string.uploads_files_title)
Thread.sleep(1000)
Espresso.pressBack()
BaristaVisibilityAssertions.assertDisplayed(R.id.roomProfileAvatarView)
// Leave
BaristaListInteractions.clickListItem(R.id.matrixProfileRecyclerView, 13)
BaristaDialogInteractions.clickDialogNegativeButton()
// Advanced
// Room addresses
BaristaListInteractions.clickListItem(R.id.matrixProfileRecyclerView, 15)
Espresso.onView(ViewMatchers.isRoot()).perform(waitForView(ViewMatchers.withText(R.string.room_alias_published_alias_title)))
Espresso.pressBack()
// Room permissions
BaristaListInteractions.clickListItem(R.id.matrixProfileRecyclerView, 17)
Espresso.onView(ViewMatchers.isRoot()).perform(waitForView(ViewMatchers.withText(R.string.room_permissions_title)))
BaristaClickInteractions.clickOn(R.string.room_permissions_change_room_avatar)
BaristaDialogInteractions.clickDialogNegativeButton()
// Toggle
BaristaClickInteractions.clickOn(R.string.show_advanced)
BaristaClickInteractions.clickOn(R.string.hide_advanced)
Espresso.pressBack()
// Menu share
// clickMenu(R.id.roomProfileShareAction)
// pressBack()
}
private fun navigateToRoomParameters() {
// Room history readability
BaristaListInteractions.clickListItem(R.id.roomSettingsRecyclerView, 4)
Espresso.pressBack()
// Room access
BaristaListInteractions.clickListItem(R.id.roomSettingsRecyclerView, 6)
Espresso.pressBack()
}
private fun navigateToInvite() {
BaristaVisibilityAssertions.assertDisplayed(R.id.inviteUsersButton)
BaristaClickInteractions.clickOn(R.id.inviteUsersButton)
ViewActions.closeSoftKeyboard()
Espresso.pressBack()
}
private fun navigateToRoomPeople() {
// Open first user
BaristaListInteractions.clickListItem(R.id.roomSettingsRecyclerView, 1)
Thread.sleep(1000)
BaristaVisibilityAssertions.assertDisplayed(R.id.memberProfilePowerLevelView)
// Verification
BaristaListInteractions.clickListItem(R.id.matrixProfileRecyclerView, 1)
BaristaClickInteractions.clickBack()
// Role
BaristaListInteractions.clickListItem(R.id.matrixProfileRecyclerView, 3)
Thread.sleep(1000)
BaristaDialogInteractions.clickDialogNegativeButton()
Thread.sleep(1000)
BaristaClickInteractions.clickBack()
}
}