From 4727acff56a3d350e4eda480251afe5006a6b0fd Mon Sep 17 00:00:00 2001
From: cpadm <57954026+cpAdm@users.noreply.github.com>
Date: Mon, 22 Dec 2025 15:41:36 +0100
Subject: [PATCH 1/3] feat: Expose types and documentation for
 `Locator.toString`

---
 docs/src/api/class-locator.md                         |  9 ++++++++-
 docs/src/release-notes-js.md                          |  2 +-
 packages/playwright-client/types/types.d.ts           | 11 +++++++++--
 .../src/utils/isomorphic/locatorGenerators.ts         |  2 +-
 packages/playwright-core/types/types.d.ts             | 11 +++++++++--
 utils/generate_types/overrides.d.ts                   |  1 +
 6 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/docs/src/api/class-locator.md b/docs/src/api/class-locator.md
index 042c08bb99a8e..d6a1893c07421 100644
--- a/docs/src/api/class-locator.md
+++ b/docs/src/api/class-locator.md
@@ -630,7 +630,7 @@ Locator description.
 * since: v1.57
 - returns: <[null]|[string]>
 
-Returns locator description previously set with [`method: Locator.describe`]. Returns `null` if no custom description has been set. Prefer `Locator.toString()` for a human-readable representation, as it uses the description when available.
+Returns locator description previously set with [`method: Locator.describe`]. Returns `null` if no custom description has been set. Prefer [`method: Locator.toString`] for a human-readable representation, as it uses the description when available.
 
 **Usage**
 
@@ -2534,6 +2534,13 @@ If you need to assert text on the page, prefer [`method: LocatorAssertions.toHav
 ### option: Locator.textContent.timeout = %%-input-timeout-js-%%
 * since: v1.14
 
+## method: Locator.toString
+* since: v1.57
+* langs: js
+- returns: <[String]>
+
+Returns a human-readable representation of the locator, using the [`method: Locator.description`] if one exists; otherwise, it generates a string based on the locator's selector.
+
 ## async method: Locator.type
 * since: v1.14
 * deprecated: In most cases, you should use [`method: Locator.fill`] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [`method: Locator.pressSequentially`].
diff --git a/docs/src/release-notes-js.md b/docs/src/release-notes-js.md
index 2ab8bccdd4045..3347b70b8be27 100644
--- a/docs/src/release-notes-js.md
+++ b/docs/src/release-notes-js.md
@@ -69,7 +69,7 @@ After 3 years of being deprecated, we removed `page.accessibility` from our API.
 
 - New property [`property: TestConfig.tag`] adds a tag to all tests in this run. This is useful when using [merge-reports](./test-sharding.md#merging-reports-from-multiple-shards).
 - [`event: Worker.console`] event is emitted when JavaScript within the worker calls one of console API methods, e.g. console.log or console.dir. [`method: Worker.waitForEvent`] can be used to wait for it.
-- [`method: Locator.description`] returns locator description previously set with [`method: Locator.describe`], and `Locator.toString()` now uses the description when available.
+- [`method: Locator.description`] returns locator description previously set with [`method: Locator.describe`], and [`method: Locator.toString`] now uses the description when available.
 - New option [`option: Locator.click.steps`] in [`method: Locator.click`] and [`method: Locator.dragTo`] that configures the number of `mousemove` events emitted while moving the mouse pointer to the target element.
 - Network requests issued by [Service Workers](./service-workers.md#network-events-and-routing) are now reported and can be routed through the [BrowserContext](./api/class-browsercontext.md), only in Chromium. You can opt out using the `PLAYWRIGHT_DISABLE_SERVICE_WORKER_NETWORK` environment variable.
 - Console messages from Service Workers are dispatched through [`event: Worker.console`]. You can opt out of this using the `PLAYWRIGHT_DISABLE_SERVICE_WORKER_CONSOLE` environment variable.
diff --git a/packages/playwright-client/types/types.d.ts b/packages/playwright-client/types/types.d.ts
index 002616f81a0df..c37c74ae8a077 100644
--- a/packages/playwright-client/types/types.d.ts
+++ b/packages/playwright-client/types/types.d.ts
@@ -12644,6 +12644,12 @@ export interface Locator {
   elementHandle(options?: {
     timeout?: number;
   }): Promise<null|ElementHandle<SVGElement | HTMLElement>>;
+  /**
+   * Returns a human-readable representation of the locator, using the
+   * [locator.description()](https://playwright.dev/docs/api/class-locator#locator-description) if one exists;
+   * otherwise, it generates a string based on the locator's selector.
+   */
+  toString(): string;
   /**
    * When the locator points to a list of elements, this returns an array of locators, pointing to their respective
    * elements.
@@ -13198,8 +13204,9 @@ export interface Locator {
   /**
    * Returns locator description previously set with
    * [locator.describe(description)](https://playwright.dev/docs/api/class-locator#locator-describe). Returns `null` if
-   * no custom description has been set. Prefer `Locator.toString()` for a human-readable representation, as it uses the
-   * description when available.
+   * no custom description has been set. Prefer
+   * [locator.toString()](https://playwright.dev/docs/api/class-locator#locator-to-string) for a human-readable
+   * representation, as it uses the description when available.
    *
    * **Usage**
    *
diff --git a/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts b/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts
index ae58852331742..01d29f3eaecb8 100644
--- a/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts
+++ b/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts
@@ -37,7 +37,7 @@ export interface LocatorFactory {
   chainLocators(locators: string[]): string;
 }
 
-export function asLocatorDescription(lang: Language, selector: string): string | undefined {
+export function asLocatorDescription(lang: Language, selector: string): string {
   try {
     const parsed = parseSelector(selector);
     const customDescription = parseCustomDescription(parsed);
diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts
index 002616f81a0df..e97294f52829f 100644
--- a/packages/playwright-core/types/types.d.ts
+++ b/packages/playwright-core/types/types.d.ts
@@ -12644,6 +12644,12 @@ export interface Locator {
   elementHandle(options?: {
     timeout?: number;
   }): Promise<null|ElementHandle<SVGElement | HTMLElement>>;
+  /**
+   * Returns a human-readable representation of the locator, using the
+   * [locator.description()](https://playwright.dev/docs/api/class-locator#locator-description) if one exists;
+   * otherwise, it generates a string based on the locator’s selector.
+   */
+  toString(): string;
   /**
    * When the locator points to a list of elements, this returns an array of locators, pointing to their respective
    * elements.
@@ -13198,8 +13204,9 @@ export interface Locator {
   /**
    * Returns locator description previously set with
    * [locator.describe(description)](https://playwright.dev/docs/api/class-locator#locator-describe). Returns `null` if
-   * no custom description has been set. Prefer `Locator.toString()` for a human-readable representation, as it uses the
-   * description when available.
+   * no custom description has been set. Prefer
+   * [locator.toString()](https://playwright.dev/docs/api/class-locator#locator-to-string) for a human-readable
+   * representation, as it uses the description when available.
    *
    * **Usage**
    *
diff --git a/utils/generate_types/overrides.d.ts b/utils/generate_types/overrides.d.ts
index b50bb7a641949..57822056cb58f 100644
--- a/utils/generate_types/overrides.d.ts
+++ b/utils/generate_types/overrides.d.ts
@@ -200,6 +200,7 @@ export interface Locator {
   elementHandle(options?: {
     timeout?: number;
   }): Promise<null|ElementHandle<SVGElement | HTMLElement>>;
+  toString(): string;
 }
 
 export interface BrowserType<Unused = {}> {

From cd6bf62ece7b931485546dff66a329a9871775ff Mon Sep 17 00:00:00 2001
From: Chris <57954026+cpAdm@users.noreply.github.com>
Date: Mon, 22 Dec 2025 19:56:47 +0100
Subject: [PATCH 2/3] Update docs/src/api/class-locator.md

Co-authored-by: Pavel Feldman <pavel.feldman@gmail.com>
Signed-off-by: Chris <57954026+cpAdm@users.noreply.github.com>
---
 docs/src/api/class-locator.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/src/api/class-locator.md b/docs/src/api/class-locator.md
index d6a1893c07421..68e068cc3657e 100644
--- a/docs/src/api/class-locator.md
+++ b/docs/src/api/class-locator.md
@@ -2537,7 +2537,7 @@ If you need to assert text on the page, prefer [`method: LocatorAssertions.toHav
 ## method: Locator.toString
 * since: v1.57
 * langs: js
-- returns: <[String]>
+- returns: <[string]>
 
 Returns a human-readable representation of the locator, using the [`method: Locator.description`] if one exists; otherwise, it generates a string based on the locator's selector.
 

From 5e9bfa5b1e5c5881b253104f79f6d56db230595d Mon Sep 17 00:00:00 2001
From: cpadm <57954026+cpAdm@users.noreply.github.com>
Date: Wed, 24 Dec 2025 14:42:43 +0100
Subject: [PATCH 3/3] docs: Separate description docs for languages

---
 docs/src/api/class-locator.md             | 28 +++++++++++++++--------
 packages/playwright-core/types/types.d.ts |  2 +-
 utils/doclint/missingDocs.js              |  4 +++-
 3 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/docs/src/api/class-locator.md b/docs/src/api/class-locator.md
index d6a1893c07421..418c5656f8ba3 100644
--- a/docs/src/api/class-locator.md
+++ b/docs/src/api/class-locator.md
@@ -628,20 +628,13 @@ Locator description.
 
 ## method: Locator.description
 * since: v1.57
+* langs: python, java, csharp
 - returns: <[null]|[string]>
 
-Returns locator description previously set with [`method: Locator.describe`]. Returns `null` if no custom description has been set. Prefer [`method: Locator.toString`] for a human-readable representation, as it uses the description when available.
+Returns locator description previously set with [`method: Locator.describe`]. Returns `null` if no custom description has been set.
 
 **Usage**
 
-```js
-const button = page.getByRole('button').describe('Subscribe button');
-console.log(button.description()); // "Subscribe button"
-
-const input = page.getByRole('textbox');
-console.log(input.description()); // null
-```
-
 ```python async
 button = page.get_by_role("button").describe("Subscribe button")
 print(button.description())  # "Subscribe button"
@@ -674,6 +667,23 @@ var input = Page.GetByRole(AriaRole.Textbox);
 Console.WriteLine(input.Description()); // null
 ```
 
+## method: Locator.description
+* since: v1.57
+* langs: js
+- returns: <[null]|[string]>
+
+Returns locator description previously set with [`method: Locator.describe`]. Returns `null` if no custom description has been set. Prefer [`method: Locator.toString`] for a human-readable representation, as it uses the description when available.
+
+**Usage**
+
+```js
+const button = page.getByRole('button').describe('Subscribe button');
+console.log(button.description()); // "Subscribe button"
+
+const input = page.getByRole('textbox');
+console.log(input.description()); // null
+```
+
 ## async method: Locator.dispatchEvent
 * since: v1.14
 
diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts
index e97294f52829f..c37c74ae8a077 100644
--- a/packages/playwright-core/types/types.d.ts
+++ b/packages/playwright-core/types/types.d.ts
@@ -12647,7 +12647,7 @@ export interface Locator {
   /**
    * Returns a human-readable representation of the locator, using the
    * [locator.description()](https://playwright.dev/docs/api/class-locator#locator-description) if one exists;
-   * otherwise, it generates a string based on the locator’s selector.
+   * otherwise, it generates a string based on the locator's selector.
    */
   toString(): string;
   /**
diff --git a/utils/doclint/missingDocs.js b/utils/doclint/missingDocs.js
index 8467be9e0c40b..856c4f02101b6 100644
--- a/utils/doclint/missingDocs.js
+++ b/utils/doclint/missingDocs.js
@@ -118,7 +118,9 @@ function listMethods(rootNames, apiFileName) {
    * @param {string} methodName
    */
   function shouldSkipMethodByName(className, methodName) {
-    if (methodName.startsWith('_') || methodName === 'T' || methodName === 'toString')
+    if (methodName.startsWith('_') || methodName === 'T')
+      return true;
+    if (methodName === 'toString' && className !== 'Locator')
       return true;
     if (EventEmitter.prototype.hasOwnProperty(methodName))
       return true;
