UNPKG

detox

Version:

E2E tests and automation for mobile

161 lines (129 loc) 4.97 kB
const DetoxRuntimeError = require('../../errors/DetoxRuntimeError'); const invoke = require('../../invoke'); const assertIsFunction = require('../../utils/assertIsFunction'); const isArrowFunction = require('../../utils/isArrowFunction'); const actions = require('../actions/web'); const EspressoWebDetoxApi = require('../espressoapi/web/EspressoWebDetox'); const WebViewElementApi = require('../espressoapi/web/WebViewElement'); const { ActionInteraction } = require('../interactions/web'); const { WebMatcher } = require('./WebMatcher'); const _device = Symbol('device'); const _emitter = Symbol('emitter'); const _matcher = Symbol('matcher'); const _invocationManager = Symbol('invocationManager'); const _webMatcher = Symbol('webMatcher'); const _webViewElement = Symbol('webViewElement'); class WebElement { constructor({ device, invocationManager, webMatcher, webViewElement }) { this[_device] = device; this[_invocationManager] = invocationManager; this[_webMatcher] = webMatcher; this[_webViewElement] = webViewElement; this.atIndex(0); } asSecured() { throw new DetoxRuntimeError('asSecured() is not supported for Android WebElement'); } atIndex(index) { const webViewElementCall = this[_webViewElement]._call; const webMatcherCall = this[_webMatcher]._call; this._call = invoke.callDirectly(WebViewElementApi.element(webViewElementCall, webMatcherCall.value, index)); return this; } async executeAction(action) { const result = await new ActionInteraction(this[_invocationManager], action).execute(); // Workaround since Detox doesn't wait for the action to complete. await new Promise(resolve => setTimeout(resolve, 500)); return result; } async tap() { return await this.executeAction(new actions.WebTapAction(this)); } async typeText(text, isContentEditable = false) { if (isContentEditable) { return await this[_device]._typeText(text); } return await this.executeAction(new actions.WebTypeTextAction(this, text)); } // At the moment not working on content-editable async replaceText(text) { return await this.executeAction(new actions.WebReplaceTextAction(this, text)); } // At the moment not working on content-editable async clearText() { return await this.executeAction(new actions.WebClearTextAction(this)); } async scrollToView() { return await this.executeAction(new actions.WebScrollToViewAction(this)); } async getText() { return await this.executeAction(new actions.WebGetTextAction(this)); } async focus() { return await this.executeAction(new actions.WebFocusAction(this)); } async selectAllText() { return await this.executeAction(new actions.WebSelectAllText(this)); } async moveCursorToEnd() { return await this.executeAction(new actions.WebMoveCursorEnd(this)); } async runScript(maybeFunction, args) { const script = stringifyScript(maybeFunction); if (args) { return await this.executeAction(new actions.WebRunScriptWithArgsAction(this, script, args)); } else { return await this.executeAction(new actions.WebRunScriptAction(this, script)); } } async getCurrentUrl() { return await this.executeAction(new actions.WebGetCurrentUrlAction(this)); } async getTitle() { return await this.executeAction(new actions.WebGetTitleAction(this)); } } class WebViewElement { constructor({ device, emitter, invocationManager, matcher }) { this[_device] = device; this[_emitter] = emitter; this[_invocationManager] = invocationManager; this[_matcher] = matcher; if (matcher !== undefined) { this._call = invoke.callDirectly(EspressoWebDetoxApi.getWebView(matcher._call.value)); } else { this._call = invoke.callDirectly(EspressoWebDetoxApi.getWebView()); } this.element = this.element.bind(this); } element(webMatcher) { if (webMatcher instanceof WebMatcher) { return new WebElement({ device: this[_device], invocationManager: this[_invocationManager], webViewElement: this, webMatcher, }); } throw new DetoxRuntimeError(`element() argument is invalid, expected a web matcher, but got ${typeof webMatcher}`); } atIndex(_index) { // Not implemented yet throw new DetoxRuntimeError('atIndex() is not supported for Android WebViewElement'); } } function stringifyScript(maybeFunction) { if (typeof maybeFunction !== 'string' && typeof maybeFunction !== 'function') { return maybeFunction; } const script = (typeof maybeFunction === 'function' ? maybeFunction.toString() : assertIsFunction(maybeFunction)).trim(); // WebElement interactions don't support arrow functions for some reason. if (isArrowFunction(script)) { return `function arrowWorkaround() { return (${script}).apply(this, arguments); }`; } return script; } module.exports = { WebElement, WebViewElement, };