@@ -938,7 +938,7 @@ def expect_locator_values_in_list(
938938 * ,
939939 page : Page ,
940940 loc_container : Locator ,
941- el_type : str ,
941+ el_type : Locator | str ,
942942 arr_name : str ,
943943 arr : ListPatternOrStr ,
944944 is_checked : bool | MISSING_TYPE = MISSING ,
@@ -949,13 +949,20 @@ def expect_locator_values_in_list(
949949
950950 # Make sure the locator has len(uniq_arr) input elements
951951 _MultipleDomItems .assert_arr_is_unique (arr , f"`{ arr_name } ` must be unique" )
952- is_checked_str = _MultipleDomItems .checked_css_str (is_checked )
953952
954- item_selector = f"{ el_type } { is_checked_str } "
953+ if isinstance (el_type , Locator ):
954+ if not isinstance (is_checked , MISSING_TYPE ):
955+ raise RuntimeError (
956+ "`is_checked` cannot be specified if `el_type` is a Locator"
957+ )
958+ loc_item = el_type
959+ else :
960+ is_checked_str = _MultipleDomItems .checked_css_str (is_checked )
961+ loc_item = page .locator (f"{ el_type } { is_checked_str } " )
955962
956963 # If there are no items, then we should not have any elements
957964 if len (arr ) == 0 :
958- playwright_expect (loc_container .locator (item_selector )).to_have_count (
965+ playwright_expect (loc_container .locator (el_type )).to_have_count (
959966 0 , timeout = timeout
960967 )
961968 return
@@ -964,7 +971,7 @@ def expect_locator_values_in_list(
964971 # Find all items in set
965972 for item , i in zip (arr , range (len (arr ))):
966973 # Get all elements of type
967- has_locator = page . locator ( item_selector )
974+ has_locator = loc_item
968975 # Get the `n`th matching element
969976 has_locator = has_locator .nth (i )
970977 # Make sure that element has the correct attribute value
@@ -982,7 +989,7 @@ def expect_locator_values_in_list(
982989 # Make sure other items are not in set
983990 # If we know all elements are contained in the container,
984991 # and all elements all unique, then it should have a count of `len(arr)`
985- loc_inputs = loc_container .locator (item_selector )
992+ loc_inputs = loc_container .locator (loc_item )
986993 try :
987994 playwright_expect (loc_inputs ).to_have_count (len (arr ), timeout = timeout )
988995 except AssertionError as e :
@@ -992,14 +999,14 @@ def expect_locator_values_in_list(
992999 playwright_expect (loc_container_orig ).to_have_count (1 , timeout = timeout )
9931000
9941001 # Expecting the container to contain {len(arr)} items
995- playwright_expect (loc_container_orig .locator (item_selector )).to_have_count (
1002+ playwright_expect (loc_container_orig .locator (loc_item )).to_have_count (
9961003 len (arr ), timeout = timeout
9971004 )
9981005
9991006 for item , i in zip (arr , range (len (arr ))):
10001007 # Expecting item `{i}` to be `{item}`
10011008 playwright_expect (
1002- loc_container_orig .locator (item_selector ).nth (i )
1009+ loc_container_orig .locator (loc_item ).nth (i )
10031010 ).to_have_attribute (key , item , timeout = timeout )
10041011
10051012 # Could not find the reason why. Raising the original error.
@@ -2096,6 +2103,7 @@ def expect_value(
20962103 * ,
20972104 timeout : Timeout = None ,
20982105 ) -> None :
2106+ """Note this function will trim value and output text value before comparing them"""
20992107 self .expect .to_have_text (value , timeout = timeout )
21002108
21012109
@@ -2565,3 +2573,125 @@ def expect_min_height(self, value: StyleValue, *, timeout: Timeout = None) -> No
25652573
25662574 def expect_height (self , value : StyleValue , * , timeout : Timeout = None ) -> None :
25672575 expect_to_have_style (self .loc_container , "height" , value , timeout = timeout )
2576+
2577+
2578+ ### Experimental below
2579+
2580+
2581+ class Accordion (
2582+ _WidthLocM ,
2583+ _InputWithContainer ,
2584+ ):
2585+ # *args: AccordionPanel | TagAttrs,
2586+ # id: Optional[str] = None,
2587+ # open: Optional[bool | str | list[str]] = None,
2588+ # multiple: bool = True,
2589+ # class_: Optional[str] = None,
2590+ # width: Optional[CssUnit] = None,
2591+ # height: Optional[CssUnit] = None,
2592+ # **kwargs: TagAttrValue,
2593+ def __init__ (self , page : Page , id : str ) -> None :
2594+ super ().__init__ (
2595+ page ,
2596+ id = id ,
2597+ loc = "> div.accordion-item" ,
2598+ loc_container = f"div#{ id } .accordion.shiny-bound-input" ,
2599+ )
2600+ self .loc_open = self .loc .locator (
2601+ # Return self
2602+ "xpath=." ,
2603+ # Simple approach as position is not needed
2604+ has = page .locator (
2605+ "> div.accordion-collapse.show" ,
2606+ ),
2607+ )
2608+
2609+ def expect_height (self , value : StyleValue , * , timeout : Timeout = None ) -> None :
2610+ expect_to_have_style (self .loc_container , "height" , value , timeout = timeout )
2611+
2612+ def expect_width (self , value : StyleValue , * , timeout : Timeout = None ) -> None :
2613+ expect_to_have_style (self .loc_container , "width" , value , timeout = timeout )
2614+
2615+ def expect_open (
2616+ self ,
2617+ value : list [PatternOrStr ],
2618+ * ,
2619+ timeout : Timeout = None ,
2620+ ) -> None :
2621+ _MultipleDomItems .expect_locator_values_in_list (
2622+ page = self .page ,
2623+ loc_container = self .loc_container ,
2624+ el_type = self .page .locator (
2625+ "> div.accordion-item" ,
2626+ has = self .page .locator ("> div.accordion-collapse.show" ),
2627+ ),
2628+ # el_type="> div.accordion-item:has(> div.accordion-collapse.show)",
2629+ arr_name = "value" ,
2630+ arr = value ,
2631+ key = "data-value" ,
2632+ timeout = timeout ,
2633+ )
2634+
2635+ def expect_panels (
2636+ self ,
2637+ value : list [PatternOrStr ],
2638+ * ,
2639+ timeout : Timeout = None ,
2640+ ) -> None :
2641+ _MultipleDomItems .expect_locator_values_in_list (
2642+ page = self .page ,
2643+ loc_container = self .loc_container ,
2644+ el_type = "> div.accordion-item" ,
2645+ arr_name = "value" ,
2646+ arr = value ,
2647+ key = "data-value" ,
2648+ timeout = timeout ,
2649+ )
2650+
2651+ def accordion_panel (
2652+ self ,
2653+ data_value : str ,
2654+ ) -> AccordionPanel :
2655+ return AccordionPanel (self .page , self .id , data_value )
2656+
2657+
2658+ class AccordionPanel (
2659+ _WidthLocM ,
2660+ _InputWithContainer ,
2661+ ):
2662+ # self,
2663+ # *args: TagChild | TagAttrs,
2664+ # data_value: str,
2665+ # icon: TagChild | None,
2666+ # title: TagChild | None,
2667+ # id: str | None,
2668+ # **kwargs: TagAttrValue,
2669+ def __init__ (self , page : Page , id : str , data_value : str ) -> None :
2670+ super ().__init__ (
2671+ page ,
2672+ id = id ,
2673+ loc = f"> div.accordion-item[data-value='{ data_value } ']" ,
2674+ loc_container = f"div#{ id } .accordion.shiny-bound-input" ,
2675+ )
2676+
2677+ self .loc_label = self .loc .locator (
2678+ "> .accordion-header > .accordion-button > .accordion-title"
2679+ )
2680+
2681+ self .loc_icon = self .loc .locator (
2682+ "> .accordion-header > .accordion-button > .accordion-icon"
2683+ )
2684+
2685+ self .loc_body = self .loc .locator ("> .accordion-collapse" )
2686+
2687+ def expect_label (self , value : PatternOrStr , * , timeout : Timeout = None ) -> None :
2688+ playwright_expect (self .loc_label ).to_have_text (value , timeout = timeout )
2689+
2690+ def expect_body (self , value : PatternOrStr , * , timeout : Timeout = None ) -> None :
2691+ playwright_expect (self .loc_body ).to_have_text (value , timeout = timeout )
2692+
2693+ def expect_icon (self , value : PatternOrStr , * , timeout : Timeout = None ) -> None :
2694+ playwright_expect (self .loc_icon ).to_have_text (value , timeout = timeout )
2695+
2696+ def expect_open (self , is_open : bool , * , timeout : Timeout = None ) -> None :
2697+ _expect_class_value (self .loc_body , "show" , is_open , timeout = timeout )
0 commit comments