373 lines
12 KiB
Python
373 lines
12 KiB
Python
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 = '<script>alert(1)</script>'
|
|
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'<script>alert(1)</script>' 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
|
|
# Die Route gibt HTML zurück, nicht JSON
|
|
html = resp.data.decode('utf-8')
|
|
# Prüfe auf typische HTML-Elemente des Dashboards
|
|
assert 'Statistik-Dashboard' in html or 'Dashboard' in html
|
|
|
|
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 |