mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-09-24 02:33:00 +01:00
Add additional authenticator UI scaffolding.
This commit is contained in:
+2
-2
@@ -299,7 +299,7 @@ class AccountSettingsScreenTest {
|
||||
|
||||
@Test
|
||||
fun givenASignalLogin_whenIClickAuthenticatorApp_thenIExpectAuthenticatorAppEvent() {
|
||||
setContent(createState(signalLogin = AccountSettingsState.SignalLogin(keyCount = 2, hasAuthenticatorApp = false)))
|
||||
setContent(createState(signalLogin = AccountSettingsState.SignalLogin(keyCount = 2, authenticatorAppCount = 0, passkeyCount = 0)))
|
||||
|
||||
composeTestRule.onNodeWithTag(AccountSettingsTestTags.CARD_SIGNAL_LOGIN).assertIsDisplayed()
|
||||
|
||||
@@ -310,7 +310,7 @@ class AccountSettingsScreenTest {
|
||||
|
||||
@Test
|
||||
fun givenASignalLogin_whenIClickPasskeys_thenIExpectPasskeysEvent() {
|
||||
setContent(createState(signalLogin = AccountSettingsState.SignalLogin(keyCount = 2, hasAuthenticatorApp = false)))
|
||||
setContent(createState(signalLogin = AccountSettingsState.SignalLogin(keyCount = 2, authenticatorAppCount = 0, passkeyCount = 0)))
|
||||
|
||||
scrollTo(AccountSettingsTestTags.ROW_PASSKEYS)
|
||||
|
||||
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.appsettings.authenticatorapps
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.hasTestTag
|
||||
import androidx.compose.ui.test.hasText
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onAllNodesWithTag
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollToNode
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.contains
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsState.Dialog
|
||||
import org.signal.core.ui.compose.Dialogs
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(application = Application::class)
|
||||
class AuthenticatorAppsScreenTest {
|
||||
|
||||
companion object {
|
||||
private val APPS = listOf(
|
||||
AuthenticatorApp(id = 1, name = "Bitwarden Authenticator", createdAt = System.currentTimeMillis()),
|
||||
AuthenticatorApp(id = 2, name = "Twilio Authy", createdAt = System.currentTimeMillis())
|
||||
)
|
||||
}
|
||||
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
private val events = mutableListOf<AuthenticatorAppsEvent>()
|
||||
|
||||
@Test
|
||||
fun givenNoApps_whenIDisplayScreen_thenIExpectTheEmptyMessage() {
|
||||
setContent(AuthenticatorAppsState())
|
||||
|
||||
scrollTo(AuthenticatorAppsTestTags.EMPTY_MESSAGE)
|
||||
composeTestRule.onNodeWithTag(AuthenticatorAppsTestTags.EMPTY_MESSAGE).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenApps_whenIDisplayScreen_thenIExpectARowPerApp() {
|
||||
setContent(AuthenticatorAppsState(apps = APPS))
|
||||
|
||||
for (app in APPS) {
|
||||
composeTestRule.onNodeWithTag(AuthenticatorAppsTestTags.SCROLLER).performScrollToNode(hasText(app.name))
|
||||
composeTestRule.onNodeWithText(app.name).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenIClickAddAuthenticatorApp_thenIExpectAddAuthenticatorAppClickedEvent() {
|
||||
setContent(AuthenticatorAppsState())
|
||||
|
||||
composeTestRule.onNodeWithTag(AuthenticatorAppsTestTags.BUTTON_ADD)
|
||||
.assertIsDisplayed()
|
||||
.performClick()
|
||||
|
||||
assertThat(events).contains(AuthenticatorAppsEvent.AddAuthenticatorAppClicked)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenApps_whenIClickRenameInTheMenu_thenIExpectRenameAppClickedEvent() {
|
||||
setContent(AuthenticatorAppsState(apps = APPS))
|
||||
|
||||
scrollTo(AuthenticatorAppsTestTags.ROW_APP)
|
||||
composeTestRule.onAllNodesWithTag(AuthenticatorAppsTestTags.BUTTON_APP_MENU)[0].performClick()
|
||||
composeTestRule.onNodeWithTag(AuthenticatorAppsTestTags.MENU_ITEM_RENAME).performClick()
|
||||
|
||||
assertThat(events).contains(AuthenticatorAppsEvent.RenameAppClicked(appId = APPS[0].id))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenApps_whenIClickRemoveInTheMenu_thenIExpectRemoveAppClickedEvent() {
|
||||
setContent(AuthenticatorAppsState(apps = APPS))
|
||||
|
||||
scrollTo(AuthenticatorAppsTestTags.ROW_APP)
|
||||
composeTestRule.onAllNodesWithTag(AuthenticatorAppsTestTags.BUTTON_APP_MENU)[0].performClick()
|
||||
composeTestRule.onNodeWithTag(AuthenticatorAppsTestTags.MENU_ITEM_REMOVE).performClick()
|
||||
|
||||
assertThat(events).contains(AuthenticatorAppsEvent.RemoveAppClicked(appId = APPS[0].id))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenTheConfirmRemoveDialog_whenIDisplayScreen_thenIExpectTheDialog() {
|
||||
setContent(AuthenticatorAppsState(apps = APPS, dialog = Dialog.ConfirmRemove(APPS[0].id)))
|
||||
|
||||
composeTestRule.onNodeWithTag(AuthenticatorAppsTestTags.DIALOG_CONFIRM_REMOVE).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenTheConfirmRemoveDialog_whenICancel_thenIExpectDialogDismissedEvent() {
|
||||
setContent(AuthenticatorAppsState(apps = APPS, dialog = Dialog.ConfirmRemove(APPS[0].id)))
|
||||
|
||||
composeTestRule.onNodeWithTag(Dialogs.TEST_TAG_ALERT_DIALOG_DISMISS_BUTTON).performClick()
|
||||
|
||||
assertThat(events).contains(AuthenticatorAppsEvent.DialogDismissed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenTheMaxAppsDialog_whenIDisplayScreen_thenIExpectTheDialog() {
|
||||
setContent(AuthenticatorAppsState(apps = APPS, dialog = Dialog.MaxAppsReached))
|
||||
|
||||
composeTestRule.onNodeWithTag(AuthenticatorAppsTestTags.DIALOG_MAX_APPS_REACHED).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenTheMaxAppsDialog_whenIClickLearnMore_thenIExpectLearnMoreAndDismissEvents() {
|
||||
setContent(AuthenticatorAppsState(apps = APPS, dialog = Dialog.MaxAppsReached))
|
||||
|
||||
composeTestRule.onNodeWithTag(Dialogs.TEST_TAG_ALERT_DIALOG_DISMISS_BUTTON).performClick()
|
||||
|
||||
assertThat(events).contains(AuthenticatorAppsEvent.LearnMoreClicked)
|
||||
assertThat(events).contains(AuthenticatorAppsEvent.DialogDismissed)
|
||||
}
|
||||
|
||||
private fun setContent(state: AuthenticatorAppsState) {
|
||||
composeTestRule.setContent {
|
||||
AuthenticatorAppsScreen(
|
||||
state = state,
|
||||
onEvent = { events += it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun scrollTo(testTag: String) {
|
||||
composeTestRule.onNodeWithTag(AuthenticatorAppsTestTags.SCROLLER)
|
||||
.performScrollToNode(hasTestTag(testTag))
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.appsettings.authenticatorname
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.assertIsEnabled
|
||||
import androidx.compose.ui.test.assertIsNotEnabled
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextReplacement
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.contains
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(application = Application::class)
|
||||
class AuthenticatorNameScreenTest {
|
||||
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
private val events = mutableListOf<AuthenticatorNameEvent>()
|
||||
|
||||
@Test
|
||||
fun whenITypeAName_thenIExpectNameChangedEvent() {
|
||||
setContent(AuthenticatorNameState())
|
||||
|
||||
composeTestRule.onNodeWithTag(AuthenticatorNameTestTags.NAME_INPUT)
|
||||
.assertIsDisplayed()
|
||||
.performTextReplacement("Bitwarden Authenticator")
|
||||
|
||||
assertThat(events).contains(AuthenticatorNameEvent.NameChanged("Bitwarden Authenticator"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenABlankName_whenIDisplayScreen_thenIExpectNextDisabled() {
|
||||
setContent(AuthenticatorNameState())
|
||||
|
||||
composeTestRule.onNodeWithTag(AuthenticatorNameTestTags.BUTTON_NEXT).assertIsNotEnabled()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenASubmittingState_whenIDisplayScreen_thenIExpectNextDisabled() {
|
||||
setContent(AuthenticatorNameState(name = "Twilio Authy", submitting = true))
|
||||
|
||||
composeTestRule.onNodeWithTag(AuthenticatorNameTestTags.BUTTON_NEXT).assertIsNotEnabled()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAName_whenIClickNext_thenIExpectNextClickedEvent() {
|
||||
setContent(AuthenticatorNameState(name = "Twilio Authy"))
|
||||
|
||||
composeTestRule.onNodeWithTag(AuthenticatorNameTestTags.BUTTON_NEXT)
|
||||
.assertIsEnabled()
|
||||
.performClick()
|
||||
|
||||
assertThat(events).contains(AuthenticatorNameEvent.NextClicked)
|
||||
}
|
||||
|
||||
private fun setContent(state: AuthenticatorNameState) {
|
||||
composeTestRule.setContent {
|
||||
AuthenticatorNameScreen(
|
||||
state = state,
|
||||
onEvent = { events += it }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user