How to use alreadyInContext method in Appium Xcuitest Driver

Best JavaScript code snippet using appium-xcuitest-driver

Run Appium Xcuitest Driver automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Sign up Free
_

context.js

Source: context.js Github

copy
1import { iosCommands, IOSPerformanceLog, NATIVE_WIN, WEBVIEW_WIN } from 'appium-ios-driver';
2import { createRemoteDebugger, RemoteDebugger } from 'appium-remote-debugger';
3import { errors } from 'appium-base-driver';
4import { util } from 'appium-support';
5import log from '../logger';
6import { retryInterval } from 'asyncbox';
7import _ from 'lodash';
8
9
10const WEBVIEW_BASE = `${WEBVIEW_WIN}_`;
11
12let commands = {}, helpers = {}, extensions = {};
13
14Object.assign(extensions, iosCommands.context);
15
16// override, as appium-ios-driver's version uses UI Automation to close
17extensions.closeAlertBeforeTest = async function closeAlertBeforeTest () { // eslint-disable-line require-await
18  return true;
19};
20
21// the appium-ios-driver version has a wait on real devices, which is no longer
22// necessary
23extensions.navToInitialWebview = async function navToInitialWebview () {
24  if (this.useNewSafari()) {
25    await this.typeAndNavToUrl();
26  } else if (!this.isRealDevice() && this.opts.safari) {
27    await this.navToViewThroughFavorites();
28  } else {
29    await this.navToViewWithTitle(/.*/);
30  }
31};
32
33// the appium-ios-driver version of this function fails in CI,
34// and the wrong webview is almost always retrieved
35// also override so that the case where the SDK version is not set does not fail
36extensions.getLatestWebviewContextForTitle = async function getLatestWebviewContextForTitle (regExp) {
37  const currentUrl = this.getCurrentUrl();
38
39  const contexts = _.filter(await this.getContextsAndViews(), 'view');
40
41  if (currentUrl) {
42    // first try to match by current url
43    for (const ctx of contexts) {
44      if ((ctx.view.url || '') === this.getCurrentUrl()) {
45        return ctx.id;
46      }
47    }
48  }
49
50  // if not, try to match by regular expression
51  for (const ctx of contexts) {
52    if ((ctx.view.title && regExp.test(ctx.view.title)) || (ctx.view.url && regExp.test(ctx.view.url))) {
53      return ctx.id;
54    }
55  }
56};
57
58extensions.isWebContext = function isWebContext () {
59  return !!this.curContext && this.curContext !== iosCommands.context.NATIVE_WIN;
60};
61
62extensions.isWebview = function isWebview () {
63  return this.isWebContext();
64};
65
66extensions.getNewRemoteDebugger = async function getNewRemoteDebugger () {
67  let socketPath;
68  if (!this.isRealDevice()) {
69    socketPath = await this.opts.device.getWebInspectorSocket();
70  }
71  return createRemoteDebugger({
72    bundleId: this.opts.bundleId,
73    isSafari: this.isSafari(),
74    includeSafari: this.opts.includeSafariInWebviews,
75    useNewSafari: this.useNewSafari(),
76    pageLoadMs: this.pageLoadMs,
77    platformVersion: this.opts.platformVersion,
78    socketPath,
79    remoteDebugProxy: this.opts.remoteDebugProxy,
80    garbageCollectOnExecute: util.hasValue(this.opts.safariGarbageCollect)
81      ? !!this.opts.safariGarbageCollect
82      : false,
83    udid: this.opts.udid,
84  }, this.isRealDevice());
85};
86
87commands.setContext = async function setContext (name, callback, skipReadyCheck) {
88  function alreadyInContext (desired, current) {
89    return (desired === current ||
90           (desired === null && current === NATIVE_WIN) ||
91           (desired === NATIVE_WIN && current === null));
92  }
93  function isNativeContext (context) {
94    return context === NATIVE_WIN || context === null;
95  }
96
97  log.debug(`Attempting to set context to '${name}'`);
98  if (alreadyInContext(name, this.curContext)) {
99    // already in the named context, no need to do anything
100    return;
101  }
102  if (isNativeContext(name)) {
103    // switching into the native context
104    this.curContext = null;
105    return;
106  }
107
108  // switching into a webview context
109
110  // if contexts have not already been retrieved, get them
111  if (_.isUndefined(this.contexts)) {
112    await this.getContexts();
113  }
114
115  let contextId = name.replace(WEBVIEW_BASE, '');
116  if (contextId === '') {
117    // allow user to pass in "WEBVIEW" without an index
118    // the second context will be the first webview as
119    // the first is always NATIVE_APP
120    contextId = this.contexts[1];
121  }
122  if (!_.includes(this.contexts, contextId)) {
123    throw new errors.NoSuchContextError();
124  }
125
126  // `contextId` will be in the form of `appId.pageId` in this case
127  const [appIdKey, pageIdKey] = _.map(contextId.split('.'), (id) => parseInt(id, 10));
128  await this.remote.selectPage(appIdKey, pageIdKey, skipReadyCheck);
129  this.curContext = contextId;
130
131  // attempt to start performance logging, if requested
132  if (this.opts.enablePerformanceLogging && this.remote) {
133    log.debug(`Starting performance log on '${this.curContext}'`);
134    this.logs.performance = new IOSPerformanceLog(this.remote);
135    await this.logs.performance.startCapture();
136  }
137
138  // start safari logging if the logs handlers are active
139  if (name && name !== NATIVE_WIN && this.logs) {
140    if (this.logs.safariConsole) {
141      await this.remote.startConsole(this.logs.safariConsole.addLogLine.bind(this.logs.safariConsole));
142    }
143    if (this.logs.safariNetwork) {
144      await this.remote.startNetwork(this.logs.safariNetwork.addLogLine.bind(this.logs.safariNetwork));
145    }
146  }
147};
148
149extensions.listWebFrames = async function listWebFrames (useUrl = true) {
150  if (!this.opts.bundleId) {
151    log.errorAndThrow('Cannot enter web frame without a bundle ID');
152  }
153
154  useUrl = useUrl && !this.isRealDevice() && !!this.getCurrentUrl();
155  log.debug(`Selecting by url: ${useUrl} ${useUrl ? `(expected url: '${this.getCurrentUrl()}')` : ''}`);
156
157  const currentUrl = useUrl ? this.getCurrentUrl() : undefined;
158  let pageArray = [];
159  const getWebviewPages = async () => {
160    try {
161      return await this.remote.selectApp(currentUrl, this.opts.webviewConnectRetries, this.opts.ignoreAboutBlankUrl);
162    } catch (err) {
163      log.debug(`No available web pages: ${err.message}`);
164      return [];
165    }
166  };
167
168  if (this.remote && this.remote.appIdKey) {
169    // already connected
170    pageArray = await getWebviewPages();
171  } else {
172    // not connected
173    this.remote = await this.getNewRemoteDebugger();
174
175    let appInfo = await this.remote.connect();
176    if (!appInfo) {
177      log.debug('Unable to connect to the remote debugger.');
178      return [];
179    }
180    pageArray = await getWebviewPages();
181    this.remote.on(RemoteDebugger.EVENT_PAGE_CHANGE, this.onPageChange.bind(this));
182    this.remote.on(RemoteDebugger.EVENT_FRAMES_DETACHED, () => {
183      if (!_.isEmpty(this.curWebFrames)) {
184        log.debug(`Clearing ${this.curWebFrames.length} frames: ${this.curWebFrames.join(', ')}`);
185      }
186      this.curWebFrames = [];
187    });
188
189    const alertErrorMsg = 'Close alert failed. Retry.';
190    try {
191      await retryInterval(6, 1000, async () => {
192        if (!await this.closeAlertBeforeTest()) {
193          throw new Error(alertErrorMsg);
194        }
195      });
196    } catch (err) {
197      // if the loop to close alerts failed to dismiss, ignore,
198      // otherwise log and throw the error
199      if (err.message !== alertErrorMsg) {
200        log.errorAndThrow(err);
201      }
202    }
203  }
204
205  if (pageArray.length === 0) {
206    // we have no web frames, but continue anyway
207    log.debug('No web frames found.');
208  }
209  return pageArray;
210};
211
212/**
213 * @typedef {Object} Context
214 *
215 * @property {string} id - The identifier of the context. The native context
216 *                          will be 'NATIVE_APP' and the webviews will be
217 *                          'WEBVIEW_xxx'
218 * @property {?string} title - The title associated with the webview content
219 * @property {?string} url - The url associated with the webview content
220 */
221
222/**
223 * Get the contexts available, with information about the url and title of each
224 * webview
225 * @returns {Array} List of Context objects
226 */
227extensions.mobileGetContexts = async function mobileGetContexts () {
228  const curOpt = this.opts.fullContextList;
229  try {
230    // `appium-ios-driver#getContexts` returns the full list of contexts
231    // if this option is on
232    this.opts.fullContextList = true;
233    return await this.getContexts();
234  } finally {
235    // reset the option so there are no side effects
236    this.opts.fullContextList = curOpt;
237  }
238};
239
240
241Object.assign(extensions, commands, helpers);
242export default extensions;
243
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Appium Xcuitest Driver on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)