mirror of
https://github.com/bitwarden/android.git
synced 2026-05-30 07:44:15 -05:00
Add support to copy a send url to the clipboard (#508)
This commit is contained in:
@@ -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.platform.repository.model.Environment
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNull
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
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
|
||||
fun `labelOrBaseUrlHost should correctly convert US environment to the correct label`() {
|
||||
val environment = EnvironmentUrlDataJson.DEFAULT_US
|
||||
@@ -52,20 +129,11 @@ class EnvironmentUrlsDataJsonExtensionsTest {
|
||||
|
||||
@Test
|
||||
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(
|
||||
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
|
||||
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(
|
||||
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",
|
||||
type = SendState.ViewState.Content.SendItem.Type.FILE,
|
||||
iconList = emptyList(),
|
||||
shareUrl = "www.test.com/#/send/mockAccessId-1/mockKey-1",
|
||||
)
|
||||
|
||||
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",
|
||||
type = SendState.ViewState.Content.SendItem.Type.TEXT,
|
||||
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 com.x8bit.bitwarden.R
|
||||
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.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.model.SendData
|
||||
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 clipboardManager: BitwardenClipboardManager = mockk()
|
||||
private val environmentRepo: EnvironmentRepository = mockk {
|
||||
every { environment } returns Environment.Us
|
||||
}
|
||||
private val vaultRepo: VaultRepository = mockk {
|
||||
every { sendDataStateFlow } returns mutableSendDataFlow
|
||||
}
|
||||
@@ -114,12 +120,18 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `CopyClick should emit ShowToast`() = runTest {
|
||||
fun `CopyClick should call setText on the ClipboardManager`() {
|
||||
val viewModel = createViewModel()
|
||||
val sendItem = mockk<SendState.ViewState.Content.SendItem>()
|
||||
viewModel.eventFlow.test {
|
||||
viewModel.trySendAction(SendAction.CopyClick(sendItem))
|
||||
assertEquals(SendEvent.ShowToast("Not yet implemented".asText()), awaitItem())
|
||||
val testUrl = "www.test.com/"
|
||||
val sendItem = mockk<SendState.ViewState.Content.SendItem> {
|
||||
every { shareUrl } returns testUrl
|
||||
}
|
||||
every { clipboardManager.setText(testUrl) } just runs
|
||||
|
||||
viewModel.trySendAction(SendAction.CopyClick(sendItem))
|
||||
|
||||
verify(exactly = 1) {
|
||||
clipboardManager.setText(testUrl)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +194,9 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
val viewModel = createViewModel()
|
||||
val viewState = mockk<SendState.ViewState.Content>()
|
||||
val sendData = mockk<SendData> {
|
||||
every { toViewState() } returns viewState
|
||||
every {
|
||||
toViewState(Environment.Us.environmentUrlData.baseWebSendUrl)
|
||||
} returns viewState
|
||||
}
|
||||
|
||||
mutableSendDataFlow.value = DataState.Loaded(sendData)
|
||||
@@ -225,7 +239,9 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
val viewModel = createViewModel()
|
||||
val viewState = mockk<SendState.ViewState.Content>()
|
||||
val sendData = mockk<SendData> {
|
||||
every { toViewState() } returns viewState
|
||||
every {
|
||||
toViewState(Environment.Us.environmentUrlData.baseWebSendUrl)
|
||||
} returns viewState
|
||||
}
|
||||
|
||||
mutableSendDataFlow.value = DataState.Pending(sendData)
|
||||
@@ -236,12 +252,14 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
private fun createViewModel(
|
||||
state: SendState? = null,
|
||||
bitwardenClipboardManager: BitwardenClipboardManager = clipboardManager,
|
||||
environmentRepository: EnvironmentRepository = environmentRepo,
|
||||
vaultRepository: VaultRepository = vaultRepo,
|
||||
): SendViewModel = SendViewModel(
|
||||
savedStateHandle = SavedStateHandle().apply {
|
||||
set("state", state)
|
||||
},
|
||||
clipboardManager = bitwardenClipboardManager,
|
||||
environmentRepo = environmentRepository,
|
||||
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.ui.tools.feature.send.SendState
|
||||
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.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
@@ -17,32 +20,40 @@ class SendDataExtensionsTest {
|
||||
fun setup() {
|
||||
// Setting the timezone so the tests pass consistently no matter the environment.
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
|
||||
mockkStatic(SEND_VIEW_EXTENSIONS_PATH)
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
// Clearing the timezone after the test.
|
||||
TimeZone.setDefault(null)
|
||||
unmockkStatic(SEND_VIEW_EXTENSIONS_PATH)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toViewState should return Empty when SendData is empty`() {
|
||||
val sendData = SendData(emptyList())
|
||||
|
||||
val result = sendData.toViewState()
|
||||
val result = sendData.toViewState(DEFAULT_BASE_URL)
|
||||
|
||||
assertEquals(SendState.ViewState.Empty, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
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(
|
||||
createMockSendView(number = 2, type = SendType.TEXT),
|
||||
createMockSendView(number = 1, type = SendType.FILE),
|
||||
textSendView,
|
||||
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)
|
||||
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(
|
||||
SendState.ViewState.Content(
|
||||
@@ -60,6 +71,7 @@ class SendDataExtensionsTest {
|
||||
SendStatusIcon.EXPIRED,
|
||||
SendStatusIcon.PENDING_DELETE,
|
||||
),
|
||||
shareUrl = "www.test.com/#/send/mockAccessId-1/mockKey-1",
|
||||
),
|
||||
SendState.ViewState.Content.SendItem(
|
||||
id = "mockId-2",
|
||||
@@ -72,6 +84,7 @@ class SendDataExtensionsTest {
|
||||
SendStatusIcon.EXPIRED,
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user