BIT-1315: Add dummy data fulfillment (#602)

This commit is contained in:
Lucas Kivi 2024-01-13 15:51:38 -06:00 committed by Álison Fernandes
parent 5d73f97831
commit 67d7b7a9f5
16 changed files with 522 additions and 50 deletions

View file

@ -1,37 +1,52 @@
package com.x8bit.bitwarden.data.autofill.builder
import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
import com.x8bit.bitwarden.data.autofill.model.AutofillPartition
import com.x8bit.bitwarden.data.autofill.model.AutofillRequest
import com.x8bit.bitwarden.data.autofill.model.AutofillView
import com.x8bit.bitwarden.data.autofill.model.FilledData
import com.x8bit.bitwarden.data.autofill.model.FilledItem
import com.x8bit.bitwarden.data.autofill.model.FilledPartition
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProvider
import com.x8bit.bitwarden.data.autofill.util.buildFilledItemOrNull
/**
* The default [FilledDataBuilder]. This converts parsed autofill data into filled data that is
* ready to be loaded into an autofill response.
*/
class FilledDataBuilderImpl : FilledDataBuilder {
class FilledDataBuilderImpl(
private val autofillCipherProvider: AutofillCipherProvider,
) : FilledDataBuilder {
override suspend fun build(autofillRequest: AutofillRequest.Fillable): FilledData {
// TODO: determine whether or not the vault is locked (BIT-1296)
val filledPartitions = when (autofillRequest.partition) {
is AutofillPartition.Card -> {
// TODO: perform fulfillment with dummy data (BIT-1315)
listOf(
fillCardPartition(
autofillViews = autofillRequest.partition.views,
),
)
autofillCipherProvider
.getCardAutofillCiphers()
.map { autofillCipher ->
fillCardPartition(
autofillCipher = autofillCipher,
autofillViews = autofillRequest.partition.views,
)
}
}
is AutofillPartition.Login -> {
// TODO: perform fulfillment with dummy data (BIT-1315)
listOf(
fillLoginPartition(
autofillViews = autofillRequest.partition.views,
),
)
autofillRequest
.uri
?.let { nonNullUri ->
autofillCipherProvider
.getLoginAutofillCiphers(
uri = nonNullUri,
)
.map { autofillCipher ->
fillLoginPartition(
autofillCipher = autofillCipher,
autofillViews = autofillRequest.partition.views,
)
}
}
?: emptyList()
}
}
@ -42,37 +57,56 @@ class FilledDataBuilderImpl : FilledDataBuilder {
}
/**
* Construct a [FilledPartition] by fulfilling the card [autofillViews] with data.
* Construct a [FilledPartition] by fulfilling the card [autofillViews] with data from the
* card [autofillCipher].
*/
private fun fillCardPartition(
autofillCipher: AutofillCipher.Card,
autofillViews: List<AutofillView.Card>,
): FilledPartition {
val filledItems = autofillViews
.map { autofillView ->
FilledItem(
autofillId = autofillView.data.autofillId,
val value = when (autofillView) {
is AutofillView.Card.ExpirationMonth -> autofillCipher.expirationMonth
is AutofillView.Card.ExpirationYear -> autofillCipher.expirationYear
is AutofillView.Card.Number -> autofillCipher.number
is AutofillView.Card.SecurityCode -> autofillCipher.code
}
autofillView.buildFilledItemOrNull(
value = value,
)
}
return FilledPartition(
autofillCipher = autofillCipher,
filledItems = filledItems,
)
}
/**
* Construct a [FilledPartition] by fulfilling the login [autofillViews] with data.
* Construct a [FilledPartition] by fulfilling the login [autofillViews] with data from the
* login [autofillCipher].
*/
private fun fillLoginPartition(
autofillCipher: AutofillCipher.Login,
autofillViews: List<AutofillView.Login>,
): FilledPartition {
val filledItems = autofillViews
.map { autofillView ->
FilledItem(
autofillId = autofillView.data.autofillId,
val value = when (autofillView) {
is AutofillView.Login.EmailAddress,
is AutofillView.Login.Username,
-> autofillCipher.username
is AutofillView.Login.Password -> autofillCipher.password
}
autofillView.buildFilledItemOrNull(
value = value,
)
}
return FilledPartition(
autofillCipher = autofillCipher,
filledItems = filledItems,
)
}

View file

@ -8,6 +8,8 @@ import com.x8bit.bitwarden.data.autofill.parser.AutofillParser
import com.x8bit.bitwarden.data.autofill.parser.AutofillParserImpl
import com.x8bit.bitwarden.data.autofill.processor.AutofillProcessor
import com.x8bit.bitwarden.data.autofill.processor.AutofillProcessorImpl
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProvider
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProviderImpl
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
import dagger.Module
import dagger.Provides
@ -23,6 +25,9 @@ object AutofillModule {
@Provides
fun providesAutofillParser(): AutofillParser = AutofillParserImpl()
@Provides
fun providesAutofillCipherProvider(): AutofillCipherProvider = AutofillCipherProviderImpl()
@Provides
fun providesAutofillProcessor(
dispatcherManager: DispatcherManager,
@ -38,7 +43,11 @@ object AutofillModule {
)
@Provides
fun providesFillDataBuilder(): FilledDataBuilder = FilledDataBuilderImpl()
fun providesFillDataBuilder(
autofillCipherProvider: AutofillCipherProvider,
): FilledDataBuilder = FilledDataBuilderImpl(
autofillCipherProvider = autofillCipherProvider,
)
@Provides
fun providesFillResponseBuilder(): FillResponseBuilder = FillResponseBuilderImpl()

View file

@ -0,0 +1,41 @@
package com.x8bit.bitwarden.data.autofill.model
/**
* A paired down model of the CipherView for use within the autofill feature.
*/
sealed class AutofillCipher {
/**
* The name of the cipher.
*/
abstract val name: String
/**
* The subtitle for giving additional context to the cipher.
*/
abstract val subtitle: String
/**
* The card [AutofillCipher] model. This contains all of the data for building fulfilling a card
* partition.
*/
data class Card(
override val name: String,
override val subtitle: String,
val cardholderName: String,
val code: String,
val expirationMonth: String,
val expirationYear: String,
val number: String,
) : AutofillCipher()
/**
* The card [AutofillCipher] model. This contains all of the data for building fulfilling a
* login partition.
*/
data class Login(
override val name: String,
override val subtitle: String,
val password: String,
val username: String,
) : AutofillCipher()
}

View file

@ -1,6 +1,7 @@
package com.x8bit.bitwarden.data.autofill.model
import android.view.autofill.AutofillId
import android.view.autofill.AutofillValue
/**
* A fulfilled autofill view. This contains everything required to build the autofill UI
@ -8,4 +9,5 @@ import android.view.autofill.AutofillId
*/
data class FilledItem(
val autofillId: AutofillId,
val value: AutofillValue,
)

View file

@ -1,11 +1,13 @@
package com.x8bit.bitwarden.data.autofill.model
/**
* All of the data required to build a `Dataset` for fulfilling a partition of data based on a
* cipher.
* All of the data required to build a `Dataset` for fulfilling a partition of data based on an
* [AutofillCipher].
*
* @param autofillCipher The cipher used to fulfill these [filledItems].
* @param filledItems A filled copy of each view from this partition.
*/
data class FilledPartition(
val autofillCipher: AutofillCipher,
val filledItems: List<FilledItem>,
)

View file

@ -0,0 +1,20 @@
package com.x8bit.bitwarden.data.autofill.provider
import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
/**
* A service for getting [AutofillCipher]s.
*/
interface AutofillCipherProvider {
/**
* Get all [AutofillCipher.Card]s for the current user.
*/
suspend fun getCardAutofillCiphers(): List<AutofillCipher.Card>
/**
* Get all [AutofillCipher.Login]s for the current user.
*/
suspend fun getLoginAutofillCiphers(
uri: String,
): List<AutofillCipher.Login>
}

View file

@ -0,0 +1,56 @@
package com.x8bit.bitwarden.data.autofill.provider
import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
/**
* The default [AutofillCipherProvider] implementation. This service is used for getting currrent
* [AutofillCipher]s.
*/
class AutofillCipherProviderImpl : AutofillCipherProvider {
override suspend fun getCardAutofillCiphers(): List<AutofillCipher.Card> {
// TODO: fulfill with real ciphers (BIT-1294)
return cardCiphers
}
override suspend fun getLoginAutofillCiphers(
uri: String,
): List<AutofillCipher.Login> {
// TODO: fulfill with real ciphers (BIT-1294)
return loginCiphers
}
}
private val cardCiphers = listOf(
AutofillCipher.Card(
cardholderName = "John",
code = "123",
expirationMonth = "January",
expirationYear = "1999",
name = "John",
number = "1234567890",
subtitle = "123...",
),
AutofillCipher.Card(
cardholderName = "Doe",
code = "456",
expirationMonth = "December",
expirationYear = "2024",
name = "Doe",
number = "0987654321",
subtitle = "098...",
),
)
private val loginCiphers = listOf(
AutofillCipher.Login(
name = "Bitwarden1",
password = "password123",
subtitle = "John-Bitwarden",
username = "John-Bitwarden",
),
AutofillCipher.Login(
name = "Bitwarden2",
password = "password123",
subtitle = "Doe-Bitwarden",
username = "Doe-Bitwarden",
),
)

View file

@ -0,0 +1,17 @@
package com.x8bit.bitwarden.data.autofill.util
import android.view.autofill.AutofillValue
import com.x8bit.bitwarden.data.autofill.model.AutofillView
import com.x8bit.bitwarden.data.autofill.model.FilledItem
/**
* Convert this [AutofillView] into a [FilledItem].
*/
fun AutofillView.buildFilledItemOrNull(
value: String,
): FilledItem =
// TODO: handle other autofill types (BIT-1457)
FilledItem(
autofillId = data.autofillId,
value = AutofillValue.forText(value),
)

View file

@ -19,6 +19,7 @@ fun FilledItem.applyToDatasetPostTiramisu(
datasetBuilder.setField(
autofillId,
Field.Builder()
.setValue(value)
.setPresentations(presentations)
.build(),
)
@ -35,7 +36,7 @@ fun FilledItem.applyToDatasetPreTiramisu(
) {
datasetBuilder.setValue(
autofillId,
null,
value,
remoteViews,
)
}

View file

@ -5,7 +5,6 @@ import android.os.Build
import android.service.autofill.Dataset
import android.service.autofill.Presentations
import android.widget.RemoteViews
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
import com.x8bit.bitwarden.data.autofill.model.FilledPartition
import com.x8bit.bitwarden.ui.autofill.buildAutofillRemoteViews
@ -19,7 +18,7 @@ fun FilledPartition.buildDataset(
): Dataset {
val remoteViewsPlaceholder = buildAutofillRemoteViews(
packageName = autofillAppInfo.packageName,
title = autofillAppInfo.context.resources.getString(R.string.app_name),
title = autofillCipher.name,
)
val datasetBuilder = Dataset.Builder()

View file

@ -74,6 +74,7 @@ class FillResponseBuilderTest {
fun `build should return null when filledPartitions contains no views`() {
// Test
val filledPartitions = FilledPartition(
autofillCipher = mockk(),
filledItems = emptyList(),
)
val filledData = FilledData(

View file

@ -1,14 +1,25 @@
package com.x8bit.bitwarden.data.autofill.builder
import android.view.autofill.AutofillId
import android.view.autofill.AutofillValue
import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
import com.x8bit.bitwarden.data.autofill.model.AutofillPartition
import com.x8bit.bitwarden.data.autofill.model.AutofillRequest
import com.x8bit.bitwarden.data.autofill.model.AutofillView
import com.x8bit.bitwarden.data.autofill.model.FilledData
import com.x8bit.bitwarden.data.autofill.model.FilledItem
import com.x8bit.bitwarden.data.autofill.model.FilledPartition
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProvider
import com.x8bit.bitwarden.data.autofill.util.buildFilledItemOrNull
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import io.mockk.verify
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@ -16,6 +27,8 @@ import org.junit.jupiter.api.Test
class FilledDataBuilderTest {
private lateinit var filledDataBuilder: FilledDataBuilder
private val autofillCipherProvider: AutofillCipherProvider = mockk()
private val autofillId: AutofillId = mockk()
private val autofillViewData = AutofillView.Data(
autofillId = autofillId,
@ -27,17 +40,45 @@ class FilledDataBuilderTest {
@BeforeEach
fun setup() {
filledDataBuilder = FilledDataBuilderImpl()
mockkStatic(AutofillValue::forText)
mockkStatic(AutofillView::buildFilledItemOrNull)
filledDataBuilder = FilledDataBuilderImpl(
autofillCipherProvider = autofillCipherProvider,
)
}
@AfterEach
fun teardown() {
unmockkStatic(AutofillValue::forText)
unmockkStatic(AutofillView::buildFilledItemOrNull)
}
@Test
fun `build should return filled data and ignored AutofillIds when Login`() = runTest {
// Setup
val autofillView = AutofillView.Login.Username(
val password = "Password"
val username = "johnDoe"
val autofillCipher = AutofillCipher.Login(
name = "Cipher One",
password = password,
username = username,
subtitle = "Subtitle",
)
val autofillViewEmail = AutofillView.Login.EmailAddress(
data = autofillViewData,
)
val autofillViewPassword = AutofillView.Login.Password(
data = autofillViewData,
)
val autofillViewUsername = AutofillView.Login.Username(
data = autofillViewData,
)
val autofillPartition = AutofillPartition.Login(
views = listOf(autofillView),
views = listOf(
autofillViewEmail,
autofillViewPassword,
autofillViewUsername,
),
)
val ignoreAutofillIds: List<AutofillId> = mockk()
val autofillRequest = AutofillRequest.Fillable(
@ -45,12 +86,15 @@ class FilledDataBuilderTest {
partition = autofillPartition,
uri = URI,
)
val filledItem = FilledItem(
autofillId = autofillId,
)
val filledItemEmail: FilledItem = mockk()
val filledItemPassword: FilledItem = mockk()
val filledItemUsername: FilledItem = mockk()
val filledPartition = FilledPartition(
autofillCipher = autofillCipher,
filledItems = listOf(
filledItem,
filledItemEmail,
filledItemPassword,
filledItemUsername,
),
)
val expected = FilledData(
@ -59,6 +103,14 @@ class FilledDataBuilderTest {
),
ignoreAutofillIds = ignoreAutofillIds,
)
coEvery {
autofillCipherProvider.getLoginAutofillCiphers(
uri = URI,
)
} returns listOf(autofillCipher)
every { autofillViewEmail.buildFilledItemOrNull(username) } returns filledItemEmail
every { autofillViewPassword.buildFilledItemOrNull(password) } returns filledItemPassword
every { autofillViewUsername.buildFilledItemOrNull(username) } returns filledItemUsername
// Test
val actual = filledDataBuilder.build(
@ -67,16 +119,93 @@ class FilledDataBuilderTest {
// Verify
assertEquals(expected, actual)
coVerify(exactly = 1) {
autofillCipherProvider.getLoginAutofillCiphers(
uri = URI,
)
}
verify(exactly = 1) {
autofillViewEmail.buildFilledItemOrNull(username)
autofillViewPassword.buildFilledItemOrNull(password)
autofillViewUsername.buildFilledItemOrNull(username)
}
}
@Test
fun `build should return no partitions and ignored AutofillIds when Login and no URI`() =
runTest {
// Setup
val autofillViewEmail = AutofillView.Login.EmailAddress(
data = autofillViewData,
)
val autofillViewPassword = AutofillView.Login.Password(
data = autofillViewData,
)
val autofillViewUsername = AutofillView.Login.Username(
data = autofillViewData,
)
val autofillPartition = AutofillPartition.Login(
views = listOf(
autofillViewEmail,
autofillViewPassword,
autofillViewUsername,
),
)
val ignoreAutofillIds: List<AutofillId> = mockk()
val autofillRequest = AutofillRequest.Fillable(
ignoreAutofillIds = ignoreAutofillIds,
partition = autofillPartition,
uri = null,
)
val expected = FilledData(
filledPartitions = emptyList(),
ignoreAutofillIds = ignoreAutofillIds,
)
// Test
val actual = filledDataBuilder.build(
autofillRequest = autofillRequest,
)
// Verify
assertEquals(expected, actual)
}
@Test
fun `build should return filled data and ignored AutofillIds when Card`() = runTest {
// Setup
val autofillView = AutofillView.Card.Number(
val code = "123"
val expirationMonth = "January"
val expirationYear = "1999"
val number = "1234567890"
val autofillCipher = AutofillCipher.Card(
cardholderName = "John",
code = code,
expirationMonth = expirationMonth,
expirationYear = expirationYear,
name = "Cipher One",
number = number,
subtitle = "Subtitle",
)
val autofillViewCode = AutofillView.Card.SecurityCode(
data = autofillViewData,
)
val autofillViewExpirationMonth = AutofillView.Card.ExpirationMonth(
data = autofillViewData,
)
val autofillViewExpirationYear = AutofillView.Card.ExpirationYear(
data = autofillViewData,
)
val autofillViewNumber = AutofillView.Card.Number(
data = autofillViewData,
)
val autofillPartition = AutofillPartition.Card(
views = listOf(autofillView),
views = listOf(
autofillViewCode,
autofillViewExpirationMonth,
autofillViewExpirationYear,
autofillViewNumber,
),
)
val ignoreAutofillIds: List<AutofillId> = mockk()
val autofillRequest = AutofillRequest.Fillable(
@ -84,12 +213,17 @@ class FilledDataBuilderTest {
partition = autofillPartition,
uri = URI,
)
val filledItem = FilledItem(
autofillId = autofillId,
)
val filledItemCode: FilledItem = mockk()
val filledItemExpirationMonth: FilledItem = mockk()
val filledItemExpirationYear: FilledItem = mockk()
val filledItemNumber: FilledItem = mockk()
val filledPartition = FilledPartition(
autofillCipher = autofillCipher,
filledItems = listOf(
filledItem,
filledItemCode,
filledItemExpirationMonth,
filledItemExpirationYear,
filledItemNumber,
),
)
val expected = FilledData(
@ -98,6 +232,15 @@ class FilledDataBuilderTest {
),
ignoreAutofillIds = ignoreAutofillIds,
)
coEvery { autofillCipherProvider.getCardAutofillCiphers() } returns listOf(autofillCipher)
every { autofillViewCode.buildFilledItemOrNull(code) } returns filledItemCode
every {
autofillViewExpirationMonth.buildFilledItemOrNull(expirationMonth)
} returns filledItemExpirationMonth
every {
autofillViewExpirationYear.buildFilledItemOrNull(expirationYear)
} returns filledItemExpirationYear
every { autofillViewNumber.buildFilledItemOrNull(number) } returns filledItemNumber
// Test
val actual = filledDataBuilder.build(
@ -106,6 +249,13 @@ class FilledDataBuilderTest {
// Verify
assertEquals(expected, actual)
coVerify(exactly = 1) {
autofillCipherProvider.getCardAutofillCiphers()
autofillViewCode.buildFilledItemOrNull(code)
autofillViewExpirationMonth.buildFilledItemOrNull(expirationMonth)
autofillViewExpirationYear.buildFilledItemOrNull(expirationYear)
autofillViewNumber.buildFilledItemOrNull(number)
}
}
companion object {

View file

@ -0,0 +1,72 @@
package com.x8bit.bitwarden.data.autofill.processor
import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProvider
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProviderImpl
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class AutofillCipherProviderTest {
private lateinit var autofillCipherProvider: AutofillCipherProvider
@BeforeEach
fun setup() {
autofillCipherProvider = AutofillCipherProviderImpl()
}
@Test
fun `getCardAutofillCiphers should return default list of card ciphers`() = runTest {
// Test & Verify
val actual = autofillCipherProvider.getCardAutofillCiphers()
assertEquals(CARD_CIPHERS, actual)
}
@Test
fun `getLoginAutofillCiphers should return default list of login ciphers`() = runTest {
// Test & Verify
val actual = autofillCipherProvider.getLoginAutofillCiphers(
uri = URI,
)
assertEquals(LOGIN_CIPHERS, actual)
}
}
private val CARD_CIPHERS = listOf(
AutofillCipher.Card(
cardholderName = "John",
code = "123",
expirationMonth = "January",
expirationYear = "1999",
name = "John",
number = "1234567890",
subtitle = "123...",
),
AutofillCipher.Card(
cardholderName = "Doe",
code = "456",
expirationMonth = "December",
expirationYear = "2024",
name = "Doe",
number = "0987654321",
subtitle = "098...",
),
)
private val LOGIN_CIPHERS = listOf(
AutofillCipher.Login(
name = "Bitwarden1",
password = "password123",
subtitle = "John-Bitwarden",
username = "John-Bitwarden",
),
AutofillCipher.Login(
name = "Bitwarden2",
password = "password123",
subtitle = "Doe-Bitwarden",
username = "Doe-Bitwarden",
),
)
private const val URI: String = "androidapp://com.x8bit.bitwarden"

View file

@ -0,0 +1,62 @@
package com.x8bit.bitwarden.data.autofill.util
import android.view.autofill.AutofillId
import android.view.autofill.AutofillValue
import com.x8bit.bitwarden.data.autofill.model.AutofillView
import com.x8bit.bitwarden.data.autofill.model.FilledItem
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import io.mockk.verify
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class AutofillViewExtensionsTest {
private val autofillId: AutofillId = mockk()
private val autofillValue: AutofillValue = mockk()
private val autofillViewData = AutofillView.Data(
autofillId = autofillId,
idPackage = null,
isFocused = false,
webDomain = null,
webScheme = null,
)
@BeforeEach
fun setup() {
mockkStatic(AutofillValue::forText)
}
@AfterEach
fun teardown() {
unmockkStatic(AutofillValue::forText)
}
@Test
fun `buildFilledItem returns AutofillValue`() {
// Setup
val value = "2002421451023587L"
val autofillView = AutofillView.Card.Number(
data = autofillViewData,
)
val expected = FilledItem(
autofillId = autofillId,
value = autofillValue,
)
every { AutofillValue.forText(value) } returns autofillValue
// Test
val actual = autofillView.buildFilledItemOrNull(
value = value,
)
// Verify
assertEquals(expected, actual)
verify(exactly = 1) {
AutofillValue.forText(value)
}
}
}

View file

@ -4,6 +4,7 @@ import android.service.autofill.Dataset
import android.service.autofill.Field
import android.service.autofill.Presentations
import android.view.autofill.AutofillId
import android.view.autofill.AutofillValue
import android.widget.RemoteViews
import com.x8bit.bitwarden.data.autofill.model.FilledItem
import com.x8bit.bitwarden.data.util.mockBuilder
@ -18,10 +19,12 @@ import org.junit.jupiter.api.Test
class FilledItemExtensionsTest {
private val autofillId: AutofillId = mockk()
private val autofillValue: AutofillValue = mockk()
private val datasetBuilder: Dataset.Builder = mockk()
private val field: Field = mockk()
private val filledItem = FilledItem(
autofillId = autofillId,
value = autofillValue,
)
private val presentations: Presentations = mockk()
private val remoteViews: RemoteViews = mockk()
@ -44,7 +47,7 @@ class FilledItemExtensionsTest {
every {
datasetBuilder.setValue(
autofillId,
null,
autofillValue,
remoteViews,
)
} returns datasetBuilder
@ -59,7 +62,7 @@ class FilledItemExtensionsTest {
verify(exactly = 1) {
datasetBuilder.setValue(
autofillId,
null,
autofillValue,
remoteViews,
)
}
@ -68,6 +71,7 @@ class FilledItemExtensionsTest {
@Test
fun `applyToDatasetPostTiramisu should use setField to set presentations`() {
// Setup
mockBuilder<Field.Builder> { it.setValue(autofillValue) }
mockBuilder<Field.Builder> { it.setPresentations(presentations) }
every {
datasetBuilder.setField(
@ -84,6 +88,7 @@ class FilledItemExtensionsTest {
// Verify
verify(exactly = 1) {
anyConstructed<Field.Builder>().setValue(autofillValue)
anyConstructed<Field.Builder>().setPresentations(presentations)
datasetBuilder.setField(
autofillId,

View file

@ -5,8 +5,8 @@ import android.content.res.Resources
import android.service.autofill.Dataset
import android.service.autofill.Presentations
import android.widget.RemoteViews
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
import com.x8bit.bitwarden.data.autofill.model.FilledItem
import com.x8bit.bitwarden.data.autofill.model.FilledPartition
import com.x8bit.bitwarden.data.util.mockBuilder
@ -26,6 +26,9 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class FilledPartitionExtensionsTest {
private val autofillCipher: AutofillCipher = mockk {
every { this@mockk.name } returns CIPHER_NAME
}
private val res: Resources = mockk()
private val context: Context = mockk {
every { this@mockk.resources } returns res
@ -33,6 +36,7 @@ class FilledPartitionExtensionsTest {
private val dataset: Dataset = mockk()
private val filledItem: FilledItem = mockk()
private val filledPartition = FilledPartition(
autofillCipher = autofillCipher,
filledItems = listOf(
filledItem,
),
@ -67,12 +71,10 @@ class FilledPartitionExtensionsTest {
packageName = PACKAGE_NAME,
sdkInt = 34,
)
val title = "Bitwarden"
every { res.getString(R.string.app_name) } returns title
every {
buildAutofillRemoteViews(
packageName = PACKAGE_NAME,
title = title,
title = CIPHER_NAME,
)
} returns remoteViews
mockBuilder<Presentations.Builder> { it.setMenuPresentation(remoteViews) }
@ -94,7 +96,7 @@ class FilledPartitionExtensionsTest {
verify(exactly = 1) {
buildAutofillRemoteViews(
packageName = PACKAGE_NAME,
title = title,
title = CIPHER_NAME,
)
anyConstructed<Presentations.Builder>().setMenuPresentation(remoteViews)
anyConstructed<Presentations.Builder>().build()
@ -114,12 +116,10 @@ class FilledPartitionExtensionsTest {
packageName = PACKAGE_NAME,
sdkInt = 18,
)
val title = "Bitwarden"
every { res.getString(R.string.app_name) } returns title
every {
buildAutofillRemoteViews(
packageName = PACKAGE_NAME,
title = title,
title = CIPHER_NAME,
)
} returns remoteViews
every {
@ -139,7 +139,7 @@ class FilledPartitionExtensionsTest {
verify(exactly = 1) {
buildAutofillRemoteViews(
packageName = PACKAGE_NAME,
title = title,
title = CIPHER_NAME,
)
filledItem.applyToDatasetPreTiramisu(
datasetBuilder = any(),
@ -150,6 +150,7 @@ class FilledPartitionExtensionsTest {
}
companion object {
private const val CIPHER_NAME: String = "Autofill Cipher"
private const val PACKAGE_NAME: String = "com.x8bit.bitwarden"
}
}