1package com.peachpasswords.autofill23import com.peachpasswords.autofill.AutofillResponseBuilder.FillMode4import com.peachpasswords.vault.VaultEntry5import org.junit.Assert.assertEquals6import org.junit.Assert.assertNotNull7import org.junit.Assert.assertNull8import org.junit.Test910class AutofillPreviewLabelsTest {11 private fun entry(12 title: String = "GitHub",13 username: String? = "june",14 email: String? = null,15 url: String? = "https://github.com",16 ) = VaultEntry(17 id = title, title = title, username = username, email = email, url = url,18 createdAt = 0, modifiedAt = 0,19 )2021 @Test fun normal_mode_shows_entry_title_and_identity() {22 val labels = AutofillResponseBuilder.previewLabels(false, entry(), "github.com")23 assertEquals("GitHub", labels.title)24 assertEquals("june", labels.subtitle)25 assertEquals(FillMode.LOGIN, labels.fillMode)26 }2728 @Test fun normal_mode_falls_back_email_then_domain() {29 val emailOnly = entry(username = null, email = "[email protected]")30 assertEquals("[email protected]", AutofillResponseBuilder.previewLabels(false, emailOnly, null).subtitle)31 val bare = entry(username = null, email = null)32 assertEquals("github.com", AutofillResponseBuilder.previewLabels(false, bare, null).subtitle)33 }3435 @Test fun private_mode_hides_title_and_identity() {36 val labels = AutofillResponseBuilder.previewLabels(true, entry(), "github.com")37 assertEquals("Peach", labels.title)38 assertEquals("github.com", labels.subtitle)39 }4041 @Test fun private_mode_without_origin_has_blank_subtitle() {42 val labels = AutofillResponseBuilder.previewLabels(true, entry(), null)43 assertEquals("Peach", labels.title)44 assertEquals("", labels.subtitle)45 }4647 4849 @Test fun otpFill_mode_shows_chunked_code_as_title_and_entry_as_subtitle() {50 val labels = AutofillResponseBuilder.previewLabels(51 privatePreview = false,52 entry = entry(),53 originDomain = "github.com",54 fillMode = FillMode.OTP_FILL,55 otpCode = "482901",56 )57 assertEquals("482 901", labels.title)58 assertEquals("2FA", labels.subtitle)59 assertEquals("GitHub", labels.iconSource)60 assertEquals(FillMode.OTP_FILL, labels.fillMode)61 }6263 @Test fun otpFill_mode_passes_through_long_codes_unchunked() {64 val labels = AutofillResponseBuilder.previewLabels(65 privatePreview = false,66 entry = entry(),67 originDomain = null,68 fillMode = FillMode.OTP_FILL,69 otpCode = "JBSWY3DPEHPK3PXP",70 )71 72 assertEquals("JBSWY3DPEHPK3PXP", labels.title)73 assertEquals("2FA", labels.subtitle)74 }7576 @Test fun otpFill_mode_never_leaks_digits_in_private_preview() {77 val labels = AutofillResponseBuilder.previewLabels(78 privatePreview = true,79 entry = entry(),80 originDomain = "github.com",81 fillMode = FillMode.OTP_FILL,82 otpCode = "482901",83 )84 85 assertEquals("Peach", labels.title)86 assertEquals("github.com", labels.subtitle)87 }8889 @Test(expected = IllegalArgumentException::class)90 fun otpFill_mode_requires_otpCode() {91 AutofillResponseBuilder.previewLabels(92 privatePreview = false,93 entry = entry(),94 originDomain = "github.com",95 fillMode = FillMode.OTP_FILL,96 otpCode = null,97 )98 }99100 @Test fun otpFill_mode_subtitle_appends_countdown_when_secondsRemaining_is_set() {101 val labels = AutofillResponseBuilder.previewLabels(102 privatePreview = false,103 entry = entry(),104 originDomain = "github.com",105 fillMode = FillMode.OTP_FILL,106 otpCode = "482901",107 secondsRemaining = 23,108 )109 assertEquals("2FA · 23s", labels.subtitle)110 assertEquals("482 901", labels.title)111 }112113 @Test fun otpFill_mode_subtitle_says_expired_when_secondsRemaining_is_zero() {114 val labels = AutofillResponseBuilder.previewLabels(115 privatePreview = false,116 entry = entry(),117 originDomain = "github.com",118 fillMode = FillMode.OTP_FILL,119 otpCode = "482901",120 secondsRemaining = 0,121 )122 assertEquals("2FA · expired", labels.subtitle)123 }124125 @Test fun otpFill_mode_subtitle_says_expired_when_secondsRemaining_is_negative() {126 127 128 129 val labels = AutofillResponseBuilder.previewLabels(130 privatePreview = false,131 entry = entry(),132 originDomain = null,133 fillMode = FillMode.OTP_FILL,134 otpCode = "482901",135 secondsRemaining = -1,136 )137 assertEquals("2FA · expired", labels.subtitle)138 }139140 @Test fun otpFill_mode_subtitle_is_just_2fa_when_secondsRemaining_is_null() {141 142 143 val labels = AutofillResponseBuilder.previewLabels(144 privatePreview = false,145 entry = entry(),146 originDomain = null,147 fillMode = FillMode.OTP_FILL,148 otpCode = "482901",149 secondsRemaining = null,150 )151 assertEquals("2FA", labels.subtitle)152 assertNull("no end icon when secondsRemaining is unknown", labels.endIcon)153 }154155 @Test fun chunkOtpForDisplay_groups_only_6digit_codes_with_space() {156 157 assertEquals("482 901", AutofillResponseBuilder.chunkOtpForDisplay("482901"))158 159 assertEquals("12345", AutofillResponseBuilder.chunkOtpForDisplay("12345"))160 assertEquals("1234567", AutofillResponseBuilder.chunkOtpForDisplay("1234567"))161 162 assertEquals("JBSWY3DPEHPK3PXP", AutofillResponseBuilder.chunkOtpForDisplay("JBSWY3DPEHPK3PXP"))163 }164}165166167168class AutofillPreviewLabelsCountdownTest {169 private fun entry(title: String = "GitHub") = VaultEntry(170 id = title, title = title, username = "june",171 createdAt = 0, modifiedAt = 0,172 )173174 @Test fun otpFill_chip_counts_down_seconds_remaining_in_subtitle() {175 val labels = AutofillResponseBuilder.previewLabels(176 privatePreview = false,177 entry = entry(),178 originDomain = "github.com",179 fillMode = FillMode.OTP_FILL,180 otpCode = "482901",181 secondsRemaining = 23,182 )183 assertEquals("482 901", labels.title)184 assertEquals("2FA · 23s", labels.subtitle)185 }186187 @Test fun otpFill_chip_amber_zone_at_five_to_nine_seconds() {188 val labels = AutofillResponseBuilder.previewLabels(189 false, entry(), null,190 fillMode = FillMode.OTP_FILL, otpCode = "123456", secondsRemaining = 7,191 )192 assertEquals("2FA · 7s", labels.subtitle)193 }194195 @Test fun otpFill_chip_red_zone_at_or_below_four_seconds() {196 val labels = AutofillResponseBuilder.previewLabels(197 false, entry(), null,198 fillMode = FillMode.OTP_FILL, otpCode = "123456", secondsRemaining = 3,199 )200 assertEquals("2FA · 3s", labels.subtitle)201 }202203 @Test fun otpFill_chip_at_zero_or_below_shows_expired() {204 val labels = AutofillResponseBuilder.previewLabels(205 false, entry(), null,206 fillMode = FillMode.OTP_FILL, otpCode = "123456", secondsRemaining = 0,207 )208 assertEquals("2FA · expired", labels.subtitle)209 }210211 @Test fun otpFill_chip_without_secondsRemaining_keeps_legacy_subtitle() {212 213 214 215 val labels = AutofillResponseBuilder.previewLabels(216 false, entry(), "github.com",217 fillMode = FillMode.OTP_FILL, otpCode = "482901",218 )219 assertEquals("2FA", labels.subtitle)220 assertEquals(null, labels.endIcon)221 }222223 @Test fun private_mode_still_hides_digits_even_with_countdown() {224 225 val labels = AutofillResponseBuilder.previewLabels(226 true, entry(), "github.com",227 fillMode = FillMode.OTP_FILL, otpCode = "482901", secondsRemaining = 7,228 )229 assertEquals("Peach", labels.title)230 assertEquals("github.com", labels.subtitle)231 }232}