-
Notifications
You must be signed in to change notification settings - Fork 4.3k
feat: add focused and focusable information to _snapshotForAI #36059
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
31d1797
c9453ed
7783506
6473964
4a40ed7
e9746cc
d14a0c1
5056a57
44bc50b
1b45524
74d6d98
002a235
a7f952f
cfb46a7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,7 @@ it('should generate refs', async ({ page }) => { | |
|
||
const snapshot1 = await snapshotForAI(page); | ||
expect(snapshot1).toContainYaml(` | ||
- generic [ref=e1]: | ||
- generic [active] [ref=e1]: | ||
- button "One" [ref=e2] | ||
- button "Two" [ref=e3] | ||
- button "Three" [ref=e4] | ||
|
@@ -44,7 +44,7 @@ it('should generate refs', async ({ page }) => { | |
|
||
const snapshot2 = await snapshotForAI(page); | ||
expect(snapshot2).toContainYaml(` | ||
- generic [ref=e1]: | ||
- generic [active] [ref=e1]: | ||
- button "One" [ref=e2] | ||
- button "Not Two" [ref=e5] | ||
- button "Three" [ref=e4] | ||
|
@@ -68,9 +68,9 @@ it('should stitch all frame snapshots', async ({ page, server }) => { | |
await page.goto(server.PREFIX + '/frames/nested-frames.html'); | ||
const snapshot = await snapshotForAI(page); | ||
expect(snapshot).toContainYaml(` | ||
- generic [ref=e1]: | ||
- generic [active] [ref=e1]: | ||
- iframe [ref=e2]: | ||
- generic [ref=f1e1]: | ||
- generic [active] [ref=f1e1]: | ||
- iframe [ref=f1e2]: | ||
- generic [ref=f2e2]: Hi, I'm frame | ||
- iframe [ref=f1e3]: | ||
|
@@ -128,7 +128,7 @@ it('should not generate refs for elements with pointer-events:none', async ({ pa | |
|
||
const snapshot = await snapshotForAI(page); | ||
expect(snapshot).toContainYaml(` | ||
- generic [ref=e1]: | ||
- generic [active] [ref=e1]: | ||
- button "no-ref" | ||
- button "with-ref" [ref=e4] | ||
- button "with-ref" [ref=e7] | ||
|
@@ -224,8 +224,74 @@ it('should gracefully fallback when child frame cant be captured', async ({ page | |
`, { waitUntil: 'domcontentloaded' }); | ||
const snapshot = await snapshotForAI(page); | ||
expect(snapshot).toContainYaml(` | ||
- generic [ref=e1]: | ||
- generic [active] [ref=e1]: | ||
- paragraph [ref=e2]: Test | ||
- iframe [ref=e3] | ||
`); | ||
}); | ||
|
||
it('should include active element information', async ({ page }) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. toMatchSnapshot tests are missing in a separate file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added to-match-aria-snapshot-active.spec.ts with comprehensive toMatchAriaSnapshot tests for active functionality in commit a7f952f. |
||
await page.setContent(` | ||
<button id="btn1">Button 1</button> | ||
<button id="btn2" autofocus>Button 2</button> | ||
yury-s marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<div>Not focusable</div> | ||
`); | ||
|
||
// Wait for autofocus to take effect | ||
await page.waitForFunction(() => document.activeElement?.id === 'btn2'); | ||
|
||
const snapshot = await snapshotForAI(page); | ||
|
||
expect(snapshot).toContainYaml(` | ||
- generic [ref=e1]: | ||
- button "Button 1" [ref=e2] | ||
- button "Button 2" [active] [ref=e3] | ||
- generic [ref=e4]: Not focusable | ||
`); | ||
}); | ||
|
||
it('should update active element on focus', async ({ page }) => { | ||
await page.setContent(` | ||
<input id="input1" placeholder="First input"> | ||
<input id="input2" placeholder="Second input"> | ||
`); | ||
|
||
// Initially there shouldn't be an active element on the inputs | ||
const initialSnapshot = await snapshotForAI(page); | ||
expect(initialSnapshot).toContainYaml(` | ||
- generic [active] [ref=e1]: | ||
- textbox "First input" [ref=e2] | ||
- textbox "Second input" [ref=e3] | ||
`); | ||
|
||
// Focus the second input | ||
await page.locator('#input2').focus(); | ||
|
||
// After focus, the second input should be active | ||
const afterFocusSnapshot = await snapshotForAI(page); | ||
|
||
expect(afterFocusSnapshot).toContainYaml(` | ||
- generic [ref=e1]: | ||
- textbox "First input" [ref=e2] | ||
- textbox "Second input" [active] [ref=e3] | ||
`); | ||
}); | ||
|
||
it('should mark iframe as active when it contains focused element', async ({ page }) => { | ||
// Create a simple HTML file for the iframe | ||
await page.setContent(` | ||
<input id="regular-input" placeholder="Regular input"> | ||
<iframe src="data:text/html,<input id='iframe-input' placeholder='Input in iframe'>" tabindex="0"></iframe> | ||
`); | ||
|
||
// Test 1: Focus the input inside the iframe | ||
await page.frameLocator('iframe').locator('#iframe-input').focus(); | ||
const inputInIframeFocusedSnapshot = await snapshotForAI(page); | ||
|
||
// The iframe should be marked as active when it contains a focused element | ||
expect(inputInIframeFocusedSnapshot).toContain('iframe [active]'); | ||
yury-s marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Also check that the input element inside the iframe is active | ||
const iframeSnapshot = await page.frameLocator('iframe').locator('body').ariaSnapshot(); | ||
expect(iframeSnapshot).toContain('textbox "Input in iframe" [active]'); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import { test, expect } from './pageTest'; | ||
|
||
test('should match active element', async ({ page }) => { | ||
await page.setContent(` | ||
<button id="btn1">Button 1</button> | ||
<button id="btn2" autofocus>Button 2</button> | ||
`); | ||
|
||
// Wait for autofocus to take effect | ||
await page.waitForFunction(() => document.activeElement?.id === 'btn2'); | ||
|
||
await expect(page.locator('body')).toMatchAriaSnapshot(` | ||
- button "Button 1" | ||
- button "Button 2" [active] | ||
`); | ||
}); | ||
|
||
test('should match active element after focus', async ({ page }) => { | ||
await page.setContent(` | ||
<input id="input1" placeholder="First input"> | ||
<input id="input2" placeholder="Second input"> | ||
`); | ||
|
||
// Focus the second input | ||
await page.locator('#input2').focus(); | ||
|
||
await expect(page.locator('body')).toMatchAriaSnapshot(` | ||
- textbox "First input" | ||
- textbox "Second input" [active] | ||
`); | ||
}); | ||
|
||
test('should match active iframe', async ({ page }) => { | ||
await page.setContent(` | ||
<input id="regular-input" placeholder="Regular input"> | ||
<iframe src="data:text/html,<input id='iframe-input' placeholder='Input in iframe'>" tabindex="0"></iframe> | ||
`); | ||
|
||
// Focus the input inside the iframe | ||
await page.frameLocator('iframe').locator('#iframe-input').focus(); | ||
|
||
await expect(page.locator('body')).toMatchAriaSnapshot(` | ||
- textbox "Regular input" | ||
- iframe [active] | ||
`); | ||
|
||
// Also check that the input element inside the iframe is active | ||
await expect(page.frameLocator('iframe').locator('body')).toMatchAriaSnapshot(` | ||
- textbox "Input in iframe" [active] | ||
`); | ||
}); |
Uh oh!
There was an error while loading. Please reload this page.