mirror of
https://github.com/ProtonMail/android-mail.git
synced 2026-05-15 09:50:40 +00:00
Add basic UI test on settings feature
MAILANDR-75
This commit is contained in:
@@ -50,3 +50,4 @@ private.properties
|
||||
|
||||
# Test users credentials
|
||||
**/users.json
|
||||
**/internal_api.json
|
||||
|
||||
@@ -28,7 +28,7 @@ will show all the possible actions that are available.
|
||||
|
||||
## UI Tests
|
||||
UI tests are executed on firebase through the CI. Firebase test lab can be triggered also locally with `bundle exec fastlane uiTests` or tests can be run in a local emulator through android studio.
|
||||
The `app/src/uiTest/assets/users.json` file will be needed for UI tests to work, its value can be found in confluence or in the CI env vars
|
||||
The `app/src/uiTest/assets/users.json` and `app/src/uiTest/assets/internal_api.json` files will be needed for UI tests to work, their value can be found in confluence or in the CI env vars
|
||||
**Currently, only the ui tests that are included in the `SmokeSuite` class are run on firebase**
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
@@ -63,6 +64,8 @@ import me.proton.core.domain.entity.UserId
|
||||
import me.proton.core.label.domain.entity.LabelId
|
||||
import timber.log.Timber
|
||||
|
||||
const val TEST_TAG_SIDEBAR_MENU = "SidebarMenuTestTag"
|
||||
|
||||
@Composable
|
||||
@Suppress("ComplexMethod")
|
||||
fun Sidebar(
|
||||
@@ -166,7 +169,7 @@ fun Sidebar(
|
||||
viewState: SidebarState
|
||||
) {
|
||||
ProtonSidebarLazy(
|
||||
modifier = modifier,
|
||||
modifier = modifier.testTag(TEST_TAG_SIDEBAR_MENU),
|
||||
drawerState = viewState.drawerState,
|
||||
) {
|
||||
item {
|
||||
|
||||
@@ -18,13 +18,21 @@
|
||||
|
||||
package ch.protonmail.android.uitest
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import ch.protonmail.android.MainActivity
|
||||
import ch.protonmail.android.di.AppDatabaseModule
|
||||
import ch.protonmail.android.test.BuildConfig
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import me.proton.core.auth.presentation.testing.ProtonTestEntryPoint
|
||||
import me.proton.core.test.android.instrumented.ProtonTest.Companion.getTargetContext
|
||||
import me.proton.core.test.android.instrumented.utils.Shell.setupDeviceForAutomation
|
||||
import me.proton.core.test.android.plugins.Quark
|
||||
import me.proton.core.test.android.plugins.data.User
|
||||
import me.proton.core.test.android.plugins.data.User.Users
|
||||
import org.junit.After
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.RuleChain
|
||||
import org.junit.rules.TestName
|
||||
@@ -43,17 +51,33 @@ open class BaseTest(
|
||||
.around(composeTestRule)
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
fun cleanup() {
|
||||
if (clearAppDatabaseOnTearDown) {
|
||||
Timber.d("Finishing Testing: Clearing all database tables")
|
||||
runBlocking {
|
||||
appDatabase.accountDao().deleteAll()
|
||||
}
|
||||
}
|
||||
Timber.d("Finishing Testing: Clearing all database tables")
|
||||
}
|
||||
|
||||
fun login(user: User) {
|
||||
Timber.d("Login user: ${user.name}")
|
||||
authHelper.login(user.name, user.password)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val users = Users("users.json")
|
||||
val quark = Quark(BuildConfig.HOST, BuildConfig.PROXY_TOKEN, "internal_api.json")
|
||||
val appDatabase = AppDatabaseModule.provideAppDatabase(getTargetContext())
|
||||
val authHelper = ProtonTestEntryPoint.provide(
|
||||
ApplicationProvider.getApplicationContext<Application>()
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@BeforeClass
|
||||
fun prepare() {
|
||||
setupDeviceForAutomation(true)
|
||||
authHelper.logoutAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,18 @@
|
||||
package ch.protonmail.android.uitest.robot.menu
|
||||
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.hasText
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import androidx.compose.ui.test.onChild
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.onRoot
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollToNode
|
||||
import androidx.compose.ui.test.performTouchInput
|
||||
import androidx.compose.ui.test.swipeRight
|
||||
import ch.protonmail.android.sidebar.TEST_TAG_SIDEBAR_MENU
|
||||
import ch.protonmail.android.uitest.robot.contacts.ContactsRobot
|
||||
import ch.protonmail.android.uitest.robot.mailbox.archive.ArchiveRobot
|
||||
import ch.protonmail.android.uitest.robot.mailbox.drafts.DraftsRobot
|
||||
@@ -34,14 +46,30 @@ import ch.protonmail.android.uitest.robot.settings.SettingsRobot
|
||||
* [MenuRobot] class contains actions and verifications for menu functionality.
|
||||
*/
|
||||
@Suppress("unused", "TooManyFunctions", "ExpressionBodySyntax")
|
||||
class MenuRobot {
|
||||
class MenuRobot(
|
||||
private val composeTestRule: ComposeContentTestRule? = null
|
||||
) {
|
||||
|
||||
fun archive(): ArchiveRobot {
|
||||
return ArchiveRobot()
|
||||
}
|
||||
|
||||
fun settings(): SettingsRobot {
|
||||
return SettingsRobot()
|
||||
composeTestRule!!
|
||||
.onRoot()
|
||||
.performTouchInput { swipeRight() }
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithTag(TEST_TAG_SIDEBAR_MENU)
|
||||
.onChild()
|
||||
.performScrollToNode(hasText("Settings"))
|
||||
.assertIsDisplayed()
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText("Settings")
|
||||
.performClick()
|
||||
|
||||
return SettingsRobot(composeTestRule)
|
||||
}
|
||||
|
||||
fun drafts(): DraftsRobot {
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
*/
|
||||
package ch.protonmail.android.uitest.robot.settings
|
||||
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
import ch.protonmail.android.mailsettings.presentation.settings.TEST_TAG_SETTINGS_SCREEN_ACCOUNT_ITEM
|
||||
import ch.protonmail.android.uitest.robot.mailbox.inbox.InboxRobot
|
||||
import ch.protonmail.android.uitest.robot.settings.account.AccountSettingsRobot
|
||||
import ch.protonmail.android.uitest.robot.settings.autolock.AutoLockRobot
|
||||
@@ -26,7 +30,9 @@ import ch.protonmail.android.uitest.robot.settings.autolock.AutoLockRobot
|
||||
* [SettingsRobot] class contains actions and verifications for Settings view.
|
||||
*/
|
||||
@Suppress("unused", "ExpressionBodySyntax")
|
||||
class SettingsRobot {
|
||||
class SettingsRobot(
|
||||
private val composeTestRule: ComposeContentTestRule? = null
|
||||
) {
|
||||
|
||||
fun navigateUpToInbox(): InboxRobot {
|
||||
return InboxRobot()
|
||||
@@ -37,7 +43,10 @@ class SettingsRobot {
|
||||
}
|
||||
|
||||
fun openUserAccountSettings(): AccountSettingsRobot {
|
||||
return AccountSettingsRobot()
|
||||
composeTestRule!!
|
||||
.onNodeWithTag(TEST_TAG_SETTINGS_SCREEN_ACCOUNT_ITEM)
|
||||
.performClick()
|
||||
return AccountSettingsRobot(composeTestRule)
|
||||
}
|
||||
|
||||
fun selectAutoLock(): AutoLockRobot {
|
||||
|
||||
+19
-3
@@ -19,6 +19,11 @@
|
||||
package ch.protonmail.android.uitest.robot.settings.account
|
||||
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import androidx.compose.ui.test.onAllNodesWithTag
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import ch.protonmail.android.mailsettings.presentation.accountsettings.TEST_TAG_ACCOUNT_SETTINGS_SCREEN
|
||||
import ch.protonmail.android.uitest.robot.settings.SettingsRobot
|
||||
import ch.protonmail.android.uitest.robot.settings.account.labelsandfolders.LabelsAndFoldersRobot
|
||||
import ch.protonmail.android.uitest.robot.settings.account.privacy.PrivacySettingsRobot
|
||||
@@ -29,7 +34,9 @@ import ch.protonmail.android.uitest.robot.settings.account.swipinggestures.Swipi
|
||||
* Account settings functionality.
|
||||
*/
|
||||
@Suppress("unused", "ExpressionBodySyntax")
|
||||
class AccountSettingsRobot {
|
||||
class AccountSettingsRobot(
|
||||
private val composeTestRule: ComposeContentTestRule? = null
|
||||
) {
|
||||
|
||||
fun subscription(): SubscriptionRobot {
|
||||
return SubscriptionRobot()
|
||||
@@ -67,8 +74,17 @@ class AccountSettingsRobot {
|
||||
*/
|
||||
class Verify {
|
||||
|
||||
@SuppressWarnings("EmptyFunctionBlock")
|
||||
fun accountSettingsOpened() {}
|
||||
fun accountSettingsOpened(composeRule: ComposeContentTestRule) {
|
||||
composeRule.waitUntil(timeoutMillis = 5000) {
|
||||
composeRule
|
||||
.onAllNodesWithTag(TEST_TAG_ACCOUNT_SETTINGS_SCREEN)
|
||||
.fetchSemanticsNodes(false)
|
||||
.isNotEmpty()
|
||||
}
|
||||
composeRule
|
||||
.onNodeWithTag(TEST_TAG_ACCOUNT_SETTINGS_SCREEN)
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun verify(block: Verify.() -> Unit) = Verify().apply(block)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package ch.protonmail.android.uitest.test.settings
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import ch.protonmail.android.uitest.BaseTest
|
||||
import ch.protonmail.android.uitest.annotation.SmokeTest
|
||||
import ch.protonmail.android.uitest.robot.menu.MenuRobot
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.experimental.categories.Category
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SettingsTest : BaseTest(clearAppDatabaseOnTearDown = false) {
|
||||
|
||||
private val user = quark.userCreate()
|
||||
private val menuRobot = MenuRobot(composeTestRule)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
login(user)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Category(SmokeTest::class)
|
||||
fun openAccountSettings() {
|
||||
menuRobot
|
||||
.settings()
|
||||
.openUserAccountSettings()
|
||||
.verify { accountSettingsOpened(composeTestRule) }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package ch.protonmail.android.uitest.test.suite
|
||||
|
||||
import ch.protonmail.android.uitest.annotation.SmokeTest
|
||||
import ch.protonmail.android.uitest.test.login.LoginTests
|
||||
import ch.protonmail.android.uitest.test.settings.SettingsTest
|
||||
import org.junit.experimental.categories.Categories
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Suite
|
||||
@@ -9,6 +10,7 @@ import org.junit.runners.Suite
|
||||
@RunWith(Categories::class)
|
||||
@Categories.IncludeCategory(SmokeTest::class)
|
||||
@Suite.SuiteClasses(
|
||||
LoginTests::class
|
||||
LoginTests::class,
|
||||
SettingsTest::class
|
||||
)
|
||||
class SmokeSuite
|
||||
|
||||
+2
@@ -40,6 +40,7 @@ import me.proton.core.compose.component.ProtonSettingsTopBar
|
||||
import me.proton.core.compose.flow.rememberAsState
|
||||
|
||||
const val TEST_TAG_SETTINGS_SCREEN = "SettingsScreenTestTag"
|
||||
const val TEST_TAG_SETTINGS_SCREEN_ACCOUNT_ITEM = "AccountSettingsItemTestTag"
|
||||
|
||||
@Composable
|
||||
fun MainSettingsScreen(
|
||||
@@ -101,6 +102,7 @@ fun MainSettingsScreen(
|
||||
item { ProtonSettingsHeader(title = R.string.account_settings) }
|
||||
item {
|
||||
AccountSettingsItem(
|
||||
modifier = Modifier.testTag(TEST_TAG_SETTINGS_SCREEN_ACCOUNT_ITEM),
|
||||
accountInfo = state.account,
|
||||
onAccountClicked = onAccountClick
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user