mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-20 20:18:27 +00:00
Add 1 day after read test
This commit is contained in:
parent
a7111b0d49
commit
92cae9adde
@ -319,6 +319,7 @@ dependencies {
|
|||||||
// Assertions
|
// Assertions
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
androidTestImplementation 'androidx.test.ext:truth:1.5.0'
|
androidTestImplementation 'androidx.test.ext:truth:1.5.0'
|
||||||
|
testImplementation 'com.google.truth:truth:1.1.3'
|
||||||
androidTestImplementation 'com.google.truth:truth:1.1.3'
|
androidTestImplementation 'com.google.truth:truth:1.1.3'
|
||||||
|
|
||||||
// Espresso dependencies
|
// Espresso dependencies
|
||||||
|
@ -48,7 +48,7 @@ data class State(
|
|||||||
val isSelfAdmin: Boolean = true,
|
val isSelfAdmin: Boolean = true,
|
||||||
val address: Address? = null,
|
val address: Address? = null,
|
||||||
val isNoteToSelf: Boolean = false,
|
val isNoteToSelf: Boolean = false,
|
||||||
val expiryMode: ExpiryMode? = ExpiryMode.NONE,
|
val expiryMode: ExpiryMode? = null,
|
||||||
val isNewConfigEnabled: Boolean = true,
|
val isNewConfigEnabled: Boolean = true,
|
||||||
val persistedMode: ExpiryMode? = null,
|
val persistedMode: ExpiryMode? = null,
|
||||||
val showDebugOptions: Boolean = false
|
val showDebugOptions: Boolean = false
|
||||||
@ -58,11 +58,10 @@ data class State(
|
|||||||
else -> GetString(R.string.activity_expiration_settings_subtitle)
|
else -> GetString(R.string.activity_expiration_settings_subtitle)
|
||||||
}
|
}
|
||||||
|
|
||||||
val modeOptionsHidden get() = isNoteToSelf || (isGroup && isNewConfigEnabled)
|
val typeOptionsHidden get() = isNoteToSelf || (isGroup && isNewConfigEnabled)
|
||||||
|
|
||||||
val duration get() = expiryMode?.duration
|
val duration get() = expiryMode?.duration
|
||||||
val expiryType get() = expiryMode?.type
|
val expiryType get() = expiryMode?.type
|
||||||
val expiryTypeOrNone: ExpiryType = expiryType ?: ExpiryType.NONE
|
|
||||||
|
|
||||||
val isTimeOptionsEnabled = isNoteToSelf || isSelfAdmin && (isNewConfigEnabled || expiryType == ExpiryType.LEGACY)
|
val isTimeOptionsEnabled = isNoteToSelf || isSelfAdmin && (isNewConfigEnabled || expiryType == ExpiryType.LEGACY)
|
||||||
}
|
}
|
||||||
@ -104,15 +103,12 @@ class ExpirationSettingsViewModel(
|
|||||||
.map(::UiState)
|
.map(::UiState)
|
||||||
.stateIn(viewModelScope, SharingStarted.Eagerly, UiState())
|
.stateIn(viewModelScope, SharingStarted.Eagerly, UiState())
|
||||||
|
|
||||||
private var expirationConfig: ExpirationConfiguration? = null
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
expirationConfig = storage.getExpirationConfiguration(threadId)
|
val expiryMode = storage.getExpirationConfiguration(threadId)?.expiryMode ?: ExpiryMode.NONE
|
||||||
val expiryMode = expirationConfig?.expiryMode ?: ExpiryMode.NONE
|
|
||||||
val recipient = threadDb.getRecipientForThreadId(threadId)
|
val recipient = threadDb.getRecipientForThreadId(threadId)
|
||||||
val groupRecord = recipient?.takeIf { it.isClosedGroupRecipient }
|
val groupRecord = recipient?.takeIf { it.isClosedGroupRecipient }
|
||||||
?.run { address.toGroupString().let(groupDb::getGroup).orNull() }
|
?.run { groupDb.getGroup(address.toGroupString()).orNull() }
|
||||||
|
|
||||||
_state.update { state ->
|
_state.update { state ->
|
||||||
state.copy(
|
state.copy(
|
||||||
@ -127,23 +123,13 @@ class ExpirationSettingsViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setMode(mode: ExpiryMode) {
|
override fun setMode(mode: ExpiryMode) = _state.update { it.copy(expiryMode = mode) }
|
||||||
_state.update { it.copy(
|
|
||||||
expiryMode = mode
|
|
||||||
) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSetClick() = viewModelScope.launch {
|
override fun onSetClick() = viewModelScope.launch {
|
||||||
val state = _state.value
|
val state = _state.value
|
||||||
val mode = state.expiryMode.let {
|
val mode = state.expiryMode
|
||||||
when {
|
|
||||||
it !is ExpiryMode.Legacy -> it
|
|
||||||
state.isGroup -> ExpiryMode.AfterSend(it.expirySeconds)
|
|
||||||
else -> ExpiryMode.AfterRead(it.expirySeconds)
|
|
||||||
} ?: ExpiryMode.NONE
|
|
||||||
}
|
|
||||||
val address = state.address
|
val address = state.address
|
||||||
if (address == null) {
|
if (address == null || mode == null) {
|
||||||
_event.send(Event.FAIL)
|
_event.send(Event.FAIL)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
@ -194,12 +180,6 @@ class ExpirationSettingsViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ExpiryType.defaultMode(persistedMode: ExpiryMode?) = when(this) {
|
|
||||||
persistedMode?.type -> persistedMode
|
|
||||||
ExpiryType.AFTER_READ -> mode(12.hours)
|
|
||||||
else -> mode(1.days)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class UiState(
|
data class UiState(
|
||||||
val cards: List<CardModel> = emptyList(),
|
val cards: List<CardModel> = emptyList(),
|
||||||
val showGroupFooter: Boolean = false
|
val showGroupFooter: Boolean = false
|
||||||
@ -211,62 +191,43 @@ data class UiState(
|
|||||||
),
|
),
|
||||||
showGroupFooter = state.isGroup && state.isNewConfigEnabled
|
showGroupFooter = state.isGroup && state.isNewConfigEnabled
|
||||||
)
|
)
|
||||||
|
|
||||||
|
constructor(showGroupFooter: Boolean, vararg cards: CardModel): this(cards.asList(), showGroupFooter)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class CardModel(
|
data class CardModel(
|
||||||
val title: GetString,
|
val title: GetString,
|
||||||
val options: List<OptionModel>
|
val options: List<OptionModel>
|
||||||
)
|
) {
|
||||||
|
constructor(title: GetString, vararg options: OptionModel): this(title, options.asList())
|
||||||
|
constructor(@StringRes title: Int, vararg options: OptionModel): this(GetString(title), options.asList())
|
||||||
|
}
|
||||||
|
|
||||||
private fun typeOptions(state: State) =
|
fun offTypeOption(state: State) = typeOption(ExpiryType.NONE, state)
|
||||||
state.takeUnless { it.modeOptionsHidden }?.run {
|
fun legacyTypeOption(state: State) = typeOption(ExpiryType.LEGACY, state)
|
||||||
|
fun afterReadTypeOption(state: State) = newTypeOption(ExpiryType.AFTER_READ, state)
|
||||||
|
fun afterSendTypeOption(state: State) = newTypeOption(ExpiryType.AFTER_SEND, state)
|
||||||
|
private fun newTypeOption(type: ExpiryType, state: State) = typeOption(type, state, state.run { isNewConfigEnabled && isSelfAdmin })
|
||||||
|
|
||||||
|
private fun typeOptions(state: State) = state.takeUnless { it.typeOptionsHidden }?.run {
|
||||||
listOfNotNull(
|
listOfNotNull(
|
||||||
typeOption(
|
offTypeOption(state),
|
||||||
ExpiryMode.NONE,
|
takeUnless { isNewConfigEnabled }?.let(::legacyTypeOption),
|
||||||
state,
|
takeUnless { isGroup }?.let(::afterReadTypeOption),
|
||||||
R.string.expiration_off,
|
afterSendTypeOption(state)
|
||||||
contentDescription = R.string.AccessibilityId_disable_disappearing_messages,
|
|
||||||
enabled = isSelfAdmin
|
|
||||||
),
|
|
||||||
if (!isNewConfigEnabled) typeOption(
|
|
||||||
ExpiryType.LEGACY.defaultMode(persistedMode),
|
|
||||||
state,
|
|
||||||
R.string.expiration_type_disappear_legacy,
|
|
||||||
contentDescription = R.string.expiration_type_disappear_legacy_description,
|
|
||||||
enabled = isSelfAdmin
|
|
||||||
) else null,
|
|
||||||
if (!isGroup) typeOption(
|
|
||||||
ExpiryType.AFTER_READ.defaultMode(persistedMode),
|
|
||||||
state,
|
|
||||||
R.string.expiration_type_disappear_after_read,
|
|
||||||
R.string.expiration_type_disappear_after_read_description,
|
|
||||||
contentDescription = R.string.expiration_type_disappear_after_read_description,
|
|
||||||
enabled = isNewConfigEnabled && isSelfAdmin
|
|
||||||
) else null,
|
|
||||||
typeOption(
|
|
||||||
ExpiryType.AFTER_SEND.defaultMode(persistedMode),
|
|
||||||
state,
|
|
||||||
R.string.expiration_type_disappear_after_send,
|
|
||||||
R.string.expiration_type_disappear_after_read_description,
|
|
||||||
contentDescription = R.string.expiration_type_disappear_after_send_description,
|
|
||||||
enabled = isNewConfigEnabled && isSelfAdmin
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun typeOption(
|
private fun typeOption(
|
||||||
mode: ExpiryMode,
|
type: ExpiryType,
|
||||||
state: State,
|
state: State,
|
||||||
@StringRes title: Int,
|
enabled: Boolean = state.isSelfAdmin,
|
||||||
@StringRes subtitle: Int? = null,
|
|
||||||
@StringRes contentDescription: Int = title,
|
|
||||||
enabled: Boolean = true,
|
|
||||||
) = OptionModel(
|
) = OptionModel(
|
||||||
value = mode,
|
value = type.defaultMode(state.persistedMode),
|
||||||
title = GetString(title),
|
title = GetString(type.title),
|
||||||
subtitle = subtitle?.let(::GetString),
|
subtitle = type.subtitle?.let(::GetString),
|
||||||
contentDescription = GetString(contentDescription),
|
contentDescription = GetString(type.contentDescription),
|
||||||
selected = state.expiryType == mode.type,
|
selected = state.expiryType == type,
|
||||||
enabled = enabled
|
enabled = enabled
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -292,26 +253,26 @@ val afterReadModes = afterReadTimes.map { it.inWholeSeconds }.map(ExpiryMode::Af
|
|||||||
fun afterReadOptions(state: State) = afterReadModes.map { timeOption(it, state) }
|
fun afterReadOptions(state: State) = afterReadModes.map { timeOption(it, state) }
|
||||||
|
|
||||||
private fun timeOptions(state: State): List<OptionModel>? =
|
private fun timeOptions(state: State): List<OptionModel>? =
|
||||||
if (state.modeOptionsHidden) timeOptionsAfterSend(state)
|
if (state.typeOptionsHidden) timeOptionsAfterSend(state)
|
||||||
else when (state.expiryMode) {
|
else when (state.expiryMode) {
|
||||||
is ExpiryMode.Legacy, is ExpiryMode.AfterRead -> debugOptions(state) + afterReadOptions(state)
|
is ExpiryMode.Legacy, is ExpiryMode.AfterRead -> debugOptions(state) + afterReadOptions(state)
|
||||||
is ExpiryMode.AfterSend -> debugOptions(state) + afterSendOptions(state)
|
is ExpiryMode.AfterSend -> debugOptions(state) + afterSendOptions(state)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun timeOptionsAfterSend(state: State) = listOf(
|
private fun timeOptionsAfterSend(state: State): List<OptionModel> =
|
||||||
typeOption(ExpiryMode.NONE, state, R.string.expiration_off, enabled = state.isSelfAdmin),
|
listOf(offTypeOption(state)) + debugOptions(state) + afterSendOptions(state)
|
||||||
) + debugOptions(state) + afterSendModes.map { timeOption(it, state) }
|
|
||||||
|
|
||||||
private fun timeOption(
|
fun timeOption(
|
||||||
mode: ExpiryMode,
|
mode: ExpiryMode,
|
||||||
state: State,
|
state: State,
|
||||||
title: GetString = GetString(mode.duration, ExpirationUtil::getExpirationDisplayValue),
|
title: GetString = GetString(mode.duration),
|
||||||
subtitle: GetString? = null,
|
subtitle: GetString? = null,
|
||||||
) = OptionModel(
|
) = OptionModel(
|
||||||
value = mode,
|
value = mode,
|
||||||
title = title,
|
title = title,
|
||||||
subtitle = subtitle,
|
subtitle = subtitle,
|
||||||
|
contentDescription = title,
|
||||||
selected = state.expiryMode == mode,
|
selected = state.expiryMode == mode,
|
||||||
enabled = state.isTimeOptionsEnabled
|
enabled = state.isTimeOptionsEnabled
|
||||||
)
|
)
|
||||||
@ -325,14 +286,43 @@ data class OptionModel(
|
|||||||
val enabled: Boolean = true,
|
val enabled: Boolean = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class ExpiryType(private val createMode: (Long) -> ExpiryMode) {
|
enum class ExpiryType(
|
||||||
NONE({ ExpiryMode.NONE }),
|
private val createMode: (Long) -> ExpiryMode,
|
||||||
LEGACY(ExpiryMode::Legacy),
|
@StringRes val title: Int,
|
||||||
AFTER_SEND(ExpiryMode::AfterSend),
|
@StringRes val subtitle: Int? = null,
|
||||||
AFTER_READ(ExpiryMode::AfterRead);
|
@StringRes val contentDescription: Int = title,
|
||||||
|
) {
|
||||||
|
NONE(
|
||||||
|
{ ExpiryMode.NONE },
|
||||||
|
R.string.expiration_off,
|
||||||
|
contentDescription = R.string.AccessibilityId_disable_disappearing_messages,
|
||||||
|
),
|
||||||
|
LEGACY(
|
||||||
|
ExpiryMode::Legacy,
|
||||||
|
R.string.expiration_type_disappear_legacy,
|
||||||
|
contentDescription = R.string.expiration_type_disappear_legacy_description
|
||||||
|
),
|
||||||
|
AFTER_SEND(
|
||||||
|
ExpiryMode::AfterSend,
|
||||||
|
R.string.expiration_type_disappear_after_send,
|
||||||
|
R.string.expiration_type_disappear_after_read_description,
|
||||||
|
R.string.expiration_type_disappear_after_send_description
|
||||||
|
),
|
||||||
|
AFTER_READ(
|
||||||
|
ExpiryMode::AfterRead,
|
||||||
|
R.string.expiration_type_disappear_after_read,
|
||||||
|
R.string.expiration_type_disappear_after_read_description,
|
||||||
|
R.string.expiration_type_disappear_after_read_description
|
||||||
|
);
|
||||||
|
|
||||||
fun mode(seconds: Long) = if (seconds != 0L) createMode(seconds) else ExpiryMode.NONE
|
fun mode(seconds: Long) = if (seconds != 0L) createMode(seconds) else ExpiryMode.NONE
|
||||||
fun mode(duration: Duration) = mode(duration.inWholeSeconds)
|
fun mode(duration: Duration) = mode(duration.inWholeSeconds)
|
||||||
|
|
||||||
|
fun defaultMode(persistedMode: ExpiryMode?) = when(this) {
|
||||||
|
persistedMode?.type -> persistedMode
|
||||||
|
AFTER_READ -> mode(12.hours)
|
||||||
|
else -> mode(1.days)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val ExpiryMode.type: ExpiryType get() = when(this) {
|
val ExpiryMode.type: ExpiryType get() = when(this) {
|
||||||
|
@ -120,6 +120,3 @@ class RadioOptionBuilder<out T>(
|
|||||||
contentDescription
|
contentDescription
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias StringRadioOption = RadioOption<String>
|
|
||||||
typealias ExpirationRadioOption = RadioOption<ExpiryMode>
|
|
||||||
|
@ -1,76 +1,73 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.expiration
|
package org.thoughtcrime.securesms.conversation.expiration
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.advanceUntilIdle
|
import kotlinx.coroutines.test.advanceUntilIdle
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.libsession_util.util.ExpiryMode
|
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||||
import org.hamcrest.CoreMatchers
|
|
||||||
import org.hamcrest.MatcherAssert
|
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito
|
import org.mockito.Mockito
|
||||||
import org.mockito.Mockito.mock
|
import org.mockito.Mockito.mock
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner
|
||||||
import org.mockito.kotlin.whenever
|
import org.mockito.kotlin.whenever
|
||||||
import org.session.libsession.messaging.messages.ExpirationConfiguration
|
import org.session.libsession.messaging.messages.ExpirationConfiguration
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.SSKEnvironment
|
import org.session.libsession.utilities.SSKEnvironment
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.utilities.guava.Optional
|
|
||||||
import org.thoughtcrime.securesms.MainCoroutineRule
|
import org.thoughtcrime.securesms.MainCoroutineRule
|
||||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||||
import org.thoughtcrime.securesms.database.Storage
|
import org.thoughtcrime.securesms.database.Storage
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
import org.thoughtcrime.securesms.ui.GetString
|
import org.thoughtcrime.securesms.ui.GetString
|
||||||
import kotlin.time.Duration.Companion.hours
|
import kotlin.reflect.typeOf
|
||||||
import network.loki.messenger.R
|
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
|
import kotlin.time.Duration.Companion.hours
|
||||||
|
|
||||||
|
private const val THREAD_ID = 1L
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@RunWith(MockitoJUnitRunner::class)
|
||||||
class ExpirationSettingsViewModelTest {
|
class ExpirationSettingsViewModelTest {
|
||||||
|
|
||||||
@ExperimentalCoroutinesApi
|
@ExperimentalCoroutinesApi
|
||||||
@get:Rule
|
@get:Rule
|
||||||
var mainCoroutineRule = MainCoroutineRule()
|
var mainCoroutineRule = MainCoroutineRule()
|
||||||
|
|
||||||
private val application: Application = mock(Application::class.java)
|
@Mock lateinit var application: Application
|
||||||
private val textSecurePreferences: TextSecurePreferences = mock(TextSecurePreferences::class.java)
|
@Mock lateinit var textSecurePreferences: TextSecurePreferences
|
||||||
private val messageExpirationManager: SSKEnvironment.MessageExpirationManagerProtocol = mock(SSKEnvironment.MessageExpirationManagerProtocol::class.java)
|
@Mock lateinit var messageExpirationManager: SSKEnvironment.MessageExpirationManagerProtocol
|
||||||
private val threadDb: ThreadDatabase = mock(ThreadDatabase::class.java)
|
@Mock lateinit var threadDb: ThreadDatabase
|
||||||
private val groupDb: GroupDatabase = mock(GroupDatabase::class.java)
|
@Mock lateinit var groupDb: GroupDatabase
|
||||||
private val storage: Storage = mock(Storage::class.java)
|
@Mock lateinit var storage: Storage
|
||||||
private val recipient = mock(Recipient::class.java)
|
@Mock lateinit var recipient: Recipient
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `UI should show a list of times and an Off option`() = runTest {
|
fun `1-1 conversation, 12 hours after send, new config`() = runTest {
|
||||||
val threadId = 1L
|
val time = 12.hours
|
||||||
|
|
||||||
val expirationConfig = ExpirationConfiguration(
|
|
||||||
threadId = threadId,
|
|
||||||
expiryMode = ExpiryMode.AfterSend(12.hours.inWholeSeconds),
|
|
||||||
updatedTimestampMs = 0
|
|
||||||
)
|
|
||||||
whenever(threadDb.getRecipientForThreadId(Mockito.anyLong())).thenReturn(recipient)
|
|
||||||
whenever(storage.getExpirationConfiguration(Mockito.anyLong())).thenReturn(expirationConfig)
|
|
||||||
whenever(textSecurePreferences.getLocalNumber()).thenReturn("05---LOCAL---ADDRESS")
|
|
||||||
|
|
||||||
val userAddress = Address.fromSerialized(textSecurePreferences.getLocalNumber()!!)
|
|
||||||
val someAddress = Address.fromSerialized("05---SOME---ADDRESS")
|
val someAddress = Address.fromSerialized("05---SOME---ADDRESS")
|
||||||
|
val config = newExpirationConfiguration(time)
|
||||||
|
|
||||||
|
whenever(threadDb.getRecipientForThreadId(Mockito.anyLong())).thenReturn(recipient)
|
||||||
|
whenever(storage.getExpirationConfiguration(Mockito.anyLong())).thenReturn(config)
|
||||||
|
whenever(textSecurePreferences.getLocalNumber()).thenReturn("05---LOCAL---ADDRESS")
|
||||||
whenever(recipient.isClosedGroupRecipient).thenReturn(false)
|
whenever(recipient.isClosedGroupRecipient).thenReturn(false)
|
||||||
whenever(recipient.address).thenReturn(someAddress)
|
whenever(recipient.address).thenReturn(someAddress)
|
||||||
|
|
||||||
whenever(groupDb.getGroup(Mockito.anyString())).thenReturn(Optional.absent())
|
|
||||||
|
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
|
|
||||||
advanceUntilIdle()
|
advanceUntilIdle()
|
||||||
|
|
||||||
MatcherAssert.assertThat(
|
assertThat(
|
||||||
viewModel.state.value,
|
viewModel.state.value
|
||||||
CoreMatchers.equalTo(
|
).isEqualTo(
|
||||||
State(
|
State(
|
||||||
isGroup = false,
|
isGroup = false,
|
||||||
isSelfAdmin = true,
|
isSelfAdmin = true,
|
||||||
@ -82,51 +79,110 @@ class ExpirationSettingsViewModelTest {
|
|||||||
showDebugOptions = false
|
showDebugOptions = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
val uiState = viewModel.uiState.value
|
val newTypeOption = TypeOptionCreator(time)
|
||||||
|
val newTimeOption = TimeOptionCreator(ExpiryType.AFTER_SEND)
|
||||||
|
|
||||||
MatcherAssert.assertThat(
|
assertThat(
|
||||||
uiState.cards.map { it.title },
|
viewModel.uiState.value
|
||||||
CoreMatchers.equalTo(
|
).isEqualTo(
|
||||||
listOf(
|
UiState(
|
||||||
|
showGroupFooter = false,
|
||||||
|
CardModel(
|
||||||
R.string.activity_expiration_settings_delete_type,
|
R.string.activity_expiration_settings_delete_type,
|
||||||
R.string.activity_expiration_settings_timer
|
newTypeOption(ExpiryType.NONE),
|
||||||
).map(::GetString)
|
newTypeOption(ExpiryType.AFTER_READ),
|
||||||
|
newTypeOption(ExpiryType.AFTER_SEND, selected = true)
|
||||||
|
),
|
||||||
|
CardModel(
|
||||||
|
GetString(R.string.activity_expiration_settings_timer),
|
||||||
|
newTimeOption(duration = 12.hours, selected = true),
|
||||||
|
newTimeOption(duration = 1.days),
|
||||||
|
newTimeOption(duration = 7.days),
|
||||||
|
newTimeOption(duration = 14.days)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `1-1 conversation, 1 day after send, new config`() = runTest {
|
||||||
|
val time = 1.days
|
||||||
|
val someAddress = Address.fromSerialized("05---SOME---ADDRESS")
|
||||||
|
val config = newExpirationConfiguration(time)
|
||||||
|
|
||||||
|
whenever(threadDb.getRecipientForThreadId(Mockito.anyLong())).thenReturn(recipient)
|
||||||
|
whenever(storage.getExpirationConfiguration(Mockito.anyLong())).thenReturn(config)
|
||||||
|
whenever(textSecurePreferences.getLocalNumber()).thenReturn("05---LOCAL---ADDRESS")
|
||||||
|
whenever(recipient.isClosedGroupRecipient).thenReturn(false)
|
||||||
|
whenever(recipient.address).thenReturn(someAddress)
|
||||||
|
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
assertThat(
|
||||||
|
viewModel.state.value
|
||||||
|
).isEqualTo(
|
||||||
|
State(
|
||||||
|
isGroup = false,
|
||||||
|
isSelfAdmin = true,
|
||||||
|
address = someAddress,
|
||||||
|
isNoteToSelf = false,
|
||||||
|
expiryMode = ExpiryMode.AfterSend(1.days.inWholeSeconds),
|
||||||
|
isNewConfigEnabled = true,
|
||||||
|
persistedMode = ExpiryMode.AfterSend(1.days.inWholeSeconds),
|
||||||
|
showDebugOptions = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
MatcherAssert.assertThat(
|
val newTypeOption = TypeOptionCreator(time)
|
||||||
uiState.cards[0].options.map { it.title },
|
val newTimeOption = TimeOptionCreator(ExpiryType.AFTER_SEND)
|
||||||
CoreMatchers.equalTo(
|
|
||||||
listOf(
|
assertThat(
|
||||||
R.string.expiration_off,
|
viewModel.uiState.value
|
||||||
R.string.expiration_type_disappear_after_read,
|
).isEqualTo(
|
||||||
R.string.expiration_type_disappear_after_send,
|
UiState(
|
||||||
).map(::GetString)
|
showGroupFooter = false,
|
||||||
|
CardModel(
|
||||||
|
R.string.activity_expiration_settings_delete_type,
|
||||||
|
newTypeOption(ExpiryType.NONE),
|
||||||
|
typeOption(12.hours, ExpiryType.AFTER_READ),
|
||||||
|
newTypeOption(ExpiryType.AFTER_SEND, selected = true)
|
||||||
|
),
|
||||||
|
CardModel(
|
||||||
|
GetString(R.string.activity_expiration_settings_timer),
|
||||||
|
newTimeOption(duration = 12.hours),
|
||||||
|
newTimeOption(duration = 1.days, selected = true),
|
||||||
|
newTimeOption(duration = 7.days),
|
||||||
|
newTimeOption(duration = 14.days)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun newExpirationConfiguration(time: Duration) = ExpirationConfiguration(
|
||||||
|
threadId = THREAD_ID,
|
||||||
|
expiryMode = ExpiryMode.AfterSend(time.inWholeSeconds),
|
||||||
|
updatedTimestampMs = 0
|
||||||
|
)
|
||||||
|
|
||||||
MatcherAssert.assertThat(
|
private class TypeOptionCreator(private val time: Duration) {
|
||||||
uiState.cards[1].options.map { it.title },
|
operator fun invoke(type: ExpiryType, selected: Boolean = false, enabled: Boolean = true) =
|
||||||
CoreMatchers.equalTo(
|
typeOption(time, type, selected, enabled)
|
||||||
listOf(
|
}
|
||||||
12.hours,
|
|
||||||
1.days,
|
|
||||||
7.days,
|
|
||||||
14.days,
|
|
||||||
).map(::GetString)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
MatcherAssert.assertThat(
|
private class TimeOptionCreator(private val type: ExpiryType) {
|
||||||
uiState.showGroupFooter,
|
operator fun invoke(duration: Duration, selected: Boolean = false, enabled: Boolean = true) = OptionModel(
|
||||||
CoreMatchers.equalTo(false)
|
value = type.mode(duration),
|
||||||
|
title = GetString(duration),
|
||||||
|
enabled = enabled,
|
||||||
|
selected = selected
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createViewModel(isNewConfigEnabled: Boolean = true) = ExpirationSettingsViewModel(
|
private fun createViewModel(isNewConfigEnabled: Boolean = true) = ExpirationSettingsViewModel(
|
||||||
1L,
|
THREAD_ID,
|
||||||
application,
|
application,
|
||||||
textSecurePreferences,
|
textSecurePreferences,
|
||||||
messageExpirationManager,
|
messageExpirationManager,
|
||||||
@ -134,6 +190,16 @@ class ExpirationSettingsViewModelTest {
|
|||||||
groupDb,
|
groupDb,
|
||||||
storage,
|
storage,
|
||||||
isNewConfigEnabled,
|
isNewConfigEnabled,
|
||||||
false
|
showDebugOptions = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun typeOption(time: Duration, type: ExpiryType, selected: Boolean = false, enabled: Boolean = true) =
|
||||||
|
OptionModel(
|
||||||
|
type.mode(time),
|
||||||
|
GetString(type.title),
|
||||||
|
type.subtitle?.let(::GetString),
|
||||||
|
GetString(type.contentDescription),
|
||||||
|
selected = selected,
|
||||||
|
enabled = enabled
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user