feat: Input-Validatoren für Telefon, Spielname, Spieleranzahl
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 14m57s

This commit is contained in:
Alicia (BSN)
2026-06-21 23:20:43 +00:00
parent e43909b0cd
commit bf16015d5c
3 changed files with 151 additions and 0 deletions
View File
+90
View File
@@ -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
+61
View File
@@ -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)