Merge pull request #4420 from vector-im/feature/adm/sanity-check-robot

Sanity tests robot pattern and reliability refactor
This commit is contained in:
Benoit Marty 2021-11-08 14:54:27 +01:00 committed by GitHub
commit cea2206e97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 961 additions and 443 deletions

View file

@ -18,7 +18,9 @@ package im.vector.app
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
import androidx.annotation.StringRes
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.test.espresso.Espresso
import androidx.test.espresso.IdlingRegistry import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.IdlingResource import androidx.test.espresso.IdlingResource
import androidx.test.espresso.PerformException import androidx.test.espresso.PerformException
@ -32,6 +34,7 @@ import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.runner.lifecycle.ActivityLifecycleCallback import androidx.test.runner.lifecycle.ActivityLifecycleCallback
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage import androidx.test.runner.lifecycle.Stage
import com.adevinta.android.barista.interaction.BaristaClickInteractions
import org.hamcrest.Matcher import org.hamcrest.Matcher
import org.hamcrest.Matchers import org.hamcrest.Matchers
import org.hamcrest.StringDescription import org.hamcrest.StringDescription
@ -70,6 +73,8 @@ fun waitForView(viewMatcher: Matcher<View>, timeout: Long = 10_000, waitForDispl
val endTime = startTime + timeout val endTime = startTime + timeout
val visibleMatcher = isDisplayed() val visibleMatcher = isDisplayed()
uiController.loopMainThreadForAtLeast(100)
do { do {
println("*** waitForView loop $view end:$endTime current:${System.currentTimeMillis()}") println("*** waitForView loop $view end:$endTime current:${System.currentTimeMillis()}")
val viewVisible = TreeIterables.breadthFirstViewTraversal(view) val viewVisible = TreeIterables.breadthFirstViewTraversal(view)
@ -205,3 +210,9 @@ fun allSecretsKnownIdling(session: Session): IdlingResource {
return res return res
} }
fun clickOnAndGoBack(@StringRes name: Int, block: () -> Unit) {
BaristaClickInteractions.clickOn(name)
block()
Espresso.pressBack()
}

View file

@ -18,7 +18,7 @@ package im.vector.app
import android.net.Uri import android.net.Uri
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import im.vector.app.ui.UiTestBase import im.vector.app.ui.robot.OnboardingRobot
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -39,7 +39,7 @@ abstract class VerificationTestBase {
val password = "password" val password = "password"
val homeServerUrl: String = "http://10.0.2.2:8080" val homeServerUrl: String = "http://10.0.2.2:8080"
protected val uiTestBase = UiTestBase() protected val uiTestBase = OnboardingRobot()
fun createAccountAndSync(matrix: Matrix, fun createAccountAndSync(matrix: Matrix,
userName: String, userName: String,

View file

@ -17,9 +17,18 @@
package im.vector.app.espresso.tools package im.vector.app.espresso.tools
import android.app.Activity import android.app.Activity
import android.view.View
import androidx.test.espresso.Espresso
import androidx.test.espresso.matcher.ViewMatchers
import im.vector.app.activityIdlingResource import im.vector.app.activityIdlingResource
import im.vector.app.waitForView
import im.vector.app.withIdlingResource import im.vector.app.withIdlingResource
import org.hamcrest.Matcher
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)
} }
fun waitUntilViewVisible(viewMatcher: Matcher<View>) {
Espresso.onView(ViewMatchers.isRoot()).perform(waitForView(viewMatcher))
}

View file

@ -17,48 +17,18 @@
package im.vector.app.ui package im.vector.app.ui
import android.view.View import android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.pressBack
import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.matcher.ViewMatchers.withId
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.clickDialogPositiveButton
import com.adevinta.android.barista.interaction.BaristaDrawerInteractions.openDrawer
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.BuildConfig
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
import im.vector.app.activityIdlingResource
import im.vector.app.espresso.tools.clickOnPreference
import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.features.MainActivity import im.vector.app.features.MainActivity
import im.vector.app.features.createdirect.CreateDirectRoomActivity import im.vector.app.ui.robot.ElementRobot
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.roomdirectory.RoomDirectoryActivity
import im.vector.app.initialSyncIdlingResource
import im.vector.app.waitForView
import im.vector.app.withIdlingResource
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@ -75,7 +45,7 @@ class UiAllScreensSanityTest {
@get:Rule @get:Rule
val activityRule = ActivityScenarioRule(MainActivity::class.java) val activityRule = ActivityScenarioRule(MainActivity::class.java)
private val uiTestBase = UiTestBase() private val elementRobot = ElementRobot()
// Last passing: // Last passing:
// 2020-11-09 // 2020-11-09
@ -85,63 +55,49 @@ class UiAllScreensSanityTest {
fun allScreensTest() { fun allScreensTest() {
// Create an account // Create an account
val userId = "UiTest_" + UUID.randomUUID().toString() val userId = "UiTest_" + UUID.randomUUID().toString()
uiTestBase.createAccount(userId = userId) elementRobot.login(userId)
withIdlingResource(activityIdlingResource(HomeActivity::class.java)) { elementRobot.settings {
assertDisplayed(R.id.roomListContainer) general { crawl() }
closeSoftKeyboard() notifications { crawl() }
preferences { crawl() }
voiceAndVideo()
ignoredUsers()
securityAndPrivacy { crawl() }
labs()
advancedSettings { crawl() }
helpAndAbout { crawl() }
} }
val activity = EspressoHelper.getCurrentActivity()!! elementRobot.newDirectMessage {
val uiSession = (activity as HomeActivity).activeSessionHolder.getActiveSession() verifyQrCodeButton()
verifyInviteFriendsButton()
withIdlingResource(initialSyncIdlingResource(uiSession)) {
assertDisplayed(R.id.roomListContainer)
} }
assertDisplayed(R.id.bottomNavigationView) elementRobot.newRoom {
createNewRoom {
// Settings crawl()
navigateToSettings() createRoom {
postMessage("Hello world!")
// Create DM crawl()
clickOn(R.id.bottom_action_people) openSettings { crawl() }
createDm() }
}
// Create Room
// First navigate to the other tab
clickOn(R.id.bottom_action_rooms)
createRoom()
assertDisplayed(R.id.bottomNavigationView)
// Long click on the room
onView(withId(R.id.roomListView))
.perform(
actionOnItem<RecyclerView.ViewHolder>(
hasDescendant(withText(R.string.room_displayname_empty_room)),
longClick()
)
)
pressBack()
uiTestBase.signout()
// We have sent a message in a e2e room, accept to loose it
clickOn(R.id.exitAnywayButton)
// Dark pattern
clickDialogNegativeButton()
// Login again on the same account
waitUntilActivityVisible<LoginActivity> {
assertDisplayed(R.id.loginSplashLogo)
} }
uiTestBase.login(userId) elementRobot.roomList {
ignoreVerification() verifyCreatedRoom()
}
uiTestBase.signout() // Disable until the "you don't have a session for id %d" sign out bug is fixed
clickDialogPositiveButton() // elementRobot.signout()
// // Login again on the same account
// elementRobot.login(userId)
//
// ignoreVerification()
//
// elementRobot.signout()
// clickDialogPositiveButton()
// TODO Deactivate account instead of logout? // TODO Deactivate account instead of logout?
} }
@ -163,361 +119,4 @@ 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()
}
private fun createDm() {
clickOn(R.id.createChatRoomButton)
withIdlingResource(activityIdlingResource(CreateDirectRoomActivity::class.java)) {
onView(withId(R.id.userListRecyclerView))
.perform(waitForView(withText(R.string.qr_code)))
onView(withId(R.id.userListRecyclerView))
.perform(waitForView(withText(R.string.invite_friends)))
}
closeSoftKeyboard()
pressBack()
pressBack()
}
private fun navigateToSettings() {
// clickOn(R.id.groupToolbarAvatarImageView)
openDrawer()
clickOn(R.id.homeDrawerHeaderSettingsView)
clickOn(R.string.settings_general_title)
navigateToSettingsGeneral()
pressBack()
clickOn(R.string.settings_notifications)
navigateToSettingsNotifications()
pressBack()
clickOn(R.string.settings_preferences)
navigateToSettingsPreferences()
pressBack()
clickOn(R.string.preference_voice_and_video)
pressBack()
clickOn(R.string.settings_ignored_users)
pressBack()
clickOn(R.string.settings_security_and_privacy)
navigateToSettingsSecurity()
pressBack()
clickOn(R.string.room_settings_labs_pref_title)
pressBack()
clickOn(R.string.settings_advanced_settings)
navigateToSettingsAdvanced()
pressBack()
clickOn(R.string.preference_root_help_about)
navigateToSettingsHelp()
pressBack()
pressBack()
}
private fun navigateToSettingsHelp() {
/*
clickOn(R.string.settings_app_info_link_title)
Cannot go back...
pressBack()
clickOn(R.string.settings_copyright)
pressBack()
clickOn(R.string.settings_app_term_conditions)
pressBack()
clickOn(R.string.settings_privacy_policy)
pressBack()
*/
clickOn(R.string.settings_third_party_notices)
clickDialogPositiveButton()
}
private fun navigateToSettingsAdvanced() {
clickOnPreference(R.string.settings_notifications_targets)
pressBack()
clickOnPreference(R.string.settings_push_rules)
pressBack()
/* TODO P2 test developer screens
// Enable developer mode
clickOnSwitchPreference("SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY")
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")
*/
}
private fun navigateToSettingsSecurity() {
clickOnPreference(R.string.settings_active_sessions_show_all)
pressBack()
clickOnPreference(R.string.encryption_message_recovery)
// TODO go deeper here
pressBack()
/* Cannot exit
clickOnPreference(R.string.encryption_export_e2e_room_keys)
pressBack()
*/
}
private fun navigateToSettingsPreferences() {
clickOn(R.string.settings_interface_language)
onView(isRoot())
.perform(waitForView(withText("Dansk (Danmark)")))
pressBack()
clickOn(R.string.settings_theme)
clickDialogNegativeButton()
clickOn(R.string.font_size)
clickDialogNegativeButton()
}
private fun navigateToSettingsNotifications() {
if (BuildConfig.USE_NOTIFICATION_SETTINGS_V2) {
clickOn(R.string.settings_notification_default)
pressBack()
clickOn(R.string.settings_notification_mentions_and_keywords)
// TODO Test adding a keyword?
pressBack()
clickOn(R.string.settings_notification_other)
pressBack()
} else {
clickOn(R.string.settings_notification_advanced)
pressBack()
}
/*
clickOn(R.string.settings_noisy_notifications_preferences)
TODO Cannot go back
pressBack()
clickOn(R.string.settings_silent_notifications_preferences)
pressBack()
clickOn(R.string.settings_call_notifications_preferences)
pressBack()
*/
clickOnPreference(R.string.settings_notification_troubleshoot)
pressBack()
}
private fun navigateToSettingsGeneral() {
clickOn(R.string.settings_profile_picture)
clickDialogPositiveButton()
clickOn(R.string.settings_display_name)
clickDialogNegativeButton()
clickOn(R.string.settings_password)
clickDialogNegativeButton()
clickOn(R.string.settings_emails_and_phone_numbers_title)
pressBack()
clickOn(R.string.settings_discovery_manage)
clickOn(R.string.add_identity_server)
pressBack()
pressBack()
// Homeserver
clickOnPreference(R.string.settings_home_server)
pressBack()
// Identity server
clickOnPreference(R.string.settings_identity_server)
pressBack()
// Deactivate account
clickOnPreference(R.string.settings_deactivate_my_account)
pressBack()
}
} }

View file

@ -0,0 +1,49 @@
/*
* 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.pressBack
import androidx.test.espresso.matcher.ViewMatchers.withId
import com.adevinta.android.barista.assertion.BaristaListAssertions
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.espresso.tools.waitUntilViewVisible
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> {
waitUntilViewVisible(withId(R.id.composerEditText))
}
block(RoomDetailRobot())
pressBack()
}
fun crawl() {
// Room access bottom sheet
BaristaClickInteractions.clickOn(R.string.room_settings_room_access_private_title)
pressBack()
}
}

View file

@ -0,0 +1,29 @@
/*
* 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 com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
class DialogRobot(
var returnedToPreviousScreen: Boolean = false
) {
fun negativeAction() {
clickDialogNegativeButton()
returnedToPreviousScreen = true
}
}

View file

@ -0,0 +1,96 @@
/*
* 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.pressBack
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.matcher.ViewMatchers.withId
import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaDrawerInteractions.openDrawer
import im.vector.app.EspressoHelper
import im.vector.app.R
import im.vector.app.activityIdlingResource
import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.app.features.createdirect.CreateDirectRoomActivity
import im.vector.app.features.home.HomeActivity
import im.vector.app.features.login.LoginActivity
import im.vector.app.initialSyncIdlingResource
import im.vector.app.ui.robot.settings.SettingsRobot
import im.vector.app.withIdlingResource
class ElementRobot {
fun login(userId: String) {
val onboardingRobot = OnboardingRobot()
onboardingRobot.createAccount(userId = userId)
withIdlingResource(activityIdlingResource(HomeActivity::class.java)) {
BaristaVisibilityAssertions.assertDisplayed(R.id.roomListContainer)
ViewActions.closeSoftKeyboard()
}
val activity = EspressoHelper.getCurrentActivity()!!
val uiSession = (activity as HomeActivity).activeSessionHolder.getActiveSession()
withIdlingResource(initialSyncIdlingResource(uiSession)) {
BaristaVisibilityAssertions.assertDisplayed(R.id.roomListContainer)
}
waitUntilViewVisible(withId(R.id.bottomNavigationView))
}
fun settings(block: SettingsRobot.() -> Unit) {
openDrawer()
clickOn(R.id.homeDrawerHeaderSettingsView)
block(SettingsRobot())
pressBack()
waitUntilViewVisible(withId(R.id.bottomNavigationView))
}
fun newDirectMessage(block: NewDirectMessageRobot.() -> Unit) {
clickOn(R.id.bottom_action_people)
clickOn(R.id.createChatRoomButton)
waitUntilActivityVisible<CreateDirectRoomActivity> {
waitUntilViewVisible(withId(R.id.userListSearch))
}
// close keyboard
pressBack()
block(NewDirectMessageRobot())
pressBack()
waitUntilViewVisible(withId(R.id.bottomNavigationView))
}
fun newRoom(block: NewRoomRobot.() -> Unit) {
clickOn(R.id.bottom_action_rooms)
RoomListRobot().newRoom { block() }
waitUntilViewVisible(withId(R.id.bottomNavigationView))
}
fun roomList(block: RoomListRobot.() -> Unit) {
clickOn(R.id.bottom_action_rooms)
block(RoomListRobot())
waitUntilViewVisible(withId(R.id.bottomNavigationView))
}
fun signout() {
OnboardingRobot().signout()
waitUntilActivityVisible<LoginActivity> {
BaristaVisibilityAssertions.assertDisplayed(R.id.loginSplashLogo)
}
}
}

View file

@ -0,0 +1,35 @@
/*
* 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.matcher.ViewMatchers
import im.vector.app.R
import im.vector.app.waitForView
class NewDirectMessageRobot {
fun verifyQrCodeButton() {
Espresso.onView(ViewMatchers.withId(R.id.userListRecyclerView))
.perform(waitForView(ViewMatchers.withText(R.string.qr_code)))
}
fun verifyInviteFriendsButton() {
Espresso.onView(ViewMatchers.withId(R.id.userListRecyclerView))
.perform(waitForView(ViewMatchers.withText(R.string.invite_friends)))
}
}

View file

@ -0,0 +1,39 @@
/*
* 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.pressBack
import androidx.test.espresso.matcher.ViewMatchers.withId
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilViewVisible
class NewRoomRobot(
var createdRoom: Boolean = false
) {
fun createNewRoom(block: CreateNewRoomRobot.() -> Unit) {
clickOn(R.string.create_new_room)
waitUntilViewVisible(withId(R.id.createRoomForm))
val createNewRoomRobot = CreateNewRoomRobot()
block(createNewRoomRobot)
createdRoom = createNewRoomRobot.createdRoom
if (!createNewRoomRobot.createdRoom) {
pressBack()
}
}
}

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package im.vector.app.ui package im.vector.app.ui.robot
import androidx.test.espresso.Espresso.closeSoftKeyboard import androidx.test.espresso.Espresso.closeSoftKeyboard
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
@ -24,13 +24,15 @@ import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertDis
import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertEnabled import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertEnabled
import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaDialogInteractions
import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo
import im.vector.app.R import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.features.home.HomeActivity import im.vector.app.features.home.HomeActivity
import im.vector.app.waitForView import im.vector.app.waitForView
class UiTestBase { class OnboardingRobot {
fun createAccount(userId: String, password: String = "password", homeServerUrl: String = "http://10.0.2.2:8080") { fun createAccount(userId: String, password: String = "password", homeServerUrl: String = "http://10.0.2.2:8080") {
initSession(true, userId, password, homeServerUrl) initSession(true, userId, password, homeServerUrl)
} }
@ -86,5 +88,10 @@ class UiTestBase {
fun signout() { fun signout() {
clickOn(R.id.groupToolbarAvatarImageView) clickOn(R.id.groupToolbarAvatarImageView)
clickOn(R.id.homeDrawerHeaderSignoutView) clickOn(R.id.homeDrawerHeaderSignoutView)
// We have sent a message in a e2e room, accept to loose it
clickOn(R.id.exitAnywayButton)
// Dark pattern
BaristaDialogInteractions.clickDialogNegativeButton()
} }
} }

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.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso
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.withId
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.waitForView
import java.lang.Thread.sleep
class RoomDetailRobot {
fun postMessage(content: String) {
writeTo(R.id.composerEditText, content)
clickOn(R.id.sendButton)
}
fun crawl() {
clickOn(R.id.attachmentButton)
BaristaClickInteractions.clickBack()
// Menu
openMenu()
pressBack()
clickMenu(R.id.voice_call)
pressBack()
clickMenu(R.id.video_call)
pressBack()
clickMenu(R.id.search)
pressBack()
// Long click on the message
longClickOnMessageTest()
}
private fun longClickOnMessageTest() {
// Test quick reaction
longClickOnMessage()
waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
// Add quick reaction
clickOn("\uD83D\uDC4D") // 👍
waitUntilViewVisible(withId(R.id.composerEditText))
// Open reactions
longClickOn("\uD83D\uDC4D") // 👍
// 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)
waitUntilViewVisible(withId(R.id.composerEditText))
// Test Edit mode
longClickOnMessage()
waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
clickOn(R.string.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)
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()
}
private fun longClickOnMessage(text: String = "Hello world!") {
Espresso.onView(withId(R.id.timelineRecyclerView))
.perform(
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
ViewMatchers.hasDescendant(ViewMatchers.withText(text)),
ViewActions.longClick()
)
)
}
fun openSettings(block: RoomSettingsRobot.() -> Unit) {
clickOn(R.id.roomToolbarTitleView)
waitForView(withId(R.id.roomProfileAvatarView))
sleep(1000)
block(RoomSettingsRobot())
pressBack()
}
}

View file

@ -0,0 +1,54 @@
/*
* 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.assertion.BaristaVisibilityAssertions
import com.adevinta.android.barista.interaction.BaristaClickInteractions
import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.features.roomdirectory.RoomDirectoryActivity
class RoomListRobot {
fun verifyCreatedRoom() {
Espresso.onView(ViewMatchers.withId(R.id.roomListView))
.perform(
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
ViewMatchers.hasDescendant(ViewMatchers.withText(R.string.room_displayname_empty_room)),
ViewActions.longClick()
)
)
Espresso.pressBack()
}
fun newRoom(block: NewRoomRobot.() -> Unit) {
BaristaClickInteractions.clickOn(R.id.createGroupRoomButton)
waitUntilActivityVisible<RoomDirectoryActivity> {
BaristaVisibilityAssertions.assertDisplayed(R.id.publicRoomsList)
}
val newRoomRobot = NewRoomRobot()
block(newRoomRobot)
if (!newRoomRobot.createdRoom) {
Espresso.pressBack()
}
}
}

View file

@ -0,0 +1,143 @@
/*
* 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.pressBack
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
import com.adevinta.android.barista.interaction.BaristaListInteractions.clickListItem
import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.app.features.roommemberprofile.RoomMemberProfileActivity
class RoomSettingsRobot {
fun crawl() {
// 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)
waitUntilViewVisible(withText(R.string.uploads_media_title))
pressBack()
waitUntilViewVisible(withId(R.id.matrixProfileRecyclerView))
assertDisplayed(R.id.roomProfileAvatarView)
// Leave
leaveRoom {
negativeAction()
}
// Advanced
// Room addresses
clickListItem(R.id.matrixProfileRecyclerView, 15)
waitUntilViewVisible(withText(R.string.room_alias_published_alias_title))
pressBack()
// Room permissions
clickListItem(R.id.matrixProfileRecyclerView, 17)
waitUntilViewVisible(withText(R.string.room_permissions_title))
clickOn(R.string.room_permissions_change_room_avatar)
waitUntilViewVisible(withId(android.R.id.button2))
clickDialogNegativeButton()
waitUntilViewVisible(withText(R.string.room_permissions_title))
// Toggle
clickOn(R.string.show_advanced)
clickOn(R.string.hide_advanced)
pressBack()
// Menu share
// clickMenu(R.id.roomProfileShareAction)
// pressBack()
}
private fun leaveRoom(block: DialogRobot.() -> Unit) {
clickListItem(R.id.matrixProfileRecyclerView, 13)
waitUntilViewVisible(withId(android.R.id.button2))
val dialogRobot = DialogRobot()
block(dialogRobot)
if (dialogRobot.returnedToPreviousScreen) {
waitUntilViewVisible(withId(R.id.matrixProfileRecyclerView))
}
}
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)
ViewActions.closeSoftKeyboard()
pressBack()
}
private fun navigateToRoomPeople() {
// Open first user
clickListItem(R.id.roomSettingsRecyclerView, 1)
waitUntilActivityVisible<RoomMemberProfileActivity> {
waitUntilViewVisible(withId(R.id.memberProfilePowerLevelView))
}
// Verification
clickListItem(R.id.matrixProfileRecyclerView, 1)
waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
pressBack()
waitUntilViewVisible(withId(R.id.matrixProfileRecyclerView))
// Role
clickListItem(R.id.matrixProfileRecyclerView, 3)
waitUntilViewVisible(withId(android.R.id.button2))
clickDialogNegativeButton()
waitUntilViewVisible(withId(R.id.matrixProfileRecyclerView))
pressBack()
}
}

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.settings
import androidx.test.espresso.Espresso.pressBack
import im.vector.app.R
import im.vector.app.espresso.tools.clickOnPreference
class SettingsAdvancedRobot {
fun crawl() {
clickOnPreference(R.string.settings_notifications_targets)
pressBack()
clickOnPreference(R.string.settings_push_rules)
pressBack()
/* TODO P2 test developer screens
// Enable developer mode
clickOnSwitchPreference("SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY")
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")
*/
}
}

View file

@ -0,0 +1,51 @@
/*
* 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.settings
import androidx.test.espresso.Espresso.pressBack
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton
import im.vector.app.R
import im.vector.app.espresso.tools.clickOnPreference
class SettingsGeneralRobot {
fun crawl() {
clickOn(R.string.settings_profile_picture)
clickDialogPositiveButton()
clickOn(R.string.settings_display_name)
clickDialogNegativeButton()
clickOn(R.string.settings_password)
clickDialogNegativeButton()
clickOn(R.string.settings_emails_and_phone_numbers_title)
pressBack()
clickOn(R.string.settings_discovery_manage)
clickOn(R.string.add_identity_server)
pressBack()
pressBack()
// Homeserver
clickOnPreference(R.string.settings_home_server)
pressBack()
// Identity server
clickOnPreference(R.string.settings_identity_server)
pressBack()
// Deactivate account
clickOnPreference(R.string.settings_deactivate_my_account)
pressBack()
}
}

View file

@ -0,0 +1,40 @@
/*
* 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.settings
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton
import im.vector.app.R
class SettingsHelpRobot {
fun crawl() {
/*
clickOn(R.string.settings_app_info_link_title)
Cannot go back...
pressBack()
clickOn(R.string.settings_copyright)
pressBack()
clickOn(R.string.settings_app_term_conditions)
pressBack()
clickOn(R.string.settings_privacy_policy)
pressBack()
*/
clickOn(R.string.settings_third_party_notices)
clickDialogPositiveButton()
}
}

View file

@ -0,0 +1,52 @@
/*
* 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.settings
import androidx.test.espresso.Espresso.pressBack
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.espresso.tools.clickOnPreference
class SettingsNotificationsRobot {
fun crawl() {
if (BuildConfig.USE_NOTIFICATION_SETTINGS_V2) {
clickOn(R.string.settings_notification_default)
pressBack()
clickOn(R.string.settings_notification_mentions_and_keywords)
// TODO Test adding a keyword?
pressBack()
clickOn(R.string.settings_notification_other)
pressBack()
} else {
clickOn(R.string.settings_notification_advanced)
pressBack()
}
/*
clickOn(R.string.settings_noisy_notifications_preferences)
TODO Cannot go back
pressBack()
clickOn(R.string.settings_silent_notifications_preferences)
pressBack()
clickOn(R.string.settings_call_notifications_preferences)
pressBack()
*/
clickOnPreference(R.string.settings_notification_troubleshoot)
pressBack()
}
}

View file

@ -0,0 +1,38 @@
/*
* 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.settings
import androidx.test.espresso.Espresso.pressBack
import androidx.test.espresso.matcher.ViewMatchers.withText
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.app.waitForView
class SettingsPreferencesRobot {
fun crawl() {
clickOn(R.string.settings_interface_language)
waitUntilViewVisible(withText("Dansk (Danmark)"))
pressBack()
clickOn(R.string.settings_theme)
clickDialogNegativeButton()
clickOn(R.string.font_size)
clickDialogNegativeButton()
}
}

View file

@ -0,0 +1,60 @@
/*
* 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.settings
import im.vector.app.R
import im.vector.app.clickOnAndGoBack
class SettingsRobot {
fun general(block: SettingsGeneralRobot.() -> Unit) {
clickOnAndGoBack(R.string.settings_general_title) { block(SettingsGeneralRobot()) }
}
fun notifications(block: SettingsNotificationsRobot.() -> Unit) {
clickOnAndGoBack(R.string.settings_notifications) { block(SettingsNotificationsRobot()) }
}
fun preferences(block: SettingsPreferencesRobot.() -> Unit) {
clickOnAndGoBack(R.string.settings_preferences) { block(SettingsPreferencesRobot()) }
}
fun voiceAndVideo(block: () -> Unit = {}) {
clickOnAndGoBack(R.string.preference_voice_and_video) { block() }
}
fun ignoredUsers(block: () -> Unit = {}) {
clickOnAndGoBack(R.string.settings_ignored_users) { block() }
}
fun securityAndPrivacy(block: SettingsSecurityRobot.() -> Unit) {
clickOnAndGoBack(R.string.settings_security_and_privacy) { block(SettingsSecurityRobot()) }
}
fun labs(block: () -> Unit = {}) {
clickOnAndGoBack(R.string.room_settings_labs_pref_title) { block() }
}
fun advancedSettings(block: SettingsAdvancedRobot.() -> Unit) {
clickOnAndGoBack(R.string.settings_advanced_settings) { block(SettingsAdvancedRobot()) }
}
fun helpAndAbout(block: SettingsHelpRobot.() -> Unit) {
clickOnAndGoBack(R.string.preference_root_help_about) { block(SettingsHelpRobot()) }
}
}

View file

@ -0,0 +1,37 @@
/*
* 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.settings
import androidx.test.espresso.Espresso
import im.vector.app.R
import im.vector.app.espresso.tools.clickOnPreference
class SettingsSecurityRobot {
fun crawl() {
clickOnPreference(R.string.settings_active_sessions_show_all)
Espresso.pressBack()
clickOnPreference(R.string.encryption_message_recovery)
// TODO go deeper here
Espresso.pressBack()
/* Cannot exit
clickOnPreference(R.string.encryption_export_e2e_room_keys)
pressBack()
*/
}
}