Add basic UI test on settings feature

MAILANDR-75
This commit is contained in:
Marino Meneghel
2022-03-08 18:58:48 +01:00
parent e8aca3c43d
commit d82546d3f8
10 changed files with 129 additions and 12 deletions
+1
View File
@@ -50,3 +50,4 @@ private.properties
# Test users credentials
**/users.json
**/internal_api.json
+1 -1
View File
@@ -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,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
@@ -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
)