@@ -24,3 +24,93 @@ Cypress.Commands.add('accordionItem', (name) => {
2424
2525 cy . get ( '.list-group-item' ) . contains ( name ) . click ( ) ;
2626} ) ;
27+
28+ /**
29+ * Selects an accordion item based on a path of labels.
30+ * @param accordionPath: The path can be a mix of strings and regular expressions.
31+ * For example, `[/^ManageIQ Region/, 'Zone', 'Server']`
32+ * will expand the accordion until it finds the item with the label 'Server' under 'Zone' under 'ManageIQ Region'.
33+ * If the path is not found, it will throw an error.
34+ */
35+ Cypress . Commands . add ( 'selectAccordionItem' , ( accordionPath ) => {
36+ cy . get ( 'li.list-group-item' ) . then ( ( $items ) => {
37+ // Converting jQuery collection to an array for easier manipulation
38+ const listItems = [ ...$items ] ;
39+
40+ /**
41+ * Function to recursively expand the accordion and click the target item.
42+ * @param {number } accordionPathIndex: The current index in the accordionPath array.
43+ * @param {number } searchStartIndex: The index in the listItems array to start searching from,
44+ * once the first label is matched, it is not required to start iterating from the beginning.
45+ * @returns {void }
46+ */
47+ const expandAndClickPath = ( accordionPathIndex , searchStartIndex ) => {
48+ const accordionLabel = accordionPath [ accordionPathIndex ] ;
49+ const isClickableNode = accordionPathIndex === accordionPath . length - 1 ;
50+
51+ for ( let i = searchStartIndex ; i < listItems . length ; i ++ ) {
52+ /* To remove */
53+ Cypress . log ( {
54+ name : 'selectAccordionItem' ,
55+ message : `Loop index: ${ i } & Searching for label: ${ accordionLabel } ` ,
56+ } ) ;
57+
58+ const liText = listItems [ i ] . textContent . trim ( ) ;
59+ // Check if the current item matches the label
60+ // Use either string match or regex match based on the type of accordionLabel
61+ let isMatch = false ;
62+ if ( typeof accordionLabel === 'string' ) {
63+ isMatch = liText === accordionLabel ;
64+ } else if ( accordionLabel instanceof RegExp ) {
65+ isMatch = accordionLabel . test ( liText ) ;
66+ }
67+
68+ if ( isMatch ) {
69+ /* To remove */
70+ Cypress . log ( {
71+ name : 'selectAccordionItem' ,
72+ message : `Matched "${ liText } " at index ${ i } ` ,
73+ } ) ;
74+
75+ // Wrap the current li element in a jQuery object to use jQuery methods
76+ const currentLiElement = Cypress . $ ( listItems [ i ] ) ;
77+ // If it's the last label in the path, then that is the desired item to click
78+ if ( isClickableNode ) {
79+ // Click the node corresponding to the last label in the given path and terminate
80+ cy . wrap ( currentLiElement ) . click ( ) ;
81+ return ;
82+ }
83+
84+ const isExpandable =
85+ currentLiElement . find ( 'span.fa-angle-right' ) . length > 0 ;
86+
87+ // If it's not the last label in the path, either expand the node
88+ // or move to the next label in the given path
89+ if ( isExpandable ) {
90+ // Expand the node
91+ cy . wrap ( currentLiElement )
92+ . find ( 'span.fa-angle-right' )
93+ . click ( )
94+ . then ( ( ) => {
95+ // Recurse to the next label in the given path array and
96+ // start iteration from the current index
97+ expandAndClickPath ( accordionPathIndex + 1 , i + 1 ) ;
98+ } ) ;
99+ } else {
100+ // If it's already expanded, continue to the next label
101+ // start iteration from the current index
102+ expandAndClickPath ( accordionPathIndex + 1 , i + 1 ) ;
103+ }
104+ // Exit the current function scope
105+ return ;
106+ }
107+ }
108+ // If we reach here, it means the label was not found
109+ throw new Error ( `Accordion item: "${ accordionLabel } " not found` ) ;
110+ } ;
111+
112+ // Start the recursive call from the first label in the given path
113+ // and from the beginning of the accordion items in the panel
114+ expandAndClickPath ( 0 , 0 ) ;
115+ } ) ;
116+ } ) ;
0 commit comments