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