From 2bb0dd20cc2e89c787237d55d944942fb2f130c5 Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Mon, 16 Feb 2026 23:06:53 +0100 Subject: [PATCH] feat: replace failed variants 1-5 with direct /v2/ test, add per-variant logs Co-authored-by: Cursor --- src/bot/authTestProcedure.ts | 152 ++++++++++++++++++++++++++--------- 1 file changed, 114 insertions(+), 38 deletions(-) diff --git a/src/bot/authTestProcedure.ts b/src/bot/authTestProcedure.ts index 5e16c44..d983cb7 100644 --- a/src/bot/authTestProcedure.ts +++ b/src/bot/authTestProcedure.ts @@ -27,6 +27,7 @@ export interface AuthTestResult { durationMs: number; error?: string; detectedSignals: string[]; + logs: string[]; } export interface AuthTestResults { @@ -42,29 +43,9 @@ export interface AuthTestResults { const _VARIANTS: AuthTestVariant[] = [ { - id: 'baseline', - name: 'Baseline (aktuell)', - description: 'Vanilla Playwright headless, basic stealth, anon=true', - }, - { - id: 'rebrowser', - name: 'rebrowser-playwright', - description: 'rebrowser-playwright headless, CDP-Leak-Fixes, ohne anon', - }, - { - id: 'playwrightExtra', - name: 'playwright-extra + stealth', - description: 'playwright-extra mit stealth plugin headless, ohne anon', - }, - { - id: 'headful', - name: 'Headful', - description: 'Playwright headful (headless: false), enhanced stealth, ohne anon', - }, - { - id: 'headfulAuth', - name: 'Headful + Auth', - description: 'Playwright headful mit vollstaendigem Auth-Flow (System-Bot Credentials)', + id: 'headfulDirect', + name: 'Headful + Direct /v2/', + description: 'Playwright headful, navigiert direkt zu /v2/ URL (umgeht launcher.html komplett)', }, ]; @@ -90,7 +71,7 @@ const _BROWSER_ARGS = [ // ============================================================================ /** - * Run all 5 auth detection test variants against a Teams meeting URL. + * Run all 6 auth detection test variants against a Teams meeting URL. * Does NOT join the meeting — only checks which page Teams serves. */ export async function runAuthTests( @@ -144,6 +125,15 @@ async function _runVariant( const startTime = Date.now(); let browser: Browser | null = null; let context: BrowserContext | null = null; + const variantLogs: string[] = []; + + const _log = (level: 'info' | 'warn' | 'error', msg: string) => { + const prefix = `[${level.toUpperCase()}]`; + variantLogs.push(`${prefix} ${msg}`); + if (level === 'error') logger.error(`[AuthTest:${variant.id}] ${msg}`); + else if (level === 'warn') logger.warn(`[AuthTest:${variant.id}] ${msg}`); + else logger.info(`[AuthTest:${variant.id}] ${msg}`); + }; try { // Launch browser based on variant @@ -152,29 +142,69 @@ async function _runVariant( context = launchResult.context; const page = launchResult.page; - // Resolve meeting URL (with or without anon=true) - const useAnon = variant.id === 'baseline'; - const launchUrl = await _resolveMeetingUrl(meetingUrl, useAnon); - logger.info(`[AuthTest:${variant.id}] Navigating to: ${launchUrl.substring(0, 100)}`); - - // Navigate to meeting - await page.goto(launchUrl, { - waitUntil: 'domcontentloaded', - timeout: 30000, + // Collect browser console messages + page.on('console', (msg) => { + const type = msg.type(); + if (type === 'error' || type === 'warning') { + variantLogs.push(`[CONSOLE:${type}] ${msg.text().substring(0, 200)}`); + } }); - // Handle launcher dialog ("Continue on this browser") - await _handleLauncher(page); + // Collect page errors + page.on('pageerror', (err) => { + variantLogs.push(`[PAGE_ERROR] ${String(err).substring(0, 200)}`); + }); - // Wait for the pre-join page to settle - await page.waitForTimeout(5000); + // Track navigation/redirects + page.on('framenavigated', (frame) => { + if (frame === page.mainFrame()) { + variantLogs.push(`[NAV] ${frame.url().substring(0, 150)}`); + } + }); + + if (variant.id === 'headfulDirect') { + // Variant 6: Navigate directly to /v2/ URL, bypassing launcher.html entirely + const directUrl = _buildDirectV2Url(meetingUrl); + _log('info', `Direct /v2/ navigation: ${directUrl.substring(0, 120)}`); + + await page.goto(directUrl, { + waitUntil: 'domcontentloaded', + timeout: 30000, + }); + + // Wait and log where Teams actually redirects to + await page.waitForTimeout(8000); + const currentUrl = page.url(); + _log('info', `After redirect: ${currentUrl.substring(0, 120)}`); + + if (currentUrl.includes('light-meetings')) { + _log('warn', 'Teams redirected /v2/ to light-meetings'); + } else if (currentUrl.includes('/v2/')) { + _log('info', '/v2/ page loaded successfully!'); + } + } else { + // Standard flow: resolve URL, navigate, click launcher + const useAnon = variant.id === 'baseline'; + const launchUrl = await _resolveMeetingUrl(meetingUrl, useAnon); + _log('info', `Navigating to: ${launchUrl.substring(0, 100)}`); + + await page.goto(launchUrl, { + waitUntil: 'domcontentloaded', + timeout: 30000, + }); + + await _handleLauncher(page); + await page.waitForTimeout(5000); + } // If this is the auth variant, attempt login let authAttempted = false; let authSuccess: boolean | null = null; if (variant.id === 'headfulAuth' && botAccountEmail && botAccountPassword) { authAttempted = true; + _log('info', `Attempting auth as ${botAccountEmail}`); authSuccess = await _attemptAuth(page, botAccountEmail, botAccountPassword); + _log(authSuccess ? 'info' : 'warn', `Auth result: ${authSuccess ? 'success' : 'failed'}`); } // Detect page type and gather signals @@ -197,8 +227,11 @@ async function _runVariant( screenshot, durationMs: Date.now() - startTime, detectedSignals: detection.signals, + logs: variantLogs, }; } catch (err) { + _log('error', `Variant failed: ${String(err).substring(0, 300)}`); + // Try to take an error screenshot let screenshot: string | undefined; try { @@ -227,9 +260,9 @@ async function _runVariant( durationMs: Date.now() - startTime, error: String(err), detectedSignals: [], + logs: variantLogs, }; } finally { - // Clean up browser try { if (context) await context.close(); if (browser) await browser.close(); @@ -268,6 +301,10 @@ async function _launchBrowserForVariant(variant: AuthTestVariant): Promise