package com.peachpasswords.autofill import com.peachpasswords.autofill.AutofillResponseBuilder.FillMode import com.peachpasswords.vault.VaultEntry import org.junit.Assert.assertEquals import org.junit.Test class AutofillPreviewLabelsTest { private fun entry( title: String = "GitHub", username: String? = "june", email: String? = null, url: String? = "https://github.com", ) = VaultEntry( id = title, title = title, username = username, email = email, url = url, createdAt = 0, modifiedAt = 0, ) @Test fun normal_mode_shows_entry_title_and_identity() { val labels = AutofillResponseBuilder.previewLabels(false, entry(), "github.com") assertEquals("GitHub", labels.title) assertEquals("june", labels.subtitle) assertEquals(FillMode.LOGIN, labels.fillMode) } @Test fun normal_mode_falls_back_email_then_domain() { val emailOnly = entry(username = null, email = "june@example.com") assertEquals("june@example.com", AutofillResponseBuilder.previewLabels(false, emailOnly, null).subtitle) val bare = entry(username = null, email = null) assertEquals("github.com", AutofillResponseBuilder.previewLabels(false, bare, null).subtitle) } @Test fun private_mode_hides_title_and_identity() { val labels = AutofillResponseBuilder.previewLabels(true, entry(), "github.com") assertEquals("Peach", labels.title) assertEquals("github.com", labels.subtitle) } @Test fun private_mode_without_origin_has_blank_subtitle() { val labels = AutofillResponseBuilder.previewLabels(true, entry(), null) assertEquals("Peach", labels.title) assertEquals("", labels.subtitle) } // --- OTP_FILL fillMode: the chip surfaces the actual TOTP code --- @Test fun otpFill_mode_shows_chunked_code_as_title_and_entry_as_subtitle() { val labels = AutofillResponseBuilder.previewLabels( privatePreview = false, entry = entry(), originDomain = "github.com", fillMode = FillMode.OTP_FILL, otpCode = "482901", ) assertEquals("482 901", labels.title) assertEquals("2FA", labels.subtitle) assertEquals("GitHub", labels.iconSource) assertEquals(FillMode.OTP_FILL, labels.fillMode) } @Test fun otpFill_mode_passes_through_long_codes_unchunked() { val labels = AutofillResponseBuilder.previewLabels( privatePreview = false, entry = entry(), originDomain = null, fillMode = FillMode.OTP_FILL, otpCode = "JBSWY3DPEHPK3PXP", ) // 8-char Steam-style code — chunk only fires on <=6 digits, this passes through. assertEquals("JBSWY3DPEHPK3PXP", labels.title) assertEquals("2FA", labels.subtitle) } @Test fun otpFill_mode_never_leaks_digits_in_private_preview() { val labels = AutofillResponseBuilder.previewLabels( privatePreview = true, entry = entry(), originDomain = "github.com", fillMode = FillMode.OTP_FILL, otpCode = "482901", ) // Privacy always wins over fillMode — chip says "Peach" not the digits. assertEquals("Peach", labels.title) assertEquals("github.com", labels.subtitle) } @Test(expected = IllegalArgumentException::class) fun otpFill_mode_requires_otpCode() { AutofillResponseBuilder.previewLabels( privatePreview = false, entry = entry(), originDomain = "github.com", fillMode = FillMode.OTP_FILL, otpCode = null, ) } @Test fun chunkOtpForDisplay_groups_only_6digit_codes_with_space() { // 6-digit only: grouped into 3+3. assertEquals("482 901", AutofillResponseBuilder.chunkOtpForDisplay("482901")) // 5-digit and 7-digit: pass through (no sane chunking). assertEquals("12345", AutofillResponseBuilder.chunkOtpForDisplay("12345")) assertEquals("1234567", AutofillResponseBuilder.chunkOtpForDisplay("1234567")) // Alphanumeric (Steam-style base32): pass through unchanged — never strip letters. assertEquals("JBSWY3DPEHPK3PXP", AutofillResponseBuilder.chunkOtpForDisplay("JBSWY3DPEHPK3PXP")) } }