@@ -73,7 +73,9 @@ def __init__(
73
73
frame : "Frame" ,
74
74
selector : str ,
75
75
has_text : Union [str , Pattern [str ]] = None ,
76
+ has_not_text : Union [str , Pattern [str ]] = None ,
76
77
has : "Locator" = None ,
78
+ has_not : "Locator" = None ,
77
79
) -> None :
78
80
self ._frame = frame
79
81
self ._selector = selector
@@ -90,6 +92,15 @@ def __init__(
90
92
has ._selector , ensure_ascii = False
91
93
)
92
94
95
+ if has_not_text :
96
+ self ._selector += f" >> internal:has-not-text={ escape_for_text_selector (has_not_text , exact = False )} "
97
+
98
+ if has_not :
99
+ locator = has_not
100
+ if locator ._frame != frame :
101
+ raise Error ('Inner "has_not" locator must belong to the same frame.' )
102
+ self ._selector += " >> internal:has-not=" + json .dumps (locator ._selector )
103
+
93
104
def __repr__ (self ) -> str :
94
105
return f"<Locator frame={ self ._frame !r} selector={ self ._selector !r} >"
95
106
@@ -211,13 +222,17 @@ def locator(
211
222
self ,
212
223
selector_or_locator : Union [str , "Locator" ],
213
224
has_text : Union [str , Pattern [str ]] = None ,
225
+ has_not_text : Union [str , Pattern [str ]] = None ,
214
226
has : "Locator" = None ,
227
+ has_not : "Locator" = None ,
215
228
) -> "Locator" :
216
229
if isinstance (selector_or_locator , str ):
217
230
return Locator (
218
231
self ._frame ,
219
232
f"{ self ._selector } >> { selector_or_locator } " ,
220
233
has_text = has_text ,
234
+ has_not_text = has_not_text ,
235
+ has_not = has_not ,
221
236
has = has ,
222
237
)
223
238
selector_or_locator = to_impl (selector_or_locator )
@@ -227,6 +242,8 @@ def locator(
227
242
self ._frame ,
228
243
f"{ self ._selector } >> { selector_or_locator ._selector } " ,
229
244
has_text = has_text ,
245
+ has_not_text = has_not_text ,
246
+ has_not = has_not ,
230
247
has = has ,
231
248
)
232
249
@@ -317,13 +334,25 @@ def nth(self, index: int) -> "Locator":
317
334
def filter (
318
335
self ,
319
336
has_text : Union [str , Pattern [str ]] = None ,
337
+ has_not_text : Union [str , Pattern [str ]] = None ,
320
338
has : "Locator" = None ,
339
+ has_not : "Locator" = None ,
321
340
) -> "Locator" :
322
341
return Locator (
323
342
self ._frame ,
324
343
self ._selector ,
325
344
has_text = has_text ,
345
+ has_not_text = has_not_text ,
326
346
has = has ,
347
+ has_not = has_not ,
348
+ )
349
+
350
+ def or_ (self , locator : "Locator" ) -> "Locator" :
351
+ if locator ._frame != self ._frame :
352
+ raise Error ("Locators must belong to the same frame." )
353
+ return Locator (
354
+ self ._frame ,
355
+ self ._selector + " >> internal:or=" + json .dumps (locator ._selector ),
327
356
)
328
357
329
358
async def focus (self , timeout : float = None ) -> None :
@@ -677,14 +706,18 @@ def locator(
677
706
self ,
678
707
selector_or_locator : Union ["Locator" , str ],
679
708
has_text : Union [str , Pattern [str ]] = None ,
709
+ has_not_text : Union [str , Pattern [str ]] = None ,
680
710
has : "Locator" = None ,
711
+ has_not : "Locator" = None ,
681
712
) -> Locator :
682
713
if isinstance (selector_or_locator , str ):
683
714
return Locator (
684
715
self ._frame ,
685
716
f"{ self ._frame_selector } >> internal:control=enter-frame >> { selector_or_locator } " ,
686
717
has_text = has_text ,
718
+ has_not_text = has_not_text ,
687
719
has = has ,
720
+ has_not = has_not ,
688
721
)
689
722
selector_or_locator = to_impl (selector_or_locator )
690
723
if selector_or_locator ._frame != self ._frame :
@@ -693,7 +726,9 @@ def locator(
693
726
self ._frame ,
694
727
f"{ self ._frame_selector } >> internal:control=enter-frame >> { selector_or_locator ._selector } " ,
695
728
has_text = has_text ,
729
+ has_not_text = has_not_text ,
696
730
has = has ,
731
+ has_not = has_not ,
697
732
)
698
733
699
734
def get_by_alt_text (
0 commit comments