Skip to content

Commit d2dad56

Browse files
authored
chore: roll Playwright to ToT (microsoft#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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy