@@ -24,3 +24,93 @@ Cypress.Commands.add('accordionItem', (name) => {
24
24
25
25
cy . get ( '.list-group-item' ) . contains ( name ) . click ( ) ;
26
26
} ) ;
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