import os import pytest from app import app as flask_app from unittest.mock import patch, MagicMock @pytest.fixture def client(): flask_app.config['TESTING'] = True with flask_app.test_client() as client: yield client def test_homepage(client): resp = client.get('/') assert resp.status_code == 200 assert b'Elpatrons Datumsrechner' in resp.data def test_plusminus_tage(client): resp = client.post('/', data={ 'action': 'plusminus', 'datum_pm': '2024-01-10', 'anzahl_pm': '5', 'einheit_pm': 'tage', 'richtung_pm': 'add' }) assert resp.status_code == 200 assert b'plus 5 Tage' in resp.data assert b'15.01.2024' in resp.data # Subtraktion resp = client.post('/', data={ 'action': 'plusminus', 'datum_pm': '2024-01-10', 'anzahl_pm': '5', 'einheit_pm': 'tage', 'richtung_pm': 'sub' }) assert b'minus 5 Tage' in resp.data assert b'05.01.2024' in resp.data def test_plusminus_werktage(client): from numpy import busday_offset from datetime import datetime start = '2024-01-10' anzahl = 5 # Addition result = busday_offset(datetime.strptime(start, '%Y-%m-%d').date(), anzahl, roll='forward') result_str = datetime.strptime(str(result), '%Y-%m-%d').strftime('%d.%m.%Y') resp = client.post('/', data={ 'action': 'plusminus', 'datum_pm': start, 'anzahl_pm': str(anzahl), 'einheit_pm': 'tage', 'richtung_pm': 'add', 'werktage_pm': 'on' }) assert resp.status_code == 200 assert b'plus 5 Werktage' in resp.data assert result_str.encode() in resp.data # Subtraktion result = busday_offset(datetime.strptime(start, '%Y-%m-%d').date(), -anzahl, roll='forward') result_str = datetime.strptime(str(result), '%Y-%m-%d').strftime('%d.%m.%Y') resp = client.post('/', data={ 'action': 'plusminus', 'datum_pm': start, 'anzahl_pm': str(anzahl), 'einheit_pm': 'tage', 'richtung_pm': 'sub', 'werktage_pm': 'on' }) assert b'minus 5 Werktage' in resp.data assert result_str.encode() in resp.data def test_plusminus_wochen_monate(client): from datetime import datetime, timedelta from dateutil.relativedelta import relativedelta start = '2024-01-10' # Wochen addieren resp = client.post('/', data={ 'action': 'plusminus', 'datum_pm': start, 'anzahl_pm': '2', 'einheit_pm': 'wochen', 'richtung_pm': 'add' }) assert b'plus 2 Wochen' in resp.data assert b'24.01.2024' in resp.data # Wochen subtrahieren resp = client.post('/', data={ 'action': 'plusminus', 'datum_pm': start, 'anzahl_pm': '2', 'einheit_pm': 'wochen', 'richtung_pm': 'sub' }) assert b'minus 2 Wochen' in resp.data assert b'27.12.2023' in resp.data # Monate addieren resp = client.post('/', data={ 'action': 'plusminus', 'datum_pm': start, 'anzahl_pm': '2', 'einheit_pm': 'monate', 'richtung_pm': 'add' }) assert b'plus 2 Monate' in resp.data assert b'10.03.2024' in resp.data # Monate subtrahieren resp = client.post('/', data={ 'action': 'plusminus', 'datum_pm': start, 'anzahl_pm': '2', 'einheit_pm': 'monate', 'richtung_pm': 'sub' }) assert b'minus 2 Monate' in resp.data assert b'10.11.2023' in resp.data def test_xss_protection(client): # Versuche ein Skript einzuschleusen xss = '' resp = client.post('/', data={ 'action': 'tage_werktage', 'start1': xss, 'end1': '2024-01-10' }) assert resp.status_code == 200 # Das Skript darf nicht im HTML erscheinen assert b'' not in resp.data # Es sollte eine Fehlermeldung erscheinen html = resp.data.decode('utf-8') assert 'Ungültige Eingabe' in html def test_stats_login_required(client): resp = client.get('/stats') assert resp.status_code == 200 assert b'Dashboard Login' in resp.data def test_werktage_berechnung(client): from numpy import busday_count from datetime import date, timedelta start = '2024-01-01' end = '2024-03-01' expected = busday_count(date.fromisoformat(start), date.fromisoformat(end) + timedelta(days=1)) resp = client.post('/', data={ 'action': 'tage_werktage', 'start1': start, 'end1': end, 'werktage': 'on' }) assert resp.status_code == 200 assert b'Anzahl der Werktage' in resp.data assert f': {expected}'.encode() in resp.data def test_api_tage_werktage(client): # Erfolgsfall: Werktage resp = client.post('/api/tage_werktage', json={ 'start': '2024-06-01', 'end': '2024-06-10', 'werktage': True }) assert resp.status_code == 200 data = resp.get_json() assert 'result' in data # Fehlerfall: Ungültiges Datum resp = client.post('/api/tage_werktage', json={ 'start': 'foo', 'end': 'bar', 'werktage': True }) assert resp.status_code == 400 data = resp.get_json() assert 'error' in data def test_api_wochentag(client): resp = client.post('/api/wochentag', json={'datum': '2024-06-10'}) assert resp.status_code == 200 data = resp.get_json() assert data['result'] == 'Montag' # Fehlerfall resp = client.post('/api/wochentag', json={'datum': 'foo'}) assert resp.status_code == 400 assert 'error' in resp.get_json() def test_api_kw_berechnen(client): resp = client.post('/api/kw_berechnen', json={'datum': '2024-06-10'}) assert resp.status_code == 200 data = resp.get_json() assert 'KW' in data['result'] # Fehlerfall resp = client.post('/api/kw_berechnen', json={'datum': 'foo'}) assert resp.status_code == 400 assert 'error' in resp.get_json() def test_api_kw_datum(client): resp = client.post('/api/kw_datum', json={'jahr': 2024, 'kw': 24}) assert resp.status_code == 200 data = resp.get_json() assert 'result' in data and 'start' in data and 'end' in data # Fehlerfall resp = client.post('/api/kw_datum', json={'jahr': 'foo', 'kw': 'bar'}) assert resp.status_code == 400 assert 'error' in resp.get_json() def test_api_plusminus(client): # Tage addieren resp = client.post('/api/plusminus', json={ 'datum': '2024-06-10', 'anzahl': 5, 'einheit': 'tage', 'richtung': 'add', 'werktage': False }) assert resp.status_code == 200 data = resp.get_json() assert data['result'] == '2024-06-15' # Werktage subtrahieren resp = client.post('/api/plusminus', json={ 'datum': '2024-06-10', 'anzahl': 5, 'einheit': 'tage', 'richtung': 'sub', 'werktage': True }) assert resp.status_code == 200 data = resp.get_json() assert 'result' in data # Fehlerfall: ungültige Einheit resp = client.post('/api/plusminus', json={ 'datum': '2024-06-10', 'anzahl': 5, 'einheit': 'foo' }) assert resp.status_code == 400 assert 'error' in resp.get_json() def test_api_stats(client): resp = client.get('/api/stats') assert resp.status_code == 200 data = resp.get_json() assert "pageviews" in data assert "func_counts" in data assert "impressions_per_day" in data assert "api_counts" in data def test_api_monitor(client): resp = client.get('/api/monitor') assert resp.status_code == 200 data = resp.get_json() assert data['status'] == 'ok' assert 'uptime_seconds' in data # Neue Tests für bessere Coverage def test_feiertage_api_error(client): """Test Fehlerbehandlung bei Feiertage-API""" with patch('app.requests.get') as mock_get: mock_get.side_effect = Exception("Network error") resp = client.post('/', data={ 'action': 'tage_werktage', 'start1': '2024-01-01', 'end1': '2024-01-10', 'bundesland': 'BY' }) assert resp.status_code == 200 def test_logging_error_handling(client): """Test Logging-Fehlerbehandlung""" # Test ohne Mock, da die App das Logging-Handling bereits hat resp = client.get('/') assert resp.status_code == 200 def test_invalid_date_handling(client): """Test ungültige Datumseingaben""" # Ungültiges Datum bei tage_werktage resp = client.post('/', data={ 'action': 'tage_werktage', 'start1': 'invalid-date', 'end1': '2024-01-10' }) assert resp.status_code == 200 html = resp.data.decode('utf-8') assert 'Ungültige Eingabe' in html def test_invalid_wochentag_input(client): """Test ungültige Eingaben bei Wochentag-Berechnung""" resp = client.post('/', data={ 'action': 'wochentag', 'datum3': 'invalid-date' }) assert resp.status_code == 200 html = resp.data.decode('utf-8') assert 'Ungültige Eingabe' in html def test_invalid_kw_berechnen_input(client): """Test ungültige Eingaben bei KW-Berechnung""" resp = client.post('/', data={ 'action': 'kw_berechnen', 'datum6': 'invalid-date' }) assert resp.status_code == 200 html = resp.data.decode('utf-8') assert 'Ungültige Eingabe' in html def test_invalid_kw_datum_input(client): """Test ungültige Eingaben bei KW-Datum""" resp = client.post('/', data={ 'action': 'kw_datum', 'jahr7': 'invalid', 'kw7': 'invalid' }) assert resp.status_code == 200 html = resp.data.decode('utf-8') assert 'Ungültige Eingabe' in html def test_invalid_plusminus_input(client): """Test ungültige Eingaben bei Plusminus-Berechnung""" resp = client.post('/', data={ 'action': 'plusminus', 'datum_pm': 'invalid-date', 'anzahl_pm': 'invalid', 'einheit_pm': 'tage', 'richtung_pm': 'add' }) assert resp.status_code == 200 html = resp.data.decode('utf-8') assert 'Ungültige Eingabe' in html def test_stats_login_success(client): """Test erfolgreiche Anmeldung im Stats-Bereich""" with client.session_transaction() as sess: sess['stats_auth'] = True resp = client.get('/stats') assert resp.status_code == 200 def test_stats_login_failure(client): """Test fehlgeschlagene Anmeldung im Stats-Bereich""" resp = client.post('/stats', data={'password': 'wrong'}) assert resp.status_code == 200 html = resp.data.decode('utf-8') assert 'Falsches Passwort' in html def test_api_error_handling(client): """Test API-Fehlerbehandlung""" # Test mit korrektem Content-Type resp = client.post('/api/tage_werktage', data='invalid json', content_type='application/json') assert resp.status_code == 400 def test_api_plusminus_werktage_unsupported(client): """Test nicht unterstützte Werktage + Wochen/Monate""" # Werktage + Wochen resp = client.post('/api/plusminus', json={ 'datum': '2024-06-10', 'anzahl': 5, 'einheit': 'wochen', 'werktage': True }) assert resp.status_code == 400 assert 'Nicht unterstützt' in resp.get_json()['error'] # Werktage + Monate resp = client.post('/api/plusminus', json={ 'datum': '2024-06-10', 'anzahl': 5, 'einheit': 'monate', 'werktage': True }) assert resp.status_code == 400 assert 'Nicht unterstützt' in resp.get_json()['error'] def test_api_logging(client): """Test API-Logging""" resp = client.post('/api/wochentag', json={'datum': '2024-06-10'}) assert resp.status_code == 200 # Prüfe ob Log-Datei existiert log_path = os.path.join('log', 'pageviews.log') assert os.path.exists(log_path) def test_api_docs(client): """Test API-Dokumentation""" resp = client.get('/api-docs') assert resp.status_code == 200 def test_monitor_api_details(client): """Test detaillierte Monitor-API""" resp = client.get('/api/monitor') assert resp.status_code == 200 data = resp.get_json() assert 'status' in data assert 'message' in data assert 'time' in data assert 'uptime_seconds' in data assert 'pageviews_last_7_days' in data