Skip to content

Commit db2b080

Browse files
committed
DRY
1 parent 6b7c8f1 commit db2b080

File tree

5 files changed

+97
-23
lines changed

5 files changed

+97
-23
lines changed

lib/helper/Appium.js

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const { truth } = require('../assert/truth')
1010
const recorder = require('../recorder')
1111
const Locator = require('../locator')
1212
const ConnectionRefused = require('./errors/ConnectionRefused')
13+
const { dontSeeElementError, seeElementError } = require('./errors/ElementAssertion')
14+
const { getElementId } = require('../utils')
1315

1416
const mobileRoot = '//*'
1517
const webRoot = 'body'
@@ -1523,7 +1525,36 @@ class Appium extends Webdriver {
15231525
*/
15241526
async dontSeeElement(locator) {
15251527
if (this.isWeb) return super.dontSeeElement(locator)
1526-
return super.dontSeeElement(parseLocator.call(this, locator))
1528+
1529+
// For mobile apps, use native display check instead of JavaScript execution
1530+
const parsedLocator = parseLocator.call(this, locator)
1531+
const res = await this._locate(parsedLocator, false)
1532+
1533+
if (!res || res.length === 0) {
1534+
return truth(`elements of ${new Locator(parsedLocator)}`, 'to be seen').negate(false)
1535+
}
1536+
1537+
// Use native isDisplayed() method without JavaScript execution for mobile
1538+
const selected = []
1539+
for (let i = 0; i < res.length; i++) {
1540+
try {
1541+
// Get element ID using utility function
1542+
const elementId = getElementId(res[i])
1543+
1544+
// Use the native WebDriver isDisplayed method directly
1545+
const isDisplayed = await this.browser.isElementDisplayed(elementId)
1546+
selected.push(isDisplayed)
1547+
} catch (err) {
1548+
// If native method fails, element is not displayed
1549+
selected.push(false)
1550+
}
1551+
}
1552+
1553+
try {
1554+
return truth(`elements of ${new Locator(parsedLocator)}`, 'to be seen').negate(selected)
1555+
} catch (e) {
1556+
seeElementError(parsedLocator)
1557+
}
15271558
}
15281559

15291560
/**
@@ -1656,7 +1687,37 @@ class Appium extends Webdriver {
16561687
*/
16571688
async seeElement(locator) {
16581689
if (this.isWeb) return super.seeElement(locator)
1659-
return super.seeElement(parseLocator.call(this, locator))
1690+
1691+
// For mobile apps, use native display check instead of JavaScript execution
1692+
const parsedLocator = parseLocator.call(this, locator)
1693+
const res = await this._locate(parsedLocator, true)
1694+
1695+
// Check if elements exist
1696+
if (!res || res.length === 0) {
1697+
throw new AssertionFailedError(`Element ${new Locator(parsedLocator)} was not found`)
1698+
}
1699+
1700+
// Use native isDisplayed() method without JavaScript execution for mobile
1701+
const selected = []
1702+
for (let i = 0; i < res.length; i++) {
1703+
try {
1704+
// Get element ID using utility function
1705+
const elementId = getElementId(res[i])
1706+
1707+
// Use the native WebDriver isDisplayed method directly
1708+
const isDisplayed = await this.browser.isElementDisplayed(elementId)
1709+
selected.push(isDisplayed)
1710+
} catch (err) {
1711+
// If native method fails, element is not displayed
1712+
selected.push(false)
1713+
}
1714+
}
1715+
1716+
try {
1717+
return truth(`elements of ${new Locator(parsedLocator)}`, 'to be seen').assert(selected)
1718+
} catch (e) {
1719+
dontSeeElementError(parsedLocator)
1720+
}
16601721
}
16611722

16621723
/**

lib/helper/WebDriver.js

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const { focusElement } = require('./scripts/focusElement')
2121
const { blurElement } = require('./scripts/blurElement')
2222
const { dontSeeElementError, seeElementError, seeElementInDOMError, dontSeeElementInDOMError } = require('./errors/ElementAssertion')
2323
const { dontSeeTraffic, seeTraffic, grabRecordedNetworkTraffics, stopRecordingTraffic, flushNetworkTraffics } = require('./network/actions')
24+
const { getElementId } = require('../utils')
2425
const WebElement = require('../element/WebElement')
2526

2627
const SHADOW = 'shadow'
@@ -998,7 +999,7 @@ class WebDriver extends Helper {
998999
* {{ react }}
9991000
*/
10001001
async click(locator, context = null) {
1001-
const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick'
1002+
const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick'
10021003
const locateFn = prepareLocateFn.call(this, context)
10031004

10041005
const res = await findClickable.call(this, locator, locateFn)
@@ -1217,7 +1218,7 @@ class WebDriver extends Helper {
12171218
* {{> checkOption }}
12181219
*/
12191220
async checkOption(field, context = null) {
1220-
const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick'
1221+
const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick'
12211222
const locateFn = prepareLocateFn.call(this, context)
12221223

12231224
const res = await findCheckable.call(this, field, locateFn)
@@ -1237,7 +1238,7 @@ class WebDriver extends Helper {
12371238
* {{> uncheckOption }}
12381239
*/
12391240
async uncheckOption(field, context = null) {
1240-
const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick'
1241+
const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick'
12411242
const locateFn = prepareLocateFn.call(this, context)
12421243

12431244
const res = await findCheckable.call(this, field, locateFn)
@@ -2985,21 +2986,6 @@ function usingFirstElement(els) {
29852986
return els[0]
29862987
}
29872988

2988-
function getElementId(el) {
2989-
// W3C WebDriver web element identifier
2990-
// https://w3c.github.io/webdriver/#dfn-web-element-identifier
2991-
if (el['element-6066-11e4-a52e-4f735466cecf']) {
2992-
return el['element-6066-11e4-a52e-4f735466cecf']
2993-
}
2994-
// (deprecated) JsonWireProtocol identifier
2995-
// https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#webelement-json-object
2996-
if (el.ELEMENT) {
2997-
return el.ELEMENT
2998-
}
2999-
3000-
return null
3001-
}
3002-
30032989
// List of known key values to unicode code points
30042990
// https://www.w3.org/TR/webdriver/#keyboard-actions
30052991
const keyUnicodeMap = {

lib/utils.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,28 @@ const { convertColorToRGBA, isColorProperty } = require('./colorUtils')
88
const Fuse = require('fuse.js')
99
const { spawnSync } = require('child_process')
1010

11+
// WebDriver constants
12+
// W3C WebDriver web element identifier
13+
// https://w3c.github.io/webdriver/#dfn-web-element-identifier
14+
const W3C_ELEMENT_ID = 'element-6066-11e4-a52e-4f735466cecf'
15+
16+
/**
17+
* Get element ID from WebDriver element response
18+
* Supports both W3C and legacy JsonWireProtocol formats
19+
*/
20+
function getElementId(el) {
21+
// W3C WebDriver web element identifier
22+
if (el[W3C_ELEMENT_ID]) {
23+
return el[W3C_ELEMENT_ID]
24+
}
25+
// (deprecated) JsonWireProtocol identifier
26+
// https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#webelement-json-object
27+
if (el.ELEMENT) {
28+
return el.ELEMENT
29+
}
30+
return el
31+
}
32+
1133
function deepMerge(target, source) {
1234
const merge = require('lodash.merge')
1335
return merge(target, source)
@@ -659,3 +681,7 @@ module.exports.markdownToAnsi = function (markdown) {
659681
})
660682
)
661683
}
684+
685+
// WebDriver constants and utilities
686+
module.exports.W3C_ELEMENT_ID = W3C_ELEMENT_ID
687+
module.exports.getElementId = getElementId

test/helper/WebDriver.noSeleniumServer_test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const WebDriver = require('../../lib/helper/WebDriver')
1212
const AssertionFailedError = require('../../lib/assert/error')
1313
const Secret = require('../../lib/secret')
1414
global.codeceptjs = require('../../lib')
15+
const { W3C_ELEMENT_ID } = require('../../lib/utils')
1516

1617
const siteUrl = TestHelper.siteUrl()
1718
let wd
@@ -41,7 +42,7 @@ describe('WebDriver - No Selenium server started', function () {
4142
},
4243
},
4344
customLocatorStrategies: {
44-
customSelector: selector => ({ 'element-6066-11e4-a52e-4f735466cecf': `${selector}-foobar` }),
45+
customSelector: selector => ({ [W3C_ELEMENT_ID]: `${selector}-foobar` }),
4546
},
4647
})
4748
})
@@ -382,7 +383,6 @@ describe('WebDriver - No Selenium server started', function () {
382383
})
383384
})
384385

385-
386386
describe('#seeTitleEquals', () => {
387387
it('should check that title is equal to provided one', async () => {
388388
await wd.amOnPage('/')

test/helper/WebDriver_test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const AssertionFailedError = require('../../lib/assert/error')
1111
const webApiTests = require('./webapi')
1212
const Secret = require('../../lib/secret')
1313
global.codeceptjs = require('../../lib')
14+
const { W3C_ELEMENT_ID } = require('../../lib/utils')
1415

1516
const siteUrl = TestHelper.siteUrl()
1617
let wd
@@ -44,7 +45,7 @@ describe('WebDriver', function () {
4445
},
4546
},
4647
customLocatorStrategies: {
47-
customSelector: selector => ({ 'element-6066-11e4-a52e-4f735466cecf': `${selector}-foobar` }),
48+
customSelector: selector => ({ [W3C_ELEMENT_ID]: `${selector}-foobar` }),
4849
},
4950
})
5051
})

0 commit comments

Comments
 (0)