feat: Input-Validatoren für Telefon, Spielname, Spieleranzahl
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 14m57s
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 14m57s
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"""Validierungs-Helfer für Benutzereingaben."""
|
||||
|
||||
import re
|
||||
|
||||
MIN_TELEFON_ZIFFERN: int = 10
|
||||
MIN_SPIELNAME_LAENGE: int = 2
|
||||
MAX_SPIELNAME_LAENGE: int = 200
|
||||
MIN_SPIELERANZAHL: int = 1
|
||||
MAX_SPIELERANZAHL: int = 20
|
||||
|
||||
|
||||
def validiere_telefonnummer(telefon: str) -> str:
|
||||
"""Validiert und normalisiert eine Telefonnummer.
|
||||
|
||||
Args:
|
||||
telefon: Telefonnummer im beliebigen Format, z.B. '+491****7890',
|
||||
'+49 123 4567890', '00491234567890'.
|
||||
'*' wird als Maskierungs-Platzhalter behandelt (>=1 Ziffer).
|
||||
|
||||
Returns:
|
||||
Bereinigte Telefonnummer, die mit '+' beginnt, '*' als Platzhalter.
|
||||
|
||||
Raises:
|
||||
ValueError: Wenn weniger als 10 Ziffern oder kein '+' nach Bereinigung.
|
||||
"""
|
||||
# Ziffern zählen (* als Platzhalter für >=1 Ziffer)
|
||||
ziffern_count = len(re.findall(r"\d|\*", telefon))
|
||||
|
||||
# Alles außer +, * und Ziffern entfernen
|
||||
bereinigt = re.sub(r"[^\d*+]", "", telefon)
|
||||
|
||||
# "00" am Anfang zu "+" konvertieren
|
||||
if bereinigt.startswith("00"):
|
||||
bereinigt = "+" + bereinigt[2:]
|
||||
|
||||
# Muss mit + beginnen (nach Bereinigung)
|
||||
if not bereinigt.startswith("+"):
|
||||
raise ValueError(f"Telefonnummer muss mit + beginnen: {telefon}")
|
||||
|
||||
# Mindestens 10 Ziffern (* zählt als eine)
|
||||
if ziffern_count < MIN_TELEFON_ZIFFERN:
|
||||
raise ValueError(f"Telefonnummer muss mindestens 10 Ziffern haben: {telefon}")
|
||||
|
||||
return bereinigt
|
||||
|
||||
|
||||
def validiere_spiel_name(name: str) -> str:
|
||||
"""Validiert einen Spielnamen.
|
||||
|
||||
Args:
|
||||
name: Spielname mit 2-200 Zeichen.
|
||||
|
||||
Returns:
|
||||
Bereinigter Spielname ohne HTML-Tags, mit gestrippten Rändern.
|
||||
|
||||
Raises:
|
||||
ValueError: Wenn weniger als 2 oder mehr als 200 Zeichen.
|
||||
"""
|
||||
# HTML-Tags entfernen
|
||||
without_tags = re.sub(r"<[^>]*>", "", name)
|
||||
stripped = without_tags.strip()
|
||||
|
||||
if len(stripped) < MIN_SPIELNAME_LAENGE:
|
||||
raise ValueError(f"Spielname muss mindestens 2 Zeichen haben: {name}")
|
||||
if len(stripped) > MAX_SPIELNAME_LAENGE:
|
||||
raise ValueError(f"Spielname darf maximal 200 Zeichen haben: {name}")
|
||||
|
||||
return stripped
|
||||
|
||||
|
||||
def validiere_spieleranzahl(anzahl: int) -> int:
|
||||
"""Validiert eine Spieleranzahl.
|
||||
|
||||
Args:
|
||||
anzahl: Anzahl der Spieler (1-20).
|
||||
|
||||
Returns:
|
||||
Die unveränderte Spieleranzahl.
|
||||
|
||||
Raises:
|
||||
ValueError: Wenn < 1, > 20 oder kein Integer.
|
||||
"""
|
||||
if not isinstance(anzahl, int) or isinstance(anzahl, bool):
|
||||
raise ValueError(f"Spieleranzahl muss eine Ganzzahl sein: {anzahl}")
|
||||
if anzahl < MIN_SPIELERANZAHL:
|
||||
raise ValueError(f"Spieleranzahl muss mindestens 1 sein: {anzahl}")
|
||||
if anzahl > MAX_SPIELERANZAHL:
|
||||
raise ValueError(f"Spieleranzahl darf maximal 20 sein: {anzahl}")
|
||||
|
||||
return anzahl
|
||||
@@ -0,0 +1,61 @@
|
||||
"""Tests für die Input-Validatoren."""
|
||||
|
||||
import pytest
|
||||
|
||||
from src.utils.validators import (
|
||||
validiere_spieleranzahl,
|
||||
validiere_spiel_name,
|
||||
validiere_telefonnummer,
|
||||
)
|
||||
|
||||
|
||||
# --- Telefonnummer-Tests ---
|
||||
|
||||
def test_gueltige_telefonnummer_wird_bereinigt() -> None:
|
||||
"""Gültige Telefonnummer → bereinigt."""
|
||||
# 13 Ziffern, Ergebnis ist +49 + 10 Ziffern
|
||||
assert validiere_telefonnummer("00491234567890") == "+491234567890"
|
||||
# Leerzeichen werden entfernt
|
||||
assert validiere_telefonnummer("+49 123 4567890") == "+491234567890"
|
||||
# * als Platzhalter (>=1 Ziffer), Gesamt >= 10 Ziffern
|
||||
star = "*" * 6
|
||||
assert validiere_telefonnummer("+491" + star + "7890") == "+491" + star + "7890"
|
||||
|
||||
|
||||
def test_ungueltige_telefonnummer_wirft_value_error() -> None:
|
||||
"""Ungültige Telefonnummer → ValueError."""
|
||||
with pytest.raises(ValueError):
|
||||
validiere_telefonnummer("123")
|
||||
|
||||
|
||||
# --- Spielname-Tests ---
|
||||
|
||||
def test_gueltiger_spielname_wird_bereinigt() -> None:
|
||||
"""Gültiger Spielname → bereinigt."""
|
||||
assert validiere_spiel_name(" Catan ") == "Catan"
|
||||
assert validiere_spiel_name("Ticket to Ride") == "Ticket to Ride"
|
||||
|
||||
|
||||
def test_html_tags_im_spielname_werden_entfernt() -> None:
|
||||
"""HTML-Tags im Spielnamen → entfernt."""
|
||||
result = validiere_spiel_name("<b>Catan</b>")
|
||||
assert "b>" not in result
|
||||
assert "b" not in result.split(">")
|
||||
assert "Catan" in result
|
||||
|
||||
|
||||
# --- Spieleranzahl-Tests ---
|
||||
|
||||
def test_gueltige_spieleranzahl_unveraendert() -> None:
|
||||
"""Gültige Spieleranzahl → unverändert."""
|
||||
assert validiere_spieleranzahl(1) == 1
|
||||
assert validiere_spieleranzahl(4) == 4
|
||||
assert validiere_spieleranzahl(20) == 20
|
||||
|
||||
|
||||
def test_ungueltige_spieleranzahl_wirft_value_error() -> None:
|
||||
"""Ungültige Spieleranzahl → ValueError."""
|
||||
with pytest.raises(ValueError):
|
||||
validiere_spieleranzahl(0)
|
||||
with pytest.raises(ValueError):
|
||||
validiere_spieleranzahl(21)
|
||||
Reference in New Issue
Block a user