@@ -4753,7 +4753,10 @@ test('CAPTCHA dialog parsing handles descendant-only labels and escaped quotes',
47534753});
47544754
47554755test('CAPTCHA mutation preflight ignores hidden and off-viewport verification dialogs', async () => {
4756- for (const [build, gate] of [['chrome', CaptchaGateCh], ['firefox', CaptchaGateFx]]) {
4756+ for (const [build, gate, AgentClass] of [
4757+ ['chrome', CaptchaGateCh, AgentCh],
4758+ ['firefox', CaptchaGateFx, AgentFx],
4759+ ]) {
47574760 const hiddenCases = [
47584761 captchaEl('div', {
47594762 role: 'dialog',
@@ -4774,6 +4777,18 @@ test('CAPTCHA mutation preflight ignores hidden and off-viewport verification di
47744777 for (const dialog of hiddenCases) {
47754778 await withCaptchaFakePage(build, [dialog], async () => {
47764779 assert.equal(gate.detectChallengeDialogInPage(), null, `${build}: inactive dialog armed the mutation preflight`);
4780+ const agent = new AgentClass({});
4781+ const observation = await agent._observeCaptchaChallenge(
4782+ 1,
4783+ 'get_accessibility_tree',
4784+ {
4785+ pageContent: 'dialog "Security verification" [ref_1]\n button "Dismiss" [ref_2]',
4786+ pageUrl: 'https://example.test/form',
4787+ },
4788+ {},
4789+ );
4790+ assert.equal(observation.gate, null, `${build}: hidden dialog from an all-tree read armed the gate`);
4791+ assert.equal(agent._captchaGateStates.has(1), false, `${build}: hidden all-tree dialog persisted a gate`);
47774792 });
47784793 }
47794794 await withCaptchaFakePage(build, [
@@ -4796,6 +4811,39 @@ test('CAPTCHA mutation preflight ignores hidden and off-viewport verification di
47964811 `${build}: active-gate failure context was ignored`,
47974812 );
47984813 });
4814+
4815+ const hiddenStageNodes = [
4816+ captchaEl('div', {
4817+ role: 'dialog',
4818+ innerText: 'Account details',
4819+ textContent: 'Account details Security verification',
4820+ }, [
4821+ captchaEl('h2', { textContent: 'Account details' }),
4822+ captchaEl('section', {
4823+ hidden: true,
4824+ innerText: 'Security verification',
4825+ }, [
4826+ captchaEl('h2', { textContent: 'Security verification' }),
4827+ captchaEl('div', {
4828+ class: 'g-recaptcha',
4829+ 'data-sitekey': 'INACTIVE_STAGE_KEY',
4830+ }),
4831+ ]),
4832+ ]),
4833+ ];
4834+ await withCaptchaFakePage(build, hiddenStageNodes, async () => {
4835+ assert.equal(
4836+ gate.detectChallengeDialogInPage(),
4837+ null,
4838+ `${build}: hidden CAPTCHA stage labelled the visible modal as a challenge`,
4839+ );
4840+ });
4841+ const hiddenStageCandidate = await detectCaptchaOnFakePage(build, hiddenStageNodes);
4842+ assert.equal(
4843+ hiddenStageCandidate?.dialogAssociated,
4844+ false,
4845+ `${build}: hidden CAPTCHA stage associated its widget with the visible modal`,
4846+ );
47994847 }
48004848});
48014849
0 commit comments