fix: wait for Teams login redirect + universal auth selectors

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ValueOn AG 2026-02-17 10:50:01 +01:00
parent 3724e31a30
commit 08194fe241
2 changed files with 50 additions and 60 deletions

View file

@ -121,23 +121,21 @@ export class AuthProcedure {
/** /**
* Wait for the email input field. * Wait for the email input field.
* *
* Hybrid flow: Teams inline modal has input#emailOrPhonerm [data-testid="emailInput"] * Uses universal selectors that work on both:
* Direct flow: MS login portal has input[name="loginfmt"] * - MS login portal (login.microsoftonline.com): input[name="loginfmt"]
* - Teams inline modal (light-meetings): input#emailOrPhonerm
*/ */
private async _waitForEmailInput(isInlineFlow: boolean) { private async _waitForEmailInput(_isInlineFlow: boolean) {
this._logger.info('Waiting for email input field...'); this._logger.info('Waiting for email input field...');
// Primary selectors — exact IDs/attributes from the real HTML // Universal selectors — match both MS login portal and Teams inline modal
const selectors = isInlineFlow const selectors = [
? [ 'input[name="loginfmt"]', // MS login portal (primary)
'input#emailOrPhonerm', // Teams inline modal (exact ID) 'input[type="email"]', // MS login portal fallback
'input[data-testid="emailInput"]', // Teams inline modal (data-testid) 'input#emailOrPhonerm', // Teams inline modal (exact ID)
'input[placeholder="Enter your email"]', // Teams inline modal (placeholder) 'input[data-testid="emailInput"]', // Teams inline modal (data-testid)
] 'input[placeholder="Enter your email"]', // Teams inline modal (placeholder)
: [ ];
'input[name="loginfmt"]', // MS login portal
'input[type="email"]', // MS login portal fallback
];
const combinedSelector = selectors.join(', '); const combinedSelector = selectors.join(', ');
@ -161,53 +159,37 @@ export class AuthProcedure {
/** /**
* Click the "Next" button after entering email. * Click the "Next" button after entering email.
* *
* Hybrid flow: button[data-testid="authLoginDialogNextButton"] initially disabled, * Tries all known button selectors from both MS login portal and Teams inline modal.
* becomes enabled after email is typed. We wait for it to be enabled. * Works regardless of which page we're on.
* Direct flow: input[type="submit"] on the MS login portal.
*/ */
private async _clickNextButton(isInlineFlow: boolean): Promise<void> { private async _clickNextButton(_isInlineFlow: boolean): Promise<void> {
if (isInlineFlow) { // Try all known Next/Submit button selectors (MS login portal + Teams inline modal)
// Teams inline modal: wait for the Next button to become enabled const selectors = [
const nextSelector = 'button[data-testid="authLoginDialogNextButton"]'; 'input[type="submit"]', // MS login portal
this._logger.info('Waiting for Teams Next button to become enabled...'); 'button[type="submit"]', // MS login portal alt
'button[data-testid="authLoginDialogNextButton"]', // Teams inline modal
];
for (const selector of selectors) {
try { try {
await this._page.waitForSelector(`${nextSelector}:not([disabled])`, { const button = await this._page.waitForSelector(selector, {
timeout: 10000, timeout: 5000,
state: 'visible', state: 'visible',
}); });
await this._page.click(nextSelector); if (button) {
this._logger.info('Clicked Teams Next button'); await button.click();
// After clicking Next, Teams redirects to login.microsoftonline.com this._logger.info(`Clicked Next: ${selector}`);
// Wait for the redirect to begin await this._page.waitForTimeout(3000);
await this._page.waitForTimeout(3000); return;
} catch {
this._logger.warn('Teams Next button not found or not enabled, pressing Enter');
await this._page.keyboard.press('Enter');
await this._page.waitForTimeout(3000);
}
} else {
// MS login portal: click submit button
const selectors = [
'input[type="submit"]',
'button[type="submit"]',
];
for (const selector of selectors) {
try {
const button = await this._page.$(selector);
if (button && await button.isVisible()) {
await button.click();
this._logger.info(`Clicked Next: ${selector}`);
await this._page.waitForTimeout(2000);
return;
}
} catch {
// Continue
} }
} catch {
// Selector not found, try next
} }
this._logger.warn('No Next button found, pressing Enter');
await this._page.keyboard.press('Enter');
await this._page.waitForTimeout(2000);
} }
this._logger.warn('No Next button found via selectors, pressing Enter');
await this._page.keyboard.press('Enter');
await this._page.waitForTimeout(3000);
} }
/** /**

View file

@ -195,18 +195,26 @@ async function _runVariant(
waitUntil: 'domcontentloaded', waitUntil: 'domcontentloaded',
timeout: 30000, timeout: 30000,
}); });
await page.waitForTimeout(3000);
_log('info', `After Teams redirect: ${page.url().substring(0, 120)}`); // Wait for Teams to redirect to login.microsoftonline.com (up to 30s)
_log('info', 'Waiting for login redirect to login.microsoftonline.com...');
try {
await page.waitForURL('**/login.microsoftonline.com/**', { timeout: 30000 });
_log('info', `Redirected to login: ${page.url().substring(0, 150)}`);
} catch {
_log('warn', `No login redirect after 30s, current URL: ${page.url().substring(0, 150)}`);
}
// Step 2: Login // Step 2: Login
if (botAccountEmail && botAccountPassword) { if (botAccountEmail && botAccountPassword) {
authAttempted = true; authAttempted = true;
const onLoginPage = page.url().includes('login.microsoftonline.com') || page.url().includes('login.live.com'); _log('info', `Authenticating as ${botAccountEmail} (skipNavigation=true to preserve OAuth context)`);
_log('info', `On login page: ${onLoginPage}, authenticating as ${botAccountEmail}`);
const authProcedure = new AuthProcedure(page, logger); const authProcedure = new AuthProcedure(page, logger);
// skipNavigation=true because we're already on the login page after teams.microsoft.com redirect // Always skipNavigation=true: we're already on login.microsoftonline.com with the correct
authSuccess = await authProcedure.authenticateWithMicrosoft(botAccountEmail, botAccountPassword, !onLoginPage); // OAuth parameters (client_id, redirect_uri for Teams). Navigating to plain
// login.microsoftonline.com would lose this context.
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'}`);
} }