blob: 6c86911917cd7aa84fce56f06f8e69e7f48498c8 [file] [log] [blame]
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.credentials.provider.ui
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Icon
import android.os.Bundle
import androidx.core.os.BuildCompat
import androidx.credentials.PasswordCredential
import androidx.credentials.R
import androidx.credentials.equals
import androidx.credentials.provider.BeginGetPasswordOption
import androidx.credentials.provider.PasswordCredentialEntry
import androidx.credentials.provider.PasswordCredentialEntry.Companion.fromSlice
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import java.time.Instant
import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertNotNull
import org.junit.Assert.assertThrows
import org.junit.Test
import org.junit.runner.RunWith
@SdkSuppress(minSdkVersion = 34, codeName = "UpsideDownCake")
@RunWith(AndroidJUnit4::class)
@SmallTest
class PasswordCredentialEntryTest {
private val mContext = ApplicationProvider.getApplicationContext<Context>()
private val mIntent = Intent()
private val mPendingIntent = PendingIntent.getActivity(
mContext, 0, mIntent,
PendingIntent.FLAG_IMMUTABLE
)
@Test
fun constructor_requiredParams_success() {
if (!BuildCompat.isAtLeastU()) {
return
}
val entry = constructEntryWithRequiredParamsOnly()
assertNotNull(entry)
assertNotNull(entry.slice)
assertThat(entry.type).isEqualTo(PasswordCredential.TYPE_PASSWORD_CREDENTIAL)
assertEntryWithRequiredParamsOnly(entry)
}
@Test
fun constructor_allParams_success() {
if (!BuildCompat.isAtLeastU()) {
return
}
val entry = constructEntryWithAllParams()
assertNotNull(entry)
assertNotNull(entry.slice)
assertThat(entry.type).isEqualTo(PasswordCredential.TYPE_PASSWORD_CREDENTIAL)
assertEntryWithAllParams(entry)
}
@Test
fun constructor_emptyUsername_throwsIAE() {
if (!BuildCompat.isAtLeastU()) {
return
}
assertThrows(
"Expected empty username to throw IllegalArgumentException",
IllegalArgumentException::class.java
) {
PasswordCredentialEntry(
mContext, "", mPendingIntent, BEGIN_OPTION
)
}
}
@Test
fun constructor_nullIcon_defaultIconSet() {
if (!BuildCompat.isAtLeastU()) {
return
}
val entry = PasswordCredentialEntry.Builder(
mContext, USERNAME, mPendingIntent, BEGIN_OPTION).build()
assertThat(
equals(
entry.icon,
Icon.createWithResource(mContext, R.drawable.ic_password)
)
).isTrue()
}
@Test
fun constructor_nullTypeDisplayName_defaultDisplayNameSet() {
if (!BuildCompat.isAtLeastU()) {
return
}
val entry = PasswordCredentialEntry(
mContext, USERNAME, mPendingIntent, BEGIN_OPTION)
assertThat(entry.typeDisplayName).isEqualTo(
mContext.getString(
R.string.android_credentials_TYPE_PASSWORD_CREDENTIAL
)
)
}
@Test
fun constructor_isAutoSelectAllowedDefault_false() {
if (!BuildCompat.isAtLeastU()) {
return
}
val entry = constructEntryWithRequiredParamsOnly()
val entry1 = constructEntryWithAllParams()
assertFalse(entry.isAutoSelectAllowed)
assertFalse(entry1.isAutoSelectAllowed)
}
@Test
fun fromSlice_success() {
if (!BuildCompat.isAtLeastU()) {
return
}
val originalEntry = constructEntryWithAllParams()
val entry = fromSlice(originalEntry.slice)
assertNotNull(entry)
entry?.let {
assertEntryWithAllParams(entry)
}
}
private fun constructEntryWithRequiredParamsOnly(): PasswordCredentialEntry {
return PasswordCredentialEntry(
mContext,
USERNAME,
mPendingIntent,
BEGIN_OPTION
)
}
private fun constructEntryWithAllParams(): PasswordCredentialEntry {
return PasswordCredentialEntry(
mContext,
USERNAME,
mPendingIntent,
BEGIN_OPTION,
DISPLAYNAME,
LAST_USED_TIME,
ICON
)
}
private fun assertEntryWithRequiredParamsOnly(entry: PasswordCredentialEntry) {
assertThat(USERNAME == entry.username)
assertThat(mPendingIntent).isEqualTo(entry.pendingIntent)
}
private fun assertEntryWithAllParams(entry: PasswordCredentialEntry) {
assertThat(USERNAME == entry.username)
assertThat(DISPLAYNAME == entry.displayName)
assertThat(TYPE_DISPLAY_NAME == entry.typeDisplayName)
assertThat(ICON).isEqualTo(entry.icon)
assertNotNull(entry.lastUsedTime)
entry.lastUsedTime?.let {
assertThat(LAST_USED_TIME.toEpochMilli()).isEqualTo(
it.toEpochMilli())
}
assertThat(mPendingIntent).isEqualTo(entry.pendingIntent)
}
companion object {
private val USERNAME: CharSequence = "title"
private val DISPLAYNAME: CharSequence = "subtitle"
private val TYPE_DISPLAY_NAME: CharSequence = "Password"
private val LAST_USED_TIME = Instant.now()
private val BEGIN_OPTION = BeginGetPasswordOption(
emptySet<String>(),
Bundle.EMPTY, "id")
private val ICON = Icon.createWithBitmap(
Bitmap.createBitmap(
100, 100, Bitmap.Config.ARGB_8888
)
)
}
}