package com.peachpasswords.ui.vault import com.peachpasswords.vault.PasswordGenerator import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test /** * EntryEdit suite expansion (brief Suite 5): the new-card field logic * (network detection, PAN/CVC limits, expiry validation) and the password * generator the editor drawer drives. Builds on [EntryEditScreenTest]. */ class EntryEditExtraTest { // ── Network detection from the leading digit ────────────────────────────── @Test fun network_detected_from_first_digit() { assertEquals("visa", CardFieldUtils.detectNetwork("4111111111111111")) assertEquals("mastercard", CardFieldUtils.detectNetwork("5500000000000004")) assertEquals("amex", CardFieldUtils.detectNetwork("378282246310005")) assertEquals("discover", CardFieldUtils.detectNetwork("6011000000000004")) assertEquals("unknown", CardFieldUtils.detectNetwork("9999")) assertEquals("unknown", CardFieldUtils.detectNetwork("")) } @Test fun network_label_is_human_readable() { assertEquals("Visa", CardFieldUtils.networkLabel("visa")) assertEquals("Mastercard", CardFieldUtils.networkLabel("mastercard")) assertEquals("Amex", CardFieldUtils.networkLabel("amex")) assertEquals("Discover", CardFieldUtils.networkLabel("discover")) assertEquals("", CardFieldUtils.networkLabel("unknown")) assertEquals("", CardFieldUtils.networkLabel(null)) } // ── PAN / CVC limits ────────────────────────────────────────────────────── @Test fun pan_max_digits_amex_is_15_others_16() { assertEquals(15, CardFieldUtils.panMaxDigits("amex")) assertEquals(16, CardFieldUtils.panMaxDigits("visa")) assertEquals(16, CardFieldUtils.panMaxDigits(null)) } @Test fun cvc_max_digits_amex_is_4_others_3() { assertEquals(4, CardFieldUtils.cvcMaxDigits("amex")) assertEquals(3, CardFieldUtils.cvcMaxDigits("visa")) } @Test fun format_pan_caps_at_network_max() { // 20 digits typed for a Visa → capped to 16 (four groups of four). assertEquals("4242 4242 4242 4242", CardFieldUtils.formatPan("42424242424242424242")) } @Test fun format_pan_strips_non_digits() { assertEquals("4242 4242", CardFieldUtils.formatPan("4242-4242")) } @Test fun last4_extracts_trailing_digits() { assertEquals("4242", CardFieldUtils.last4("4242 4242 4242 4242")) assertEquals("", CardFieldUtils.last4(null)) } // ── Expiry validation (currentYear2 = 26, currentMonth = 6 → 2026-06) ───── @Test fun expiry_valid_in_future() { assertTrue(CardFieldUtils.isExpiryValid("06/26", currentYear2 = 26, currentMonth = 6)) // this month assertTrue(CardFieldUtils.isExpiryValid("01/30", currentYear2 = 26, currentMonth = 6)) } @Test fun expiry_rejects_past_month_this_year() { assertFalse(CardFieldUtils.isExpiryValid("05/26", currentYear2 = 26, currentMonth = 6)) } @Test fun expiry_rejects_bad_month() { assertFalse(CardFieldUtils.isExpiryValid("13/30", currentYear2 = 26, currentMonth = 6)) assertFalse(CardFieldUtils.isExpiryValid("00/30", currentYear2 = 26, currentMonth = 6)) } @Test fun expiry_rejects_incomplete() { assertFalse(CardFieldUtils.isExpiryValid("6/2", currentYear2 = 26, currentMonth = 6)) } // ── Password generator (editor drawer) ──────────────────────────────────── @Test fun generator_respects_length() { val pw = PasswordGenerator.generate(PasswordGenerator.Options(length = 24)) assertEquals(24, pw.length) } @Test fun generator_with_only_digits_yields_digits() { val pw = PasswordGenerator.generate( PasswordGenerator.Options( length = 20, includeUppercase = false, includeLowercase = false, includeNumbers = true, includeSymbols = false, ), ) assertTrue(pw.all { it.isDigit() }) } @Test fun generator_produces_distinct_passwords() { val a = PasswordGenerator.generate(PasswordGenerator.Options(length = 32)) val b = PasswordGenerator.generate(PasswordGenerator.Options(length = 32)) assertFalse("two generated passwords should differ", a == b) } }