playwright/tests/page/page-aria-snapshot-ai.spec.ts

231 lines
6.5 KiB
TypeScript
Raw Normal View History

/**
* Copyright (c) Microsoft Corporation.
*
* 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 type { FrameLocator, Page } from '@playwright/test';
import { test as it, expect } from './pageTest';
const forAI = { _forAI: true } as any;
it('should generate refs', async ({ page }) => {
await page.setContent(`
<button>One</button>
<button>Two</button>
<button>Three</button>
`);
const snapshot1 = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot1).toContainYaml(`
- generic [ref=e1]:
- button "One" [ref=e2]
- button "Two" [ref=e3]
- button "Three" [ref=e4]
`);
await expect(page.locator('aria-ref=e2')).toHaveText('One');
await expect(page.locator('aria-ref=e3')).toHaveText('Two');
await expect(page.locator('aria-ref=e4')).toHaveText('Three');
await page.locator('aria-ref=e3').evaluate((e: HTMLElement) => {
e.textContent = 'Not Two';
});
const snapshot2 = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot2).toContainYaml(`
- generic [ref=e1]:
- button "One" [ref=e2]
- button "Not Two" [ref=e5]
- button "Three" [ref=e4]
`);
});
it('should list iframes', async ({ page }) => {
await page.setContent(`
<h1>Hello</h1>
<iframe name="foo" src="data:text/html,<h1>World</h1>">
`);
const snapshot1 = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot1).toContain('- iframe');
const frameSnapshot = await page.frameLocator(`iframe`).locator('body').ariaSnapshot();
expect(frameSnapshot).toEqual('- heading "World" [level=1]');
});
it('ref mode can be used to stitch all frame snapshots', async ({ page, server }) => {
await page.goto(server.PREFIX + '/frames/nested-frames.html');
async function allFrameSnapshot(frame: Page | FrameLocator): Promise<string> {
const snapshot = await frame.locator('body').ariaSnapshot(forAI);
const lines = snapshot.split('\n');
const result = [];
for (const line of lines) {
const match = line.match(/^(\s*)- iframe \[ref=(.*)\]/);
if (!match) {
result.push(line);
continue;
}
const leadingSpace = match[1];
const ref = match[2];
const childFrame = frame.frameLocator(`aria-ref=${ref}`);
const childSnapshot = await allFrameSnapshot(childFrame);
result.push(line + ':', childSnapshot.split('\n').map(l => leadingSpace + ' ' + l).join('\n'));
}
return result.join('\n');
}
expect(await allFrameSnapshot(page)).toContainYaml(`
- generic [ref=e1]:
- iframe [ref=e2]:
- generic [ref=e1]:
- iframe [ref=e2]:
- generic [ref=e2]: Hi, I'm frame
- iframe [ref=e3]:
- generic [ref=e2]: Hi, I'm frame
- iframe [ref=e3]:
- generic [ref=e2]: Hi, I'm frame
`);
});
it('should not generate refs for hidden elements', async ({ page }) => {
await page.setContent(`
<button>One</button>
<button style="width: 0; height: 0; appearance: none; border: 0; padding: 0;">Two</button>
<button>Three</button>
`);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- generic [ref=e1]:
- button "One" [ref=e2]
- button "Two"
- button "Three" [ref=e4]
`);
});
it('should not generate refs for elements with pointer-events:none', async ({ page }) => {
await page.setContent(`
<button style="pointer-events: none">no-ref</button>
<div style="pointer-events: none">
<button style="pointer-events: auto">with-ref</button>
</div>
<div style="pointer-events: none">
<div style="pointer-events: initial">
<button>with-ref</button>
</div>
</div>
<div style="pointer-events: none">
<div style="pointer-events: auto">
<button>with-ref</button>
</div>
</div>
<div style="pointer-events: auto">
<div style="pointer-events: none">
<button>no-ref</button>
</div>
</div>
`);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- generic [ref=e1]:
- button "no-ref"
- button "with-ref" [ref=e4]
- button "with-ref" [ref=e7]
- button "with-ref" [ref=e10]
- generic [ref=e11]:
- generic:
- button "no-ref"
`);
});
it('emit generic roles for nodes w/o roles', async ({ page }) => {
await page.setContent(`
<style>
input {
width: 0;
height: 0;
opacity: 0;
}
</style>
<div>
<label>
<span>
<input type="radio" value="Apple" checked="">
</span>
<span>Apple</span>
</label>
<label>
<span>
<input type="radio" value="Pear">
</span>
<span>Pear</span>
</label>
<label>
<span>
<input type="radio" value="Orange">
</span>
<span>Orange</span>
</label>
</div>
`);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- generic [ref=e2]:
- generic [ref=e3]:
- generic [ref=e4]:
- radio "Apple" [checked]
- generic [ref=e6]: Apple
- generic [ref=e7]:
- generic [ref=e8]:
- radio "Pear"
- generic [ref=e10]: Pear
- generic [ref=e11]:
- generic [ref=e12]:
- radio "Orange"
- generic [ref=e14]: Orange
`);
});
it('should collapse generic nodes', async ({ page }) => {
await page.setContent(`
<div>
<div>
<div>
<button>Button</button>
</div>
</div>
</div>
`);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- button \"Button\" [ref=e5]
`);
});
it('should include cursor pointer hint', async ({ page }) => {
await page.setContent(`
<button style="cursor: pointer">Button</button>
`);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- button \"Button\" [ref=e2] [cursor=pointer]
`);
});