From 2f9de759ebd21912e4e8ede37be0c160fd40acd3 Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Mon, 16 Feb 2026 23:06:55 +0100 Subject: [PATCH] feat(teamsbot): show per-variant logs in auth test UI, single direct /v2/ test Co-authored-by: Cursor --- src/api/teamsbotApi.ts | 1 + src/pages/views/teamsbot/Teamsbot.module.css | 63 +++++++++ .../views/teamsbot/TeamsbotSettingsView.tsx | 121 ++++++++++++------ 3 files changed, 149 insertions(+), 36 deletions(-) diff --git a/src/api/teamsbotApi.ts b/src/api/teamsbotApi.ts index 4ba16c9..0aa036d 100644 --- a/src/api/teamsbotApi.ts +++ b/src/api/teamsbotApi.ts @@ -131,6 +131,7 @@ export interface AuthTestResult { durationMs: number; error?: string; detectedSignals: string[]; + logs: string[]; } export interface AuthTestResults { diff --git a/src/pages/views/teamsbot/Teamsbot.module.css b/src/pages/views/teamsbot/Teamsbot.module.css index cfc6997..af8e16f 100644 --- a/src/pages/views/teamsbot/Teamsbot.module.css +++ b/src/pages/views/teamsbot/Teamsbot.module.css @@ -732,6 +732,69 @@ max-width: 250px; } +/* Variant cell with expand toggle */ +.testVariantCell { + display: flex; + align-items: center; + gap: 0.35rem; +} + +.testLogToggle { + display: inline-flex; + align-items: center; + justify-content: center; + background: none; + border: none; + cursor: pointer; + padding: 0.15rem; + font-size: 0.7rem; + color: var(--text-secondary, #666); + border-radius: 3px; + flex-shrink: 0; +} + +.testLogToggle:hover { + background: var(--surface-alt, #f5f5f5); + color: var(--primary-color, #4A90D9); +} + +/* Log row */ +.testLogRow td { + padding: 0 !important; + border-top: none !important; +} + +.testLogContainer { + background: var(--surface-dark, #1e1e1e); + color: var(--text-light, #d4d4d4); + font-family: 'Fira Code', 'Consolas', 'Courier New', monospace; + font-size: 0.72rem; + line-height: 1.5; + padding: 0.5rem 0.75rem; + max-height: 200px; + overflow-y: auto; + border-radius: 0 0 4px 4px; + margin: 0 0.5rem 0.5rem; +} + +.testLogLine { + white-space: pre-wrap; + word-break: break-all; + padding: 0.05rem 0; +} + +.testLogInfo { + color: var(--text-light, #d4d4d4); +} + +.testLogWarn { + color: #e5a100; +} + +.testLogError { + color: #f14c4c; +} + @keyframes spin { to { transform: rotate(360deg); } } diff --git a/src/pages/views/teamsbot/TeamsbotSettingsView.tsx b/src/pages/views/teamsbot/TeamsbotSettingsView.tsx index b64a427..1234616 100644 --- a/src/pages/views/teamsbot/TeamsbotSettingsView.tsx +++ b/src/pages/views/teamsbot/TeamsbotSettingsView.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect, useCallback, useRef } from 'react'; import { useCurrentInstance } from '../../../hooks/useCurrentInstance'; import * as teamsbotApi from '../../../api/teamsbotApi'; import type { TeamsbotConfig, ConfigUpdateRequest, VoiceOption, AuthTestResults, AuthTestResult } from '../../../api/teamsbotApi'; -import { FaPlay, FaSpinner, FaFlask, FaImage } from 'react-icons/fa'; +import { FaPlay, FaSpinner, FaFlask, FaImage, FaChevronDown, FaChevronRight } from 'react-icons/fa'; import styles from './Teamsbot.module.css'; /** Format voice name for display: "de-DE-Wavenet-A" -> "Wavenet A" + gender */ @@ -43,6 +43,7 @@ export const TeamsbotSettingsView: React.FC = () => { const [testResults, setTestResults] = useState(null); const [testError, setTestError] = useState(null); const [screenshotPreview, setScreenshotPreview] = useState<{ src: string; caption: string } | null>(null); + const [expandedLogs, setExpandedLogs] = useState>(new Set()); const _loadConfig = useCallback(async () => { if (!instanceId) return; @@ -189,6 +190,28 @@ export const TeamsbotSettingsView: React.FC = () => { return `${(ms / 1000).toFixed(1)}s`; }; + const _toggleLogs = (variantId: string) => { + setExpandedLogs(prev => { + const next = new Set(prev); + if (next.has(variantId)) { + next.delete(variantId); + } else { + next.add(variantId); + } + return next; + }); + }; + + const _getLogLevelClass = (log: string): string => { + if (log.startsWith('[ERROR]') || log.startsWith('[CONSOLE:error]') || log.startsWith('[PAGE_ERROR]')) { + return styles.testLogError; + } + if (log.startsWith('[WARN]') || log.startsWith('[CONSOLE:warning]')) { + return styles.testLogWarn; + } + return styles.testLogInfo; + }; + if (loading) return
Lade Konfiguration...
; return ( @@ -206,7 +229,7 @@ export const TeamsbotSettingsView: React.FC = () => {

Auth-Erkennung testen

- Testet 5 Browser-Konfigurationen gegen einen aktiven Teams-Call. + Testet Direct-/v2/-Navigation gegen einen aktiven Teams-Call. Prueft ob Teams /v2/ (Auth moeglich) oder light-meetings (anonym erzwungen) liefert. Der Bot tritt dem Meeting NICHT bei. @@ -233,7 +256,7 @@ export const TeamsbotSettingsView: React.FC = () => { {testRunning && (
- 5 Varianten werden sequentiell getestet (~2-3 Minuten)... + Test laeuft (~30-45 Sekunden)...
)} @@ -256,40 +279,66 @@ export const TeamsbotSettingsView: React.FC = () => { {testResults.variants.map((result) => ( - - - {result.variantName} - {result.error && ( -
- {result.error} + + + +
+ {result.logs && result.logs.length > 0 && ( + + )} + {result.variantName}
- )} - - {_getPageTypeBadge(result)} - {result.success ? _getCheckmark(result.hasSignInLink) : } - {result.success ? _getCheckmark(result.hasNameInput) : } - {result.success ? _getCheckmark(result.hasJoinButton) : } - - {result.authAttempted - ? (result.authSuccess ? Erfolgreich : Fehlgeschlagen) - : - } - - {_formatDuration(result.durationMs)} - - {result.screenshot && ( - - )} - - + {result.error && ( +
+ {result.error.length > 120 ? result.error.substring(0, 120) + '...' : result.error} +
+ )} + + {_getPageTypeBadge(result)} + {result.success ? _getCheckmark(result.hasSignInLink) : } + {result.success ? _getCheckmark(result.hasNameInput) : } + {result.success ? _getCheckmark(result.hasJoinButton) : } + + {result.authAttempted + ? (result.authSuccess ? Erfolgreich : Fehlgeschlagen) + : + } + + {_formatDuration(result.durationMs)} + + {result.screenshot && ( + + )} + + + {expandedLogs.has(result.variantId) && result.logs && result.logs.length > 0 && ( + + +
+ {result.logs.map((log, idx) => ( +
+ {log} +
+ ))} +
+ + + )} +
))}