diff --git a/docs/src/api/class-frame.md b/docs/src/api/class-frame.md
index 4a48d4dbf1..8dfef202b1 100644
--- a/docs/src/api/class-frame.md
+++ b/docs/src/api/class-frame.md
@@ -908,6 +908,16 @@ Attribute name to get the value for.
* since: v1.8
+## method: Frame.getByAltText
+* since: v1.27
+- returns: <[Locator]>
+
+%%-template-locator-get-by-alt-text-%%
+
+### param: Frame.getByAltText.text = %%-locator-get-by-text-text-%%
+### option: Frame.getByAltText.exact = %%-locator-get-by-text-exact-%%
+
+
## method: Frame.getByLabelText
* since: v1.27
- returns: <[Locator]>
@@ -960,6 +970,16 @@ Attribute name to get the value for.
### option: Frame.getByText.exact = %%-locator-get-by-text-exact-%%
+## method: Frame.getByTitle
+* since: v1.27
+- returns: <[Locator]>
+
+%%-template-locator-get-by-title-%%
+
+### param: Frame.getByTitle.text = %%-locator-get-by-text-text-%%
+### option: Frame.getByTitle.exact = %%-locator-get-by-text-exact-%%
+
+
## async method: Frame.goto
* since: v1.8
* langs:
diff --git a/docs/src/api/class-framelocator.md b/docs/src/api/class-framelocator.md
index 78b02dc374..019354cf33 100644
--- a/docs/src/api/class-framelocator.md
+++ b/docs/src/api/class-framelocator.md
@@ -114,6 +114,16 @@ in that iframe.
* since: v1.17
+## method: FrameLocator.getByAltText
+* since: v1.27
+- returns: <[Locator]>
+
+%%-template-locator-get-by-alt-text-%%
+
+### param: FrameLocator.getByAltText.text = %%-locator-get-by-text-text-%%
+### option: FrameLocator.getByAltText.exact = %%-locator-get-by-text-exact-%%
+
+
## method: FrameLocator.getByLabelText
* since: v1.27
- returns: <[Locator]>
@@ -165,6 +175,16 @@ in that iframe.
### option: FrameLocator.getByText.exact = %%-locator-get-by-text-exact-%%
+## method: FrameLocator.getByTitle
+* since: v1.27
+- returns: <[Locator]>
+
+%%-template-locator-get-by-title-%%
+
+### param: FrameLocator.getByTitle.text = %%-locator-get-by-text-text-%%
+### option: FrameLocator.getByTitle.exact = %%-locator-get-by-text-exact-%%
+
+
## method: FrameLocator.last
* since: v1.17
- returns: <[FrameLocator]>
diff --git a/docs/src/api/class-locator.md b/docs/src/api/class-locator.md
index 7f3465bfeb..1f2b0a3df7 100644
--- a/docs/src/api/class-locator.md
+++ b/docs/src/api/class-locator.md
@@ -634,6 +634,16 @@ Attribute name to get the value for.
* since: v1.14
+## method: Locator.getByAltText
+* since: v1.27
+- returns: <[Locator]>
+
+%%-template-locator-get-by-alt-text-%%
+
+### param: Locator.getByAltText.text = %%-locator-get-by-text-text-%%
+### option: Locator.getByAltText.exact = %%-locator-get-by-text-exact-%%
+
+
## method: Locator.getByLabelText
* since: v1.27
- returns: <[Locator]>
@@ -685,6 +695,16 @@ Attribute name to get the value for.
### option: Locator.getByText.exact = %%-locator-get-by-text-exact-%%
+## method: Locator.getByTitle
+* since: v1.27
+- returns: <[Locator]>
+
+%%-template-locator-get-by-title-%%
+
+### param: Locator.getByTitle.text = %%-locator-get-by-text-text-%%
+### option: Locator.getByTitle.exact = %%-locator-get-by-text-exact-%%
+
+
## async method: Locator.highlight
* since: v1.20
diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md
index 63f1083951..e4bf776050 100644
--- a/docs/src/api/class-page.md
+++ b/docs/src/api/class-page.md
@@ -2183,6 +2183,16 @@ Attribute name to get the value for.
* since: v1.8
+## method: Page.getByAltText
+* since: v1.27
+- returns: <[Locator]>
+
+%%-template-locator-get-by-alt-text-%%
+
+### param: Page.getByAltText.text = %%-locator-get-by-text-text-%%
+### option: Page.getByAltText.exact = %%-locator-get-by-text-exact-%%
+
+
## method: Page.getByLabelText
* since: v1.27
- returns: <[Locator]>
@@ -2234,6 +2244,16 @@ Attribute name to get the value for.
### option: Page.getByText.exact = %%-locator-get-by-text-exact-%%
+## method: Page.getByTitle
+* since: v1.27
+- returns: <[Locator]>
+
+%%-template-locator-get-by-title-%%
+
+### param: Page.getByTitle.text = %%-locator-get-by-text-text-%%
+### option: Page.getByTitle.exact = %%-locator-get-by-text-exact-%%
+
+
## async method: Page.goBack
* since: v1.8
- returns: <[null]|[Response]>
diff --git a/docs/src/api/params.md b/docs/src/api/params.md
index 669aa40d0d..109bd5781d 100644
--- a/docs/src/api/params.md
+++ b/docs/src/api/params.md
@@ -1180,6 +1180,14 @@ Locate element by the test id. By default, the `data-testid` attribute is used a
Allows locating elements that contain given text.
+## template-locator-get-by-alt-text
+
+Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
+
+```html
+
+```
+
## template-locator-get-by-label-text
Allows locating input elements by the text of the associated label. For example, this method will find the input by label text Password in the following DOM:
@@ -1188,6 +1196,7 @@ Allows locating input elements by the text of the associated label. For example,
```
+
## template-locator-get-by-placeholder-text
Allows locating input elements by the placeholder text. For example, this method will find the input by placeholder "Country":
@@ -1202,3 +1211,10 @@ Allows locating elements by their [ARIA role](https://www.w3.org/TR/wai-aria-1.2
Note that many html elements have an implicitly [defined role](https://w3c.github.io/html-aam/#html-element-role-mappings) that is recognized by the role selector. You can find all the [supported roles here](https://www.w3.org/TR/wai-aria-1.2/#role_definitions). ARIA guidelines **do not recommend** duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
+## template-locator-get-by-title
+
+Allows locating elements by their title. For example, this method will find the button by its title "Submit":
+
+```html
+
+```
diff --git a/packages/playwright-core/src/client/frame.ts b/packages/playwright-core/src/client/frame.ts
index a3420ee834..9a40225f12 100644
--- a/packages/playwright-core/src/client/frame.ts
+++ b/packages/playwright-core/src/client/frame.ts
@@ -303,6 +303,10 @@ export class Frame extends ChannelOwner implements api.Fr
return this.locator(Locator.getByTestIdSelector(testId));
}
+ getByAltText(text: string | RegExp, options?: { exact?: boolean }): Locator {
+ return this.locator(Locator.getByAltTextSelector(text, options));
+ }
+
getByLabelText(text: string | RegExp, options?: { exact?: boolean }): Locator {
return this.locator(Locator.getByLabelTextSelector(text, options));
}
@@ -315,6 +319,10 @@ export class Frame extends ChannelOwner implements api.Fr
return this.locator(Locator.getByTextSelector(text, options));
}
+ getByTitle(text: string | RegExp, options?: { exact?: boolean }): Locator {
+ return this.locator(Locator.getByTitleSelector(text, options));
+ }
+
getByRole(role: string, options: ByRoleOptions = {}): Locator {
return this.locator(Locator.getByRoleSelector(role, options));
}
diff --git a/packages/playwright-core/src/client/locator.ts b/packages/playwright-core/src/client/locator.ts
index 90cd069684..6d4386b93b 100644
--- a/packages/playwright-core/src/client/locator.ts
+++ b/packages/playwright-core/src/client/locator.ts
@@ -52,7 +52,13 @@ export class Locator implements api.Locator {
}
static getByTestIdSelector(testId: string): string {
- return `attr=[${Locator._testIdAttributeName}=${JSON.stringify(testId)}]`;
+ return Locator.getByAttributeTextSelector(this._testIdAttributeName, testId, { exact: true });
+ }
+
+ private static getByAttributeTextSelector(attrName: string, text: string | RegExp, options?: { exact?: boolean }): string {
+ if (!isString(text))
+ return `attr=[${attrName}=${text}]`;
+ return `attr=[${attrName}=${JSON.stringify(text)}${options?.exact ? 's' : 'i'}]`;
}
static getByLabelTextSelector(text: string | RegExp, options?: { exact?: boolean }): string {
@@ -63,10 +69,16 @@ export class Locator implements api.Locator {
return selector + ' >> control=resolve-label';
}
+ static getByAltTextSelector(text: string | RegExp, options?: { exact?: boolean }): string {
+ return Locator.getByAttributeTextSelector('alt', text, options);
+ }
+
+ static getByTitleSelector(text: string | RegExp, options?: { exact?: boolean }): string {
+ return Locator.getByAttributeTextSelector('title', text, options);
+ }
+
static getByPlaceholderTextSelector(text: string | RegExp, options?: { exact?: boolean }): string {
- if (!isString(text))
- return `attr=[placeholder=${text}]`;
- return `attr=[placeholder=${JSON.stringify(text)}${options?.exact ? 's' : 'i'}]`;
+ return Locator.getByAttributeTextSelector('placeholder', text, options);
}
static getByTextSelector(text: string | RegExp, options?: { exact?: boolean }): string {
@@ -199,6 +211,10 @@ export class Locator implements api.Locator {
return this.locator(Locator.getByTestIdSelector(testId));
}
+ getByAltText(text: string | RegExp, options?: { exact?: boolean }): Locator {
+ return this.locator(Locator.getByAltTextSelector(text, options));
+ }
+
getByLabelText(text: string | RegExp, options?: { exact?: boolean }): Locator {
return this.locator(Locator.getByLabelTextSelector(text, options));
}
@@ -211,6 +227,10 @@ export class Locator implements api.Locator {
return this.locator(Locator.getByTextSelector(text, options));
}
+ getByTitle(text: string | RegExp, options?: { exact?: boolean }): Locator {
+ return this.locator(Locator.getByTitleSelector(text, options));
+ }
+
getByRole(role: string, options: ByRoleOptions = {}): Locator {
return this.locator(Locator.getByRoleSelector(role, options));
}
@@ -393,6 +413,10 @@ export class FrameLocator implements api.FrameLocator {
return this.locator(Locator.getByTestIdSelector(testId));
}
+ getByAltText(text: string | RegExp, options?: { exact?: boolean }): Locator {
+ return this.locator(Locator.getByAltTextSelector(text, options));
+ }
+
getByLabelText(text: string | RegExp, options?: { exact?: boolean }): Locator {
return this.locator(Locator.getByLabelTextSelector(text, options));
}
@@ -405,6 +429,10 @@ export class FrameLocator implements api.FrameLocator {
return this.locator(Locator.getByTextSelector(text, options));
}
+ getByTitle(text: string | RegExp, options?: { exact?: boolean }): Locator {
+ return this.locator(Locator.getByTitleSelector(text, options));
+ }
+
getByRole(role: string, options: ByRoleOptions = {}): Locator {
return this.locator(Locator.getByRoleSelector(role, options));
}
diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts
index b28d87d216..42cfac43b1 100644
--- a/packages/playwright-core/src/client/page.ts
+++ b/packages/playwright-core/src/client/page.ts
@@ -568,6 +568,10 @@ export class Page extends ChannelOwner implements api.Page
return this.mainFrame().getByTestId(testId);
}
+ getByAltText(text: string | RegExp, options?: { exact?: boolean }): Locator {
+ return this.mainFrame().getByAltText(text, options);
+ }
+
getByLabelText(text: string | RegExp, options?: { exact?: boolean }): Locator {
return this.mainFrame().getByLabelText(text, options);
}
@@ -580,6 +584,10 @@ export class Page extends ChannelOwner implements api.Page
return this.mainFrame().getByText(text, options);
}
+ getByTitle(text: string | RegExp, options?: { exact?: boolean }): Locator {
+ return this.mainFrame().getByTitle(text, options);
+ }
+
getByRole(role: string, options: ByRoleOptions = {}): Locator {
return this.mainFrame().getByRole(role, options);
}
diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts
index e5d4a52324..db80053da6 100644
--- a/packages/playwright-core/types/types.d.ts
+++ b/packages/playwright-core/types/types.d.ts
@@ -2456,6 +2456,23 @@ export interface Page {
timeout?: number;
}): Promise;
+ /**
+ * Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
+ *
+ * ```html
+ *
+ * ```
+ *
+ * @param text Text to locate the element for.
+ * @param options
+ */
+ getByAltText(text: string|RegExp, options?: {
+ /**
+ * Whether to find an exact match: case-sensitive and whole-string. Default to false.
+ */
+ exact?: boolean;
+ }): Locator;
+
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
@@ -2588,6 +2605,23 @@ export interface Page {
exact?: boolean;
}): Locator;
+ /**
+ * Allows locating elements by their title. For example, this method will find the button by its title "Submit":
+ *
+ * ```html
+ *
+ * ```
+ *
+ * @param text Text to locate the element for.
+ * @param options
+ */
+ getByTitle(text: string|RegExp, options?: {
+ /**
+ * Whether to find an exact match: case-sensitive and whole-string. Default to false.
+ */
+ exact?: boolean;
+ }): Locator;
+
/**
* Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
* last redirect. If can not go back, returns `null`.
@@ -5508,6 +5542,23 @@ export interface Frame {
timeout?: number;
}): Promise;
+ /**
+ * Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
+ *
+ * ```html
+ *
+ * ```
+ *
+ * @param text Text to locate the element for.
+ * @param options
+ */
+ getByAltText(text: string|RegExp, options?: {
+ /**
+ * Whether to find an exact match: case-sensitive and whole-string. Default to false.
+ */
+ exact?: boolean;
+ }): Locator;
+
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
@@ -5640,6 +5691,23 @@ export interface Frame {
exact?: boolean;
}): Locator;
+ /**
+ * Allows locating elements by their title. For example, this method will find the button by its title "Submit":
+ *
+ * ```html
+ *
+ * ```
+ *
+ * @param text Text to locate the element for.
+ * @param options
+ */
+ getByTitle(text: string|RegExp, options?: {
+ /**
+ * Whether to find an exact match: case-sensitive and whole-string. Default to false.
+ */
+ exact?: boolean;
+ }): Locator;
+
/**
* Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
* last redirect.
@@ -9908,6 +9976,23 @@ export interface Locator {
timeout?: number;
}): Promise;
+ /**
+ * Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
+ *
+ * ```html
+ *
+ * ```
+ *
+ * @param text Text to locate the element for.
+ * @param options
+ */
+ getByAltText(text: string|RegExp, options?: {
+ /**
+ * Whether to find an exact match: case-sensitive and whole-string. Default to false.
+ */
+ exact?: boolean;
+ }): Locator;
+
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
@@ -10040,6 +10125,23 @@ export interface Locator {
exact?: boolean;
}): Locator;
+ /**
+ * Allows locating elements by their title. For example, this method will find the button by its title "Submit":
+ *
+ * ```html
+ *
+ * ```
+ *
+ * @param text Text to locate the element for.
+ * @param options
+ */
+ getByTitle(text: string|RegExp, options?: {
+ /**
+ * Whether to find an exact match: case-sensitive and whole-string. Default to false.
+ */
+ exact?: boolean;
+ }): Locator;
+
/**
* Highlight the corresponding element(s) on the screen. Useful for debugging, don't commit the code that uses
* [locator.highlight()](https://playwright.dev/docs/api/class-locator#locator-highlight).
@@ -15129,6 +15231,23 @@ export interface FrameLocator {
*/
frameLocator(selector: string): FrameLocator;
+ /**
+ * Allows locating elements by their alt text. For example, this method will find the image by alt text "Castle":
+ *
+ * ```html
+ *
+ * ```
+ *
+ * @param text Text to locate the element for.
+ * @param options
+ */
+ getByAltText(text: string|RegExp, options?: {
+ /**
+ * Whether to find an exact match: case-sensitive and whole-string. Default to false.
+ */
+ exact?: boolean;
+ }): Locator;
+
/**
* Allows locating input elements by the text of the associated label. For example, this method will find the input by
* label text Password in the following DOM:
@@ -15261,6 +15380,23 @@ export interface FrameLocator {
exact?: boolean;
}): Locator;
+ /**
+ * Allows locating elements by their title. For example, this method will find the button by its title "Submit":
+ *
+ * ```html
+ *
+ * ```
+ *
+ * @param text Text to locate the element for.
+ * @param options
+ */
+ getByTitle(text: string|RegExp, options?: {
+ /**
+ * Whether to find an exact match: case-sensitive and whole-string. Default to false.
+ */
+ exact?: boolean;
+ }): Locator;
+
/**
* Returns locator to the last matching frame.
*/
diff --git a/tests/page/locator-frame.spec.ts b/tests/page/locator-frame.spec.ts
index 6e43190ffb..4755141021 100644
--- a/tests/page/locator-frame.spec.ts
+++ b/tests/page/locator-frame.spec.ts
@@ -35,7 +35,7 @@ async function routeIframe(page: Page) {
1
2
-
+