package com.peachpasswords.autofill import com.peachpasswords.vault.VaultEntry import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test class IdentitiesTest { private fun login( id: String, username: String? = null, email: String? = null, url: String? = null, modifiedAt: Long = 100, deleted: Boolean = false, type: String? = "login", ) = VaultEntry( id = id, title = id, username = username, email = email, url = url, createdAt = 0, modifiedAt = modifiedAt, deletedAt = if (deleted) 1L else null, type = type, ) @Test fun usernames_and_emails_are_derived_from_login_entries() { val identities = deriveIdentities( listOf( login("a", username = "june", url = "https://github.com"), login("b", email = "june@fastmail.com", url = "https://fastmail.com"), ), ) assertEquals( listOf( SavedIdentity("june@fastmail.com", IdentityType.EMAIL, 100, 1, "fastmail.com"), SavedIdentity("june", IdentityType.USERNAME, 100, 1, "github.com"), ), identities, ) } @Test fun username_shaped_like_an_email_counts_as_email() { val identities = deriveIdentities(listOf(login("a", username = "june@example.com"))) assertEquals(listOf(SavedIdentity("june@example.com", IdentityType.EMAIL, 100, 1, null)), identities) } @Test fun same_email_across_entries_appears_once_with_use_count() { val identities = deriveIdentities( listOf( login("a", email = "june@fastmail.com", url = "https://one.com", modifiedAt = 10), login("b", username = "june@fastmail.com", url = "https://two.com", modifiedAt = 30), login("c", email = "june@fastmail.com", url = "https://three.com", modifiedAt = 20), ), ) val identity = identities.single() assertEquals("june@fastmail.com", identity.value) assertEquals(3, identity.useCount) assertEquals(30L, identity.lastUsed) assertEquals("two.com", identity.exampleDomain) } @Test fun emails_come_first_and_sort_by_use_count() { val identities = deriveIdentities( listOf( login("a", username = "u1"), login("b", username = "u2"), login("c", email = "rare@x.com"), login("d", email = "often@x.com"), login("e", email = "often@x.com"), ), ) assertEquals( listOf("often@x.com", "rare@x.com", "u1", "u2"), identities.map { it.value }, ) } @Test fun deleted_and_non_login_entries_are_ignored() { val identities = deriveIdentities( listOf( login("a", username = "gone", deleted = true), login("b", username = "cardholder", type = "card"), login("c", username = "note-taker", type = "note"), ), ) assertTrue(identities.isEmpty()) } @Test fun filter_modes_restrict_the_type() { val identities = listOf( SavedIdentity("june@x.com", IdentityType.EMAIL, 2, 1), SavedIdentity("june", IdentityType.USERNAME, 1, 1), ) assertEquals(listOf("june@x.com"), filterIdentities(identities, "", IdentityFilterMode.EMAIL).map { it.value }) assertEquals(listOf("june"), filterIdentities(identities, "", IdentityFilterMode.USERNAME).map { it.value }) assertEquals(2, filterIdentities(identities, "", IdentityFilterMode.BOTH).size) } @Test fun filter_orders_by_last_used_then_use_count() { val identities = listOf( SavedIdentity("old@x.com", IdentityType.EMAIL, lastUsed = 1, useCount = 9), SavedIdentity("new@x.com", IdentityType.EMAIL, lastUsed = 5, useCount = 1), SavedIdentity("mid@x.com", IdentityType.EMAIL, lastUsed = 3, useCount = 2), ) assertEquals( listOf("new@x.com", "mid@x.com", "old@x.com"), filterIdentities(identities, "", IdentityFilterMode.BOTH).map { it.value }, ) } @Test fun filter_query_matches_value_domain_or_type() { val identities = listOf( SavedIdentity("june@fastmail.com", IdentityType.EMAIL, 2, 1, "fastmail.com"), SavedIdentity("june", IdentityType.USERNAME, 1, 1, "github.com"), ) assertEquals(listOf("june@fastmail.com"), filterIdentities(identities, "fastmail", IdentityFilterMode.BOTH).map { it.value }) assertEquals(listOf("june"), filterIdentities(identities, "github", IdentityFilterMode.BOTH).map { it.value }) assertEquals(listOf("june@fastmail.com"), filterIdentities(identities, "email", IdentityFilterMode.BOTH).map { it.value }) assertTrue(filterIdentities(identities, "zzz", IdentityFilterMode.BOTH).isEmpty()) } }