1package com.peachpasswords.autofill23import org.junit.Assert.assertEquals4import org.junit.Assert.assertNull5import org.junit.Test67class PasswordPolicyTest {89 @Test fun reads_minlength_and_maxlength_attributes() {10 val p = PasswordPolicy.fromHtmlAttributes(mapOf("minlength" to "8", "maxlength" to "64"))11 assertEquals(8, p.minLength)12 assertEquals(64, p.maxLength)13 }1415 @Test fun ignores_non_positive_lengths() {16 val p = PasswordPolicy.fromHtmlAttributes(mapOf("minlength" to "0", "maxlength" to "-1"))17 assertNull(p.minLength)18 assertNull(p.maxLength)19 }2021 @Test fun pattern_range_fills_both_bounds() {22 val p = PasswordPolicy.fromHtmlAttributes(mapOf("pattern" to ".{8,20}"))23 assertEquals(8, p.minLength)24 assertEquals(20, p.maxLength)25 }2627 @Test fun pattern_min_only() {28 val p = PasswordPolicy.fromHtmlAttributes(mapOf("pattern" to ".{12,}"))29 assertEquals(12, p.minLength)30 assertNull(p.maxLength)31 }3233 @Test fun pattern_exact_sets_both() {34 val p = PasswordPolicy.fromHtmlAttributes(mapOf("pattern" to "[a-z]{10}"))35 assertEquals(10, p.minLength)36 assertEquals(10, p.maxLength)37 }3839 @Test fun attributes_win_over_pattern() {40 val p = PasswordPolicy.fromHtmlAttributes(41 mapOf("minlength" to "6", "maxlength" to "30", "pattern" to ".{8,20}"),42 )43 assertEquals(6, p.minLength)44 assertEquals(30, p.maxLength)45 }4647 @Test fun no_constraints_yields_empty_policy() {48 val p = PasswordPolicy.fromHtmlAttributes(mapOf("autocomplete" to "new-password"))49 assertNull(p.minLength)50 assertNull(p.maxLength)51 }5253 @Test fun generation_prefers_max_length() {54 55 assertEquals(64, PasswordPolicy(minLength = 8, maxLength = 64).generationLength())56 }5758 @Test fun generation_caps_at_hard_max() {59 assertEquals(256, PasswordPolicy(maxLength = 500).generationLength())60 }6162 @Test fun generation_snaps_up_to_min() {63 64 assertEquals(25, PasswordPolicy(minLength = 25).generationLength())65 }6667 @Test fun generation_default_when_unconstrained() {68 assertEquals(PasswordPolicy.DEFAULT_LENGTH, PasswordPolicy().generationLength())69 }7071 @Test fun generation_never_below_one() {72 assertEquals(1, PasswordPolicy(maxLength = 0).generationLength())73 }7475 @Test fun constraint_note_max() {76 val p = PasswordPolicy(maxLength = 20)77 assertEquals("This site allows max 20 characters", p.constraintNote(20))78 }7980 @Test fun constraint_note_min() {81 val p = PasswordPolicy(minLength = 12)82 assertEquals("This site requires at least 12 characters", p.constraintNote(12))83 }8485 @Test fun constraint_note_empty_when_interior() {86 val p = PasswordPolicy(minLength = 8, maxLength = 64)87 assertEquals("", p.constraintNote(30))88 }89}