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