@@ -391,6 +391,29 @@ class Appium extends Webdriver {
391
391
return `${ protocol } ://${ hostname } :${ port } ${ normalizedPath } /session/${ this . browser . sessionId } `
392
392
}
393
393
394
+ /**
395
+ * Helper method to safely call isDisplayed() on mobile elements.
396
+ * Handles the case where webdriverio tries to use execute/sync which isn't supported in Appium.
397
+ * @private
398
+ */
399
+ async _isDisplayedSafe ( element ) {
400
+ if ( this . isWeb ) {
401
+ // For web contexts, use the normal isDisplayed
402
+ return element . isDisplayed ( )
403
+ }
404
+
405
+ try {
406
+ return await element . isDisplayed ( )
407
+ } catch ( err ) {
408
+ // If isDisplayed fails due to execute/sync not being supported in native mobile contexts,
409
+ // fall back to assuming the element is displayed (since we found it)
410
+ if ( err . message && err . message . includes ( 'Method is not implemented' ) ) {
411
+ return true
412
+ }
413
+ throw err
414
+ }
415
+ }
416
+
394
417
/**
395
418
* Execute code only on iOS
396
419
*
@@ -619,6 +642,7 @@ class Appium extends Webdriver {
619
642
*/
620
643
async resetApp ( ) {
621
644
onlyForApps . call ( this )
645
+ this . isWeb = false // Reset to native context after app reset
622
646
return this . axios ( {
623
647
method : 'post' ,
624
648
url : `${ this . _buildAppiumEndpoint ( ) } /appium/app/reset` ,
@@ -1134,7 +1158,7 @@ class Appium extends Webdriver {
1134
1158
] ,
1135
1159
} ,
1136
1160
] )
1137
- await this . browser . pause ( 1000 )
1161
+ await this . browser . pause ( 2000 )
1138
1162
}
1139
1163
1140
1164
/**
@@ -1296,28 +1320,26 @@ class Appium extends Webdriver {
1296
1320
let currentSource
1297
1321
return browser
1298
1322
. waitUntil (
1299
- ( ) => {
1323
+ async ( ) => {
1300
1324
if ( err ) {
1301
1325
return new Error ( `Scroll to the end and element ${ searchableLocator } was not found` )
1302
1326
}
1303
- return browser
1304
- . $$ ( parseLocator . call ( this , searchableLocator ) )
1305
- . then ( els => els . length && els [ 0 ] . isDisplayed ( ) )
1306
- . then ( res => {
1307
- if ( res ) {
1308
- return true
1309
- }
1310
- return this [ direction ] ( scrollLocator , offset , speed )
1311
- . getSource ( )
1312
- . then ( source => {
1313
- if ( source === currentSource ) {
1314
- err = true
1315
- } else {
1316
- currentSource = source
1317
- return false
1318
- }
1319
- } )
1320
- } )
1327
+ const els = await browser . $$ ( parseLocator . call ( this , searchableLocator ) )
1328
+ if ( els . length ) {
1329
+ const displayed = await this . _isDisplayedSafe ( els [ 0 ] )
1330
+ if ( displayed ) {
1331
+ return true
1332
+ }
1333
+ }
1334
+
1335
+ await this [ direction ] ( scrollLocator , offset , speed )
1336
+ const source = await this . browser . getPageSource ( )
1337
+ if ( source === currentSource ) {
1338
+ err = true
1339
+ } else {
1340
+ currentSource = source
1341
+ return false
1342
+ }
1321
1343
} ,
1322
1344
timeout * 1000 ,
1323
1345
errorMsg ,
@@ -1523,7 +1545,28 @@ class Appium extends Webdriver {
1523
1545
*/
1524
1546
async dontSeeElement ( locator ) {
1525
1547
if ( this . isWeb ) return super . dontSeeElement ( locator )
1526
- return super . dontSeeElement ( parseLocator . call ( this , locator ) )
1548
+
1549
+ // For mobile native apps, use safe isDisplayed wrapper
1550
+ const parsedLocator = parseLocator . call ( this , locator )
1551
+ const res = await this . _locate ( parsedLocator , false )
1552
+ const { truth } = require ( '../assert/truth' )
1553
+ const Locator = require ( '../locator' )
1554
+
1555
+ if ( ! res || res . length === 0 ) {
1556
+ return truth ( `elements of ${ new Locator ( parsedLocator ) } ` , 'to be seen' ) . negate ( false )
1557
+ }
1558
+
1559
+ const selected = [ ]
1560
+ for ( const el of res ) {
1561
+ const displayed = await this . _isDisplayedSafe ( el )
1562
+ if ( displayed ) selected . push ( true )
1563
+ }
1564
+
1565
+ try {
1566
+ return truth ( `elements of ${ new Locator ( parsedLocator ) } ` , 'to be seen' ) . negate ( selected )
1567
+ } catch ( err ) {
1568
+ throw err
1569
+ }
1527
1570
}
1528
1571
1529
1572
/**
@@ -1577,7 +1620,18 @@ class Appium extends Webdriver {
1577
1620
*/
1578
1621
async grabNumberOfVisibleElements ( locator ) {
1579
1622
if ( this . isWeb ) return super . grabNumberOfVisibleElements ( locator )
1580
- return super . grabNumberOfVisibleElements ( parseLocator . call ( this , locator ) )
1623
+
1624
+ // For mobile native apps, use safe isDisplayed wrapper
1625
+ const parsedLocator = parseLocator . call ( this , locator )
1626
+ const res = await this . _locate ( parsedLocator )
1627
+
1628
+ const selected = [ ]
1629
+ for ( const el of res ) {
1630
+ const displayed = await this . _isDisplayedSafe ( el )
1631
+ if ( displayed ) selected . push ( true )
1632
+ }
1633
+
1634
+ return selected . length
1581
1635
}
1582
1636
1583
1637
/**
@@ -1656,7 +1710,30 @@ class Appium extends Webdriver {
1656
1710
*/
1657
1711
async seeElement ( locator ) {
1658
1712
if ( this . isWeb ) return super . seeElement ( locator )
1659
- return super . seeElement ( parseLocator . call ( this , locator ) )
1713
+
1714
+ // For mobile native apps, use safe isDisplayed wrapper
1715
+ const parsedLocator = parseLocator . call ( this , locator )
1716
+ const res = await this . _locate ( parsedLocator , true )
1717
+ const ElementNotFound = require ( './errors/ElementNotFound' )
1718
+ const { truth } = require ( '../assert/truth' )
1719
+ const { dontSeeElementError } = require ( './errors/ElementAssertion' )
1720
+ const Locator = require ( '../locator' )
1721
+
1722
+ if ( ! res || res . length === 0 ) {
1723
+ throw new ElementNotFound ( parsedLocator )
1724
+ }
1725
+
1726
+ const selected = [ ]
1727
+ for ( const el of res ) {
1728
+ const displayed = await this . _isDisplayedSafe ( el )
1729
+ if ( displayed ) selected . push ( true )
1730
+ }
1731
+
1732
+ try {
1733
+ return truth ( `elements of ${ new Locator ( parsedLocator ) } ` , 'to be seen' ) . assert ( selected )
1734
+ } catch ( e ) {
1735
+ dontSeeElementError ( parsedLocator )
1736
+ }
1660
1737
}
1661
1738
1662
1739
/**
@@ -1703,7 +1780,30 @@ class Appium extends Webdriver {
1703
1780
*/
1704
1781
async waitForVisible ( locator , sec = null ) {
1705
1782
if ( this . isWeb ) return super . waitForVisible ( locator , sec )
1706
- return super . waitForVisible ( parseLocator . call ( this , locator ) , sec )
1783
+
1784
+ // For mobile native apps, use safe isDisplayed wrapper
1785
+ const parsedLocator = parseLocator . call ( this , locator )
1786
+ const aSec = sec || this . options . waitForTimeoutInSeconds
1787
+ const Locator = require ( '../locator' )
1788
+
1789
+ return this . browser . waitUntil (
1790
+ async ( ) => {
1791
+ const res = await this . _res ( parsedLocator )
1792
+ if ( ! res || res . length === 0 ) return false
1793
+
1794
+ const selected = [ ]
1795
+ for ( const el of res ) {
1796
+ const displayed = await this . _isDisplayedSafe ( el )
1797
+ if ( displayed ) selected . push ( true )
1798
+ }
1799
+
1800
+ return selected . length > 0
1801
+ } ,
1802
+ {
1803
+ timeout : aSec * 1000 ,
1804
+ timeoutMsg : `element (${ new Locator ( parsedLocator ) } ) still not visible after ${ aSec } sec` ,
1805
+ } ,
1806
+ )
1707
1807
}
1708
1808
1709
1809
/**
@@ -1712,7 +1812,27 @@ class Appium extends Webdriver {
1712
1812
*/
1713
1813
async waitForInvisible ( locator , sec = null ) {
1714
1814
if ( this . isWeb ) return super . waitForInvisible ( locator , sec )
1715
- return super . waitForInvisible ( parseLocator . call ( this , locator ) , sec )
1815
+
1816
+ // For mobile native apps, use safe isDisplayed wrapper
1817
+ const parsedLocator = parseLocator . call ( this , locator )
1818
+ const aSec = sec || this . options . waitForTimeoutInSeconds
1819
+ const Locator = require ( '../locator' )
1820
+
1821
+ return this . browser . waitUntil (
1822
+ async ( ) => {
1823
+ const res = await this . _res ( parsedLocator )
1824
+ if ( ! res || res . length === 0 ) return true
1825
+
1826
+ const selected = [ ]
1827
+ for ( const el of res ) {
1828
+ const displayed = await this . _isDisplayedSafe ( el )
1829
+ if ( displayed ) selected . push ( true )
1830
+ }
1831
+
1832
+ return selected . length === 0
1833
+ } ,
1834
+ { timeout : aSec * 1000 , timeoutMsg : `element (${ new Locator ( parsedLocator ) } ) still visible after ${ aSec } sec` } ,
1835
+ )
1716
1836
}
1717
1837
1718
1838
/**
0 commit comments