fix: Restore all files lost during destructive rebase
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>
This commit is contained in:
@@ -3,18 +3,22 @@
|
||||
/**
|
||||
* Test Dashboard - Zentrales Test-Registry
|
||||
*
|
||||
* Aggregiert alle 195+ Tests aus allen Services:
|
||||
* Aggregiert alle 280+ Tests aus allen Services:
|
||||
* - Go Unit Tests (~57)
|
||||
* - Python Tests (~50)
|
||||
* - BQAS Golden (97)
|
||||
* - BQAS RAG (~20)
|
||||
* - TypeScript Jest (~8)
|
||||
* - SDK Vitest Unit Tests (~43)
|
||||
* - SDK Playwright E2E (~25)
|
||||
* - E2E Playwright (~5)
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { PagePurpose } from '@/components/common/PagePurpose'
|
||||
import { DevOpsPipelineSidebarResponsive } from '@/components/infrastructure/DevOpsPipelineSidebar'
|
||||
import type { LLMRoutingOption } from '@/types/infrastructure-modules'
|
||||
import type {
|
||||
ServiceTestInfo,
|
||||
TestRegistryStats,
|
||||
@@ -344,6 +348,7 @@ function FrameworkDistribution({ data }: { data: Record<string, number> }) {
|
||||
go_test: 'Go Tests',
|
||||
pytest: 'Python (pytest)',
|
||||
jest: 'Jest (TS)',
|
||||
vitest: 'Vitest (SDK)',
|
||||
playwright: 'Playwright (E2E)',
|
||||
bqas_golden: 'BQAS Golden',
|
||||
bqas_rag: 'BQAS RAG',
|
||||
@@ -354,6 +359,7 @@ function FrameworkDistribution({ data }: { data: Record<string, number> }) {
|
||||
go_test: 'bg-cyan-500',
|
||||
pytest: 'bg-yellow-500',
|
||||
jest: 'bg-blue-500',
|
||||
vitest: 'bg-orange-500',
|
||||
playwright: 'bg-purple-500',
|
||||
bqas_golden: 'bg-emerald-500',
|
||||
bqas_rag: 'bg-teal-500',
|
||||
@@ -454,15 +460,16 @@ function GuideTab() {
|
||||
Was ist das Test Dashboard?
|
||||
</h2>
|
||||
<p className="text-slate-700 leading-relaxed">
|
||||
Das <strong>Test Dashboard</strong> ist die zentrale Uebersicht fuer alle 195+ Tests im Breakpilot-System.
|
||||
Das <strong>Test Dashboard</strong> ist die zentrale Uebersicht fuer alle 260+ Tests im Breakpilot-System.
|
||||
Es aggregiert Tests aus verschiedenen Services (Go, Python, TypeScript) ohne diese physisch zu migrieren.
|
||||
Tests bleiben an ihren konventionellen Orten, werden aber hier zentral ueberwacht und ausgefuehrt.
|
||||
Seit 2026-02 inklusive AI Compliance SDK Unit Tests (Vitest) und E2E Tests (Playwright).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Test-Kategorien</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div className="p-4 bg-cyan-50 rounded-lg border border-cyan-200">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className="text-xl">🐹</span>
|
||||
@@ -508,41 +515,70 @@ function GuideTab() {
|
||||
Website Unit Tests fuer React-Komponenten
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4 bg-orange-50 rounded-lg border border-orange-200">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className="text-xl">⚡</span>
|
||||
<h4 className="font-medium text-orange-800">SDK Vitest (~43)</h4>
|
||||
</div>
|
||||
<p className="text-sm text-orange-700">
|
||||
AI Compliance SDK Unit Tests: Types, Export, Components, Reducer
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4 bg-purple-50 rounded-lg border border-purple-200">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className="text-xl">🎭</span>
|
||||
<h4 className="font-medium text-purple-800">E2E Playwright (~5)</h4>
|
||||
<h4 className="font-medium text-purple-800">SDK Playwright (~25)</h4>
|
||||
</div>
|
||||
<p className="text-sm text-purple-700">
|
||||
SDK E2E Tests: Navigation, Workflow, Command Bar, Export
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4 bg-slate-50 rounded-lg border border-slate-200">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className="text-xl">🌐</span>
|
||||
<h4 className="font-medium text-slate-800">Website E2E (~5)</h4>
|
||||
</div>
|
||||
<p className="text-sm text-slate-700">
|
||||
End-to-End Tests fuer kritische User Flows
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4 bg-indigo-50 rounded-lg border border-indigo-200">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className="text-xl">🔗</span>
|
||||
<h4 className="font-medium text-indigo-800">Integration Tests (~15)</h4>
|
||||
</div>
|
||||
<p className="text-sm text-indigo-700">
|
||||
Docker Compose basierte E2E-Tests mit Backend, Consent-Service, DB
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Architektur</h3>
|
||||
<pre className="bg-slate-50 p-4 rounded-lg text-xs overflow-x-auto">
|
||||
{`┌────────────────────────────────────────────────────────────┐
|
||||
│ Admin-v2 Test Dashboard │
|
||||
│ /infrastructure/tests │
|
||||
├────────────────────────────────────────────────────────────┤
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Unit Tests │ │ Integration │ │ BQAS │ │
|
||||
│ │ (Go, Py) │ │ Tests │ │ (LLM/RAG) │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌────────────────────────────────────────────────────┐ │
|
||||
│ │ Test Registry API │ │
|
||||
│ │ /backend/api/tests/registry.py │ │
|
||||
│ └────────────────────────────────────────────────────┘ │
|
||||
└────────────────────────────────────────────────────────────┘
|
||||
{`┌────────────────────────────────────────────────────────────────────┐
|
||||
│ Admin-v2 Test Dashboard │
|
||||
│ /infrastructure/tests │
|
||||
├────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────────┐ │
|
||||
│ │ Unit Tests │ │ SDK Tests │ │ BQAS │ │ E2E Tests │ │
|
||||
│ │ (Go, Py) │ │ (Vitest) │ │ (LLM/RAG) │ │ (Playwright)│ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ └─────────────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ ▼ ▼ ▼ ▼ │
|
||||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Test Registry API │ │
|
||||
│ │ /backend/api/tests/registry.py │ │
|
||||
│ └──────────────────────────────────────────────────────────────┘ │
|
||||
└────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
Tests bleiben wo sie sind:
|
||||
- /consent-service/internal/**/*_test.go
|
||||
- /backend/tests/test_*.py
|
||||
- /voice-service/tests/bqas/`}
|
||||
- /voice-service/tests/bqas/
|
||||
- /admin-v2/components/sdk/__tests__/*.test.ts (Vitest)
|
||||
- /admin-v2/e2e/specs/*.spec.ts (Playwright)`}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@@ -792,6 +828,8 @@ function BacklogTab({
|
||||
const [filterStatus, setFilterStatus] = useState<string>('open')
|
||||
const [filterService, setFilterService] = useState<string>('all')
|
||||
const [filterPriority, setFilterPriority] = useState<string>('all')
|
||||
const [llmAutoAnalysis, setLlmAutoAnalysis] = useState<boolean>(true)
|
||||
const [llmRouting, setLlmRouting] = useState<LLMRoutingOption>('smart_routing')
|
||||
|
||||
// Nutze PostgreSQL-Backlog wenn verfuegbar, sonst Legacy
|
||||
const items = usePostgres && backlogItems ? backlogItems : failedTests
|
||||
@@ -881,6 +919,93 @@ function BacklogTab({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* LLM Analysis Toggle */}
|
||||
<div className="bg-gradient-to-r from-violet-50 to-purple-50 border border-violet-200 rounded-xl p-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 bg-violet-100 rounded-lg flex items-center justify-center">
|
||||
<svg className="w-5 h-5 text-violet-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-medium text-slate-800">Automatische LLM-Analyse</h4>
|
||||
<p className="text-xs text-slate-500">KI-gestuetzte Fix-Vorschlaege fuer Backlog-Eintraege</p>
|
||||
</div>
|
||||
</div>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={llmAutoAnalysis}
|
||||
onChange={(e) => setLlmAutoAnalysis(e.target.checked)}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-slate-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-violet-300 rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-violet-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{llmAutoAnalysis && (
|
||||
<div className="mt-4 pt-4 border-t border-violet-200">
|
||||
<p className="text-xs text-slate-600 mb-3">LLM-Routing Strategie:</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<label className={`flex items-center gap-2 px-3 py-2 rounded-lg border cursor-pointer transition-colors ${
|
||||
llmRouting === 'local_only'
|
||||
? 'bg-violet-100 border-violet-300 text-violet-800'
|
||||
: 'bg-white border-slate-200 text-slate-600 hover:bg-slate-50'
|
||||
}`}>
|
||||
<input
|
||||
type="radio"
|
||||
name="llm-routing"
|
||||
value="local_only"
|
||||
checked={llmRouting === 'local_only'}
|
||||
onChange={() => setLlmRouting('local_only')}
|
||||
className="sr-only"
|
||||
/>
|
||||
<span className="text-sm font-medium">Nur lokales 32B LLM</span>
|
||||
<span className="text-xs px-1.5 py-0.5 bg-emerald-100 text-emerald-700 rounded">DSGVO</span>
|
||||
</label>
|
||||
<label className={`flex items-center gap-2 px-3 py-2 rounded-lg border cursor-pointer transition-colors ${
|
||||
llmRouting === 'claude_preferred'
|
||||
? 'bg-violet-100 border-violet-300 text-violet-800'
|
||||
: 'bg-white border-slate-200 text-slate-600 hover:bg-slate-50'
|
||||
}`}>
|
||||
<input
|
||||
type="radio"
|
||||
name="llm-routing"
|
||||
value="claude_preferred"
|
||||
checked={llmRouting === 'claude_preferred'}
|
||||
onChange={() => setLlmRouting('claude_preferred')}
|
||||
className="sr-only"
|
||||
/>
|
||||
<span className="text-sm font-medium">Claude bevorzugt</span>
|
||||
<span className="text-xs px-1.5 py-0.5 bg-blue-100 text-blue-700 rounded">Qualitaet</span>
|
||||
</label>
|
||||
<label className={`flex items-center gap-2 px-3 py-2 rounded-lg border cursor-pointer transition-colors ${
|
||||
llmRouting === 'smart_routing'
|
||||
? 'bg-violet-100 border-violet-300 text-violet-800'
|
||||
: 'bg-white border-slate-200 text-slate-600 hover:bg-slate-50'
|
||||
}`}>
|
||||
<input
|
||||
type="radio"
|
||||
name="llm-routing"
|
||||
value="smart_routing"
|
||||
checked={llmRouting === 'smart_routing'}
|
||||
onChange={() => setLlmRouting('smart_routing')}
|
||||
className="sr-only"
|
||||
/>
|
||||
<span className="text-sm font-medium">Smart Routing</span>
|
||||
<span className="text-xs px-1.5 py-0.5 bg-amber-100 text-amber-700 rounded">Empfohlen</span>
|
||||
</label>
|
||||
</div>
|
||||
<p className="text-xs text-slate-500 mt-2">
|
||||
{llmRouting === 'local_only' && 'Alle Analysen werden mit Qwen2.5-32B lokal durchgefuehrt. Keine Daten verlassen den Server.'}
|
||||
{llmRouting === 'claude_preferred' && 'Verwendet Claude fuer beste Fix-Qualitaet. Nur Code-Snippets werden uebertragen.'}
|
||||
{llmRouting === 'smart_routing' && 'Privacy Classifier entscheidet automatisch: Sensitive Daten → lokal, Code → Claude.'}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Filter */}
|
||||
<div className="flex flex-wrap gap-4 items-center">
|
||||
<div>
|
||||
@@ -1066,18 +1191,21 @@ export default function TestDashboardPage() {
|
||||
{ service: 'klausur-service', display_name: 'Klausur Service', port: 8086, language: 'python', total_tests: 8, passed_tests: 8, failed_tests: 0, skipped_tests: 0, pass_rate: 100, coverage_percent: 71.2, last_run: new Date().toISOString(), status: 'passed' },
|
||||
{ service: 'billing-service', display_name: 'Billing Service', port: 8082, language: 'go', total_tests: 5, passed_tests: 5, failed_tests: 0, skipped_tests: 0, pass_rate: 100, coverage_percent: 78.5, last_run: new Date().toISOString(), status: 'passed' },
|
||||
{ service: 'school-service', display_name: 'School Service', port: 8084, language: 'go', total_tests: 6, passed_tests: 6, failed_tests: 0, skipped_tests: 0, pass_rate: 100, coverage_percent: 81.4, last_run: new Date().toISOString(), status: 'passed' },
|
||||
{ service: 'sdk-unit', display_name: 'SDK Unit Tests (Vitest)', port: undefined, language: 'typescript', total_tests: 43, passed_tests: 43, failed_tests: 0, skipped_tests: 0, pass_rate: 100, coverage_percent: 85.2, last_run: new Date().toISOString(), status: 'passed' },
|
||||
{ service: 'sdk-e2e', display_name: 'SDK E2E Tests (Playwright)', port: undefined, language: 'typescript', total_tests: 25, passed_tests: 25, failed_tests: 0, skipped_tests: 0, pass_rate: 100, coverage_percent: undefined, last_run: new Date().toISOString(), status: 'passed' },
|
||||
{ service: 'integration-tests', display_name: 'Integration Tests', port: undefined, language: 'python', total_tests: 15, passed_tests: 15, failed_tests: 0, skipped_tests: 0, pass_rate: 100, coverage_percent: undefined, last_run: new Date().toISOString(), status: 'passed' },
|
||||
]
|
||||
|
||||
const DEMO_STATS: TestRegistryStats = {
|
||||
total_tests: 195,
|
||||
total_passed: 180,
|
||||
total_tests: 278,
|
||||
total_passed: 263,
|
||||
total_failed: 15,
|
||||
total_skipped: 0,
|
||||
overall_pass_rate: 92.3,
|
||||
average_coverage: 76.8,
|
||||
services_count: 8,
|
||||
by_category: { unit: 75, bqas: 117, e2e: 5 },
|
||||
by_framework: { go_test: 57, pytest: 53, bqas_golden: 97, bqas_rag: 20, jest: 8, playwright: 5 },
|
||||
overall_pass_rate: 94.6,
|
||||
average_coverage: 78.5,
|
||||
services_count: 11,
|
||||
by_category: { unit: 118, bqas: 117, e2e: 30, integration: 15 },
|
||||
by_framework: { go_test: 57, pytest: 68, bqas_golden: 97, bqas_rag: 20, jest: 8, vitest: 43, playwright: 30 },
|
||||
}
|
||||
|
||||
// Fetch data
|
||||
@@ -1460,21 +1588,25 @@ export default function TestDashboardPage() {
|
||||
|
||||
<PagePurpose
|
||||
title="Test Dashboard"
|
||||
purpose="Zentrales Dashboard fuer alle 195+ Tests. Aggregiert Unit Tests (Go, Python), Integration Tests, E2E (Playwright) und BQAS Quality Tests aus allen Services ohne physische Migration."
|
||||
purpose="Zentrales Dashboard fuer alle 260+ Tests. Aggregiert Unit Tests (Go, Python), SDK Tests (Vitest), E2E Tests (Playwright) und BQAS Quality Tests aus allen Services ohne physische Migration."
|
||||
audience={['Entwickler', 'QA', 'DevOps']}
|
||||
architecture={{
|
||||
services: ['Python Backend (Port 8000)', 'Voice Service (Port 8091)'],
|
||||
databases: ['PostgreSQL'],
|
||||
services: ['Python Backend (Port 8000)', 'Voice Service (Port 8091)', 'SDK Backend (Port 8085)'],
|
||||
databases: ['PostgreSQL', 'Qdrant'],
|
||||
}}
|
||||
relatedPages={[
|
||||
{ name: 'BQAS Dashboard', href: '/ai/test-quality', description: 'Detaillierte LLM-Qualitaetsmetriken' },
|
||||
{ name: 'CI/CD', href: '/infrastructure/ci-cd', description: 'Pipelines und Deployments' },
|
||||
{ name: 'Security', href: '/infrastructure/security', description: 'DevSecOps Dashboard' },
|
||||
{ name: 'Developer Portal', href: '/developers', description: 'SDK & API Dokumentation' },
|
||||
]}
|
||||
collapsible={true}
|
||||
defaultCollapsed={true}
|
||||
/>
|
||||
|
||||
{/* DevOps Pipeline Sidebar */}
|
||||
<DevOpsPipelineSidebarResponsive currentTool="tests" />
|
||||
|
||||
{error && (
|
||||
<div className="p-4 bg-red-50 border border-red-200 rounded-lg text-red-700 flex items-center gap-3">
|
||||
<svg className="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
||||
Reference in New Issue
Block a user