diff --git a/flows/kiro/content/register-page.js b/flows/kiro/content/register-page.js index 680f076..e192227 100644 --- a/flows/kiro/content/register-page.js +++ b/flows/kiro/content/register-page.js @@ -37,8 +37,18 @@ const KIRO_OTP_INPUT_SELECTOR = [ 'input[inputmode="numeric"]', 'input[placeholder*="6-digit" i]', 'input[placeholder*="6 位" i]', + 'input[placeholder*="verification" i]', + 'input[placeholder*="code" i]', 'input[name*="otp" i]', 'input[name*="code" i]', + 'input[id*="otp" i]', + 'input[id*="code" i]', + 'input[data-testid*="otp" i]', + 'input[data-testid*="code" i]', + 'input[aria-label*="otp" i]', + 'input[aria-label*="code" i]', + 'input[aria-label*="verification" i]', + 'input[aria-label*="one-time" i]', ].join(', '); const KIRO_PASSWORD_FIELD_SELECTOR = 'input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"])'; @@ -417,18 +427,32 @@ function parseCurrentUrl() { } } -function getKiroAuthPathKind() { +function getKiroAuthRouteText() { const parsed = parseCurrentUrl(); - const pathname = String(parsed?.pathname || '').toLowerCase(); - if (/(^|\/)login(\/|$)/.test(pathname)) { + return [ + parsed?.pathname || '', + parsed?.hash || '', + ].map((entry) => String(entry || '').toLowerCase()).join(' '); +} + +function getKiroAuthRouteKind() { + const routeText = getKiroAuthRouteText(); + if (/(^|\/)login(\/|\s|$)/.test(routeText)) { return 'login'; } - if (/(^|\/)signup(\/|$)/.test(pathname)) { + if (/(^|\/)signup(\/|\s|$)/.test(routeText)) { return 'signup'; } return ''; } +function getKiroOtpRouteState(authRouteKind = '') { + if (!/(^|\/)verify-otp(\/|\s|$)/.test(getKiroAuthRouteText())) { + return ''; + } + return authRouteKind === 'login' ? 'login_otp_page' : 'register_otp_page'; +} + function findBuilderIdButton() { return findActionButton({ textPattern: KIRO_BUILDER_ID_TEXT_PATTERN, @@ -533,7 +557,7 @@ function getKiroFatalStateMessage(snapshot = {}) { function detectKiroRegisterPageState() { const pageText = getKiroPageText(); const currentUrl = location.href; - const authPathKind = getKiroAuthPathKind(); + const authRouteKind = getKiroAuthRouteKind(); const pageEmail = findKiroPageAccountEmail(pageText); const fatalState = detectKiroFatalPageState(pageText, currentUrl, document.title || ''); if (fatalState) { @@ -566,7 +590,7 @@ function detectKiroRegisterPageState() { const passwordFields = findKiroPasswordFields(); if (passwordFields.passwordInput) { const passwordInput = passwordFields.passwordInput; - const isLoginPasswordPage = authPathKind === 'login' + const isLoginPasswordPage = authRouteKind === 'login' || (!passwordFields.confirmPasswordInput && KIRO_SIGN_IN_TEXT_PATTERN.test(pageText)); return { state: isLoginPasswordPage ? 'login_password_page' : 'create_password_page', @@ -606,15 +630,16 @@ function detectKiroRegisterPageState() { } const otpInput = findVisibleOtpInput(); - if (otpInput) { + const otpRouteState = getKiroOtpRouteState(authRouteKind); + if (otpInput || otpRouteState) { return { - state: authPathKind === 'login' ? 'login_otp_page' : 'register_otp_page', + state: otpRouteState || (authRouteKind === 'login' ? 'login_otp_page' : 'register_otp_page'), url: currentUrl, email: pageEmail, accountEmail: pageEmail, otpInput, - verifyButton: findOtpVerifyButton(otpInput), - resendButton: findOtpResendButton(otpInput), + verifyButton: otpInput ? findOtpVerifyButton(otpInput) : null, + resendButton: otpInput ? findOtpResendButton(otpInput) : null, codeInvalid: KIRO_CODE_INVALID_TEXT_PATTERN.test(pageText), }; } diff --git a/tests/kiro-register-page-fatal-state.test.js b/tests/kiro-register-page-fatal-state.test.js index 9fcc077..aef0b49 100644 --- a/tests/kiro-register-page-fatal-state.test.js +++ b/tests/kiro-register-page-fatal-state.test.js @@ -315,3 +315,33 @@ test('kiro register content classifies signup verification separately from login assert.equal(loginDetected.state, 'login_otp_page'); assert.equal(loginDetected.email, 'existing-user@duck.com'); }); + +test('kiro register content classifies AWS signup hash verify route as register OTP page', () => { + const harness = createHarness({ + href: 'https://profile.aws.amazon.com/?workflowID=abc#/signup/verify-otp', + hostname: 'profile.aws.amazon.com', + title: 'Amazon Web Services', + bodyText: 'Verify your email Verification code 6 digits Continue hash-user@duck.com', + }); + + const detected = harness.detectKiroRegisterPageState(); + + assert.equal(detected.state, 'register_otp_page'); + assert.equal(detected.email, 'hash-user@duck.com'); + assert.equal(detected.otpInput, null); + assert.equal(detected.verifyButton, null); +}); + +test('kiro register content keeps AWS login hash verify route out of register OTP branch', () => { + const harness = createHarness({ + href: 'https://profile.aws.amazon.com/?workflowID=abc#/login/verify-otp', + hostname: 'profile.aws.amazon.com', + title: 'Amazon Web Services', + bodyText: 'Verify your identity Verification code 6 digits Continue existing-hash-user@duck.com', + }); + + const detected = harness.detectKiroRegisterPageState(); + + assert.equal(detected.state, 'login_otp_page'); + assert.equal(detected.email, 'existing-hash-user@duck.com'); +});