From d93f10d2112cffab944981e1312cc8eab54298d6 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Tue, 17 Feb 2026 12:51:16 +0100
Subject: [PATCH] refactor: 5 browser variants all running Join a meeting flow,
remove Sign in path
Co-authored-by: Cursor
---
src/bot/authTestProcedure.ts | 159 ++++++++++++++++++++++-------------
1 file changed, 101 insertions(+), 58 deletions(-)
diff --git a/src/bot/authTestProcedure.ts b/src/bot/authTestProcedure.ts
index e10c0f3..ac95458 100644
--- a/src/bot/authTestProcedure.ts
+++ b/src/bot/authTestProcedure.ts
@@ -49,14 +49,29 @@ export interface AuthTestResults {
const _VARIANTS: AuthTestVariant[] = [
{
- id: 'signIn',
- name: 'Pfad: Sign in',
- description: 'Nach Login auf Teams-Landingpage "Sign in" klicken — was kommt?',
+ id: 'chromiumClean',
+ name: '1) Chromium Headful Clean',
+ description: 'Playwright Chromium headful, enhanced stealth + realistic devices',
},
{
- id: 'joinMeeting',
- name: 'Pfad: Join a meeting',
- description: 'Nach Login auf Teams-Landingpage "Join a meeting" klicken — was kommt?',
+ id: 'chromiumNoAutomation',
+ name: '2) Chromium No-Automation',
+ description: 'Chromium headful + --disable-extensions, --no-first-run',
+ },
+ {
+ id: 'rebrowserHeadful',
+ name: '3) rebrowser-playwright',
+ description: 'rebrowser-playwright headful, CDP-Leak-Fixes + realistic devices',
+ },
+ {
+ id: 'chromiumMinimal',
+ name: '4) Chromium Minimal',
+ description: 'Chromium headful, nur --no-sandbox (minimale Stealth)',
+ },
+ {
+ id: 'chromiumHeadless',
+ name: '5) Chromium Headless',
+ description: 'Chromium headless als Baseline-Vergleich',
},
];
@@ -86,13 +101,19 @@ const _BROWSER_ARGS_NO_AUTOMATION = [
'--disable-component-update',
];
+// Minimal args — just --no-sandbox, no stealth
+const _BROWSER_ARGS_MINIMAL = [
+ '--no-sandbox',
+ '--use-fake-ui-for-media-stream',
+];
+
// ============================================================================
// MAIN EXPORT
// ============================================================================
/**
- * Run auth tests: 2 variants — "Sign in" and "Join a meeting" on the Teams landing page.
- * Both do full Microsoft login first, then click different buttons to see what page loads.
+ * Run auth tests: 5 browser configs, all running the "Join a meeting" flow.
+ * Each variant: MS login → Teams landing page → "Join a meeting" → enter meeting ID + passcode → Join → screenshot.
*/
export async function runAuthTests(
meetingUrl: string,
@@ -155,8 +176,8 @@ async function _runVariant(
};
try {
- // Always use Chromium Headful Clean for both variants
- const launchResult = await _launchChromiumHeadful(_BROWSER_ARGS_CLEAN);
+ // Launch browser based on variant
+ const launchResult = await _launchBrowserForVariant(variant);
browser = launchResult.browser;
context = launchResult.context;
const page = launchResult.page;
@@ -292,51 +313,9 @@ async function _runVariant(
}
// =====================================================================
- // STEP 4: Click variant-specific button
+ // STEP 4: Click "Join a meeting"
// =====================================================================
- if (variant.id === 'signIn') {
- // --- VARIANT A: Click "Sign in" ---
- _log('info', 'Step 3: Clicking "Sign in" on Teams landing page...');
- const signInSelectors = [
- 'button:has-text("Sign in")',
- 'button:has-text("Anmelden")',
- 'a:has-text("Sign in")',
- 'a:has-text("Anmelden")',
- ];
-
- let clicked = false;
- for (const selector of signInSelectors) {
- try {
- const btn = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' });
- if (btn) {
- await btn.click();
- _log('info', `Clicked: ${selector}`);
- clicked = true;
- break;
- }
- } catch {
- // Try next
- }
- }
-
- if (!clicked) {
- _log('warn', '"Sign in" button not found on landing page');
- }
-
- // Wait for the resulting page to FULLY load
- _log('info', 'Waiting for resulting page to fully load...');
- await page.waitForTimeout(5000);
- try {
- await page.waitForLoadState('networkidle', { timeout: 20000 });
- } catch {
- _log('warn', 'networkidle timeout, continuing');
- }
- await page.waitForTimeout(5000);
- await _screenshotStep('3 - Nach "Sign in"');
-
- } else if (variant.id === 'joinMeeting') {
- // --- VARIANT B: Click "Join a meeting" ---
- _log('info', 'Step 3: Clicking "Join a meeting" on Teams landing page...');
+ _log('info', 'Step 4: Clicking "Join a meeting" on Teams landing page...');
const joinSelectors = [
'button:has-text("Join a meeting")',
'button:has-text("An Besprechung teilnehmen")',
@@ -499,7 +478,6 @@ async function _runVariant(
await page.waitForTimeout(10000);
}
await _screenshotStep('5 - Nach Join meeting');
- }
// =====================================================================
// FINAL: Log result
@@ -580,9 +558,31 @@ interface LaunchResult {
page: Page;
}
-async function _launchBrowserForVariant(_variant: AuthTestVariant): Promise {
- _requireDisplay();
- return _launchChromiumHeadful(_BROWSER_ARGS_CLEAN);
+async function _launchBrowserForVariant(variant: AuthTestVariant): Promise {
+ switch (variant.id) {
+ case 'chromiumClean':
+ _requireDisplay();
+ return _launchChromiumHeadful(_BROWSER_ARGS_CLEAN);
+
+ case 'chromiumNoAutomation':
+ _requireDisplay();
+ return _launchChromiumHeadful(_BROWSER_ARGS_NO_AUTOMATION);
+
+ case 'rebrowserHeadful':
+ _requireDisplay();
+ return _launchRebrowserHeadful();
+
+ case 'chromiumMinimal':
+ _requireDisplay();
+ return _launchChromiumMinimal();
+
+ case 'chromiumHeadless':
+ return _launchChromiumHeadless();
+
+ default:
+ _requireDisplay();
+ return _launchChromiumHeadful(_BROWSER_ARGS_CLEAN);
+ }
}
/**
@@ -658,6 +658,49 @@ async function _launchRebrowserHeadful(): Promise {
return { browser, context, page };
}
+/**
+ * Launch Chromium headful with minimal args — no stealth, just --no-sandbox.
+ */
+async function _launchChromiumMinimal(): Promise {
+ const browser = await chromium.launch({
+ headless: false,
+ args: _BROWSER_ARGS_MINIMAL,
+ });
+
+ const context = await browser.newContext({
+ permissions: ['microphone', 'camera'],
+ viewport: { width: 1920, height: 1080 },
+ userAgent: _USER_AGENT,
+ });
+
+ const page = await context.newPage();
+ await page.addInitScript(_getDeviceSpoofScript);
+
+ return { browser, context, page };
+}
+
+/**
+ * Launch Chromium headless — baseline comparison.
+ */
+async function _launchChromiumHeadless(): Promise {
+ const browser = await chromium.launch({
+ headless: true,
+ args: _BROWSER_ARGS_CLEAN,
+ });
+
+ const context = await browser.newContext({
+ permissions: ['microphone', 'camera'],
+ viewport: { width: 1920, height: 1080 },
+ userAgent: _USER_AGENT,
+ });
+
+ const page = await context.newPage();
+ await page.addInitScript(_getEnhancedStealthScript);
+ await page.addInitScript(_getDeviceSpoofScript);
+
+ return { browser, context, page };
+}
+
// ============================================================================
// STEALTH SCRIPTS
// ============================================================================