Skip to content

Commit 1c9cd99

Browse files
Accept 19-digit Visa card numbers
1 parent 22786cc commit 1c9cd99

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

‎src/validators/card.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def card_number(value: str, /):
4242

4343
@validator
4444
def visa(value: str, /):
45-
"""Return whether or not given value is a valid Visa card number.
45+
"""Return whether or not given value is a valid 16- or 19-digit Visa card number.
4646
4747
Examples:
4848
>>> visa('4242424242424242')
@@ -59,7 +59,7 @@ def visa(value: str, /):
5959
(ValidationError): If `value` is an invalid Visa card number.
6060
"""
6161
pattern = re.compile(r"^4")
62-
return card_number(value) and len(value) == 16 and pattern.match(value)
62+
return card_number(value) and len(value) in (16, 19) and pattern.match(value)
6363

6464

6565
@validator

‎tests/test_card.py‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
visa,
1818
)
1919

20-
visa_cards = ["4242424242424242", "4000002760003184"]
20+
visa_cards = ["4242424242424242", "4000002760003184", "4000000000000000006"]
2121
mastercard_cards = ["5555555555554444", "2223003122003222"]
2222
amex_cards = ["378282246310005", "371449635398431"]
2323
unionpay_cards = ["6200000000000005"]
@@ -63,6 +63,22 @@ def test_returns_true_on_valid_visa(value: str):
6363
assert visa(value)
6464

6565

66+
@pytest.mark.parametrize(
67+
"value",
68+
["400000000000006", "40000000000000006", "400000000000000002", "40000000000000000002"],
69+
)
70+
def test_visa_rejects_unsupported_lengths(value: str):
71+
"""Reject unsupported lengths even when the checksum and prefix match."""
72+
assert card_number(value) is True
73+
assert isinstance(visa(value), ValidationError)
74+
75+
76+
@pytest.mark.parametrize("value", ["4000000000000000000", "4000000000000000007"])
77+
def test_visa_rejects_bad_checksum_at_nineteen_digits(value: str):
78+
"""A supported length must not bypass the Luhn check."""
79+
assert isinstance(visa(value), ValidationError)
80+
81+
6682
@pytest.mark.parametrize(
6783
"value",
6884
mastercard_cards + amex_cards + unionpay_cards + diners_cards + jcb_cards + discover_cards,

0 commit comments

Comments
 (0)