chore: prioritize role over label and placeholder (#33970)

This commit is contained in:
Pavel Feldman 2024-12-12 08:21:00 -08:00 committed by GitHub
parent e3629dc1df
commit 0e2b984287
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 34 deletions

View File

@ -38,9 +38,9 @@ const kOtherTestIdScore = 2; // other data-test* attributes
const kIframeByAttributeScore = 10;
const kBeginPenalizedScore = 50;
const kPlaceholderScore = 100;
const kLabelScore = 120;
const kRoleWithNameScore = 140;
const kRoleWithNameScore = 100;
const kPlaceholderScore = 120;
const kLabelScore = 140;
const kAltTextScore = 160;
const kTextScore = 180;
const kTitleScore = 200;

View File

@ -472,7 +472,7 @@ await page.GetByTestId("testid").ClickAsync();`);
await recorder.setContentAndWait(`<input placeholder="Country"></input>`);
const locator = await recorder.hoverOverElement('input');
expect(locator).toBe(`getByPlaceholder('Country')`);
expect(locator).toBe(`getByRole('textbox', { name: 'Country' })`);
const [sources] = await Promise.all([
recorder.waitForOutput('JavaScript', 'click'),
@ -480,19 +480,19 @@ await page.GetByTestId("testid").ClickAsync();`);
]);
expect.soft(sources.get('JavaScript')!.text).toContain(`
await page.getByPlaceholder('Country').click();`);
await page.getByRole('textbox', { name: 'Country' }).click();`);
expect.soft(sources.get('Python')!.text).toContain(`
page.get_by_placeholder("Country").click()`);
page.get_by_role("textbox", name="Country").click()`);
expect.soft(sources.get('Python Async')!.text).toContain(`
await page.get_by_placeholder("Country").click()`);
await page.get_by_role("textbox", name="Country").click()`);
expect.soft(sources.get('Java')!.text).toContain(`
page.getByPlaceholder("Country").click()`);
page.getByRole(AriaRole.TEXTBOX, new Page.GetByRoleOptions().setName("Country")).click()`);
expect.soft(sources.get('C#')!.text).toContain(`
await page.GetByPlaceholder("Country").ClickAsync();`);
await page.GetByRole(AriaRole.Textbox, new() { Name = "Country" }).ClickAsync();`);
});
test('should generate getByAltText', async ({ openRecorder }) => {
@ -530,7 +530,7 @@ await page.GetByAltText("Country").ClickAsync();`);
await recorder.setContentAndWait(`<label for=target>Country</label><input id=target>`);
const locator = await recorder.hoverOverElement('input');
expect(locator).toBe(`getByLabel('Country')`);
expect(locator).toBe(`getByRole('textbox', { name: 'Country' })`);
const [sources] = await Promise.all([
recorder.waitForOutput('JavaScript', 'click'),
@ -538,19 +538,19 @@ await page.GetByAltText("Country").ClickAsync();`);
]);
expect.soft(sources.get('JavaScript')!.text).toContain(`
await page.getByLabel('Country').click();`);
await page.getByRole('textbox', { name: 'Country' }).click();`);
expect.soft(sources.get('Python')!.text).toContain(`
page.get_by_label("Country").click()`);
page.get_by_role("textbox", name="Country").click()`);
expect.soft(sources.get('Python Async')!.text).toContain(`
await page.get_by_label("Country").click()`);
await page.get_by_role("textbox", name="Country").click()`);
expect.soft(sources.get('Java')!.text).toContain(`
page.getByLabel("Country").click()`);
page.getByRole(AriaRole.TEXTBOX, new Page.GetByRoleOptions().setName("Country")).click()`);
expect.soft(sources.get('C#')!.text).toContain(`
await page.GetByLabel("Country").ClickAsync();`);
await page.GetByRole(AriaRole.Textbox, new() { Name = "Country" }).ClickAsync();`);
});
test('should generate getByLabel without regex', async ({ openRecorder }) => {
@ -559,7 +559,7 @@ await page.GetByLabel("Country").ClickAsync();`);
await recorder.setContentAndWait(`<label for=target>Coun"try</label><input id=target>`);
const locator = await recorder.hoverOverElement('input');
expect(locator).toBe(`getByLabel('Coun"try')`);
expect(locator).toBe(`getByRole('textbox', { name: 'Coun"try' })`);
const [sources] = await Promise.all([
recorder.waitForOutput('JavaScript', 'click'),
@ -567,19 +567,19 @@ await page.GetByLabel("Country").ClickAsync();`);
]);
expect.soft(sources.get('JavaScript')!.text).toContain(`
await page.getByLabel('Coun\"try').click();`);
await page.getByRole('textbox', { name: 'Coun\"try' }).click();`);
expect.soft(sources.get('Python')!.text).toContain(`
page.get_by_label("Coun\\"try").click()`);
page.get_by_role("textbox", name="Coun\\"try").click()`);
expect.soft(sources.get('Python Async')!.text).toContain(`
await page.get_by_label("Coun\\"try").click()`);
await page.get_by_role("textbox", name="Coun\\"try").click()`);
expect.soft(sources.get('Java')!.text).toContain(`
page.getByLabel("Coun\\"try").click()`);
page.getByRole(AriaRole.TEXTBOX, new Page.GetByRoleOptions().setName(\"Coun\\\"try\")).click();`);
expect.soft(sources.get('C#')!.text).toContain(`
await page.GetByLabel("Coun\\"try").ClickAsync();`);
await page.GetByRole(AriaRole.Textbox, new() { Name = \"Coun\\\"try\" }).ClickAsync();`);
});
test('should consume pointer events', async ({ openRecorder }) => {

View File

@ -58,7 +58,7 @@ it.describe('selector generator', () => {
it('should not escape spaces inside named attr selectors', async ({ page }) => {
await page.setContent(`<input placeholder="Foo b ar"/>`);
expect(await generate(page, 'input')).toBe('internal:attr=[placeholder=\"Foo b ar\"i]');
expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Foo b ar\"i]');
});
it('should generate text for <input type=button>', async ({ page }) => {
@ -91,7 +91,7 @@ it.describe('selector generator', () => {
it('should try to improve label text by shortening', async ({ page }) => {
await page.setContent(`<label>Longest verbose description of the item<input></label>`);
expect(await generate(page, 'input')).toBe('internal:label="Longest verbose description"i');
expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Longest verbose description\"i]');
});
it('should not improve guid text', async ({ page }) => {
@ -316,7 +316,7 @@ it.describe('selector generator', () => {
});
it('placeholder', async ({ page }) => {
await page.setContent(`<input placeholder="foobar" type="text"/>`);
expect(await generate(page, 'input')).toBe('internal:attr=[placeholder=\"foobar\"i]');
expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"foobar\"i]');
});
it('name', async ({ page }) => {
await page.setContent(`
@ -437,7 +437,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('internal:label="ariaLabel"i');
expect(await generate(page, 'button')).toBe('internal:role=button[name=\"ariaLabel\"i]');
});
it('should ignore empty role for candidate consideration', async ({ page }) => {
@ -469,15 +469,15 @@ it.describe('selector generator', () => {
<label for=target5>Target5</label><input id=target5 type=hidden>
<label for=target6>Target6</label><div id=target6>text</div>
`);
expect(await generate(page, '#target1')).toBe('internal:label="Target1"i');
expect(await generate(page, '#target2')).toBe('internal:label="Target2"i');
expect(await generate(page, '#target3')).toBe('internal:label="Target3"i');
expect(await generate(page, '#target4')).toBe('internal:label="Target4"i');
expect(await generate(page, '#target5')).toBe('#target5');
expect(await generate(page, '#target6')).toBe('internal:text="text"i');
expect.soft(await generate(page, '#target1')).toBe('internal:role=textbox[name=\"Target1\"i]');
expect.soft(await generate(page, '#target2')).toBe('internal:role=button[name=\"Target2\"i]');
expect.soft(await generate(page, '#target3')).toBe('internal:label=\"Target3\"i');
expect.soft(await generate(page, '#target4')).toBe('internal:label=\"Target4\"i');
expect.soft(await generate(page, '#target5')).toBe('#target5');
expect.soft(await generate(page, '#target6')).toBe('internal:text="text"i');
await page.setContent(`<label for=target>Coun"try</label><input id=target>`);
expect(await generate(page, 'input')).toBe('internal:label="Coun\\\"try"i');
expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Coun\\\"try\"i]');
});
it('should prefer role other input[type]', async ({ page }) => {
@ -514,7 +514,7 @@ it.describe('selector generator', () => {
<input placeholder="Text"></input>
<input placeholder="Text and more"></input>
`);
expect(await generate(page, 'input')).toBe('internal:attr=[placeholder=\"Text\"s]');
expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Text\"s]');
});
it('should generate exact role when necessary', async ({ page }) => {
@ -530,7 +530,7 @@ it.describe('selector generator', () => {
<label>Text <input></input></label>
<label>Text and more <input></input></label>
`);
expect(await generate(page, 'input')).toBe('internal:label=\"Text\"s');
expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Text\"s]');
});
it('should generate relative selector', async ({ page }) => {