Skip to content

Commit d2dad56

Browse files
authored
chore: roll Playwright to ToT (#1579)
1 parent 4fda29c commit d2dad56

File tree

4 files changed

+97
-31
lines changed

4 files changed

+97
-31
lines changed

playwright/_impl/_locator.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
escape_for_attribute_selector,
5050
escape_for_text_selector,
5151
escape_regex_flags,
52-
escape_with_quotes,
5352
)
5453

5554
if sys.version_info >= (3, 8): # pragma: no cover
@@ -79,19 +78,17 @@ def __init__(
7978
self._dispatcher_fiber = frame._connection._dispatcher_fiber
8079

8180
if has_text:
82-
if isinstance(has_text, Pattern):
83-
js_regex = f"/{has_text.pattern}/{escape_regex_flags(has_text)}"
84-
self._selector += (
85-
f' >> has={json.dumps("text=" + js_regex, ensure_ascii=False)}'
86-
)
87-
else:
88-
escaped = escape_with_quotes(has_text, '"')
89-
self._selector += f" >> :scope:has-text({escaped})"
81+
text_selector = "text=" + escape_for_text_selector(has_text, exact=False)
82+
self._selector += (
83+
f" >> internal:has={json.dumps(text_selector, ensure_ascii=False)}"
84+
)
9085

9186
if has:
9287
if has._frame != frame:
9388
raise Error('Inner "has" locator must belong to the same frame.')
94-
self._selector += " >> has=" + json.dumps(has._selector, ensure_ascii=False)
89+
self._selector += " >> internal:has=" + json.dumps(
90+
has._selector, ensure_ascii=False
91+
)
9592

9693
def __repr__(self) -> str:
9794
return f"<Locator frame={self._frame!r} selector={self._selector!r}>"
@@ -645,7 +642,7 @@ def locator(
645642
) -> Locator:
646643
return Locator(
647644
self._frame,
648-
f"{self._frame_selector} >> control=enter-frame >> {selector}",
645+
f"{self._frame_selector} >> internal:control=enter-frame >> {selector}",
649646
has_text=has_text,
650647
has=has,
651648
)
@@ -706,7 +703,8 @@ def get_by_title(
706703

707704
def frame_locator(self, selector: str) -> "FrameLocator":
708705
return FrameLocator(
709-
self._frame, f"{self._frame_selector} >> control=enter-frame >> {selector}"
706+
self._frame,
707+
f"{self._frame_selector} >> internal:control=enter-frame >> {selector}",
710708
)
711709

712710
@property
@@ -740,13 +738,13 @@ def get_by_attribute_text_selector(
740738
attr_name: str, text: Union[str, Pattern[str]], exact: bool = None
741739
) -> str:
742740
if isinstance(text, Pattern):
743-
return f"attr=[{attr_name}=/{text.pattern}/{escape_regex_flags(text)}]"
741+
return f"internal:attr=[{attr_name}=/{text.pattern}/{escape_regex_flags(text)}]"
744742
suffix = "s" if exact else "i"
745-
return f"attr=[{attr_name}={escape_for_attribute_selector(text)}{suffix}]"
743+
return f"internal:attr=[{attr_name}={escape_for_attribute_selector(text)}{suffix}]"
746744

747745

748746
def get_by_label_selector(text: Union[str, Pattern[str]], exact: bool = None) -> str:
749-
return get_by_text_selector(text, exact=exact) + " >> control=resolve-label"
747+
return "internal:label=" + escape_for_text_selector(text, exact=exact)
750748

751749

752750
def get_by_alt_text_selector(text: Union[str, Pattern[str]], exact: bool = None) -> str:

playwright/_impl/_str_utils.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,10 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import json
1615
import re
1716
from typing import Pattern, Union
1817

1918

20-
def escape_with_quotes(text: str, char: str = "'") -> str:
21-
stringified = json.dumps(text, ensure_ascii=False)
22-
escaped_text = stringified[1:-1].replace('\\"', '"')
23-
if char == "'":
24-
return char + escaped_text.replace("'", "\\'") + char
25-
if char == '"':
26-
return char + escaped_text.replace('"', '\\"') + char
27-
if char == "`":
28-
return char + escaped_text.replace("`", "\\`") + char
29-
raise ValueError("Invalid escape char")
30-
31-
3219
def escape_regex_flags(pattern: Pattern) -> str:
3320
flags = ""
3421
if pattern.flags != 0:
@@ -60,7 +47,7 @@ def escape_for_text_selector(
6047
return '"' + text.replace('"', '\\"') + '"'
6148
if '"' in text or ">>" in text or text[0] == "/":
6249
suffix = "" if case_sensitive else "i"
63-
return re.sub(r"\s+", "\\s+", escape_for_regex(text)) + suffix
50+
return "/" + re.sub(r"\s+", "\\\\s+", escape_for_regex(text)) + "/" + suffix
6451
return text
6552

6653

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
InWheel = None
3131
from wheel.bdist_wheel import bdist_wheel as BDistWheelCommand
3232

33-
driver_version = "1.27.0-alpha-1664914898000"
33+
driver_version = "1.28.0-alpha-oct-6-2022"
3434

3535

3636
def extractall(zip: zipfile.ZipFile, path: str) -> None:

tests/sync/test_locator_get_by.py

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ def test_get_by_test_id_escape_id(page: Page) -> None:
3030

3131

3232
def test_get_by_text(page: Page) -> None:
33-
page.set_content("<div>yo</div><div>ya</div><div>\nye </div>")
33+
page.set_content("<div><div>yo</div><div>ya</div><div>\nye </div></div>")
34+
35+
expect(page.get_by_text("yo")).to_have_count(1)
36+
expect(page.main_frame.get_by_text("yo")).to_have_count(1)
37+
expect(page.locator("div").get_by_text("yo")).to_have_count(1)
38+
3439
assert ">\nye </div>" in page.get_by_text("ye").evaluate("e => e.outerHTML")
3540
assert ">\nye </div>" in page.get_by_text(r"ye").evaluate("e => e.outerHTML")
3641

@@ -50,6 +55,11 @@ def test_get_by_label(page: Page) -> None:
5055
page.set_content(
5156
"<div><label for=target>Name</label><input id=target type=text></div>"
5257
)
58+
59+
expect(page.get_by_label("Name")).to_have_count(1)
60+
expect(page.main_frame.get_by_label("Name")).to_have_count(1)
61+
expect(page.locator("div").get_by_label("Name")).to_have_count(1)
62+
5363
assert page.get_by_text("Name").evaluate("e => e.nodeName") == "LABEL"
5464
assert page.get_by_label("Name").evaluate("e => e.nodeName") == "INPUT"
5565
assert page.main_frame.get_by_label("Name").evaluate("e => e.nodeName") == "INPUT"
@@ -58,13 +68,38 @@ def test_get_by_label(page: Page) -> None:
5868
)
5969

6070

71+
def test_get_by_label_with_nested_elements(page: Page) -> None:
72+
page.set_content(
73+
"<label for=target>Last <span>Name</span></label><input id=target type=text>"
74+
)
75+
76+
expect(page.get_by_label("last name")).to_have_attribute("id", "target")
77+
expect(page.get_by_label("st na")).to_have_attribute("id", "target")
78+
expect(page.get_by_label("Name")).to_have_attribute("id", "target")
79+
expect(page.get_by_label("Last Name", exact=True)).to_have_attribute("id", "target")
80+
expect(
81+
page.get_by_label(re.compile(r"Last\s+name", re.IGNORECASE))
82+
).to_have_attribute("id", "target")
83+
84+
expect(page.get_by_label("Last", exact=True)).to_have_count(0)
85+
expect(page.get_by_label("last name", exact=True)).to_have_count(0)
86+
expect(page.get_by_label("Name", exact=True)).to_have_count(0)
87+
expect(page.get_by_label("what?")).to_have_count(0)
88+
expect(page.get_by_label(re.compile(r"last name"))).to_have_count(0)
89+
90+
6191
def test_get_by_placeholder(page: Page) -> None:
6292
page.set_content(
6393
"""<div>
6494
<input placeholder="Hello">
6595
<input placeholder="Hello World">
6696
</div>"""
6797
)
98+
99+
expect(page.get_by_placeholder("hello")).to_have_count(2)
100+
expect(page.main_frame.get_by_placeholder("hello")).to_have_count(2)
101+
expect(page.locator("div").get_by_placeholder("hello")).to_have_count(2)
102+
68103
expect(page.get_by_placeholder("hello")).to_have_count(2)
69104
expect(page.get_by_placeholder("Hello", exact=True)).to_have_count(1)
70105
expect(page.get_by_placeholder(re.compile(r"wor", re.IGNORECASE))).to_have_count(1)
@@ -81,6 +116,11 @@ def test_get_by_alt_text(page: Page) -> None:
81116
<input alt="Hello World">
82117
</div>"""
83118
)
119+
120+
expect(page.get_by_alt_text("hello")).to_have_count(2)
121+
expect(page.main_frame.get_by_alt_text("hello")).to_have_count(2)
122+
expect(page.locator("div").get_by_alt_text("hello")).to_have_count(2)
123+
84124
expect(page.get_by_alt_text("hello")).to_have_count(2)
85125
expect(page.get_by_alt_text("Hello", exact=True)).to_have_count(1)
86126
expect(page.get_by_alt_text(re.compile(r"wor", re.IGNORECASE))).to_have_count(1)
@@ -97,10 +137,51 @@ def test_get_by_title(page: Page) -> None:
97137
<input title="Hello World">
98138
</div>"""
99139
)
140+
141+
expect(page.get_by_title("hello")).to_have_count(2)
142+
expect(page.main_frame.get_by_title("hello")).to_have_count(2)
143+
expect(page.locator("div").get_by_title("hello")).to_have_count(2)
144+
100145
expect(page.get_by_title("hello")).to_have_count(2)
101146
expect(page.get_by_title("Hello", exact=True)).to_have_count(1)
102147
expect(page.get_by_title(re.compile(r"wor", re.IGNORECASE))).to_have_count(1)
103148

104149
# Coverage
105150
expect(page.main_frame.get_by_title("hello")).to_have_count(2)
106151
expect(page.locator("div").get_by_title("hello")).to_have_count(2)
152+
153+
154+
def test_get_by_escaping(page: Page) -> None:
155+
page.set_content(
156+
"""<label id=label for=control>Hello
157+
wo"rld</label><input id=control />"""
158+
)
159+
page.locator("input").evaluate(
160+
"""input => {
161+
input.setAttribute('placeholder', 'hello\\nwo"rld');
162+
input.setAttribute('title', 'hello\\nwo"rld');
163+
input.setAttribute('alt', 'hello\\nwo"rld');
164+
}"""
165+
)
166+
expect(page.get_by_text('hello\nwo"rld')).to_have_attribute("id", "label")
167+
expect(page.get_by_label('hello\nwo"rld')).to_have_attribute("id", "control")
168+
expect(page.get_by_placeholder('hello\nwo"rld')).to_have_attribute("id", "control")
169+
expect(page.get_by_alt_text('hello\nwo"rld')).to_have_attribute("id", "control")
170+
expect(page.get_by_title('hello\nwo"rld')).to_have_attribute("id", "control")
171+
172+
page.set_content(
173+
"""<label id=label for=control>Hello
174+
world</label><input id=control />"""
175+
)
176+
page.locator("input").evaluate(
177+
"""input => {
178+
input.setAttribute('placeholder', 'hello\\nworld');
179+
input.setAttribute('title', 'hello\\nworld');
180+
input.setAttribute('alt', 'hello\\nworld');
181+
}"""
182+
)
183+
expect(page.get_by_text("hello\nworld")).to_have_attribute("id", "label")
184+
expect(page.get_by_label("hello\nworld")).to_have_attribute("id", "control")
185+
expect(page.get_by_placeholder("hello\nworld")).to_have_attribute("id", "control")
186+
expect(page.get_by_alt_text("hello\nworld")).to_have_attribute("id", "control")
187+
expect(page.get_by_title("hello\nworld")).to_have_attribute("id", "control")

0 commit comments

Comments
 (0)