Skip to content

Commit 9dc4609

Browse files
committed
Proper assertion titles
1 parent 1f240e4 commit 9dc4609

File tree

6 files changed

+84
-21
lines changed

6 files changed

+84
-21
lines changed

playwright/_impl/_assertions.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ async def _expect_impl(
5151
expect_options: FrameExpectOptions,
5252
expected: Any,
5353
message: str,
54+
title: str = None,
5455
) -> None:
5556
__tracebackhide__ = True
5657
expect_options["isNot"] = self._is_not
@@ -60,7 +61,7 @@ async def _expect_impl(
6061
message = message.replace("expected to", "expected not to")
6162
if "useInnerText" in expect_options and expect_options["useInnerText"] is None:
6263
del expect_options["useInnerText"]
63-
result = await self._actual_locator._expect(expression, expect_options)
64+
result = await self._actual_locator._expect(expression, expect_options, title)
6465
if result["matches"] == self._is_not:
6566
actual = result.get("received")
6667
if self._custom_message:
@@ -105,6 +106,7 @@ async def to_have_title(
105106
FrameExpectOptions(expectedText=expected_values, timeout=timeout),
106107
titleOrRegExp,
107108
"Page title expected to be",
109+
'Expect "to_have_title"',
108110
)
109111

110112
async def not_to_have_title(
@@ -129,6 +131,7 @@ async def to_have_url(
129131
FrameExpectOptions(expectedText=expected_text, timeout=timeout),
130132
urlOrRegExp,
131133
"Page URL expected to be",
134+
'Expect "to_have_url"',
132135
)
133136

134137
async def not_to_have_url(
@@ -190,6 +193,7 @@ async def to_contain_text(
190193
),
191194
expected,
192195
"Locator expected to contain text",
196+
'Expect "to_contain_text"',
193197
)
194198
else:
195199
expected_text = to_expected_text_values(
@@ -207,6 +211,7 @@ async def to_contain_text(
207211
),
208212
expected,
209213
"Locator expected to contain text",
214+
'Expect "to_contain_text"',
210215
)
211216

212217
async def not_to_contain_text(
@@ -241,6 +246,7 @@ async def to_have_attribute(
241246
),
242247
value,
243248
"Locator expected to have attribute",
249+
'Expect "to_have_attribute"',
244250
)
245251

246252
async def not_to_have_attribute(
@@ -276,6 +282,7 @@ async def to_have_class(
276282
FrameExpectOptions(expectedText=expected_text, timeout=timeout),
277283
expected,
278284
"Locator expected to have class",
285+
'Expect "to_have_class"',
279286
)
280287
else:
281288
expected_text = to_expected_text_values([expected])
@@ -284,6 +291,7 @@ async def to_have_class(
284291
FrameExpectOptions(expectedText=expected_text, timeout=timeout),
285292
expected,
286293
"Locator expected to have class",
294+
'Expect "to_have_class"',
287295
)
288296

289297
async def not_to_have_class(
@@ -318,6 +326,7 @@ async def to_contain_class(
318326
FrameExpectOptions(expectedText=expected_text, timeout=timeout),
319327
expected,
320328
"Locator expected to contain class names",
329+
'Expect "to_contain_class"',
321330
)
322331
else:
323332
expected_text = to_expected_text_values([expected])
@@ -326,6 +335,7 @@ async def to_contain_class(
326335
FrameExpectOptions(expectedText=expected_text, timeout=timeout),
327336
expected,
328337
"Locator expected to contain class",
338+
'Expect "to_contain_class"',
329339
)
330340

331341
async def not_to_contain_class(
@@ -350,6 +360,7 @@ async def to_have_count(
350360
FrameExpectOptions(expectedNumber=count, timeout=timeout),
351361
count,
352362
"Locator expected to have count",
363+
'Expect "to_have_count"',
353364
)
354365

355366
async def not_to_have_count(
@@ -375,6 +386,7 @@ async def to_have_css(
375386
),
376387
value,
377388
"Locator expected to have CSS",
389+
'Expect "to_have_css"',
378390
)
379391

380392
async def not_to_have_css(
@@ -398,6 +410,7 @@ async def to_have_id(
398410
FrameExpectOptions(expectedText=expected_text, timeout=timeout),
399411
id,
400412
"Locator expected to have ID",
413+
'Expect "to_have_id"',
401414
)
402415

403416
async def not_to_have_id(
@@ -422,6 +435,7 @@ async def to_have_js_property(
422435
),
423436
value,
424437
"Locator expected to have JS Property",
438+
'Expect "to_have_property"',
425439
)
426440

427441
async def not_to_have_js_property(
@@ -445,6 +459,7 @@ async def to_have_value(
445459
FrameExpectOptions(expectedText=expected_text, timeout=timeout),
446460
value,
447461
"Locator expected to have Value",
462+
'Expect "to_have_value"',
448463
)
449464

450465
async def not_to_have_value(
@@ -469,6 +484,7 @@ async def to_have_values(
469484
FrameExpectOptions(expectedText=expected_text, timeout=timeout),
470485
values,
471486
"Locator expected to have Values",
487+
'Expect "to_have_values"',
472488
)
473489

474490
async def not_to_have_values(
@@ -512,6 +528,7 @@ async def to_have_text(
512528
),
513529
expected,
514530
"Locator expected to have text",
531+
'Expect "to_have_text"',
515532
)
516533
else:
517534
expected_text = to_expected_text_values(
@@ -526,6 +543,7 @@ async def to_have_text(
526543
),
527544
expected,
528545
"Locator expected to have text",
546+
'Expect "to_have_text"',
529547
)
530548

531549
async def not_to_have_text(
@@ -558,6 +576,7 @@ async def to_be_attached(
558576
FrameExpectOptions(timeout=timeout),
559577
None,
560578
f"Locator expected to be {attached_string}",
579+
'Expect "to_be_attached"',
561580
)
562581

563582
async def to_be_checked(
@@ -582,6 +601,7 @@ async def to_be_checked(
582601
FrameExpectOptions(timeout=timeout, expectedValue=expected_value),
583602
None,
584603
f"Locator expected to be {checked_string}",
604+
'Expect "to_be_checked"',
585605
)
586606

587607
async def not_to_be_attached(
@@ -609,6 +629,7 @@ async def to_be_disabled(
609629
FrameExpectOptions(timeout=timeout),
610630
None,
611631
"Locator expected to be disabled",
632+
'Expect "to_be_disabled"',
612633
)
613634

614635
async def not_to_be_disabled(
@@ -632,6 +653,7 @@ async def to_be_editable(
632653
FrameExpectOptions(timeout=timeout),
633654
None,
634655
f"Locator expected to be {editable_string}",
656+
'Expect "to_be_editable"',
635657
)
636658

637659
async def not_to_be_editable(
@@ -652,6 +674,7 @@ async def to_be_empty(
652674
FrameExpectOptions(timeout=timeout),
653675
None,
654676
"Locator expected to be empty",
677+
'Expect "to_be_empty"',
655678
)
656679

657680
async def not_to_be_empty(
@@ -675,6 +698,7 @@ async def to_be_enabled(
675698
FrameExpectOptions(timeout=timeout),
676699
None,
677700
f"Locator expected to be {enabled_string}",
701+
'Expect "to_be_enabled"',
678702
)
679703

680704
async def not_to_be_enabled(
@@ -695,6 +719,7 @@ async def to_be_hidden(
695719
FrameExpectOptions(timeout=timeout),
696720
None,
697721
"Locator expected to be hidden",
722+
'Expect "to_be_hidden"',
698723
)
699724

700725
async def not_to_be_hidden(
@@ -718,6 +743,7 @@ async def to_be_visible(
718743
FrameExpectOptions(timeout=timeout),
719744
None,
720745
f"Locator expected to be {visible_string}",
746+
'Expect "to_be_visible"',
721747
)
722748

723749
async def not_to_be_visible(
@@ -738,6 +764,7 @@ async def to_be_focused(
738764
FrameExpectOptions(timeout=timeout),
739765
None,
740766
"Locator expected to be focused",
767+
'Expect "to_be_focused"',
741768
)
742769

743770
async def not_to_be_focused(
@@ -758,6 +785,7 @@ async def to_be_in_viewport(
758785
FrameExpectOptions(timeout=timeout, expectedNumber=ratio),
759786
None,
760787
"Locator expected to be in viewport",
788+
'Expect "to_be_in_viewport"',
761789
)
762790

763791
async def not_to_be_in_viewport(
@@ -781,6 +809,7 @@ async def to_have_accessible_description(
781809
FrameExpectOptions(expectedText=expected_values, timeout=timeout),
782810
None,
783811
"Locator expected to have accessible description",
812+
'Expect "to_have_accessible_description"',
784813
)
785814

786815
async def not_to_have_accessible_description(
@@ -807,6 +836,7 @@ async def to_have_accessible_name(
807836
FrameExpectOptions(expectedText=expected_values, timeout=timeout),
808837
None,
809838
"Locator expected to have accessible name",
839+
'Expect "to_have_accessible_name"',
810840
)
811841

812842
async def not_to_have_accessible_name(
@@ -828,6 +858,7 @@ async def to_have_role(self, role: AriaRole, timeout: float = None) -> None:
828858
FrameExpectOptions(expectedText=expected_values, timeout=timeout),
829859
None,
830860
"Locator expected to have accessible role",
861+
'Expect "to_have_role"',
831862
)
832863

833864
async def to_have_accessible_error_message(
@@ -845,6 +876,7 @@ async def to_have_accessible_error_message(
845876
FrameExpectOptions(expectedText=expected_values, timeout=timeout),
846877
None,
847878
"Locator expected to have accessible error message",
879+
'Expect "to_have_accessible_error_message"',
848880
)
849881

850882
async def not_to_have_accessible_error_message(
@@ -871,6 +903,7 @@ async def to_match_aria_snapshot(
871903
FrameExpectOptions(expectedValue=expected, timeout=timeout),
872904
expected,
873905
"Locator expected to match Aria snapshot",
906+
'Expect "to_match_aria_snapshot"',
874907
)
875908

876909
async def not_to_match_aria_snapshot(

playwright/_impl/_connection.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,48 @@ def __init__(self, connection: "Connection", object: "ChannelOwner") -> None:
5555
self._guid = object._guid
5656
self._object = object
5757
self.on("error", lambda exc: self._connection._on_event_listener_error(exc))
58-
self._is_internal_type = False
5958
self._timeout_calculator: Optional[Callable[[Optional[float]], float]] = None
6059

61-
async def send(self, method: str, params: Dict = None) -> Any:
60+
async def send(
61+
self,
62+
method: str,
63+
params: Dict = None,
64+
is_internal: bool = False,
65+
title: str = None,
66+
) -> Any:
6267
return await self._connection.wrap_api_call(
6368
lambda: self._inner_send(method, params, False),
64-
self._is_internal_type,
69+
is_internal,
70+
title,
6571
)
6672

67-
async def send_return_as_dict(self, method: str, params: Dict = None) -> Any:
73+
async def send_return_as_dict(
74+
self,
75+
method: str,
76+
params: Dict = None,
77+
is_internal: bool = False,
78+
title: str = None,
79+
) -> Any:
6880
return await self._connection.wrap_api_call(
6981
lambda: self._inner_send(method, params, True),
70-
self._is_internal_type,
82+
is_internal,
83+
title,
7184
)
7285

73-
def send_no_reply(self, method: str, params: Dict = None) -> None:
86+
def send_no_reply(
87+
self,
88+
method: str,
89+
params: Dict = None,
90+
is_internal: bool = False,
91+
title: str = None,
92+
) -> None:
7493
# No reply messages are used to e.g. waitForEventInfo(after).
7594
self._connection.wrap_api_call_sync(
7695
lambda: self._connection._send_message_to_server(
7796
self._object, method, {} if params is None else params, True
78-
)
97+
),
98+
is_internal,
99+
title,
79100
)
80101

81102
async def _inner_send(
@@ -360,6 +381,9 @@ def _send_message_to_server(
360381
}
361382
if location:
362383
metadata["location"] = location # type: ignore
384+
title = stack_trace_information["title"]
385+
if title:
386+
metadata["title"] = title
363387
message = {
364388
"id": id,
365389
"guid": object._guid,
@@ -512,7 +536,7 @@ def _replace_guids_with_channels(self, payload: Any) -> Any:
512536
return payload
513537

514538
async def wrap_api_call(
515-
self, cb: Callable[[], Any], is_internal: bool = False
539+
self, cb: Callable[[], Any], is_internal: bool = False, title: str = None
516540
) -> Any:
517541
if self._api_zone.get():
518542
return await cb()
@@ -521,7 +545,7 @@ async def wrap_api_call(
521545
task, "__pw_stack__", None
522546
) or inspect.stack(0)
523547

524-
parsed_st = _extract_stack_trace_information_from_stack(st, is_internal)
548+
parsed_st = _extract_stack_trace_information_from_stack(st, is_internal, title)
525549
self._api_zone.set(parsed_st)
526550
try:
527551
return await cb()
@@ -531,15 +555,15 @@ async def wrap_api_call(
531555
self._api_zone.set(None)
532556

533557
def wrap_api_call_sync(
534-
self, cb: Callable[[], Any], is_internal: bool = False
558+
self, cb: Callable[[], Any], is_internal: bool = False, title: str = None
535559
) -> Any:
536560
if self._api_zone.get():
537561
return cb()
538562
task = asyncio.current_task(self._loop)
539563
st: List[inspect.FrameInfo] = getattr(
540564
task, "__pw_stack__", None
541565
) or inspect.stack(0)
542-
parsed_st = _extract_stack_trace_information_from_stack(st, is_internal)
566+
parsed_st = _extract_stack_trace_information_from_stack(st, is_internal, title)
543567
self._api_zone.set(parsed_st)
544568
try:
545569
return cb()
@@ -567,10 +591,11 @@ class StackFrame(TypedDict):
567591
class ParsedStackTrace(TypedDict):
568592
frames: List[StackFrame]
569593
apiName: Optional[str]
594+
title: Optional[str]
570595

571596

572597
def _extract_stack_trace_information_from_stack(
573-
st: List[inspect.FrameInfo], is_internal: bool
598+
st: List[inspect.FrameInfo], is_internal: bool, title: str = None
574599
) -> ParsedStackTrace:
575600
playwright_module_path = str(Path(playwright.__file__).parents[0])
576601
last_internal_api_name = ""
@@ -610,6 +635,7 @@ def _extract_stack_trace_information_from_stack(
610635
return {
611636
"frames": parsed_frames,
612637
"apiName": "" if is_internal else api_name,
638+
"title": title,
613639
}
614640

615641

0 commit comments

Comments
 (0)