fix: parse locator with empty options (#33990)

This commit is contained in:
Yury Semikhatsky 2024-12-12 17:49:48 -08:00 committed by GitHub
parent 76d46d478f
commit 0034c6b984
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 16 additions and 2 deletions

View File

@ -91,7 +91,8 @@ function parseLocator(locator: string, testIdAttributeName: string): { selector:
.replace(/newregex\(([^)]+)\)/g, 'r$1') .replace(/newregex\(([^)]+)\)/g, 'r$1')
.replace(/string=/g, '=') .replace(/string=/g, '=')
.replace(/regex=/g, '=') .replace(/regex=/g, '=')
.replace(/,,/g, ','); .replace(/,,/g, ',')
.replace(/,\)/g, ')');
const preferredQuote = params.map(p => p.quote).filter(quote => '\'"`'.includes(quote))[0] as Quote | undefined; const preferredQuote = params.map(p => p.quote).filter(quote => '\'"`'.includes(quote))[0] as Quote | undefined;
return { selector: transform(template, params, testIdAttributeName), preferredQuote }; return { selector: transform(template, params, testIdAttributeName), preferredQuote };
@ -174,6 +175,7 @@ function transform(template: string, params: TemplateParams, testIdAttributeName
.replace(/filter\(,?hasnot2=([^)]+)\)/g, 'internal:has-not=$1') .replace(/filter\(,?hasnot2=([^)]+)\)/g, 'internal:has-not=$1')
.replace(/,exact=false/g, '') .replace(/,exact=false/g, '')
.replace(/,exact=true/g, 's') .replace(/,exact=true/g, 's')
.replace(/,includehidden=/g, ',include-hidden=')
.replace(/\,/g, ']['); .replace(/\,/g, '][');
const parts = template.split('.'); const parts = template.split('.');
@ -233,6 +235,6 @@ export function locatorOrSelectorAsSelector(language: Language, locator: string,
function digestForComparison(language: Language, locator: string) { function digestForComparison(language: Language, locator: string) {
locator = locator.replace(/\s/g, ''); locator = locator.replace(/\s/g, '');
if (language === 'javascript') if (language === 'javascript')
locator = locator.replace(/\\?["`]/g, '\''); locator = locator.replace(/\\?["`]/g, '\'').replace(/,{}/g, '');
return locator; return locator;
} }

View File

@ -196,6 +196,12 @@ it('reverse engineer getByRole', async ({ page }) => {
java: `getByRole(AriaRole.BUTTON)`, java: `getByRole(AriaRole.BUTTON)`,
csharp: `GetByRole(AriaRole.Button)`, csharp: `GetByRole(AriaRole.Button)`,
}); });
expect.soft(generate(page.getByRole('heading', {}))).toEqual({
javascript: "getByRole('heading')",
python: 'get_by_role("heading")',
java: 'getByRole(AriaRole.HEADING)',
csharp: 'GetByRole(AriaRole.Heading)'
});
expect.soft(generate(page.getByRole('button', { name: 'Hello' }))).toEqual({ expect.soft(generate(page.getByRole('button', { name: 'Hello' }))).toEqual({
javascript: `getByRole('button', { name: 'Hello' })`, javascript: `getByRole('button', { name: 'Hello' })`,
python: `get_by_role("button", name="Hello")`, python: `get_by_role("button", name="Hello")`,
@ -559,6 +565,12 @@ it('parseLocator css', async () => {
expect.soft(parseLocator('csharp', `Locator("css=.foo")`, '')).toBe(`css=.foo`); expect.soft(parseLocator('csharp', `Locator("css=.foo")`, '')).toBe(`css=.foo`);
}); });
it('parseLocator options', async () => {
expect.soft(parseLocator('javascript', `getByRole('heading', {})`, '')).toBe(`internal:role=heading`);
expect.soft(parseLocator('javascript', `getByRole('checkbox', { checked:false, includeHidden: true })`, '')).toBe(`internal:role=checkbox[checked=false][include-hidden=true]`);
});
it('parse locators strictly', () => { it('parse locators strictly', () => {
const selector = 'div >> internal:has-text=\"Goodbye world\"i >> span'; const selector = 'div >> internal:has-text=\"Goodbye world\"i >> span';