A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
286 lines
11 KiB
Python
286 lines
11 KiB
Python
"""
|
|
Tests fuer das BreakPilot Studio Modular Frontend
|
|
|
|
Testet die modulare Frontend-Architektur mit:
|
|
- BaseLayoutModule
|
|
- DashboardModule
|
|
- JitsiModule
|
|
- LettersModule
|
|
- WorksheetsModule
|
|
- CorrectionModule
|
|
|
|
Erstellt: 2024-12-18
|
|
"""
|
|
import pytest
|
|
import re
|
|
import sys
|
|
import os
|
|
|
|
# Add parent directory to path for imports
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
|
|
class TestModuleImports:
|
|
"""Tests fuer die Module-Imports."""
|
|
|
|
def test_all_modules_importable(self):
|
|
"""Testet, dass alle Module importiert werden koennen."""
|
|
from frontend.modules import (
|
|
BaseLayoutModule,
|
|
DashboardModule,
|
|
JitsiModule,
|
|
LettersModule,
|
|
WorksheetsModule,
|
|
CorrectionModule,
|
|
)
|
|
assert BaseLayoutModule is not None
|
|
assert DashboardModule is not None
|
|
assert JitsiModule is not None
|
|
assert LettersModule is not None
|
|
assert WorksheetsModule is not None
|
|
assert CorrectionModule is not None
|
|
|
|
def test_studio_modular_importable(self):
|
|
"""Testet, dass studio_modular importiert werden kann."""
|
|
from frontend.studio_modular import get_studio_html
|
|
assert callable(get_studio_html)
|
|
|
|
|
|
class TestDashboardModule:
|
|
"""Tests fuer das DashboardModule."""
|
|
|
|
@pytest.fixture
|
|
def dashboard_module(self):
|
|
from frontend.modules.dashboard import DashboardModule
|
|
return DashboardModule
|
|
|
|
def test_dashboard_has_get_css(self, dashboard_module):
|
|
"""Testet, dass DashboardModule.get_css() existiert."""
|
|
css = dashboard_module.get_css()
|
|
assert isinstance(css, str)
|
|
assert len(css) > 0
|
|
|
|
def test_dashboard_has_get_html(self, dashboard_module):
|
|
"""Testet, dass DashboardModule.get_html() existiert."""
|
|
html = dashboard_module.get_html()
|
|
assert isinstance(html, str)
|
|
assert len(html) > 0
|
|
|
|
def test_dashboard_has_get_js(self, dashboard_module):
|
|
"""Testet, dass DashboardModule.get_js() existiert."""
|
|
js = dashboard_module.get_js()
|
|
assert isinstance(js, str)
|
|
assert len(js) > 0
|
|
|
|
def test_dashboard_panel_id_in_html(self, dashboard_module):
|
|
"""Testet, dass panel-dashboard in HTML vorhanden ist."""
|
|
html = dashboard_module.get_html()
|
|
assert 'id="panel-dashboard"' in html, \
|
|
"Dashboard HTML muss panel-dashboard ID haben"
|
|
|
|
def test_dashboard_css_has_panel_styles(self, dashboard_module):
|
|
"""Testet, dass CSS fuer .panel-dashboard vorhanden ist."""
|
|
css = dashboard_module.get_css()
|
|
assert '.panel-dashboard' in css, \
|
|
"Dashboard CSS muss .panel-dashboard Styles haben"
|
|
|
|
def test_dashboard_has_module_cards(self, dashboard_module):
|
|
"""Testet, dass Dashboard Modul-Kacheln hat."""
|
|
html = dashboard_module.get_html()
|
|
assert 'dashboard-card' in html, \
|
|
"Dashboard muss Modul-Kacheln haben"
|
|
|
|
def test_dashboard_has_all_module_links(self, dashboard_module):
|
|
"""Testet, dass Dashboard Links zu allen Modulen hat."""
|
|
html = dashboard_module.get_html()
|
|
expected_modules = ['worksheets', 'correction', 'jitsi', 'letters', 'messenger']
|
|
for module in expected_modules:
|
|
assert f"loadModule('{module}')" in html, \
|
|
f"Dashboard muss Link zu {module} Modul haben"
|
|
|
|
def test_dashboard_js_has_load_function(self, dashboard_module):
|
|
"""Testet, dass Dashboard JS eine Load-Funktion hat."""
|
|
js = dashboard_module.get_js()
|
|
assert 'function loadDashboardModule' in js, \
|
|
"Dashboard JS muss loadDashboardModule Funktion haben"
|
|
|
|
|
|
class TestBaseLayoutModule:
|
|
"""Tests fuer das BaseLayoutModule."""
|
|
|
|
@pytest.fixture
|
|
def base_module(self):
|
|
from frontend.modules.base import BaseLayoutModule
|
|
return BaseLayoutModule
|
|
|
|
def test_base_has_sidebar(self, base_module):
|
|
"""Testet, dass Base HTML eine Sidebar hat."""
|
|
html = base_module.get_html()
|
|
assert '<aside class="sidebar">' in html, \
|
|
"Base HTML muss Sidebar haben"
|
|
|
|
def test_base_sidebar_has_dashboard_link(self, base_module):
|
|
"""Testet, dass Sidebar einen Dashboard-Link hat."""
|
|
html = base_module.get_html()
|
|
assert "loadModule('dashboard')" in html, \
|
|
"Sidebar muss Dashboard-Link haben"
|
|
|
|
def test_base_has_theme_toggle(self, base_module):
|
|
"""Testet, dass Base HTML Theme Toggle hat."""
|
|
html = base_module.get_html()
|
|
assert 'id="theme-toggle"' in html, \
|
|
"Base HTML muss Theme Toggle haben"
|
|
|
|
def test_base_js_has_theme_toggle_init(self, base_module):
|
|
"""Testet, dass Base JS initThemeToggle hat."""
|
|
js = base_module.get_js()
|
|
assert 'function initThemeToggle' in js, \
|
|
"Base JS muss initThemeToggle Funktion haben"
|
|
|
|
def test_base_js_has_load_module_function(self, base_module):
|
|
"""Testet, dass Base JS loadModule Funktion hat."""
|
|
js = base_module.get_js()
|
|
assert 'function loadModule' in js, \
|
|
"Base JS muss loadModule Funktion haben"
|
|
|
|
def test_base_panel_ids_include_dashboard(self, base_module):
|
|
"""Testet, dass PANEL_IDS dashboard enthaelt."""
|
|
js = base_module.get_js()
|
|
assert "'panel-dashboard'" in js, \
|
|
"PANEL_IDS muss panel-dashboard enthalten"
|
|
|
|
def test_base_default_module_is_dashboard(self, base_module):
|
|
"""Testet, dass das Default-Modul Dashboard ist."""
|
|
js = base_module.get_js()
|
|
assert "let currentModule = 'dashboard'" in js, \
|
|
"Default-Modul muss dashboard sein"
|
|
|
|
|
|
class TestStudioModularGeneration:
|
|
"""Tests fuer die vollstaendige HTML-Generierung."""
|
|
|
|
@pytest.fixture
|
|
def generated_html(self):
|
|
from frontend.studio_modular import get_studio_html
|
|
return get_studio_html()
|
|
|
|
def test_generated_html_has_doctype(self, generated_html):
|
|
"""Testet, dass generiertes HTML DOCTYPE hat."""
|
|
assert '<!DOCTYPE html>' in generated_html
|
|
|
|
def test_generated_html_has_dashboard_panel(self, generated_html):
|
|
"""Testet, dass Dashboard Panel enthalten ist."""
|
|
assert 'id="panel-dashboard"' in generated_html
|
|
|
|
def test_generated_html_has_all_module_panels(self, generated_html):
|
|
"""Testet, dass alle fertig implementierten Modul-Panels enthalten sind."""
|
|
# Diese Panels muessen vorhanden sein (vollstaendig implementiert)
|
|
required_panels = [
|
|
'panel-dashboard',
|
|
'panel-worksheets',
|
|
'panel-correction',
|
|
]
|
|
for panel in required_panels:
|
|
assert f'id="{panel}"' in generated_html, \
|
|
f"Generated HTML muss {panel} enthalten"
|
|
|
|
# Diese Panels sind optional (noch in Entwicklung)
|
|
optional_panels = ['panel-jitsi', 'panel-letters']
|
|
for panel in optional_panels:
|
|
if f'id="{panel}"' not in generated_html:
|
|
import warnings
|
|
warnings.warn(f"{panel} noch nicht vollstaendig implementiert")
|
|
|
|
def test_generated_html_has_theme_toggle(self, generated_html):
|
|
"""Testet, dass Theme Toggle im generierten HTML ist."""
|
|
assert 'id="theme-toggle"' in generated_html
|
|
|
|
def test_generated_html_has_sidebar_dashboard(self, generated_html):
|
|
"""Testet, dass Sidebar Dashboard-Link hat."""
|
|
assert 'id="sidebar-dashboard"' in generated_html
|
|
|
|
def test_generated_html_has_dom_content_loaded(self, generated_html):
|
|
"""Testet, dass DOMContentLoaded Handler vorhanden ist."""
|
|
assert "document.addEventListener('DOMContentLoaded'" in generated_html
|
|
|
|
def test_generated_html_calls_init_theme_toggle(self, generated_html):
|
|
"""Testet, dass initThemeToggle aufgerufen wird."""
|
|
assert 'initThemeToggle()' in generated_html
|
|
|
|
def test_generated_html_loads_dashboard_by_default(self, generated_html):
|
|
"""Testet, dass Dashboard standardmaessig geladen wird."""
|
|
assert "loadModule('dashboard')" in generated_html
|
|
|
|
def test_generated_html_size_reasonable(self, generated_html):
|
|
"""Testet, dass generiertes HTML eine angemessene Groesse hat."""
|
|
size = len(generated_html)
|
|
assert size > 100000, f"HTML zu klein ({size} Zeichen)"
|
|
assert size < 600000, f"HTML zu gross ({size} Zeichen)"
|
|
|
|
|
|
class TestThemeToggleFunctionality:
|
|
"""Tests fuer Theme Toggle Funktionalitaet."""
|
|
|
|
@pytest.fixture
|
|
def generated_html(self):
|
|
from frontend.studio_modular import get_studio_html
|
|
return get_studio_html()
|
|
|
|
def test_theme_toggle_button_structure(self, generated_html):
|
|
"""Testet die Theme Toggle Button Struktur."""
|
|
# Button muss existieren
|
|
assert '<button class="theme-toggle"' in generated_html
|
|
assert 'id="theme-toggle"' in generated_html
|
|
|
|
def test_theme_toggle_has_icon_element(self, generated_html):
|
|
"""Testet, dass Theme Toggle Icon-Element hat."""
|
|
assert 'id="theme-icon"' in generated_html
|
|
|
|
def test_theme_toggle_has_label_element(self, generated_html):
|
|
"""Testet, dass Theme Toggle Label-Element hat."""
|
|
assert 'id="theme-label"' in generated_html
|
|
|
|
def test_light_theme_css_exists(self, generated_html):
|
|
"""Testet, dass Light Theme CSS vorhanden ist."""
|
|
assert '[data-theme="light"]' in generated_html
|
|
|
|
def test_theme_persistence_code_exists(self, generated_html):
|
|
"""Testet, dass Theme in localStorage gespeichert wird."""
|
|
assert "localStorage.setItem('bp-theme'" in generated_html
|
|
assert "localStorage.getItem('bp-theme')" in generated_html
|
|
|
|
|
|
class TestModuleNavigation:
|
|
"""Tests fuer Modul-Navigation."""
|
|
|
|
@pytest.fixture
|
|
def generated_html(self):
|
|
from frontend.studio_modular import get_studio_html
|
|
return get_studio_html()
|
|
|
|
def test_all_sidebar_items_exist(self, generated_html):
|
|
"""Testet, dass alle Sidebar-Items vorhanden sind."""
|
|
expected_items = [
|
|
'sidebar-dashboard',
|
|
'sidebar-worksheets',
|
|
'sidebar-correction',
|
|
'sidebar-jitsi',
|
|
'sidebar-letters',
|
|
'sidebar-messenger',
|
|
]
|
|
for item in expected_items:
|
|
assert f'id="{item}"' in generated_html, \
|
|
f"Sidebar muss {item} enthalten"
|
|
|
|
def test_hide_all_panels_function_exists(self, generated_html):
|
|
"""Testet, dass hideAllPanels Funktion existiert."""
|
|
assert 'function hideAllPanels' in generated_html
|
|
|
|
def test_show_panel_function_exists(self, generated_html):
|
|
"""Testet, dass showPanel Funktion existiert."""
|
|
assert 'function showPanel' in generated_html
|
|
|
|
|
|
if __name__ == '__main__':
|
|
pytest.main([__file__, '-v'])
|