mirror of
https://github.com/bitwarden/android.git
synced 2024-11-26 11:26:09 +03:00
Add support to copy a send url to the clipboard (#508)
This commit is contained in:
parent
0a3377d98a
commit
4a39f126dd
9 changed files with 230 additions and 40 deletions
|
@ -4,6 +4,39 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJso
|
||||||
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
|
private const val DEFAULT_WEB_VAULT_URL: String = "https://vault.bitwarden.com"
|
||||||
|
private const val DEFAULT_WEB_SEND_URL: String = "https://send.bitwarden.com/#"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base web vault URL. This will check for a custom [EnvironmentUrlDataJson.webVault]
|
||||||
|
* before falling back to the [EnvironmentUrlDataJson.base]. This can still return null if both are
|
||||||
|
* null or blank.
|
||||||
|
*/
|
||||||
|
val EnvironmentUrlDataJson.baseWebVaultUrlOrNull: String?
|
||||||
|
get() =
|
||||||
|
this
|
||||||
|
.webVault
|
||||||
|
.takeIf { !it.isNullOrBlank() }
|
||||||
|
?: base.takeIf { it.isNotBlank() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base web vault URL or the default value if one is not present.
|
||||||
|
*
|
||||||
|
* See [baseWebVaultUrlOrNull] for more details.
|
||||||
|
*/
|
||||||
|
val EnvironmentUrlDataJson.baseWebVaultUrlOrDefault: String
|
||||||
|
get() = this.baseWebVaultUrlOrNull ?: DEFAULT_WEB_VAULT_URL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base web send URL or the default value if one is not present.
|
||||||
|
*/
|
||||||
|
val EnvironmentUrlDataJson.baseWebSendUrl: String
|
||||||
|
get() =
|
||||||
|
this
|
||||||
|
.baseWebVaultUrlOrNull
|
||||||
|
?.let { "$it/#/send/" }
|
||||||
|
?: DEFAULT_WEB_SEND_URL
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the appropriate pre-defined labels for environments matching the known US/EU values.
|
* Returns the appropriate pre-defined labels for environments matching the known US/EU values.
|
||||||
* Otherwise returns the host of the custom base URL.
|
* Otherwise returns the host of the custom base URL.
|
||||||
|
|
|
@ -6,7 +6,9 @@ import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.util.baseWebSendUrl
|
||||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
||||||
|
@ -34,6 +36,7 @@ private const val KEY_STATE = "state"
|
||||||
class SendViewModel @Inject constructor(
|
class SendViewModel @Inject constructor(
|
||||||
savedStateHandle: SavedStateHandle,
|
savedStateHandle: SavedStateHandle,
|
||||||
private val clipboardManager: BitwardenClipboardManager,
|
private val clipboardManager: BitwardenClipboardManager,
|
||||||
|
private val environmentRepo: EnvironmentRepository,
|
||||||
private val vaultRepo: VaultRepository,
|
private val vaultRepo: VaultRepository,
|
||||||
) : BaseViewModel<SendState, SendEvent, SendAction>(
|
) : BaseViewModel<SendState, SendEvent, SendAction>(
|
||||||
// We load the state from the savedStateHandle for testing purposes.
|
// We load the state from the savedStateHandle for testing purposes.
|
||||||
|
@ -84,7 +87,14 @@ class SendViewModel @Inject constructor(
|
||||||
|
|
||||||
is DataState.Loaded -> {
|
is DataState.Loaded -> {
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
it.copy(viewState = dataState.data.toViewState())
|
it.copy(
|
||||||
|
viewState = dataState.data.toViewState(
|
||||||
|
baseWebSendUrl = environmentRepo
|
||||||
|
.environment
|
||||||
|
.environmentUrlData
|
||||||
|
.baseWebSendUrl,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +118,14 @@ class SendViewModel @Inject constructor(
|
||||||
|
|
||||||
is DataState.Pending -> {
|
is DataState.Pending -> {
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
it.copy(viewState = dataState.data.toViewState())
|
it.copy(
|
||||||
|
viewState = dataState.data.toViewState(
|
||||||
|
baseWebSendUrl = environmentRepo
|
||||||
|
.environment
|
||||||
|
.environmentUrlData
|
||||||
|
.baseWebSendUrl,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,8 +159,7 @@ class SendViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleCopyClick(action: SendAction.CopyClick) {
|
private fun handleCopyClick(action: SendAction.CopyClick) {
|
||||||
// TODO: Create a link and copy it to the clipboard BIT-??
|
clipboardManager.setText(text = action.sendItem.shareUrl)
|
||||||
sendEvent(SendEvent.ShowToast("Not yet implemented".asText()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSendClick(action: SendAction.SendClick) {
|
private fun handleSendClick(action: SendAction.SendClick) {
|
||||||
|
@ -205,6 +221,7 @@ data class SendState(
|
||||||
val deletionDate: String,
|
val deletionDate: String,
|
||||||
val type: Type,
|
val type: Type,
|
||||||
val iconList: List<SendStatusIcon>,
|
val iconList: List<SendStatusIcon>,
|
||||||
|
val shareUrl: String,
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
/**
|
/**
|
||||||
* Indicates the type of send this, a text or file.
|
* Indicates the type of send this, a text or file.
|
||||||
|
|
|
@ -13,14 +13,18 @@ private const val DELETION_DATE_PATTERN: String = "MMM d, uuuu, hh:mm a"
|
||||||
/**
|
/**
|
||||||
* Transforms [SendData] into [SendState.ViewState].
|
* Transforms [SendData] into [SendState.ViewState].
|
||||||
*/
|
*/
|
||||||
fun SendData.toViewState(): SendState.ViewState =
|
fun SendData.toViewState(
|
||||||
|
baseWebSendUrl: String,
|
||||||
|
): SendState.ViewState =
|
||||||
this
|
this
|
||||||
.sendViewList
|
.sendViewList
|
||||||
.takeUnless { it.isEmpty() }
|
.takeUnless { it.isEmpty() }
|
||||||
?.toSendContent()
|
?.toSendContent(baseWebSendUrl)
|
||||||
?: SendState.ViewState.Empty
|
?: SendState.ViewState.Empty
|
||||||
|
|
||||||
private fun List<SendView>.toSendContent(): SendState.ViewState.Content {
|
private fun List<SendView>.toSendContent(
|
||||||
|
baseWebSendUrl: String,
|
||||||
|
): SendState.ViewState.Content {
|
||||||
return SendState.ViewState.Content(
|
return SendState.ViewState.Content(
|
||||||
textTypeCount = this.count { it.type == SendType.TEXT },
|
textTypeCount = this.count { it.type == SendType.TEXT },
|
||||||
fileTypeCount = this.count { it.type == SendType.FILE },
|
fileTypeCount = this.count { it.type == SendType.FILE },
|
||||||
|
@ -49,6 +53,7 @@ private fun List<SendView>.toSendContent(): SendState.ViewState.Content {
|
||||||
sendView.deletionDate.isBefore(Instant.now())
|
sendView.deletionDate.isBefore(Instant.now())
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
shareUrl = sendView.toSendUrl(baseWebSendUrl),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.sortedBy { it.name },
|
.sortedBy { it.name },
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.x8bit.bitwarden.ui.tools.feature.send.util
|
||||||
|
|
||||||
|
import com.bitwarden.core.SendView
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a sharable url from a [SendView].
|
||||||
|
*/
|
||||||
|
fun SendView.toSendUrl(
|
||||||
|
baseWebSendUrl: String,
|
||||||
|
// TODO: The `key` being used here is not correct and should be updated (BIT-1386)
|
||||||
|
): String = "$baseWebSendUrl$accessId/$key"
|
|
@ -3,9 +3,86 @@ package com.x8bit.bitwarden.data.platform.repository.util
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
|
||||||
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertNull
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
class EnvironmentUrlsDataJsonExtensionsTest {
|
class EnvironmentUrlsDataJsonExtensionsTest {
|
||||||
|
@Test
|
||||||
|
fun `baseWebVaultUrlOrNull should return webVault when populated`() {
|
||||||
|
val result = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.baseWebVaultUrlOrNull
|
||||||
|
assertEquals("webVault", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `baseWebVaultUrlOrNull should return base when webvault is not populated`() {
|
||||||
|
val result = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||||
|
.copy(webVault = null)
|
||||||
|
.baseWebVaultUrlOrNull
|
||||||
|
assertEquals("base", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `baseWebVaultUrlOrNull should return null when webvault and base are not populated`() {
|
||||||
|
val result = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||||
|
.copy(
|
||||||
|
webVault = null,
|
||||||
|
base = "",
|
||||||
|
)
|
||||||
|
.baseWebVaultUrlOrNull
|
||||||
|
assertNull(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `baseWebVaultUrlOrDefault should return webVault when populated`() {
|
||||||
|
val result = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.baseWebVaultUrlOrDefault
|
||||||
|
assertEquals("webVault", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `baseWebVaultUrlOrDefault should return base when webvault is not populated`() {
|
||||||
|
val result = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||||
|
.copy(webVault = null)
|
||||||
|
.baseWebVaultUrlOrDefault
|
||||||
|
assertEquals("base", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
|
@Test
|
||||||
|
fun `baseWebVaultUrlOrDefault should return the default when webvault and base are not populated`() {
|
||||||
|
val result = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||||
|
.copy(
|
||||||
|
webVault = null,
|
||||||
|
base = "",
|
||||||
|
)
|
||||||
|
.baseWebVaultUrlOrDefault
|
||||||
|
assertEquals("https://vault.bitwarden.com", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `baseWebSendUrl should return the correct result when webVault when populated`() {
|
||||||
|
val result = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.baseWebSendUrl
|
||||||
|
assertEquals("webVault/#/send/", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `baseWebSendUrl should return the correct result when webvault is not populated`() {
|
||||||
|
val result = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||||
|
.copy(webVault = null)
|
||||||
|
.baseWebSendUrl
|
||||||
|
assertEquals("base/#/send/", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `baseWebSendUrl should return the default when webvault and base are not populated`() {
|
||||||
|
val result = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||||
|
.copy(
|
||||||
|
webVault = null,
|
||||||
|
base = "",
|
||||||
|
)
|
||||||
|
.baseWebSendUrl
|
||||||
|
assertEquals("https://send.bitwarden.com/#", result)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `labelOrBaseUrlHost should correctly convert US environment to the correct label`() {
|
fun `labelOrBaseUrlHost should correctly convert US environment to the correct label`() {
|
||||||
val environment = EnvironmentUrlDataJson.DEFAULT_US
|
val environment = EnvironmentUrlDataJson.DEFAULT_US
|
||||||
|
@ -52,20 +129,11 @@ class EnvironmentUrlsDataJsonExtensionsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `toEnvironmentUrls should correctly convert custom urls to the expected type`() {
|
fun `toEnvironmentUrls should correctly convert custom urls to the expected type`() {
|
||||||
val environmentUrlData = EnvironmentUrlDataJson(
|
|
||||||
base = "base",
|
|
||||||
api = "api",
|
|
||||||
identity = "identity",
|
|
||||||
icon = "icon",
|
|
||||||
notifications = "notifications",
|
|
||||||
webVault = "webVault",
|
|
||||||
events = "events",
|
|
||||||
)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
Environment.SelfHosted(
|
Environment.SelfHosted(
|
||||||
environmentUrlData = environmentUrlData,
|
environmentUrlData = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA,
|
||||||
),
|
),
|
||||||
environmentUrlData.toEnvironmentUrls(),
|
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.toEnvironmentUrls(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,20 +155,11 @@ class EnvironmentUrlsDataJsonExtensionsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `toEnvironmentUrlsOrDefault should correctly convert custom urls to the expected type`() {
|
fun `toEnvironmentUrlsOrDefault should correctly convert custom urls to the expected type`() {
|
||||||
val environmentUrlData = EnvironmentUrlDataJson(
|
|
||||||
base = "base",
|
|
||||||
api = "api",
|
|
||||||
identity = "identity",
|
|
||||||
icon = "icon",
|
|
||||||
notifications = "notifications",
|
|
||||||
webVault = "webVault",
|
|
||||||
events = "events",
|
|
||||||
)
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
Environment.SelfHosted(
|
Environment.SelfHosted(
|
||||||
environmentUrlData = environmentUrlData,
|
environmentUrlData = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA,
|
||||||
),
|
),
|
||||||
environmentUrlData.toEnvironmentUrlsOrDefault(),
|
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.toEnvironmentUrlsOrDefault(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,3 +171,13 @@ class EnvironmentUrlsDataJsonExtensionsTest {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA = EnvironmentUrlDataJson(
|
||||||
|
base = "base",
|
||||||
|
api = "api",
|
||||||
|
identity = "identity",
|
||||||
|
icon = "icon",
|
||||||
|
notifications = "notifications",
|
||||||
|
webVault = "webVault",
|
||||||
|
events = "events",
|
||||||
|
)
|
||||||
|
|
|
@ -487,6 +487,7 @@ private val DEFAULT_SEND_ITEM: SendState.ViewState.Content.SendItem =
|
||||||
deletionDate = "1",
|
deletionDate = "1",
|
||||||
type = SendState.ViewState.Content.SendItem.Type.FILE,
|
type = SendState.ViewState.Content.SendItem.Type.FILE,
|
||||||
iconList = emptyList(),
|
iconList = emptyList(),
|
||||||
|
shareUrl = "www.test.com/#/send/mockAccessId-1/mockKey-1",
|
||||||
)
|
)
|
||||||
|
|
||||||
private val DEFAULT_CONTENT_VIEW_STATE: SendState.ViewState.Content = SendState.ViewState.Content(
|
private val DEFAULT_CONTENT_VIEW_STATE: SendState.ViewState.Content = SendState.ViewState.Content(
|
||||||
|
@ -500,6 +501,7 @@ private val DEFAULT_CONTENT_VIEW_STATE: SendState.ViewState.Content = SendState.
|
||||||
deletionDate = "1",
|
deletionDate = "1",
|
||||||
type = SendState.ViewState.Content.SendItem.Type.TEXT,
|
type = SendState.ViewState.Content.SendItem.Type.TEXT,
|
||||||
iconList = emptyList(),
|
iconList = emptyList(),
|
||||||
|
shareUrl = "www.test.com/#/send/mockAccessId-1/mockKey-1",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,10 @@ import androidx.lifecycle.SavedStateHandle
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.util.baseWebSendUrl
|
||||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
||||||
|
@ -30,6 +33,9 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||||
private val mutableSendDataFlow = MutableStateFlow<DataState<SendData>>(DataState.Loading)
|
private val mutableSendDataFlow = MutableStateFlow<DataState<SendData>>(DataState.Loading)
|
||||||
|
|
||||||
private val clipboardManager: BitwardenClipboardManager = mockk()
|
private val clipboardManager: BitwardenClipboardManager = mockk()
|
||||||
|
private val environmentRepo: EnvironmentRepository = mockk {
|
||||||
|
every { environment } returns Environment.Us
|
||||||
|
}
|
||||||
private val vaultRepo: VaultRepository = mockk {
|
private val vaultRepo: VaultRepository = mockk {
|
||||||
every { sendDataStateFlow } returns mutableSendDataFlow
|
every { sendDataStateFlow } returns mutableSendDataFlow
|
||||||
}
|
}
|
||||||
|
@ -114,12 +120,18 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `CopyClick should emit ShowToast`() = runTest {
|
fun `CopyClick should call setText on the ClipboardManager`() {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
val sendItem = mockk<SendState.ViewState.Content.SendItem>()
|
val testUrl = "www.test.com/"
|
||||||
viewModel.eventFlow.test {
|
val sendItem = mockk<SendState.ViewState.Content.SendItem> {
|
||||||
|
every { shareUrl } returns testUrl
|
||||||
|
}
|
||||||
|
every { clipboardManager.setText(testUrl) } just runs
|
||||||
|
|
||||||
viewModel.trySendAction(SendAction.CopyClick(sendItem))
|
viewModel.trySendAction(SendAction.CopyClick(sendItem))
|
||||||
assertEquals(SendEvent.ShowToast("Not yet implemented".asText()), awaitItem())
|
|
||||||
|
verify(exactly = 1) {
|
||||||
|
clipboardManager.setText(testUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +194,9 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
val viewState = mockk<SendState.ViewState.Content>()
|
val viewState = mockk<SendState.ViewState.Content>()
|
||||||
val sendData = mockk<SendData> {
|
val sendData = mockk<SendData> {
|
||||||
every { toViewState() } returns viewState
|
every {
|
||||||
|
toViewState(Environment.Us.environmentUrlData.baseWebSendUrl)
|
||||||
|
} returns viewState
|
||||||
}
|
}
|
||||||
|
|
||||||
mutableSendDataFlow.value = DataState.Loaded(sendData)
|
mutableSendDataFlow.value = DataState.Loaded(sendData)
|
||||||
|
@ -225,7 +239,9 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
val viewState = mockk<SendState.ViewState.Content>()
|
val viewState = mockk<SendState.ViewState.Content>()
|
||||||
val sendData = mockk<SendData> {
|
val sendData = mockk<SendData> {
|
||||||
every { toViewState() } returns viewState
|
every {
|
||||||
|
toViewState(Environment.Us.environmentUrlData.baseWebSendUrl)
|
||||||
|
} returns viewState
|
||||||
}
|
}
|
||||||
|
|
||||||
mutableSendDataFlow.value = DataState.Pending(sendData)
|
mutableSendDataFlow.value = DataState.Pending(sendData)
|
||||||
|
@ -236,12 +252,14 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||||
private fun createViewModel(
|
private fun createViewModel(
|
||||||
state: SendState? = null,
|
state: SendState? = null,
|
||||||
bitwardenClipboardManager: BitwardenClipboardManager = clipboardManager,
|
bitwardenClipboardManager: BitwardenClipboardManager = clipboardManager,
|
||||||
|
environmentRepository: EnvironmentRepository = environmentRepo,
|
||||||
vaultRepository: VaultRepository = vaultRepo,
|
vaultRepository: VaultRepository = vaultRepo,
|
||||||
): SendViewModel = SendViewModel(
|
): SendViewModel = SendViewModel(
|
||||||
savedStateHandle = SavedStateHandle().apply {
|
savedStateHandle = SavedStateHandle().apply {
|
||||||
set("state", state)
|
set("state", state)
|
||||||
},
|
},
|
||||||
clipboardManager = bitwardenClipboardManager,
|
clipboardManager = bitwardenClipboardManager,
|
||||||
|
environmentRepo = environmentRepository,
|
||||||
vaultRepo = vaultRepository,
|
vaultRepo = vaultRepository,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@ import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSendView
|
||||||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||||
import com.x8bit.bitwarden.ui.tools.feature.send.SendState
|
import com.x8bit.bitwarden.ui.tools.feature.send.SendState
|
||||||
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendStatusIcon
|
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendStatusIcon
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockkStatic
|
||||||
|
import io.mockk.unmockkStatic
|
||||||
import org.junit.jupiter.api.AfterEach
|
import org.junit.jupiter.api.AfterEach
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
@ -17,32 +20,40 @@ class SendDataExtensionsTest {
|
||||||
fun setup() {
|
fun setup() {
|
||||||
// Setting the timezone so the tests pass consistently no matter the environment.
|
// Setting the timezone so the tests pass consistently no matter the environment.
|
||||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
|
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
|
||||||
|
mockkStatic(SEND_VIEW_EXTENSIONS_PATH)
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
fun tearDown() {
|
fun tearDown() {
|
||||||
// Clearing the timezone after the test.
|
// Clearing the timezone after the test.
|
||||||
TimeZone.setDefault(null)
|
TimeZone.setDefault(null)
|
||||||
|
unmockkStatic(SEND_VIEW_EXTENSIONS_PATH)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `toViewState should return Empty when SendData is empty`() {
|
fun `toViewState should return Empty when SendData is empty`() {
|
||||||
val sendData = SendData(emptyList())
|
val sendData = SendData(emptyList())
|
||||||
|
|
||||||
val result = sendData.toViewState()
|
val result = sendData.toViewState(DEFAULT_BASE_URL)
|
||||||
|
|
||||||
assertEquals(SendState.ViewState.Empty, result)
|
assertEquals(SendState.ViewState.Empty, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `toViewState should return Content when SendData is not empty`() {
|
fun `toViewState should return Content when SendData is not empty`() {
|
||||||
|
val textSendView = createMockSendView(number = 2, type = SendType.TEXT)
|
||||||
|
val fileSendView = createMockSendView(number = 1, type = SendType.FILE)
|
||||||
val list = listOf(
|
val list = listOf(
|
||||||
createMockSendView(number = 2, type = SendType.TEXT),
|
textSendView,
|
||||||
createMockSendView(number = 1, type = SendType.FILE),
|
fileSendView,
|
||||||
)
|
)
|
||||||
|
val textSendViewUrl1 = "www.test.com/#/send/mockAccessId-1/mockKey-1"
|
||||||
|
val textSendViewUrl2 = "www.test.com/#/send/mockAccessId-2/mockKey-2"
|
||||||
val sendData = SendData(list)
|
val sendData = SendData(list)
|
||||||
|
every { textSendView.toSendUrl(DEFAULT_BASE_URL) } returns textSendViewUrl2
|
||||||
|
every { fileSendView.toSendUrl(DEFAULT_BASE_URL) } returns textSendViewUrl1
|
||||||
|
|
||||||
val result = sendData.toViewState()
|
val result = sendData.toViewState(DEFAULT_BASE_URL)
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
SendState.ViewState.Content(
|
SendState.ViewState.Content(
|
||||||
|
@ -60,6 +71,7 @@ class SendDataExtensionsTest {
|
||||||
SendStatusIcon.EXPIRED,
|
SendStatusIcon.EXPIRED,
|
||||||
SendStatusIcon.PENDING_DELETE,
|
SendStatusIcon.PENDING_DELETE,
|
||||||
),
|
),
|
||||||
|
shareUrl = "www.test.com/#/send/mockAccessId-1/mockKey-1",
|
||||||
),
|
),
|
||||||
SendState.ViewState.Content.SendItem(
|
SendState.ViewState.Content.SendItem(
|
||||||
id = "mockId-2",
|
id = "mockId-2",
|
||||||
|
@ -72,6 +84,7 @@ class SendDataExtensionsTest {
|
||||||
SendStatusIcon.EXPIRED,
|
SendStatusIcon.EXPIRED,
|
||||||
SendStatusIcon.PENDING_DELETE,
|
SendStatusIcon.PENDING_DELETE,
|
||||||
),
|
),
|
||||||
|
shareUrl = "www.test.com/#/send/mockAccessId-2/mockKey-2",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -79,3 +92,8 @@ class SendDataExtensionsTest {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val SEND_VIEW_EXTENSIONS_PATH: String =
|
||||||
|
"com.x8bit.bitwarden.ui.tools.feature.send.util.SendViewExtensionsKt"
|
||||||
|
|
||||||
|
private const val DEFAULT_BASE_URL: String = "www.test.com/"
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.x8bit.bitwarden.ui.tools.feature.send.util
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSendView
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class SendViewTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `toSendUrl should create an appropriate url`() {
|
||||||
|
val sendView = createMockSendView(number = 1)
|
||||||
|
|
||||||
|
val result = sendView.toSendUrl(baseWebSendUrl = "www.test.com/")
|
||||||
|
|
||||||
|
assertEquals("www.test.com/mockAccessId-1/mockKey-1", result)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue