Skip to content

Commit

Permalink
(feat): enable chromium protocol for edge (#12432)
Browse files Browse the repository at this point in the history
* (feat): enable chromium protocol for edge

* update doc

* fix test

* fix mistake
  • Loading branch information
lacell75 authored and christian-bromann committed Mar 5, 2024
1 parent 8a9e2fa commit bbbbece
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 32 deletions.
37 changes: 34 additions & 3 deletions packages/wdio-utils/src/envDetector.ts
@@ -1,4 +1,5 @@
import type { Capabilities } from '@wdio/types'
import { SUPPORTED_BROWSERNAMES } from './constants.js'

const MOBILE_BROWSER_NAMES = ['ipad', 'iphone', 'android']
const MOBILE_CAPABILITIES = [
Expand Down Expand Up @@ -65,6 +66,21 @@ function isChrome(capabilities?: Capabilities.DesiredCapabilities) {
return Boolean(capabilities.chrome || capabilities['goog:chromeOptions'])
}

/**
* check if session is run by Edgedriver
* @param {Object} capabilities caps of session response
* @return {Boolean} true if run by Edgedriver
*/
function isEdge(capabilities?: Capabilities.DesiredCapabilities) {
if (!capabilities) {
return false
}
return (
Boolean(capabilities.browserName && SUPPORTED_BROWSERNAMES.edge.includes(capabilities.browserName.toLowerCase()) ||
capabilities['ms:edgeOptions'])
)
}

/**
* check if session is run by Geckodriver
* @param {Object} capabilities caps of session response
Expand Down Expand Up @@ -222,6 +238,18 @@ function isSeleniumStandalone(capabilities?: Capabilities.DesiredCapabilities) {
)
}

/**
* detects if session is run using Chromium protocol
* @param {object} capabilities session capabilities
* @return {Boolean} true if session is run with Chromium protocol
*/
function isChromium(capabilities?: Capabilities.DesiredCapabilities) {
if (!capabilities) {
return false
}
return (isChrome(capabilities) || isEdge(capabilities))
}

/**
* returns information about the environment before the session is created
* @param {Object} capabilities caps provided by user
Expand Down Expand Up @@ -254,7 +282,8 @@ export function sessionEnvironmentDetector({ capabilities, requestedCapabilities
isAndroid: isAndroid(cap),
isSauce: isSauce(requestedCapabilities),
isSeleniumStandalone: isSeleniumStandalone(cap),
isBidi: isBidi(capabilities)
isBidi: isBidi(capabilities),
isChromium: isChromium(cap)
}
}

Expand All @@ -274,7 +303,8 @@ export function devtoolsEnvironmentDetector({ browserName }: WebdriverIO.Capabil
isChrome: browserName === 'chrome',
isSauce: false,
isSeleniumStandalone: false,
isBidi: false
isBidi: false,
isChromium: browserName === 'chrome'
}
}

Expand All @@ -292,6 +322,7 @@ export function webdriverEnvironmentDetector(capabilities: WebdriverIO.Capabilit
isIOS: isIOS(capabilities),
isAndroid: isAndroid(capabilities),
isSauce: isSauce(capabilities),
isBidi: isBidi(capabilities)
isBidi: isBidi(capabilities),
isChromium: isChromium(capabilities)
}
}
10 changes: 10 additions & 0 deletions packages/wdio-utils/tests/envDetector.test.ts
Expand Up @@ -95,6 +95,16 @@ describe('sessionEnvironmentDetector', () => {
expect(sessionEnvironmentDetector({ capabilities: phantomCaps, requestedCapabilities }).isChrome).toBe(false)
})

it('isChromium', () => {
const requestedCapabilities = { browserName: '' }
expect(sessionEnvironmentDetector({ capabilities: {}, requestedCapabilities: {} }).isChromium).toBe(false)
expect(sessionEnvironmentDetector({ capabilities: appiumCaps, requestedCapabilities }).isChromium).toBe(false)
expect(sessionEnvironmentDetector({ capabilities: chromeCaps, requestedCapabilities }).isChromium).toBe(true)
expect(sessionEnvironmentDetector({ capabilities: edgeCaps, requestedCapabilities }).isChromium).toBe(true)
expect(sessionEnvironmentDetector({ capabilities: geckoCaps, requestedCapabilities }).isChromium).toBe(false)
expect(sessionEnvironmentDetector({ capabilities: phantomCaps, requestedCapabilities }).isChromium).toBe(false)
})

it('isFirefox', () => {
const requestedCapabilities = { browserName: '' }
expect(sessionEnvironmentDetector({ capabilities: {}, requestedCapabilities: {} }).isFirefox).toBe(false)
Expand Down
2 changes: 1 addition & 1 deletion packages/webdriver/src/types.ts
Expand Up @@ -13,7 +13,7 @@ export interface JSONWPCommandError extends Error {

export interface SessionFlags {
isW3C: boolean
isChrome: boolean
isChromium: boolean
isFirefox: boolean
isAndroid: boolean
isMobile: boolean
Expand Down
12 changes: 6 additions & 6 deletions packages/webdriver/src/utils.ts
Expand Up @@ -172,7 +172,7 @@ export function isSuccessfulResponse (statusCode?: number, body?: WebDriverRespo
/**
* creates the base prototype for the webdriver monad
*/
export function getPrototype ({ isW3C, isChrome, isFirefox, isMobile, isSauce, isSeleniumStandalone }: Partial<SessionFlags>) {
export function getPrototype ({ isW3C, isChromium, isFirefox, isMobile, isSauce, isSeleniumStandalone }: Partial<SessionFlags>) {
const prototype: Record<string, PropertyDescriptor> = {}
const ProtocolCommands: Protocol = deepmerge(
/**
Expand All @@ -192,9 +192,9 @@ export function getPrototype ({ isW3C, isChrome, isFirefox, isMobile, isSauce, i
*/
isMobile ? deepmerge(MJsonWProtocol, AppiumProtocol) : {},
/**
* only apply special Chrome commands if session is using Chrome
* only apply special Chromium commands if session is using Chrome or Edge
*/
isChrome ? ChromiumProtocol : {},
isChromium ? ChromiumProtocol : {},
/**
* only apply special Firefox commands if session is using Firefox
*/
Expand Down Expand Up @@ -276,17 +276,17 @@ export class CustomRequestError extends Error {
* @param {Object} options driver instance or option object containing these flags
* @return {Object} prototype object
*/
export function getEnvironmentVars({ isW3C, isMobile, isIOS, isAndroid, isChrome, isFirefox, isSauce, isSeleniumStandalone, isBidi }: Partial<SessionFlags>): PropertyDescriptorMap {
export function getEnvironmentVars({ isW3C, isMobile, isIOS, isAndroid, isFirefox, isSauce, isSeleniumStandalone, isBidi, isChromium }: Partial<SessionFlags>): PropertyDescriptorMap {
return {
isW3C: { value: isW3C },
isMobile: { value: isMobile },
isIOS: { value: isIOS },
isAndroid: { value: isAndroid },
isFirefox: { value: isFirefox },
isChrome: { value: isChrome },
isSauce: { value: isSauce },
isSeleniumStandalone: { value: isSeleniumStandalone },
isBidi: { value: isBidi }
isBidi: { value: isBidi },
isChromium: { value: isChromium },
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/webdriver/tests/command.test.ts
Expand Up @@ -64,7 +64,7 @@ vi.mock('../src/request/node', () => {

class FakeClient extends EventEmitter {
isW3C = false
isChrome = false
isChromium = false
isAndroid = false
isMobile = false
isIOS = false
Expand Down
14 changes: 7 additions & 7 deletions packages/webdriver/tests/index.test.ts
Expand Up @@ -187,7 +187,7 @@ describe('WebDriver', () => {
const client = WebDriver.attachToSession({ ...sessionOptions }) as any as TestClient
await client.getUrl()

expect(client.isChrome).toBeFalsy()
expect(client.isChromium).toBeFalsy()
expect(client.isMobile).toBeFalsy()
expect(client.isSauce).toBeFalsy()
expect(client.getApplicationCacheStatus).toBeFalsy()
Expand All @@ -211,13 +211,13 @@ describe('WebDriver', () => {

it('should allow to attach to existing session - mobile', async () => {
const client = WebDriver.attachToSession({ ...sessionOptions,
isChrome: true,
isChromium: true,
isMobile: true
}) as any as TestClient

await client.getUrl()

expect(client.isChrome).toBe(true)
expect(client.isChromium).toBe(true)
expect(client.isMobile).toBe(true)
expect(client.getApplicationCacheStatus).toBeTruthy()
expect(client.takeElementScreenshot).toBeTruthy()
Expand All @@ -230,29 +230,29 @@ describe('WebDriver', () => {
isMobile: false,
isIOS: false,
isAndroid: false,
isChrome: false,
isChromium: false,
isSauce: false
})
expect(client.isW3C).toBe(false)
expect(client.isMobile).toBe(false)
expect(client.isIOS).toBe(false)
expect(client.isAndroid).toBe(false)
expect(client.isChrome).toBe(false)
expect(client.isChromium).toBe(false)
expect(client.isSauce).toBe(false)

const anotherClient = WebDriver.attachToSession({ ...sessionOptions,
isW3C: true,
isMobile: true,
isIOS: true,
isAndroid: true,
isChrome: true,
isChromium: true,
isSauce: true
})
expect(anotherClient.isW3C).toBe(true)
expect(anotherClient.isMobile).toBe(true)
expect(anotherClient.isIOS).toBe(true)
expect(anotherClient.isAndroid).toBe(true)
expect(anotherClient.isChrome).toBe(true)
expect(anotherClient.isChromium).toBe(true)
expect(anotherClient.isSauce).toBe(true)
})

Expand Down
16 changes: 8 additions & 8 deletions packages/webdriver/tests/utils.test.ts
Expand Up @@ -40,23 +40,23 @@ describe('utils', () => {

it('getPrototype', () => {
const isW3C = false
const isChrome = false
const isChromium = false
const isMobile = false
const isSauce = false
const isIOS = false
const isAndroid = false
const isSeleniumStandalone = false

const jsonWireProtocolPrototype = getPrototype({
isW3C, isChrome, isMobile, isSauce, isSeleniumStandalone, isIOS, isAndroid
isW3C, isChromium, isMobile, isSauce, isSeleniumStandalone, isIOS, isAndroid
})
expect(jsonWireProtocolPrototype instanceof Object).toBe(true)
expect(typeof jsonWireProtocolPrototype.sendKeys.value).toBe('function')
expect(typeof jsonWireProtocolPrototype.sendCommand).toBe('undefined')
expect(typeof jsonWireProtocolPrototype.lock).toBe('undefined')

const webdriverPrototype = getPrototype({
isW3C: true, isChrome, isMobile, isSauce, isSeleniumStandalone, isIOS, isAndroid
isW3C: true, isChromium, isMobile, isSauce, isSeleniumStandalone, isIOS, isAndroid
})
expect(webdriverPrototype instanceof Object).toBe(true)
expect(typeof webdriverPrototype.sendKeys).toBe('undefined')
Expand All @@ -65,7 +65,7 @@ describe('utils', () => {
expect(typeof webdriverPrototype.lock).toBe('undefined')

const chromiumPrototype = getPrototype({
isW3C: false, isChrome: true, isMobile, isSauce, isSeleniumStandalone, isIOS, isAndroid
isW3C: false, isChromium: true, isMobile, isSauce, isSeleniumStandalone, isIOS, isAndroid
})
expect(chromiumPrototype instanceof Object).toBe(true)
expect(typeof chromiumPrototype.sendCommand.value).toBe('function')
Expand All @@ -74,7 +74,7 @@ describe('utils', () => {
expect(typeof chromiumPrototype.lock).toBe('undefined')

const geckoPrototype = getPrototype({
isW3C: true, isChrome: false, isFirefox: true, isMobile, isSauce, isSeleniumStandalone, isIOS, isAndroid
isW3C: true, isChromium: false, isFirefox: true, isMobile, isSauce, isSeleniumStandalone, isIOS, isAndroid
})
expect(geckoPrototype instanceof Object).toBe(true)
expect(typeof geckoPrototype.setMozContext.value).toBe('function')
Expand All @@ -83,7 +83,7 @@ describe('utils', () => {
expect(typeof geckoPrototype.lock).toBe('undefined')

const mobilePrototype = getPrototype({
isW3C: true, isChrome: false, isMobile: true, isSauce, isSeleniumStandalone, isIOS, isAndroid
isW3C: true, isChromium: false, isMobile: true, isSauce, isSeleniumStandalone, isIOS, isAndroid
})
expect(mobilePrototype instanceof Object).toBe(true)
expect(typeof mobilePrototype.performActions.value).toBe('function')
Expand All @@ -92,7 +92,7 @@ describe('utils', () => {
expect(typeof mobilePrototype.getNetworkConnection.value).toBe('function')

const mobileChromePrototype = getPrototype({
isW3C: true, isChrome: true, isMobile: true, isSauce, isSeleniumStandalone, isIOS, isAndroid
isW3C: true, isChromium: true, isMobile: true, isSauce, isSeleniumStandalone, isIOS, isAndroid
})
expect(mobileChromePrototype instanceof Object).toBe(true)
expect(typeof mobileChromePrototype.sendCommand.value).toBe('function')
Expand All @@ -102,7 +102,7 @@ describe('utils', () => {
expect(typeof mobileChromePrototype.getNetworkConnection.value).toBe('function')

const saucePrototype = getPrototype({
isW3C: true, isChrome, isMobile, isSauce: true, isSeleniumStandalone, isIOS, isAndroid
isW3C: true, isChromium, isMobile, isSauce: true, isSeleniumStandalone, isIOS, isAndroid
})
expect(saucePrototype instanceof Object).toBe(true)
expect(typeof saucePrototype.getPageLogs.value).toBe('function')
Expand Down
6 changes: 3 additions & 3 deletions packages/webdriverio/src/commands/browser/uploadFile.ts
Expand Up @@ -4,9 +4,9 @@ import archiver from 'archiver'

/**
* Uploads a file to the Selenium Standalone server or other browser driver
* (e.g. Chromedriver) by using the [`file`](https://webdriver.io/docs/api/selenium#file) command.
* _Note:_ that this command is only supported if you use a Selenium Hub or
* Chromedriver directly.
* (e.g. Chromedriver or EdgeDriver) by using the [`file`](https://webdriver.io/docs/api/selenium#file) command.
* _Note:_ that this command is only supported if you use a Selenium Hub,
* Chromedriver or EdgeDriver directly.
*
* __Note:__ this command uses an un-offical protocol feature that is currently
* only supported in Chrome and when running a [Selenium Grid](https://www.selenium.dev/documentation/en/grid/).
Expand Down
1 change: 1 addition & 0 deletions packages/webdriverio/tests/module.test.ts
Expand Up @@ -186,6 +186,7 @@ describe('WebdriverIO module interface', () => {
expect(flags).toEqual({
isAndroid: false,
isChrome: true,
isChromium: true,
isFirefox: false,
isIOS: false,
isMobile: false,
Expand Down
3 changes: 2 additions & 1 deletion packages/webdriverio/tests/protocol-stub.test.ts
Expand Up @@ -19,9 +19,10 @@ describe('newSession', () => {
foo: 'bar'
}
})
expect(Object.keys(session)).toHaveLength(15)
expect(Object.keys(session)).toHaveLength(16)
expect(session.isAndroid).toBe(false)
expect(session.isChrome).toBe(false)
expect(session.isChromium).toBe(false)
expect(session.isFirefox).toBe(false)
expect(session.isIOS).toBe(true)
expect(session.isMobile).toBe(true)
Expand Down
2 changes: 1 addition & 1 deletion website/docs/api/Protocols.md
Expand Up @@ -45,7 +45,7 @@ According to Appium [documentation](https://appium.github.io/appium.io/docs/en/a

## Chromium

The Chromium protocol offers a super set of commands on top of the WebDriver protocol that is only supported when running automated session through [Chromedriver](https://chromedriver.chromium.org/chromedriver-canary).
The Chromium protocol offers a super set of commands on top of the WebDriver protocol that is only supported when running automated session through [Chromedriver](https://chromedriver.chromium.org/chromedriver-canary) or [Edgedriver](https://developer.microsoft.com/fr-fr/microsoft-edge/tools/webdriver).

## Firefox

Expand Down
Expand Up @@ -45,7 +45,7 @@ According to Appium [documentation](https://appium.github.io/appium.io/docs/en/a

## Chromium

The Chromium protocol offers a super set of commands on top of the WebDriver protocol that is only supported when running automated session through [Chromedriver](https://chromedriver.chromium.org/chromedriver-canary).
The Chromium protocol offers a super set of commands on top of the WebDriver protocol that is only supported when running automated session through [Chromedriver](https://chromedriver.chromium.org/chromedriver-canary) or [Edgedriver](https://developer.microsoft.com/fr-fr/microsoft-edge/tools/webdriver).

## Firefox

Expand Down

0 comments on commit bbbbece

Please sign in to comment.