Merge pull request #4439 from vector-im/feature/adm/developer-mode-sanity-check
Developer mode sanity check & failure screenshots
This commit is contained in:
commit
8b655edd34
|
@ -18,7 +18,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
api-level: [28]
|
||||
api-level: [ 29 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
|
@ -56,7 +56,24 @@ jobs:
|
|||
java-version: '11'
|
||||
- name: Run sanity tests on API ${{ matrix.api-level }}
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
continue-on-error: true # allow pipeline to upload failure results
|
||||
with:
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
api-level: ${{ matrix.api-level }}
|
||||
script: ./gradlew $CI_GRADLE_ARG_PROPERTIES -PallWarningsAsErrors=false connectedGplayDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest
|
||||
emulator-build: 7425822 # workaround to emulator bug: https://github.com/ReactiveCircus/android-emulator-runner/issues/160
|
||||
script: |
|
||||
adb root
|
||||
adb logcat -c
|
||||
touch emulator.log
|
||||
chmod 777 emulator.log
|
||||
adb logcat >> emulator.log &
|
||||
./gradlew $CI_GRADLE_ARG_PROPERTIES -PallWarningsAsErrors=false connectedGplayDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest || adb pull storage/emulated/0/Pictures/failure_screenshots
|
||||
|
||||
- name: Upload Failing Test Report Log
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: sanity-error-results
|
||||
path: |
|
||||
emulator.log
|
||||
failure_screenshots/
|
||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.app
|
|||
import android.app.Activity
|
||||
import android.view.View
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.test.espresso.Espresso
|
||||
import androidx.test.espresso.IdlingRegistry
|
||||
|
@ -35,6 +36,11 @@ import androidx.test.runner.lifecycle.ActivityLifecycleCallback
|
|||
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
|
||||
import androidx.test.runner.lifecycle.Stage
|
||||
import com.adevinta.android.barista.interaction.BaristaClickInteractions
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||
import im.vector.app.espresso.tools.waitUntilViewVisible
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.Matchers
|
||||
import org.hamcrest.StringDescription
|
||||
|
@ -52,6 +58,18 @@ object EspressoHelper {
|
|||
}
|
||||
return currentActivity
|
||||
}
|
||||
|
||||
inline fun <reified T : VectorBaseBottomSheetDialogFragment<*>> getBottomSheetDialog(): BottomSheetDialogFragment? {
|
||||
return (getCurrentActivity() as? FragmentActivity)
|
||||
?.supportFragmentManager
|
||||
?.fragments
|
||||
?.filterIsInstance<T>()
|
||||
?.firstOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
fun getString(@StringRes id: Int): String {
|
||||
return EspressoHelper.getCurrentActivity()!!.resources.getString(id)
|
||||
}
|
||||
|
||||
fun waitForView(viewMatcher: Matcher<View>, timeout: Long = 10_000, waitForDisplayed: Boolean = true): ViewAction {
|
||||
|
@ -216,3 +234,46 @@ fun clickOnAndGoBack(@StringRes name: Int, block: () -> Unit) {
|
|||
block()
|
||||
Espresso.pressBack()
|
||||
}
|
||||
|
||||
inline fun <reified T : VectorBaseBottomSheetDialogFragment<*>> interactWithSheet(contentMatcher: Matcher<View>, noinline block: () -> Unit = {}) {
|
||||
waitUntilViewVisible(contentMatcher)
|
||||
val behaviour = (EspressoHelper.getBottomSheetDialog<T>()!!.dialog as BottomSheetDialog).behavior
|
||||
withIdlingResource(BottomSheetResource(behaviour, BottomSheetBehavior.STATE_EXPANDED), block)
|
||||
withIdlingResource(BottomSheetResource(behaviour, BottomSheetBehavior.STATE_HIDDEN)) {}
|
||||
}
|
||||
|
||||
class BottomSheetResource(
|
||||
private val bottomSheetBehavior: BottomSheetBehavior<*>,
|
||||
@BottomSheetBehavior.State private val wantedState: Int
|
||||
) : IdlingResource, BottomSheetBehavior.BottomSheetCallback() {
|
||||
|
||||
private var isIdle: Boolean = false
|
||||
private var resourceCallback: IdlingResource.ResourceCallback? = null
|
||||
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
|
||||
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
val wasIdle = isIdle
|
||||
isIdle = newState == BottomSheetBehavior.STATE_EXPANDED
|
||||
if (!wasIdle && isIdle) {
|
||||
bottomSheetBehavior.removeBottomSheetCallback(this)
|
||||
resourceCallback?.onTransitionToIdle()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getName() = "BottomSheet awaiting state: $wantedState"
|
||||
|
||||
override fun isIdleNow() = isIdle
|
||||
|
||||
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback) {
|
||||
resourceCallback = callback
|
||||
|
||||
val state = bottomSheetBehavior.state
|
||||
isIdle = state == wantedState
|
||||
if (isIdle) {
|
||||
resourceCallback!!.onTransitionToIdle()
|
||||
} else {
|
||||
bottomSheetBehavior.addBottomSheetCallback(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* 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.espresso.tools
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.ContentValues
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.provider.MediaStore
|
||||
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import org.junit.rules.TestWatcher
|
||||
import org.junit.runner.Description
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
private val SCREENSHOT_FOLDER_LOCATION = "${Environment.DIRECTORY_PICTURES}/failure_screenshots"
|
||||
private val deviceLanguage = Locale.getDefault().language
|
||||
|
||||
class ScreenshotFailureRule : TestWatcher() {
|
||||
override fun failed(e: Throwable?, description: Description) {
|
||||
val screenShotName = "$deviceLanguage-${description.methodName}-${SimpleDateFormat("EEE-MMMM-dd-HH:mm:ss").format(Date())}"
|
||||
val bitmap = getInstrumentation().uiAutomation.takeScreenshot()
|
||||
storeFailureScreenshot(bitmap, screenShotName)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores screenshots in sdcard/Pictures/failure_screenshots
|
||||
*/
|
||||
private fun storeFailureScreenshot(bitmap: Bitmap, screenshotName: String) {
|
||||
val contentResolver = getInstrumentation().targetContext.applicationContext.contentResolver
|
||||
|
||||
val contentValues = ContentValues().apply {
|
||||
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
|
||||
put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
|
||||
}
|
||||
if (android.os.Build.VERSION.SDK_INT >= 29) {
|
||||
useMediaStoreScreenshotStorage(
|
||||
contentValues,
|
||||
contentResolver,
|
||||
screenshotName,
|
||||
SCREENSHOT_FOLDER_LOCATION,
|
||||
bitmap
|
||||
)
|
||||
} else {
|
||||
usePublicExternalScreenshotStorage(
|
||||
contentValues,
|
||||
contentResolver,
|
||||
screenshotName,
|
||||
SCREENSHOT_FOLDER_LOCATION,
|
||||
bitmap
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun useMediaStoreScreenshotStorage(
|
||||
contentValues: ContentValues,
|
||||
contentResolver: ContentResolver,
|
||||
screenshotName: String,
|
||||
screenshotLocation: String,
|
||||
bitmap: Bitmap
|
||||
) {
|
||||
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "$screenshotName.jpeg")
|
||||
contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, screenshotLocation)
|
||||
val uri: Uri? = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
|
||||
if (uri != null) {
|
||||
contentResolver.openOutputStream(uri)?.let { saveScreenshotToStream(bitmap, it) }
|
||||
contentResolver.update(uri, contentValues, null, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun usePublicExternalScreenshotStorage(
|
||||
contentValues: ContentValues,
|
||||
contentResolver: ContentResolver,
|
||||
screenshotName: String,
|
||||
screenshotLocation: String,
|
||||
bitmap: Bitmap
|
||||
) {
|
||||
val directory = File(Environment.getExternalStoragePublicDirectory(screenshotLocation).toString())
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs()
|
||||
}
|
||||
val file = File(directory, "$screenshotName.jpeg")
|
||||
saveScreenshotToStream(bitmap, FileOutputStream(file))
|
||||
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
|
||||
}
|
||||
|
||||
private fun saveScreenshotToStream(bitmap: Bitmap, outputStream: OutputStream) {
|
||||
outputStream.use {
|
||||
try {
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, it)
|
||||
} catch (e: IOException) {
|
||||
Timber.e("Screenshot was not stored at this time")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,10 +19,15 @@ 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.espresso.tools.ScreenshotFailureRule
|
||||
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.rules.RuleChain
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.UUID
|
||||
|
||||
|
@ -34,7 +39,9 @@ import java.util.UUID
|
|||
class UiAllScreensSanityTest {
|
||||
|
||||
@get:Rule
|
||||
val activityRule = ActivityScenarioRule(MainActivity::class.java)
|
||||
val testRule = RuleChain
|
||||
.outerRule(ActivityScenarioRule(MainActivity::class.java))
|
||||
.around(ScreenshotFailureRule())
|
||||
|
||||
private val elementRobot = ElementRobot()
|
||||
|
||||
|
@ -69,13 +76,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()
|
||||
}
|
||||
|
|
|
@ -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() }
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
import androidx.test.espresso.Espresso.pressBack
|
||||
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
|
||||
import com.adevinta.android.barista.interaction.BaristaListInteractions.clickListItem
|
||||
import im.vector.app.R
|
||||
import java.lang.Thread.sleep
|
||||
|
||||
class MessageMenuRobot(
|
||||
var autoClosed: Boolean = false
|
||||
) {
|
||||
|
||||
fun viewSource() {
|
||||
clickOn(R.string.view_source)
|
||||
// wait for library
|
||||
sleep(1000)
|
||||
pressBack()
|
||||
autoClosed = true
|
||||
}
|
||||
|
||||
fun editHistory() {
|
||||
clickOn(R.string.message_view_edit_history)
|
||||
pressBack()
|
||||
autoClosed = true
|
||||
}
|
||||
|
||||
fun addQuickReaction(quickReaction: String) {
|
||||
clickOn(quickReaction)
|
||||
autoClosed = true
|
||||
}
|
||||
|
||||
fun addReactionFromEmojiPicker() {
|
||||
clickOn(R.string.message_add_reaction)
|
||||
// Wait for emoji to load, it's async now
|
||||
sleep(2000)
|
||||
clickListItem(R.id.emojiRecyclerView, 4)
|
||||
autoClosed = true
|
||||
}
|
||||
|
||||
fun edit() {
|
||||
clickOn(R.string.edit)
|
||||
autoClosed = true
|
||||
}
|
||||
}
|
|
@ -17,21 +17,24 @@
|
|||
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.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
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.home.room.detail.timeline.action.MessageActionsBottomSheet
|
||||
import im.vector.app.features.reactions.data.EmojiDataSource
|
||||
import im.vector.app.interactWithSheet
|
||||
import im.vector.app.waitForView
|
||||
import java.lang.Thread.sleep
|
||||
|
||||
|
@ -39,7 +42,9 @@ class RoomDetailRobot {
|
|||
|
||||
fun postMessage(content: String) {
|
||||
writeTo(R.id.composerEditText, content)
|
||||
waitUntilViewVisible(withId(R.id.sendButton))
|
||||
clickOn(R.id.sendButton)
|
||||
waitUntilViewVisible(withText(content))
|
||||
}
|
||||
|
||||
fun crawl() {
|
||||
|
@ -55,61 +60,54 @@ 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️") // 👍
|
||||
waitUntilViewVisible(withId(R.id.composerEditText))
|
||||
|
||||
val quickReaction = EmojiDataSource.quickEmojis[0] // 👍
|
||||
openMessageMenu(message) {
|
||||
addQuickReaction(quickReaction)
|
||||
}
|
||||
// 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)
|
||||
waitUntilViewVisible(withId(R.id.composerEditText))
|
||||
|
||||
openMessageMenu(message) {
|
||||
addReactionFromEmojiPicker()
|
||||
}
|
||||
// Test Edit mode
|
||||
longClickOnMessage()
|
||||
waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
|
||||
clickOn(R.string.edit)
|
||||
waitUntilViewVisible(withId(R.id.composerEditText))
|
||||
openMessageMenu(message) {
|
||||
edit()
|
||||
}
|
||||
// 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)
|
||||
waitUntilViewVisible(withText("Hello universe! (edited)"))
|
||||
// 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()
|
||||
)
|
||||
)
|
||||
interactWithSheet<MessageActionsBottomSheet>(contentMatcher = withId(R.id.bottomSheetRecyclerView)) {
|
||||
val messageMenuRobot = MessageMenuRobot()
|
||||
block(messageMenuRobot)
|
||||
if (!messageMenuRobot.autoClosed) {
|
||||
pressBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun openSettings(block: RoomSettingsRobot.() -> Unit) {
|
||||
|
|
|
@ -17,38 +17,46 @@
|
|||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
// Disable developer mode
|
||||
clickOnSwitchPreference("SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY")
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue