refactor: drastically shortened auth test flow - direct login to chat to pre-join to meeting
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
68cf43c5fa
commit
35dd781d90
1 changed files with 88 additions and 254 deletions
|
|
@ -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');
|
_log('info', 'Step 1: Navigate to teams.microsoft.com');
|
||||||
await page.goto('https://teams.microsoft.com', {
|
await page.goto('https://teams.microsoft.com', {
|
||||||
|
|
@ -242,7 +242,6 @@ async function _runVariant(
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Wait for login redirect OR the Teams landing page to appear
|
|
||||||
_log('info', 'Waiting for login.microsoftonline.com redirect...');
|
_log('info', 'Waiting for login.microsoftonline.com redirect...');
|
||||||
try {
|
try {
|
||||||
await page.waitForURL('**/login.microsoftonline.com/**', { timeout: 30000 });
|
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)}`);
|
_log('warn', `No login redirect, current URL: ${page.url().substring(0, 150)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the login page to FULLY RENDER (email input visible)
|
// Wait for login page to render
|
||||||
_log('info', 'Waiting for login page to fully render...');
|
|
||||||
try {
|
try {
|
||||||
await page.waitForSelector(
|
await page.waitForSelector('input[name="loginfmt"], input[type="email"]', { timeout: 15000, state: 'visible' });
|
||||||
'input[name="loginfmt"], input[type="email"], button:has-text("Sign in"), button:has-text("Join a meeting")',
|
|
||||||
{ timeout: 15000, state: 'visible' },
|
|
||||||
);
|
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
} catch {
|
} catch {
|
||||||
_log('warn', 'Login page elements not found, taking screenshot anyway');
|
_log('warn', 'Login page elements not found');
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
}
|
}
|
||||||
await _screenshotStep('1 - Login-Seite');
|
await _screenshotStep('1 - Login-Seite');
|
||||||
|
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
// STEP 2: Microsoft Login
|
// STEP 2: Microsoft Authentication
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
if (botAccountEmail && botAccountPassword) {
|
if (botAccountEmail && botAccountPassword) {
|
||||||
authAttempted = true;
|
authAttempted = true;
|
||||||
|
|
||||||
// Check if we're on login.microsoftonline.com or on the Teams landing page
|
|
||||||
const currentUrl = page.url();
|
const currentUrl = page.url();
|
||||||
const onMsLogin = currentUrl.includes('login.microsoftonline.com') || currentUrl.includes('login.live.com');
|
const onMsLogin = currentUrl.includes('login.microsoftonline.com') || currentUrl.includes('login.live.com');
|
||||||
|
|
||||||
if (onMsLogin) {
|
if (onMsLogin) {
|
||||||
_log('info', `On MS login page, authenticating as ${botAccountEmail}`);
|
_log('info', `Authenticating as ${botAccountEmail}`);
|
||||||
const authProcedure = new AuthProcedure(page, logger);
|
const authProcedure = new AuthProcedure(page, logger);
|
||||||
authSuccess = await authProcedure.authenticateWithMicrosoft(botAccountEmail, botAccountPassword, true);
|
authSuccess = await authProcedure.authenticateWithMicrosoft(botAccountEmail, botAccountPassword, true);
|
||||||
_log(authSuccess ? 'info' : 'warn', `Auth result: ${authSuccess ? 'success' : 'failed'}`);
|
_log(authSuccess ? 'info' : 'warn', `Auth result: ${authSuccess ? 'success' : 'failed'}`);
|
||||||
} else {
|
} 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;
|
authSuccess = null;
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
if (authSuccess) {
|
||||||
try {
|
try {
|
||||||
await page.waitForURL('**/teams.microsoft.com/**', { timeout: 30000 });
|
await page.waitForURL('**/teams.microsoft.com/**', { timeout: 30000 });
|
||||||
|
|
@ -302,285 +295,16 @@ async function _runVariant(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for either "Sign in" or "Join a meeting" button to be visible
|
// Wait for the "Join" button in the chat header — this confirms we're on the chat page
|
||||||
// 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
|
|
||||||
try {
|
try {
|
||||||
await page.waitForSelector(
|
await page.waitForSelector(
|
||||||
'button[data-tid="chat-join-button"], button[data-tid="join-call-button"]',
|
'button[data-tid="chat-join-button"], button[data-tid="join-call-button"]',
|
||||||
{ timeout: 30000, state: 'visible' },
|
{ 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 {
|
} 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');
|
||||||
try {
|
// Log all visible buttons for debugging
|
||||||
const buttons = await page.evaluate(() => {
|
|
||||||
const btns = document.querySelectorAll('button');
|
|
||||||
return Array.from(btns).slice(0, 30).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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await _screenshotStep('6 - Teams Chat (vor Join-Klick)');
|
|
||||||
|
|
||||||
// Click the "Join" button in the 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;
|
|
||||||
for (const selector of chatJoinSelectors) {
|
|
||||||
try {
|
|
||||||
const btn = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' });
|
|
||||||
if (btn) {
|
|
||||||
await btn.click();
|
|
||||||
_log('info', `Clicked chat "Join" button: ${selector}`);
|
|
||||||
chatJoinClicked = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// Try next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!chatJoinClicked) {
|
|
||||||
_log('warn', '"Join" button in chat header not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the meeting to load after clicking Join
|
|
||||||
if (chatJoinClicked) {
|
|
||||||
_log('info', 'Waiting for meeting view to load...');
|
|
||||||
await page.waitForTimeout(5000);
|
|
||||||
|
|
||||||
// Wait for meeting UI elements (hangup button, video controls, etc.)
|
|
||||||
try {
|
|
||||||
await page.waitForSelector(
|
|
||||||
'button[id="hangup-button"], button[data-tid="hangup-button"], [data-tid="prejoin-join-button"], [data-tid="calling-prejoin"]',
|
|
||||||
{ timeout: 30000, state: 'visible' },
|
|
||||||
);
|
|
||||||
_log('info', 'Meeting UI elements detected');
|
|
||||||
} catch {
|
|
||||||
_log('warn', 'Meeting UI elements not found after 30s');
|
|
||||||
}
|
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
|
||||||
}
|
|
||||||
await _screenshotStep('7 - Nach Join (Meeting-Ansicht)');
|
|
||||||
|
|
||||||
// Log all visible buttons on the final page for debugging
|
|
||||||
try {
|
try {
|
||||||
const buttons = await page.evaluate(() => {
|
const buttons = await page.evaluate(() => {
|
||||||
const btns = document.querySelectorAll('button');
|
const btns = document.querySelectorAll('button');
|
||||||
|
|
@ -590,10 +314,120 @@ async function _runVariant(
|
||||||
return `[BUTTON tid="${tid}"] ${text}`;
|
return `[BUTTON tid="${tid}"] ${text}`;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
buttons.forEach(b => _log('info', ` Final page button: ${b}`));
|
buttons.forEach(b => _log('info', ` ${b}`));
|
||||||
} catch {
|
} catch { /* ignore */ }
|
||||||
// Ignore
|
|
||||||
}
|
}
|
||||||
|
await _screenshotStep('2 - Teams Chat');
|
||||||
|
|
||||||
|
// =====================================================================
|
||||||
|
// 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"]',
|
||||||
|
];
|
||||||
|
|
||||||
|
let chatJoinClicked = false;
|
||||||
|
for (const selector of chatJoinSelectors) {
|
||||||
|
try {
|
||||||
|
const btn = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' });
|
||||||
|
if (btn) {
|
||||||
|
await btn.click();
|
||||||
|
_log('info', `Clicked: ${selector}`);
|
||||||
|
chatJoinClicked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch { /* try next */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chatJoinClicked) {
|
||||||
|
_log('warn', '"Join" button in chat header not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for pre-join screen (camera preview, "Join now" button)
|
||||||
|
if (chatJoinClicked) {
|
||||||
|
_log('info', 'Waiting for pre-join screen...');
|
||||||
|
try {
|
||||||
|
await page.waitForSelector(
|
||||||
|
'button:has-text("Join now"), button:has-text("Jetzt teilnehmen"), button[data-tid="prejoin-join-button"]',
|
||||||
|
{ timeout: 30000, state: 'visible' },
|
||||||
|
);
|
||||||
|
_log('info', 'Pre-join screen loaded');
|
||||||
|
} catch {
|
||||||
|
_log('warn', 'Pre-join "Join now" button not found after 30s');
|
||||||
|
}
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
}
|
||||||
|
await _screenshotStep('3 - Pre-Join Ansicht');
|
||||||
|
|
||||||
|
// =====================================================================
|
||||||
|
// 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');
|
||||||
|
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', ` Final: ${b}`));
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
// FINAL: Log result
|
// FINAL: Log result
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue