forked from appium/appium-espresso-driver
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/master' into AND-50867_Update_co…
…mpose_to_1_5
- Loading branch information
Showing
14 changed files
with
712 additions
and
705 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { errors } from 'appium/driver'; | ||
import { qualifyActivityName, requireOptions } from '../utils'; | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
// eslint-disable-next-line require-await | ||
export async function launchApp () { | ||
throw new errors.UnsupportedOperationError( | ||
'Please create a new session in order to launch the application under test' | ||
); | ||
} | ||
|
||
/** | ||
* @typedef {Object} BackgroundAppOptions | ||
* @property {number} [seconds] The amount of seconds to wait between putting the app to background and restoring it. | ||
* Any negative value means to not restore the app after putting it to the background (the default behavior). | ||
*/ | ||
|
||
/** | ||
* Puts the app under test to the background | ||
* and then restores it (if needed). The call is blocking is the | ||
* app needs to be restored afterwards. | ||
* | ||
* @this {import('../driver').EspressoDriver} | ||
* @param {BackgroundAppOptions} [opts={}] | ||
*/ | ||
export async function mobileBackgroundApp (opts = {}) { | ||
const {seconds = -1} = opts; | ||
return await this.background(seconds); | ||
Check failure on line 30 in lib/commands/app-management.js GitHub Actions / kotlin_test
Check failure on line 30 in lib/commands/app-management.js GitHub Actions / node_test (20)
Check failure on line 30 in lib/commands/app-management.js GitHub Actions / node_test (18)
|
||
} | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
// eslint-disable-next-line require-await | ||
export async function closeApp () { | ||
throw new errors.UnsupportedOperationError( | ||
'Please quit the session in order to close the application under test' | ||
); | ||
} | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
// eslint-disable-next-line require-await | ||
export async function reset () { | ||
throw new errors.UnsupportedOperationError( | ||
'Please quit the session and create a new one ' + | ||
'in order to close and launch the application under test'); | ||
} | ||
|
||
/** | ||
* @typedef {Object} StartActivityOptions | ||
* @property {string} appActivity | ||
* @property {string} [locale] | ||
* @property {string} [optionalIntentArguments] | ||
* @property {string} [optionalActivityArguments] | ||
*/ | ||
|
||
/** | ||
* Starts the given activity with intent options, activity options and locale. | ||
* Activity could only be executed in scope of the current app package. | ||
* | ||
* @this {import('../driver').EspressoDriver} | ||
* @param {StartActivityOptions} opts | ||
* @returns {Promise<string>} | ||
*/ | ||
export async function mobileStartActivity (opts) { | ||
const appPackage = this.caps.appPackage; | ||
const { | ||
appActivity, | ||
locale, | ||
optionalIntentArguments, | ||
optionalActivityArguments | ||
} = requireOptions(opts, ['appActivity']); | ||
return /** @type {string} */ (await this.espresso.jwproxy.command(`/appium/device/start_activity`, 'POST', { | ||
appPackage, | ||
appActivity, | ||
locale, | ||
optionalIntentArguments, | ||
optionalActivityArguments | ||
})); | ||
} | ||
|
||
/** | ||
* | ||
* @this {import('../driver').EspressoDriver} | ||
* @param {string} appPackage | ||
* @param {string} appActivity | ||
* @param {string} appWaitPackage | ||
* @param {string} appWaitActivity | ||
*/ | ||
export async function startActivity ( | ||
appPackage, appActivity, appWaitPackage, appWaitActivity | ||
) { | ||
// intentAction, intentCategory, intentFlags, optionalIntentArguments, dontStopAppOnReset | ||
// parameters are not supported by Espresso | ||
const pkg = /** @type {string} */ (appPackage || this.caps.appPackage); | ||
const appWaitPkg = /** @type {string} */ (appWaitPackage || pkg); | ||
const appAct = qualifyActivityName(appActivity, pkg); | ||
const appWaitAct = qualifyActivityName(appWaitActivity || appAct, appWaitPkg); | ||
this.log.debug(`Starting activity '${appActivity}' for package '${appPackage}'`); | ||
await this.espresso.jwproxy.command(`/appium/device/start_activity`, 'POST', { | ||
appPackage: pkg, | ||
appActivity: appAct, | ||
}); | ||
await this.adb.waitForActivity(appWaitPkg, appWaitAct); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { requireOptions } from '../utils'; | ||
|
||
/** | ||
* Stop proxying to any Chromedriver and redirect to Espresso | ||
* | ||
* @this {import('../driver').EspressoDriver} | ||
* @returns {void} | ||
*/ | ||
export function suspendChromedriverProxy () { | ||
this.chromedriver = undefined; | ||
this.proxyReqRes = this.espresso.proxyReqRes.bind(this.espresso); | ||
this.proxyCommand = this.espresso.proxyCommand.bind(this.espresso); | ||
this.jwpProxyActive = true; | ||
} | ||
|
||
/** | ||
* Runs a chain of Espresso web atoms (see https://developer.android.com/training/testing/espresso/web for reference) | ||
* | ||
* Takes JSON of the form | ||
* | ||
* { | ||
* "webviewEl": "<ELEMENT_ID>", // optional webview element to operate on | ||
* "forceJavascriptEnabled": true|false, // if webview disables javascript, webatoms won't work, this forces it | ||
* "methodChain": [ | ||
* {"name": "methodName", "atom": {"name": "atomName", "args": ["arg1", "arg2", ...]}}, | ||
* ... | ||
* ] | ||
* } | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileWebAtoms (opts = {}) { | ||
opts = requireOptions(opts, ['methodChain']); | ||
return await this.espresso.jwproxy.command(`/appium/execute_mobile/web_atoms`, 'POST', opts); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
import _ from 'lodash'; | ||
import { errors } from 'appium/driver'; | ||
import { util } from 'appium/support'; | ||
import { requireOptions } from '../utils'; | ||
|
||
/** | ||
* Flash the element with given id. | ||
* durationMillis and repeatCount are optional | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileFlashElement (opts = {}) { | ||
const {durationMillis, repeatCount} = opts; | ||
return await this.espresso.jwproxy.command( | ||
`/appium/execute_mobile/${requireElementId(opts)}/flash`, | ||
'POST', { | ||
durationMillis, | ||
repeatCount | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileDismissAutofill (opts = {}) { | ||
await this.espresso.jwproxy.command( | ||
`/session/:sessionId/appium/execute_mobile/${requireElementId(opts)}/dismiss_autofill`, | ||
'POST', | ||
{} | ||
); | ||
} | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileSwipe (opts = {}) { | ||
const {direction, swiper, startCoordinates, endCoordinates, precisionDescriber} = opts; | ||
const element = requireElementId(opts); | ||
return await this.espresso.jwproxy.command( | ||
`/appium/execute_mobile/${element}/swipe`, | ||
'POST', | ||
{ | ||
direction, | ||
element, | ||
swiper, | ||
startCoordinates, | ||
endCoordinates, | ||
precisionDescriber, | ||
} | ||
); | ||
} | ||
|
||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileOpenDrawer (opts = {}) { | ||
const {gravity} = opts; | ||
return await this.espresso.jwproxy.command( | ||
`/appium/execute_mobile/${requireElementId(opts)}/open_drawer`, | ||
'POST', | ||
{gravity} | ||
); | ||
} | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileCloseDrawer (opts = {}) { | ||
const {gravity} = opts; | ||
return await this.espresso.jwproxy.command( | ||
`/appium/execute_mobile/${requireElementId(opts)}/close_drawer`, | ||
'POST', | ||
{gravity} | ||
); | ||
} | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileSetDate (opts = {}) { | ||
const {year, monthOfYear, dayOfMonth} = requireOptions( | ||
opts, ['year', 'monthOfYear', 'dayOfMonth'] | ||
); | ||
return await this.espresso.jwproxy.command( | ||
`/appium/execute_mobile/${requireElementId(opts)}/set_date`, | ||
'POST', { | ||
year, | ||
monthOfYear, | ||
dayOfMonth, | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileSetTime (opts = {}) { | ||
const {hours, minutes} = requireOptions(opts, ['hours', 'minutes']); | ||
return await this.espresso.jwproxy.command( | ||
`/appium/execute_mobile/${requireElementId(opts)}/set_time`, | ||
'POST', { | ||
hours, | ||
minutes, | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileNavigateTo (opts = {}) { | ||
const {menuItemId} = requireOptions(opts, ['menuItemId']); | ||
const menuItemIdAsNumber = parseInt(menuItemId, 10); | ||
if (_.isNaN(menuItemIdAsNumber) || menuItemIdAsNumber < 0) { | ||
throw new errors.InvalidArgumentError( | ||
`'menuItemId' must be a non-negative number. Found ${menuItemId}` | ||
); | ||
} | ||
return await this.espresso.jwproxy.command( | ||
`/appium/execute_mobile/${requireElementId(opts)}/navigate_to`, | ||
'POST', | ||
{menuItemId} | ||
); | ||
} | ||
|
||
/** | ||
* Perform a 'GeneralClickAction' (https://developer.android.com/reference/androidx/test/espresso/action/GeneralClickAction) | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileClickAction (opts = {}) { | ||
const { | ||
tapper, coordinatesProvider, precisionDescriber, inputDevice, buttonState | ||
} = opts; | ||
return await this.espresso.jwproxy.command( | ||
`/appium/execute_mobile/${requireElementId(opts)}/click_action`, | ||
'POST', { | ||
tapper, coordinatesProvider, precisionDescriber, inputDevice, buttonState | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* | ||
* @this {import('../driver').EspressoDriver} | ||
*/ | ||
export async function mobileScrollToPage (opts = {}) { | ||
const {scrollTo, scrollToPage, smoothScroll} = opts; | ||
const scrollToTypes = ['first', 'last', 'left', 'right']; | ||
if (!scrollToTypes.includes(scrollTo)) { | ||
throw new errors.InvalidArgumentError( | ||
`"scrollTo" must be one of "${scrollToTypes.join(', ')}" found '${scrollTo}'` | ||
); | ||
} | ||
if (!_.isInteger(scrollToPage) || scrollToPage < 0) { | ||
throw new errors.InvalidArgumentError( | ||
`"scrollToPage" must be a non-negative integer. Found '${scrollToPage}'` | ||
); | ||
} | ||
if (util.hasValue(scrollTo) && util.hasValue(scrollToPage)) { | ||
this.log.warn(`'scrollTo' and 'scrollToPage' where both provided. Defaulting to 'scrollTo'`); | ||
} | ||
|
||
return await this.espresso.jwproxy.command( | ||
`/appium/execute_mobile/${requireElementId(opts)}/scroll_to_page`, | ||
'POST', { | ||
scrollTo, | ||
scrollToPage, | ||
smoothScroll, | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* @typedef {Object} PerformEditorActionOpts | ||
* @property {string|number} action | ||
*/ | ||
|
||
/** | ||
* @this {import('../driver').EspressoDriver} | ||
* @param {PerformEditorActionOpts} opts | ||
* @returns {Promise<void>} | ||
*/ | ||
export async function mobilePerformEditorAction (opts) { | ||
const {action} = requireOptions(opts, ['action']); | ||
await this.espresso.jwproxy.command('/appium/device/perform_editor_action', 'POST', {action}); | ||
} | ||
|
||
// #region Internal Helpers | ||
|
||
/** | ||
* @param {Record<string, any>} opts | ||
* @returns {string} | ||
*/ | ||
function requireElementId (opts) { | ||
const {element, elementId} = opts; | ||
if (!element && !elementId) { | ||
throw new errors.InvalidArgumentError('Element Id must be provided'); | ||
} | ||
return util.unwrapElement(elementId || element); | ||
} | ||
|
||
// #endregion |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.