Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package com.android.messaging.ui.appsettings.privacy.ui

import androidx.activity.ComponentActivity
import androidx.annotation.StringRes
import androidx.compose.ui.test.SemanticsMatcher
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsOff
import androidx.compose.ui.test.assertIsSelected
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.isSelectable
import androidx.compose.ui.test.isToggleable
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import com.android.messaging.R
import com.android.messaging.data.appsettings.model.LinkOpeningMode
import com.android.messaging.ui.appsettings.general.model.AppSettingsAction as Action
import com.android.messaging.ui.appsettings.general.model.AppSettingsUiState
import com.android.messaging.ui.core.AppTheme
Expand Down Expand Up @@ -58,11 +64,58 @@ class PrivacySettingsScreenTest {
}
}

private fun setContent() {
@Test
fun linkOpeningItem_showsCurrentMode() {
setContent(appSettings = AppSettingsUiState(linkOpeningMode = LinkOpeningMode.DoNotOpen))

composeTestRule.onNodeWithText(string(R.string.link_opening_pref_title))
.assertIsDisplayed()
composeTestRule.onNodeWithText(string(R.string.link_opening_off)).assertIsDisplayed()
}

@Test
fun linkOpeningDialog_selectsCurrentModeAndConfirmsNewMode() {
setContent()

composeTestRule.onNodeWithText(string(R.string.link_opening_pref_title)).performClick()
composeTestRule.onNode(linkOpeningOption(titleResId = R.string.link_opening_ask))
.assertIsSelected()
composeTestRule.onNode(linkOpeningOption(titleResId = R.string.link_opening_open))
.performClick()
composeTestRule.onNodeWithText(string(android.R.string.ok)).performClick()

verify(exactly = 1) {
onAction(Action.LinkOpeningModeChanged(LinkOpeningMode.OpenOnTap))
}
composeTestRule.onNodeWithText(string(android.R.string.ok)).assertDoesNotExist()
}

@Test
fun linkOpeningDialog_cancelKeepsMode() {
setContent()

composeTestRule.onNodeWithText(string(R.string.link_opening_pref_title)).performClick()
composeTestRule.onNode(linkOpeningOption(titleResId = R.string.link_opening_off))
.performClick()
composeTestRule.onNodeWithText(string(android.R.string.cancel)).performClick()

verify(exactly = 0) { onAction(any<Action.LinkOpeningModeChanged>()) }
composeTestRule.onNodeWithText(string(android.R.string.cancel)).assertDoesNotExist()
}

private fun linkOpeningOption(@StringRes titleResId: Int): SemanticsMatcher {
return isSelectable() and hasText(string(titleResId))
}

private fun string(@StringRes resId: Int): String {
return composeTestRule.activity.getString(resId)
}

private fun setContent(appSettings: AppSettingsUiState = AppSettingsUiState()) {
composeTestRule.setContent {
AppTheme {
PrivacySettingsScreen(
appSettings = AppSettingsUiState(),
appSettings = appSettings,
onAction = onAction,
onNavigateBack = {},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.android.messaging.ui.conversation.messages.ui.attachment.rendering

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.platform.testTag
Expand All @@ -12,6 +13,7 @@ import androidx.compose.ui.test.longClick
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.unit.Dp
import com.android.messaging.data.appsettings.model.LinkOpeningMode
import com.android.messaging.ui.conversation.messages.model.attachment.ConversationAttachmentSections
import com.android.messaging.ui.conversation.messages.model.attachment.ConversationInlineAttachment
import com.android.messaging.ui.conversation.messages.model.attachment.ConversationMessageAttachment
Expand All @@ -21,6 +23,7 @@ import com.android.messaging.ui.conversation.messages.ui.attachment.Conversation
import com.android.messaging.ui.conversation.messages.ui.attachment.ConversationMessageAttachments
import com.android.messaging.ui.conversation.messages.ui.attachment.ConversationStandaloneVisualAttachment
import com.android.messaging.ui.conversation.messages.ui.attachment.rememberConversationInlineAudioAttachmentColors
import com.android.messaging.ui.conversation.messages.ui.text.LocalConversationMessageLinkOpeningMode
import com.android.messaging.ui.core.AppTheme
import io.mockk.clearAllMocks
import io.mockk.mockk
Expand Down Expand Up @@ -50,23 +53,28 @@ internal abstract class BaseConversationMessageAttachmentRenderingTest {
isSelectionMode: Boolean = false,
useStandaloneAudioAttachmentBackground: Boolean = false,
width: Dp = ATTACHMENT_WIDTH,
linkOpeningMode: LinkOpeningMode = LinkOpeningMode.AskBeforeOpening,
) {
composeTestRule.setContent {
AppTheme {
ConversationMessageAttachments(
modifier = Modifier
.width(width = width)
.testTag(tag = MESSAGE_ATTACHMENTS_TAG),
attachmentSections = attachmentSections,
hasTextAboveVisualAttachments = hasTextAboveVisualAttachments,
hasTextBelowVisualAttachments = hasTextBelowVisualAttachments,
isIncoming = isIncoming,
isSelectionMode = isSelectionMode,
useStandaloneAudioAttachmentBg = useStandaloneAudioAttachmentBackground,
onAttachmentClick = onAttachmentClick,
onExternalUriClick = onExternalUriClick,
onMessageLongClick = onMessageLongClick,
)
CompositionLocalProvider(
LocalConversationMessageLinkOpeningMode provides linkOpeningMode,
) {
ConversationMessageAttachments(
modifier = Modifier
.width(width = width)
.testTag(tag = MESSAGE_ATTACHMENTS_TAG),
attachmentSections = attachmentSections,
hasTextAboveVisualAttachments = hasTextAboveVisualAttachments,
hasTextBelowVisualAttachments = hasTextBelowVisualAttachments,
isIncoming = isIncoming,
isSelectionMode = isSelectionMode,
useStandaloneAudioAttachmentBg = useStandaloneAudioAttachmentBackground,
onAttachmentClick = onAttachmentClick,
onExternalUriClick = onExternalUriClick,
onMessageLongClick = onMessageLongClick,
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performSemanticsAction
import androidx.compose.ui.test.performTouchInput
import androidx.core.net.toUri
import com.android.messaging.data.appsettings.model.LinkOpeningMode
import com.android.messaging.data.conversation.model.MessageId
import com.android.messaging.data.conversation.model.ParticipantId
import com.android.messaging.datamodel.data.ParticipantData
Expand All @@ -32,6 +33,7 @@ import com.android.messaging.ui.conversation.messages.ui.message.ConversationMes
import com.android.messaging.ui.conversation.messages.ui.message.ConversationMessageAvatar
import com.android.messaging.ui.conversation.messages.ui.message.ConversationMmsDownloadBody
import com.android.messaging.ui.conversation.messages.ui.text.ConversationTextSelectionHost
import com.android.messaging.ui.conversation.messages.ui.text.LocalConversationMessageLinkOpeningMode
import com.android.messaging.ui.conversation.screen.model.ConversationMessageAction
import com.android.messaging.ui.core.AppTheme
import io.mockk.clearAllMocks
Expand Down Expand Up @@ -70,12 +72,14 @@ internal abstract class BaseConversationMessageRenderingTest {
showIncomingParticipantIdentity: Boolean = true,
simDisplayName: String? = null,
textContextMenuToolbar: TextContextMenuProvider? = null,
linkOpeningMode: LinkOpeningMode = LinkOpeningMode.AskBeforeOpening,
) {
composeTestRule.setContent {
AppTheme {
CompositionLocalProvider(
LocalTextContextMenuToolbarProvider provides
(textContextMenuToolbar ?: LocalTextContextMenuToolbarProvider.current),
LocalConversationMessageLinkOpeningMode provides linkOpeningMode,
) {
ConversationTextSelectionHost(
conversationId = message.conversationId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.res.Resources
import com.android.messaging.Factory
import com.android.messaging.R
import com.android.messaging.data.appsettings.model.AppBooleanPref
import com.android.messaging.data.appsettings.model.LinkOpeningMode
import com.android.messaging.data.appsettings.repository.AppSettingsRepositoryImpl
import com.android.messaging.data.debug.DebugFeaturesProvider
import com.android.messaging.datamodel.data.ParticipantData
Expand Down Expand Up @@ -73,6 +74,10 @@ internal class AppSettingsRepositoryImplTest {
every {
resources.getBoolean(R.bool.youtube_link_previews_pref_default)
} returns YOUTUBE_LINK_PREVIEWS_DEFAULT
every { context.getString(R.string.link_opening_pref_key) } returns LINK_OPENING_PREF_KEY
every {
context.getString(R.string.link_opening_pref_default)
} returns LINK_OPENING_DEFAULT
every { resources.getBoolean(R.bool.send_sound_pref_default) } returns
SEND_SOUND_DEFAULT
every {
Expand Down Expand Up @@ -108,6 +113,9 @@ internal class AppSettingsRepositoryImplTest {
YOUTUBE_LINK_PREVIEWS_DEFAULT,
)
} returns true
every {
appPrefs.getString(LINK_OPENING_PREF_KEY, LINK_OPENING_DEFAULT)
} returns LinkOpeningMode.OpenOnTap.prefValue

val result = createRepository(
ioDispatcher = UnconfinedTestDispatcher(testScheduler),
Expand All @@ -118,6 +126,7 @@ internal class AppSettingsRepositoryImplTest {
assertFalse(result.sendSoundEnabled)
assertTrue(result.inConversationSoundEnabled)
assertTrue(result.youTubeLinkPreviewsEnabled)
assertEquals(LinkOpeningMode.OpenOnTap, result.linkOpeningMode)
assertTrue(result.isDebugEnabled)
assertTrue(result.dumpSmsEnabled)
assertFalse(result.dumpMmsEnabled)
Expand Down Expand Up @@ -224,6 +233,68 @@ internal class AppSettingsRepositoryImplTest {
}
}

@Test
fun getLinkOpeningMode_readsEveryStoredMode() {
runTest {
val repository = createRepository(
ioDispatcher = UnconfinedTestDispatcher(testScheduler),
)

LinkOpeningMode.entries.forEach { mode ->
every {
appPrefs.getString(LINK_OPENING_PREF_KEY, LINK_OPENING_DEFAULT)
} returns mode.prefValue

assertEquals(mode, repository.getLinkOpeningMode())
}
}
}

@Test
fun getLinkOpeningMode_fallsBackToAskBeforeOpeningForUnknownStoredValue() {
runTest {
every {
appPrefs.getString(LINK_OPENING_PREF_KEY, LINK_OPENING_DEFAULT)
} returns "unknown"

val result = createRepository(
ioDispatcher = UnconfinedTestDispatcher(testScheduler),
).getLinkOpeningMode()

assertEquals(LinkOpeningMode.AskBeforeOpening, result)
}
}

@Test
fun getLinkOpeningMode_defaultsToAskBeforeOpeningFromResources() {
runTest {
every { appPrefs.getString(any(), any()) } answers { secondArg() }

val result = AppSettingsRepositoryImpl(
context = RuntimeEnvironment.getApplication().applicationContext,
ioDispatcher = UnconfinedTestDispatcher(testScheduler),
debugFeaturesProvider = debugFeaturesProvider,
).getLinkOpeningMode()

assertEquals(LinkOpeningMode.AskBeforeOpening, result)
}
}

@Test
fun setLinkOpeningMode_writesModePreferenceValue() {
runTest {
every { appPrefs.putString(any(), any()) } just runs

createRepository(
ioDispatcher = UnconfinedTestDispatcher(testScheduler),
).setLinkOpeningMode(mode = LinkOpeningMode.DoNotOpen)

verify(exactly = 1) {
appPrefs.putString(LINK_OPENING_PREF_KEY, LinkOpeningMode.DoNotOpen.prefValue)
}
}
}

private fun createRepository(ioDispatcher: CoroutineDispatcher): AppSettingsRepositoryImpl {
return AppSettingsRepositoryImpl(
context = context,
Expand All @@ -240,6 +311,8 @@ internal class AppSettingsRepositoryImplTest {
private const val DUMP_SMS_PREF_KEY = "dump_sms"
private const val IN_CONVERSATION_SOUND_DEFAULT = false
private const val IN_CONVERSATION_SOUND_PREF_KEY = "in_conversation_sound"
private const val LINK_OPENING_DEFAULT = "ask"
private const val LINK_OPENING_PREF_KEY = "link_opening"
private const val SEND_SOUND_DEFAULT = true
private const val SEND_SOUND_PREF_KEY = "send_sound"
private const val YOUTUBE_LINK_PREVIEWS_DEFAULT = false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.android.messaging.ui.appsettings.general

import app.cash.turbine.test
import com.android.messaging.data.appsettings.model.LinkOpeningMode
import com.android.messaging.testutil.MainDispatcherRule
import com.android.messaging.ui.appsettings.general.delegate.AppSettingsDelegate
import com.android.messaging.ui.appsettings.general.model.AppSettingsAction as Action
Expand Down Expand Up @@ -108,6 +109,20 @@ class AppSettingsViewModelTest {
}
}

@Test
fun onLinkOpeningModeChanged_delegatesToAppSettings() {
runTest(context = mainDispatcherRule.testDispatcher) {
val delegate = mockDelegate()
val viewModel = createViewModel(delegate = delegate)

viewModel.onAction(Action.LinkOpeningModeChanged(mode = LinkOpeningMode.DoNotOpen))

verify(exactly = 1) {
delegate.onLinkOpeningModeChanged(mode = LinkOpeningMode.DoNotOpen)
}
}
}

@Test
fun onDefaultSmsAppClick_whenDefault_emitsOpenManageDefaultApps() {
runTest(context = mainDispatcherRule.testDispatcher) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.android.messaging.ui.appsettings.general.delegate.appsettingsdelegate

import com.android.messaging.data.appsettings.model.AppBooleanPref
import com.android.messaging.data.appsettings.model.LinkOpeningMode
import io.mockk.coVerify
import io.mockk.coVerifyOrder
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand Down Expand Up @@ -91,6 +92,25 @@ internal class AppSettingsDelegatePreferenceTest : BaseAppSettingsDelegateTest()
}
}

@Test
fun onLinkOpeningModeChanged_writesModeThenRefreshesState() {
runTest(
context = mainDispatcherRule.testDispatcher,
) {
givenSecondLoadProducesReloadedState()
val delegate = createBoundDelegate()

delegate.onLinkOpeningModeChanged(mode = LinkOpeningMode.DoNotOpen)
runCurrent()

coVerifyOrder {
repository.setLinkOpeningMode(mode = LinkOpeningMode.DoNotOpen)
repository.getAppSettings()
}
assertEquals(reloadedState, delegate.state.value)
}
}

@Test
fun booleanPrefChange_beforeBind_doesNotWriteOrLoad() {
runTest(
Expand All @@ -101,6 +121,7 @@ internal class AppSettingsDelegatePreferenceTest : BaseAppSettingsDelegateTest()
delegate.onSendSoundChanged(enabled = false)
delegate.onDumpSmsChanged(enabled = true)
delegate.onDumpMmsChanged(enabled = true)
delegate.onLinkOpeningModeChanged(mode = LinkOpeningMode.OpenOnTap)
runCurrent()

coVerify(exactly = 0) {
Expand All @@ -109,6 +130,7 @@ internal class AppSettingsDelegatePreferenceTest : BaseAppSettingsDelegateTest()
enabled = any(),
)
}
coVerify(exactly = 0) { repository.setLinkOpeningMode(mode = any()) }
coVerify(exactly = 0) { repository.getAppSettings() }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ internal abstract class BaseAppSettingsDelegateTest {
enabled = any(),
)
} just Runs
coEvery { repository.setLinkOpeningMode(mode = any()) } just Runs
}

protected fun createDelegate(): AppSettingsDelegateImpl {
Expand Down
Loading
Loading