chore: prioritize role over label and placeholder (#33970)
This commit is contained in:
parent
e3629dc1df
commit
0e2b984287
|
|
@ -38,9 +38,9 @@ const kOtherTestIdScore = 2; // other data-test* attributes
|
||||||
const kIframeByAttributeScore = 10;
|
const kIframeByAttributeScore = 10;
|
||||||
|
|
||||||
const kBeginPenalizedScore = 50;
|
const kBeginPenalizedScore = 50;
|
||||||
const kPlaceholderScore = 100;
|
const kRoleWithNameScore = 100;
|
||||||
const kLabelScore = 120;
|
const kPlaceholderScore = 120;
|
||||||
const kRoleWithNameScore = 140;
|
const kLabelScore = 140;
|
||||||
const kAltTextScore = 160;
|
const kAltTextScore = 160;
|
||||||
const kTextScore = 180;
|
const kTextScore = 180;
|
||||||
const kTitleScore = 200;
|
const kTitleScore = 200;
|
||||||
|
|
|
||||||
|
|
@ -472,7 +472,7 @@ await page.GetByTestId("testid").ClickAsync();`);
|
||||||
await recorder.setContentAndWait(`<input placeholder="Country"></input>`);
|
await recorder.setContentAndWait(`<input placeholder="Country"></input>`);
|
||||||
|
|
||||||
const locator = await recorder.hoverOverElement('input');
|
const locator = await recorder.hoverOverElement('input');
|
||||||
expect(locator).toBe(`getByPlaceholder('Country')`);
|
expect(locator).toBe(`getByRole('textbox', { name: 'Country' })`);
|
||||||
|
|
||||||
const [sources] = await Promise.all([
|
const [sources] = await Promise.all([
|
||||||
recorder.waitForOutput('JavaScript', 'click'),
|
recorder.waitForOutput('JavaScript', 'click'),
|
||||||
|
|
@ -480,19 +480,19 @@ await page.GetByTestId("testid").ClickAsync();`);
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect.soft(sources.get('JavaScript')!.text).toContain(`
|
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(`
|
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(`
|
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(`
|
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(`
|
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 }) => {
|
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>`);
|
await recorder.setContentAndWait(`<label for=target>Country</label><input id=target>`);
|
||||||
|
|
||||||
const locator = await recorder.hoverOverElement('input');
|
const locator = await recorder.hoverOverElement('input');
|
||||||
expect(locator).toBe(`getByLabel('Country')`);
|
expect(locator).toBe(`getByRole('textbox', { name: 'Country' })`);
|
||||||
|
|
||||||
const [sources] = await Promise.all([
|
const [sources] = await Promise.all([
|
||||||
recorder.waitForOutput('JavaScript', 'click'),
|
recorder.waitForOutput('JavaScript', 'click'),
|
||||||
|
|
@ -538,19 +538,19 @@ await page.GetByAltText("Country").ClickAsync();`);
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect.soft(sources.get('JavaScript')!.text).toContain(`
|
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(`
|
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(`
|
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(`
|
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(`
|
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 }) => {
|
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>`);
|
await recorder.setContentAndWait(`<label for=target>Coun"try</label><input id=target>`);
|
||||||
|
|
||||||
const locator = await recorder.hoverOverElement('input');
|
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([
|
const [sources] = await Promise.all([
|
||||||
recorder.waitForOutput('JavaScript', 'click'),
|
recorder.waitForOutput('JavaScript', 'click'),
|
||||||
|
|
@ -567,19 +567,19 @@ await page.GetByLabel("Country").ClickAsync();`);
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect.soft(sources.get('JavaScript')!.text).toContain(`
|
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(`
|
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(`
|
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(`
|
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(`
|
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 }) => {
|
test('should consume pointer events', async ({ openRecorder }) => {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ it.describe('selector generator', () => {
|
||||||
|
|
||||||
it('should not escape spaces inside named attr selectors', async ({ page }) => {
|
it('should not escape spaces inside named attr selectors', async ({ page }) => {
|
||||||
await page.setContent(`<input placeholder="Foo b ar"/>`);
|
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 }) => {
|
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 }) => {
|
it('should try to improve label text by shortening', async ({ page }) => {
|
||||||
await page.setContent(`<label>Longest verbose description of the item<input></label>`);
|
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 }) => {
|
it('should not improve guid text', async ({ page }) => {
|
||||||
|
|
@ -316,7 +316,7 @@ it.describe('selector generator', () => {
|
||||||
});
|
});
|
||||||
it('placeholder', async ({ page }) => {
|
it('placeholder', async ({ page }) => {
|
||||||
await page.setContent(`<input placeholder="foobar" type="text"/>`);
|
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 }) => {
|
it('name', async ({ page }) => {
|
||||||
await page.setContent(`
|
await page.setContent(`
|
||||||
|
|
@ -437,7 +437,7 @@ it.describe('selector generator', () => {
|
||||||
|
|
||||||
it('should accept valid aria-label for candidate consideration', async ({ page }) => {
|
it('should accept valid aria-label for candidate consideration', async ({ page }) => {
|
||||||
await page.setContent(`<button aria-label="ariaLabel" id="buttonId"></button>`);
|
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 }) => {
|
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=target5>Target5</label><input id=target5 type=hidden>
|
||||||
<label for=target6>Target6</label><div id=target6>text</div>
|
<label for=target6>Target6</label><div id=target6>text</div>
|
||||||
`);
|
`);
|
||||||
expect(await generate(page, '#target1')).toBe('internal:label="Target1"i');
|
expect.soft(await generate(page, '#target1')).toBe('internal:role=textbox[name=\"Target1\"i]');
|
||||||
expect(await generate(page, '#target2')).toBe('internal:label="Target2"i');
|
expect.soft(await generate(page, '#target2')).toBe('internal:role=button[name=\"Target2\"i]');
|
||||||
expect(await generate(page, '#target3')).toBe('internal:label="Target3"i');
|
expect.soft(await generate(page, '#target3')).toBe('internal:label=\"Target3\"i');
|
||||||
expect(await generate(page, '#target4')).toBe('internal:label="Target4"i');
|
expect.soft(await generate(page, '#target4')).toBe('internal:label=\"Target4\"i');
|
||||||
expect(await generate(page, '#target5')).toBe('#target5');
|
expect.soft(await generate(page, '#target5')).toBe('#target5');
|
||||||
expect(await generate(page, '#target6')).toBe('internal:text="text"i');
|
expect.soft(await generate(page, '#target6')).toBe('internal:text="text"i');
|
||||||
|
|
||||||
await page.setContent(`<label for=target>Coun"try</label><input id=target>`);
|
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 }) => {
|
it('should prefer role other input[type]', async ({ page }) => {
|
||||||
|
|
@ -514,7 +514,7 @@ it.describe('selector generator', () => {
|
||||||
<input placeholder="Text"></input>
|
<input placeholder="Text"></input>
|
||||||
<input placeholder="Text and more"></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 }) => {
|
it('should generate exact role when necessary', async ({ page }) => {
|
||||||
|
|
@ -530,7 +530,7 @@ it.describe('selector generator', () => {
|
||||||
<label>Text <input></input></label>
|
<label>Text <input></input></label>
|
||||||
<label>Text and more <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 }) => {
|
it('should generate relative selector', async ({ page }) => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue