chore: use internal locator for role (#18187)

This commit is contained in:
Pavel Feldman 2022-10-19 22:38:47 -04:00 committed by GitHub
parent ad9729f246
commit 84daeafb3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 17 additions and 16 deletions

View File

@ -442,5 +442,5 @@ export function getByRoleSelector(role: string, options: ByRoleOptions = {}): st
props.push(['name', isString(options.name) ? escapeForAttributeSelector(options.name, false) : String(options.name)]);
if (options.pressed !== undefined)
props.push(['pressed', String(options.pressed)]);
return `role=${role}${props.map(([n, v]) => `[${n}=${v}]`).join('')}`;
return `internal:role=${role}${props.map(([n, v]) => `[${n}=${v}]`).join('')}`;
}

View File

@ -112,6 +112,7 @@ export class InjectedScript {
this._engines.set('internal:label', this._createInternalLabelEngine());
this._engines.set('internal:text', this._createTextEngine(true, true));
this._engines.set('internal:attr', this._createNamedAttributeEngine());
this._engines.set('internal:role', RoleEngine);
for (const { name, engine } of customEngines)
this._engines.set(name, engine);

View File

@ -170,9 +170,9 @@ function buildCandidates(injectedScript: InjectedScript, element: Element, acces
if (ariaRole) {
const ariaName = getElementAccessibleName(element, false, accessibleNameCache);
if (ariaName)
candidates.push({ engine: 'role', selector: `${ariaRole}[name=${escapeForAttributeSelector(ariaName, true)}]`, score: 3 });
candidates.push({ engine: 'internal:role', selector: `${ariaRole}[name=${escapeForAttributeSelector(ariaName, true)}]`, score: 3 });
else
candidates.push({ engine: 'role', selector: ariaRole, score: 150 });
candidates.push({ engine: 'internal:role', selector: ariaRole, score: 150 });
}
if (element.getAttribute('alt') && ['APPLET', 'AREA', 'IMG', 'INPUT'].includes(element.nodeName))

View File

@ -55,7 +55,7 @@ function innerAsLocator(factory: LocatorFactory, selector: string, isFrameLocato
tokens.push(factory.generateLocator(base, 'label', text, { exact }));
continue;
}
if (part.name === 'role') {
if (part.name === 'internal:role') {
const attrSelector = parseAttributeSelector(part.body as string, true);
const attrs: Record<string, boolean | string> = {};
for (const attr of attrSelector.attributes!)

View File

@ -46,7 +46,7 @@ export class Selectors {
'data-test-id', 'data-test-id:light',
'data-test', 'data-test:light',
'nth', 'visible', 'internal:control', 'internal:has',
'role', 'internal:attr', 'internal:label', 'internal:text'
'role', 'internal:attr', 'internal:label', 'internal:text', 'internal:role',
]);
this._builtinEnginesInMainWorld = new Set([
'_react', '_vue',

View File

@ -26,7 +26,7 @@ test.describe('cli codegen', () => {
await recorder.setContentAndWait(`<button onclick="console.log('click')">Submit</button>`);
const selector = await recorder.hoverOverElement('button');
expect(selector).toBe('role=button[name=\"Submit\"]');
expect(selector).toBe('internal:role=button[name=\"Submit\"]');
const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'),
@ -69,7 +69,7 @@ test.describe('cli codegen', () => {
await page.waitForTimeout(1000);
const selector = await recorder.hoverOverElement('button');
expect(selector).toBe('role=button[name=\"Submit\"]');
expect(selector).toBe('internal:role=button[name=\"Submit\"]');
const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'),
@ -149,7 +149,7 @@ test.describe('cli codegen', () => {
</body>`);
const selector = await recorder.hoverOverElement('button');
expect(selector).toBe('role=button[name=\"Submit\"]');
expect(selector).toBe('internal:role=button[name=\"Submit\"]');
const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'),
@ -540,7 +540,7 @@ test.describe('cli codegen', () => {
await recorder.setContentAndWait('<a target=_blank rel=noopener href="about:blank">link</a>');
const selector = await recorder.hoverOverElement('a');
expect(selector).toBe('role=link[name=\"link\"]');
expect(selector).toBe('internal:role=link[name=\"link\"]');
const [popup, sources] = await Promise.all([
page.context().waitForEvent('page'),

View File

@ -333,7 +333,7 @@ test.describe('cli codegen', () => {
await recorder.setContentAndWait(`<a href="about:blank?foo">link</a>`);
const selector = await recorder.hoverOverElement('a');
expect(selector).toBe('role=link[name=\"link\"]');
expect(selector).toBe('internal:role=link[name=\"link\"]');
await page.click('a', { modifiers: [platform === 'darwin' ? 'Meta' : 'Control'] });
const sources = await recorder.waitForOutput('JavaScript', 'page1');

View File

@ -28,7 +28,7 @@ test.describe('cli codegen', () => {
`);
const selector = await recorder.hoverOverElement('button');
expect(selector).toBe('role=button[name=\"Submit\"] >> nth=0');
expect(selector).toBe('internal:role=button[name=\"Submit\"] >> nth=0');
const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'),
@ -63,7 +63,7 @@ test.describe('cli codegen', () => {
`);
const selector = await recorder.hoverOverElement('button >> nth=1');
expect(selector).toBe('role=button[name=\"Submit\"] >> nth=1');
expect(selector).toBe('internal:role=button[name=\"Submit\"] >> nth=1');
const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'),

View File

@ -35,7 +35,7 @@ it.describe('selector generator', () => {
it('should prefer role=button over inner span', async ({ page }) => {
await page.setContent(`<div role=button><span></span></div>`);
expect(await generate(page, 'div')).toBe('role=button');
expect(await generate(page, 'div')).toBe('internal:role=button');
});
it('should generate text and normalize whitespace', async ({ page }) => {
@ -50,7 +50,7 @@ it.describe('selector generator', () => {
it('should generate text for <input type=button>', async ({ page }) => {
await page.setContent(`<input type=button value="Click me">`);
expect(await generate(page, 'input')).toBe('role=button[name=\"Click me\"]');
expect(await generate(page, 'input')).toBe('internal:role=button[name=\"Click me\"]');
});
it('should trim text', async ({ page }) => {
@ -319,7 +319,7 @@ it.describe('selector generator', () => {
await page.setContent(`<button><span></span></button><button></button>`);
await page.$eval('button', button => button.setAttribute('aria-label', `!#'!?:`));
expect(await generate(page, 'button')).toBe(`role=button[name="!#'!?:"]`);
expect(await generate(page, 'button')).toBe(`internal:role=button[name="!#'!?:"]`);
expect(await page.$(`role=button[name="!#'!?:"]`)).toBeTruthy();
await page.setContent(`<div><span></span></div>`);
@ -343,7 +343,7 @@ it.describe('selector generator', () => {
it('should accept valid aria-label for candidate consideration', async ({ page }) => {
await page.setContent(`<button aria-label="ariaLabel" id="buttonId"></button>`);
expect(await generate(page, 'button')).toBe('role=button[name=\"ariaLabel\"]');
expect(await generate(page, 'button')).toBe('internal:role=button[name=\"ariaLabel\"]');
});
it('should ignore empty role for candidate consideration', async ({ page }) => {