1313 })
1414 ```
1515 */
16- const xpath = ( selector ) => {
16+ const xpath = ( selector , options = { } ) => {
1717 /* global XPathResult */
1818 const isNumber = ( xpathResult ) => xpathResult . resultType === XPathResult . NUMBER_TYPE
1919 const numberResult = ( xpathResult ) => xpathResult . numberValue
@@ -24,87 +24,96 @@ const xpath = (selector) => {
2424 const isBoolean = ( xpathResult ) => xpathResult . resultType === XPathResult . BOOLEAN_TYPE
2525 const booleanResult = ( xpathResult ) => xpathResult . booleanValue
2626
27- let nodes = [ ]
28- const document = cy . state ( 'window' ) . document
29- let iterator = document . evaluate ( selector , document )
30-
31- if ( isNumber ( iterator ) ) {
32- const result = numberResult ( iterator )
33- Cypress . log ( {
34- name : 'xpath' ,
35- message : selector ,
36- $el : nodes ,
37- consoleProps ( ) {
27+ const isPrimitive = ( x ) =>
28+ Cypress . _ . isNumber ( x ) || Cypress . _ . isString ( x ) || Cypress . _ . isBoolean ( x )
29+
30+ // options to log later
31+ const log = {
32+ name : 'xpath' ,
33+ message : selector ,
34+ }
35+
36+ const getValue = ( ) => {
37+ let nodes = [ ]
38+ const document = cy . state ( 'window' ) . document
39+ let iterator = document . evaluate ( selector , document )
40+
41+ if ( isNumber ( iterator ) ) {
42+ const result = numberResult ( iterator )
43+ log . consoleProps = ( ) => {
3844 return {
3945 'XPath' : selector ,
4046 type : 'number' ,
4147 result
4248 }
43- } ,
44- } )
45- return result
46- }
49+ }
50+ return result
51+ }
4752
48- if ( isString ( iterator ) ) {
49- const result = stringResult ( iterator )
50- Cypress . log ( {
51- name : 'xpath' ,
52- message : selector ,
53- $el : nodes ,
54- consoleProps ( ) {
53+ if ( isString ( iterator ) ) {
54+ const result = stringResult ( iterator )
55+ log . consoleProps = ( ) => {
5556 return {
5657 'XPath' : selector ,
5758 type : 'string' ,
5859 result
5960 }
60- } ,
61- } )
62- return result
63- }
61+ }
62+ return result
63+ }
6464
65- if ( isBoolean ( iterator ) ) {
66- const result = booleanResult ( iterator )
67- Cypress . log ( {
68- name : 'xpath' ,
69- message : selector ,
70- $el : nodes ,
71- consoleProps ( ) {
65+ if ( isBoolean ( iterator ) ) {
66+ const result = booleanResult ( iterator )
67+ log . consoleProps = ( ) => {
7268 return {
7369 'XPath' : selector ,
7470 type : 'boolean' ,
7571 result
7672 }
77- } ,
78- } )
79- return result
80- }
73+ }
74+ return result
75+ }
76+
77+ try {
78+ let node = iterator . iterateNext ( )
79+
80+ while ( node ) {
81+ nodes . push ( node )
82+ node = iterator . iterateNext ( )
83+ }
84+
85+ log . consoleProps = ( ) => {
86+ return {
87+ 'XPath' : selector ,
88+ }
89+ }
8190
82- try {
83- let node = iterator . iterateNext ( )
91+ return nodes
92+ } catch ( e ) {
93+ console . error ( 'Document tree modified during iteration' , e )
8494
85- while ( node ) {
86- nodes . push ( node )
87- node = iterator . iterateNext ( )
95+ return null
8896 }
89- } catch ( e ) {
90- console . error ( 'Document tree modified during iteration' , e )
97+ }
9198
92- return null
99+ const resolveValue = ( ) => {
100+ return Cypress . Promise . try ( getValue ) . then ( value => {
101+ return cy . verifyUpcomingAssertions ( value , options , {
102+ onRetry : resolveValue ,
103+ } )
104+ } )
93105 }
94106
95- // TODO set found elements on the command log?
96- Cypress . log ( {
97- name : 'xpath' ,
98- message : selector ,
99- $el : nodes ,
100- consoleProps ( ) {
101- return {
102- 'XPath' : selector ,
103- }
104- } ,
107+ return resolveValue ( ) . then ( ( value ) => {
108+ // TODO set found elements on the command log?
109+ Cypress . log ( log )
110+ if ( isPrimitive ( value ) ) {
111+ return value
112+ }
113+ return Cypress . $ ( value )
105114 } )
106115
107- return Cypress . $ ( nodes )
116+
108117}
109118
110119Cypress . Commands . add ( 'xpath' , xpath )
0 commit comments