diff --git a/src/bot/authTestProcedure.ts b/src/bot/authTestProcedure.ts index e57d98d..1e1808b 100644 --- a/src/bot/authTestProcedure.ts +++ b/src/bot/authTestProcedure.ts @@ -234,7 +234,7 @@ async function _runVariant( } // ===================================================================== - // STEP 1: Navigate to teams.microsoft.com + // STEP 1: Navigate to teams.microsoft.com → MS Login // ===================================================================== _log('info', 'Step 1: Navigate to teams.microsoft.com'); await page.goto('https://teams.microsoft.com', { @@ -242,7 +242,6 @@ async function _runVariant( timeout: 30000, }); - // Wait for login redirect OR the Teams landing page to appear _log('info', 'Waiting for login.microsoftonline.com redirect...'); try { await page.waitForURL('**/login.microsoftonline.com/**', { timeout: 30000 }); @@ -251,37 +250,31 @@ async function _runVariant( _log('warn', `No login redirect, current URL: ${page.url().substring(0, 150)}`); } - // Wait for the login page to FULLY RENDER (email input visible) - _log('info', 'Waiting for login page to fully render...'); + // Wait for login page to render try { - await page.waitForSelector( - 'input[name="loginfmt"], input[type="email"], button:has-text("Sign in"), button:has-text("Join a meeting")', - { timeout: 15000, state: 'visible' }, - ); + await page.waitForSelector('input[name="loginfmt"], input[type="email"]', { timeout: 15000, state: 'visible' }); await page.waitForTimeout(1000); } catch { - _log('warn', 'Login page elements not found, taking screenshot anyway'); + _log('warn', 'Login page elements not found'); await page.waitForTimeout(2000); } await _screenshotStep('1 - Login-Seite'); // ===================================================================== - // STEP 2: Microsoft Login + // STEP 2: Microsoft Authentication // ===================================================================== if (botAccountEmail && botAccountPassword) { authAttempted = true; - - // Check if we're on login.microsoftonline.com or on the Teams landing page const currentUrl = page.url(); const onMsLogin = currentUrl.includes('login.microsoftonline.com') || currentUrl.includes('login.live.com'); if (onMsLogin) { - _log('info', `On MS login page, authenticating as ${botAccountEmail}`); + _log('info', `Authenticating as ${botAccountEmail}`); const authProcedure = new AuthProcedure(page, logger); authSuccess = await authProcedure.authenticateWithMicrosoft(botAccountEmail, botAccountPassword, true); _log(authSuccess ? 'info' : 'warn', `Auth result: ${authSuccess ? 'success' : 'failed'}`); } else { - _log('info', 'Not on MS login page — Teams may already be loaded. Skipping auth step.'); + _log('info', 'Not on MS login page, skipping auth'); authSuccess = null; } } else { @@ -289,11 +282,11 @@ async function _runVariant( } // ===================================================================== - // STEP 3: Wait for Teams landing page to fully render + // STEP 3: Wait for Teams Chat page (= landing page after auth) + // After login, bot lands directly on the Teams chat page with "Join" button // ===================================================================== - _log('info', 'Waiting for Teams landing page to fully render...'); + _log('info', 'Step 3: Waiting for Teams chat page to load...'); - // Wait for redirect back to Teams (if we were on login page) if (authSuccess) { try { await page.waitForURL('**/teams.microsoft.com/**', { timeout: 30000 }); @@ -302,243 +295,37 @@ async function _runVariant( } } - // Wait for either "Sign in" or "Join a meeting" button to be visible - // This is the Teams landing page ("Everyone together in Teams") - _log('info', 'Waiting for "Sign in" or "Join a meeting" button to appear...'); - try { - await page.waitForSelector( - 'button:has-text("Sign in"), button:has-text("Join a meeting"), button:has-text("Anmelden"), button:has-text("An Besprechung teilnehmen")', - { timeout: 30000, state: 'visible' }, - ); - await page.waitForTimeout(1000); - _log('info', 'Teams landing page loaded'); - } catch { - _log('warn', 'Landing page buttons not found after 30s'); - await page.waitForTimeout(2000); - } - await _screenshotStep('2 - Teams Landingpage'); - - // Log all visible buttons for debugging - try { - const buttons = await page.evaluate(() => { - const btns = document.querySelectorAll('button, a[role="button"]'); - return Array.from(btns).slice(0, 20).map(b => { - const text = (b.textContent || '').trim().substring(0, 80); - const tid = b.getAttribute('data-tid') || ''; - return `[${b.tagName} tid="${tid}"] ${text}`; - }); - }); - buttons.forEach(b => _log('info', ` Visible button: ${b}`)); - } catch { - // Ignore - } - - // ===================================================================== - // STEP 4: Click "Join a meeting" - // ===================================================================== - _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")', - 'a:has-text("Join a meeting")', - 'a:has-text("An Besprechung teilnehmen")', - ]; - - let clicked = false; - for (const selector of joinSelectors) { - 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', '"Join a meeting" button not found on landing page'); - } - - // Wait for the "Join a meeting" form to load (wait for Meeting ID input) - _log('info', 'Waiting for Join a meeting form to load...'); - try { - await page.waitForSelector('input[placeholder*="meeting" i], input[placeholder*="Meeting" i], input[placeholder*="ID" i]', { - timeout: 15000, state: 'visible', - }); - await page.waitForTimeout(1000); - } catch { - _log('warn', 'Meeting form input not found, continuing'); - await page.waitForTimeout(2000); - } - await _screenshotStep('3 - Join a meeting Formular'); - - // Parse meeting URL to extract Meeting ID and Passcode - // URL format: https://teams.microsoft.com/meet/36438888781520?p=5fGqrujxzewPFjJacW - const { meetingId, passcode } = _parseMeetingUrl(meetingUrl); - _log('info', `Parsed meeting URL: ID="${meetingId}", Passcode="${passcode ? passcode.substring(0, 5) + '...' : 'none'}"`); - - // Fill Meeting ID field - if (meetingId) { - _log('info', 'Looking for Meeting ID input...'); - const idInputSelectors = [ - 'input[placeholder*="meeting" i]', - 'input[placeholder*="Meeting ID" i]', - 'input[placeholder*="ID" i]', - 'input[aria-label*="Meeting ID" i]', - 'input[type="text"]:first-of-type', - ]; - - let idFilled = false; - for (const selector of idInputSelectors) { - try { - const input = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' }); - if (input) { - await input.fill(meetingId); - _log('info', `Entered Meeting ID in: ${selector}`); - idFilled = true; - await page.waitForTimeout(1000); - break; - } - } catch { - // Try next - } - } - if (!idFilled) { - _log('warn', 'Meeting ID input not found'); - } - } - - // Fill Passcode field - if (passcode) { - _log('info', 'Looking for Passcode input...'); - const passcodeSelectors = [ - 'input[placeholder*="passcode" i]', - 'input[placeholder*="Passcode" i]', - 'input[placeholder*="password" i]', - 'input[aria-label*="passcode" i]', - 'input[aria-label*="Passcode" i]', - ]; - - let passcodeFilled = false; - for (const selector of passcodeSelectors) { - try { - const input = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' }); - if (input) { - await input.fill(passcode); - _log('info', `Entered Passcode in: ${selector}`); - passcodeFilled = true; - await page.waitForTimeout(1000); - break; - } - } catch { - // Try next - } - } - if (!passcodeFilled) { - _log('warn', 'Passcode input not found'); - } - } - - await _screenshotStep('4 - Meeting-Daten eingegeben'); - - // Click "Join meeting" button - _log('info', 'Looking for "Join meeting" button...'); - const joinBtnSelectors = [ - 'button:has-text("Join meeting")', - 'button:has-text("Besprechung beitreten")', - 'button:has-text("Join now")', - 'button:has-text("Jetzt teilnehmen")', - 'button[data-tid="joinMeetingButton"]', - 'button[data-tid="join-meeting-button"]', - ]; - - let joinClicked = false; - for (const selector of joinBtnSelectors) { - try { - const btn = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' }); - if (btn) { - await btn.click(); - _log('info', `Clicked "Join meeting": ${selector}`); - joinClicked = true; - break; - } - } catch { - // Try next - } - } - - if (!joinClicked) { - _log('warn', '"Join meeting" button not found — logging all visible buttons'); - try { - const buttons = await page.evaluate(() => { - const btns = document.querySelectorAll('button'); - return Array.from(btns).slice(0, 20).map(b => { - const text = (b.textContent || '').trim().substring(0, 80); - const tid = b.getAttribute('data-tid') || ''; - const disabled = b.disabled ? ' DISABLED' : ''; - return `[BUTTON tid="${tid}"${disabled}] ${text}`; - }); - }); - buttons.forEach(b => _log('info', ` ${b}`)); - } catch { - // Ignore - } - } - - // Wait for resulting page after clicking Join - if (joinClicked) { - _log('info', 'Waiting for page after Join meeting...'); - await page.waitForTimeout(3000); - try { - await page.waitForLoadState('networkidle', { timeout: 20000 }); - } catch { - _log('warn', 'networkidle timeout after Join, continuing'); - } - await page.waitForTimeout(5000); - } - await _screenshotStep('5 - Nach Join meeting'); - - // ===================================================================== - // STEP 6: Click "Join" button in Teams chat header to join the call - // ===================================================================== - _log('info', 'Step 6: Looking for "Join" button in Teams chat header...'); - - // Wait for the Teams chat page to fully render + // Wait for the "Join" button in the chat header — this confirms we're on the chat page try { await page.waitForSelector( 'button[data-tid="chat-join-button"], button[data-tid="join-call-button"]', { timeout: 30000, state: 'visible' }, ); - _log('info', 'Teams chat page loaded, "Join" button found'); + _log('info', 'Teams chat page loaded, "Join" button found in header'); } catch { - _log('warn', '"Join" button not found in chat header after 30s — logging all buttons'); + _log('warn', '"Join" button not found in chat header after 30s'); + // Log all visible buttons for debugging try { const buttons = await page.evaluate(() => { const btns = document.querySelectorAll('button'); - return Array.from(btns).slice(0, 30).map(b => { + return Array.from(btns).slice(0, 25).map(b => { const text = (b.textContent || '').trim().substring(0, 80); const tid = b.getAttribute('data-tid') || ''; return `[BUTTON tid="${tid}"] ${text}`; }); }); buttons.forEach(b => _log('info', ` ${b}`)); - } catch { - // Ignore - } + } catch { /* ignore */ } } + await _screenshotStep('2 - Teams Chat'); - await _screenshotStep('6 - Teams Chat (vor Join-Klick)'); - - // Click the "Join" button in the chat header + // ===================================================================== + // STEP 4: Click "Join" in chat header → Pre-Join screen + // ===================================================================== + _log('info', 'Step 4: Clicking "Join" in chat header...'); const chatJoinSelectors = [ 'button[data-tid="chat-join-button"]', 'button[data-tid="join-call-button"]', - 'button:has-text("Join")', - 'button:has-text("Beitreten")', ]; let chatJoinClicked = false; @@ -547,40 +334,89 @@ async function _runVariant( const btn = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' }); if (btn) { await btn.click(); - _log('info', `Clicked chat "Join" button: ${selector}`); + _log('info', `Clicked: ${selector}`); chatJoinClicked = true; break; } - } catch { - // Try next - } + } catch { /* try next */ } } if (!chatJoinClicked) { _log('warn', '"Join" button in chat header not found'); } - // Wait for the meeting to load after clicking Join + // Wait for pre-join screen (camera preview, "Join now" button) if (chatJoinClicked) { - _log('info', 'Waiting for meeting view to load...'); - await page.waitForTimeout(5000); - - // Wait for meeting UI elements (hangup button, video controls, etc.) + _log('info', 'Waiting for pre-join screen...'); try { await page.waitForSelector( - 'button[id="hangup-button"], button[data-tid="hangup-button"], [data-tid="prejoin-join-button"], [data-tid="calling-prejoin"]', + 'button:has-text("Join now"), button:has-text("Jetzt teilnehmen"), button[data-tid="prejoin-join-button"]', { timeout: 30000, state: 'visible' }, ); - _log('info', 'Meeting UI elements detected'); + _log('info', 'Pre-join screen loaded'); } catch { - _log('warn', 'Meeting UI elements not found after 30s'); + _log('warn', 'Pre-join "Join now" button not found after 30s'); } - - await page.waitForTimeout(5000); + await page.waitForTimeout(2000); } - await _screenshotStep('7 - Nach Join (Meeting-Ansicht)'); + await _screenshotStep('3 - Pre-Join Ansicht'); - // Log all visible buttons on the final page for debugging + // ===================================================================== + // STEP 5: Click "Join now" → Enter the meeting + // ===================================================================== + _log('info', 'Step 5: Clicking "Join now"...'); + const joinNowSelectors = [ + 'button:has-text("Join now")', + 'button:has-text("Jetzt teilnehmen")', + 'button[data-tid="prejoin-join-button"]', + ]; + + let joinNowClicked = false; + for (const selector of joinNowSelectors) { + try { + const btn = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' }); + if (btn) { + await btn.click(); + _log('info', `Clicked "Join now": ${selector}`); + joinNowClicked = true; + break; + } + } catch { /* try next */ } + } + + if (!joinNowClicked) { + _log('warn', '"Join now" button not found — logging all buttons'); + try { + const buttons = await page.evaluate(() => { + const btns = document.querySelectorAll('button'); + return Array.from(btns).slice(0, 25).map(b => { + const text = (b.textContent || '').trim().substring(0, 80); + const tid = b.getAttribute('data-tid') || ''; + return `[BUTTON tid="${tid}"] ${text}`; + }); + }); + buttons.forEach(b => _log('info', ` ${b}`)); + } catch { /* ignore */ } + } + + // Wait for the actual meeting view (hangup button = we're in the meeting) + if (joinNowClicked) { + _log('info', 'Waiting for meeting to load...'); + await page.waitForTimeout(5000); + try { + await page.waitForSelector( + 'button[id="hangup-button"], button[data-tid="hangup-button"], #hangup-button', + { timeout: 30000, state: 'visible' }, + ); + _log('info', 'IN THE MEETING — hangup button visible!'); + } catch { + _log('warn', 'Hangup button not found after 30s'); + } + await page.waitForTimeout(3000); + } + await _screenshotStep('4 - Im Meeting'); + + // Log final page buttons for debugging try { const buttons = await page.evaluate(() => { const btns = document.querySelectorAll('button'); @@ -590,10 +426,8 @@ async function _runVariant( return `[BUTTON tid="${tid}"] ${text}`; }); }); - buttons.forEach(b => _log('info', ` Final page button: ${b}`)); - } catch { - // Ignore - } + buttons.forEach(b => _log('info', ` Final: ${b}`)); + } catch { /* ignore */ } // ===================================================================== // FINAL: Log result