Repository: microsoft/playwright-python
Pull request #2732 (2025-02-05 10:41:15)

fix(locator): fix is_enabled method
Fixes https://github.com/microsoft/playwright-python/issues/2731


Patch:
diff --git a/playwright/_impl/_locator.py b/playwright/_impl/_locator.py
index 91ea790..1ad18f9 100644
--- a/playwright/_impl/_locator.py
+++ b/playwright/_impl/_locator.py
@@ -481,7 +481,7 @@ class Locator:
 
     async def is_enabled(self, timeout: float = None) -> bool:
         params = locals_to_params(locals())
-        return await self._frame.is_editable(
+        return await self._frame.is_enabled(
             self._selector,
             strict=True,
             **params,


Test patch:
diff --git a/tests/async/test_fill.py b/tests/async/test_fill.py
index 4dd6db3..c5f0a55 100644
--- a/tests/async/test_fill.py
+++ b/tests/async/test_fill.py
@@ -22,7 +22,14 @@ async def test_fill_textarea(page: Page, server: Server) -> None:
     assert await page.evaluate("result") == "some value"
 
 
-#
+async def test_is_enabled_for_non_editable_button(page: Page) -> None:
+    await page.set_content(
+        """
+        <button>button</button>
+    """
+    )
+    button = page.locator("button")
+    assert await button.is_enabled() is True
 
 
 async def test_fill_input(page: Page, server: Server) -> None:
diff --git a/tests/async/test_locators.py b/tests/async/test_locators.py
index 3855384..aceb399 100644
--- a/tests/async/test_locators.py
+++ b/tests/async/test_locators.py
@@ -128,27 +128,15 @@ async def test_locators_is_enabled_and_is_disabled_should_work(page: Page) -> No
     )
 
     div = page.locator("div")
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert await div.is_enabled()
+    assert await div.is_enabled()
     assert await div.is_disabled() is False
 
     button1 = page.locator(':text("button1")')
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert await button1.is_enabled()
+    assert await button1.is_enabled() is False
     assert await button1.is_disabled() is True
 
     button1 = page.locator(':text("button2")')
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert await button1.is_enabled()
+    assert await button1.is_enabled()
     assert await button1.is_disabled() is False
 
 
diff --git a/tests/sync/test_locators.py b/tests/sync/test_locators.py
index f3a1e74..f373abd 100644
--- a/tests/sync/test_locators.py
+++ b/tests/sync/test_locators.py
@@ -126,27 +126,15 @@ def test_locators_is_enabled_and_is_disabled_should_work(page: Page) -> None:
     )
 
     div = page.locator("div")
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        div.is_enabled()
+    assert div.is_enabled()
     assert div.is_disabled() is False
 
     button1 = page.locator(':text("button1")')
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert button1.is_enabled()
+    assert button1.is_enabled() is False
     assert button1.is_disabled() is True
 
     button1 = page.locator(':text("button2")')
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert button1.is_enabled()
+    assert button1.is_enabled()
     assert button1.is_disabled() is False