Validate a Signup Form
The signup page needs server-side validation for its three fields. The README has the rules, and signup.py already checks username length and the password's letters and digits. Build the rest with the assistant: accept, edit, or reject each suggestion, and keep the tests green.
signup.py1 of 3
Files
signup.py
Python · Editableimport re
USERNAME_MIN = 3
USERNAME_MAX = 20
PASSWORD_MIN = 8
def validate_signup(username, email, password):
"""Returns {field: message} for each invalid field. An empty dict means the form is valid."""
username = username.strip()
email = email.strip()
problems = {
"username": username_error(username),
"email": email_error(email),
"password": password_error(password, username),
}
return {field: message for field, message in problems.items() if message}
def username_error(username):
"""Returns why the username is invalid, or None."""
if not USERNAME_MIN <= len(username) <= USERNAME_MAX:
return f"must be {USERNAME_MIN} to {USERNAME_MAX} characters"
return None
def email_error(email):
"""Returns why the email is invalid, or None."""
return None
def password_error(password, username):
"""Returns why the password is invalid, or None."""
if not any(c.isalpha() for c in password) or not any(c.isdigit() for c in password):
return "must include a letter and a digit"
return None
import pytest
from signup import validate_signup
EMAIL = "maya@example.com"
PASSWORD = "orbit2024"
def test_valid_form_has_no_errors():
assert validate_signup("maya_r", EMAIL, PASSWORD) == {}
def test_username_length_limits():
assert "username" in validate_signup("ab", EMAIL, PASSWORD)
assert "username" in validate_signup("a" * 21, EMAIL, PASSWORD)
assert "username" not in validate_signup("abc", EMAIL, PASSWORD)
def test_username_characters():
assert "username" in validate_signup("maya.r", EMAIL, PASSWORD)
assert "username" in validate_signup("2maya", EMAIL, PASSWORD)
assert "username" not in validate_signup("Maya_R2", EMAIL, PASSWORD)
def test_email_format():
for address in ["maya.example.com", "@example.com", "maya@@example.com", "maya@example", "maya@example..com", "maya r@example.com"]:
assert "email" in validate_signup("maya_r", address, PASSWORD)
assert validate_signup("maya_r", "maya.r+jobs@mail.example.co", PASSWORD) == {}
def test_short_password_is_rejected():
assert "password" in validate_signup("maya_r", EMAIL, "orbit12")
def test_password_of_exactly_min_length_is_accepted():
assert "password" not in validate_signup("maya_r", EMAIL, "orbit123")
def test_password_needs_a_letter_and_a_digit():
assert "password" in validate_signup("maya_r", EMAIL, "orbitorbit")
assert "password" in validate_signup("maya_r", EMAIL, "2024202420")
def test_password_must_not_contain_username():
assert validate_signup("maya_r", EMAIL, "MAYA_R2024") == {"password": "must not contain your username"}
# Signup Form
The signup page posts a username, an email, and a password to validate_signup (signup.py). It returns a dict of field to error message, and an empty dict means the form is valid. Fields are trimmed before they're checked.
## Rules
- Username: 3 to 20 characters. ASCII letters, digits, and underscores only, starting with a letter.
- Email: one @ with text before it. The domain after it has two or more parts separated by dots, and no part is empty, so maya@example and maya@example..com are both invalid. No spaces.
- Password: at least 8 characters, with at least one letter and one digit. It must not contain the username, ignoring case.
The tests are in test_signup.py.
Test Output
No runs yet.