How to use proxySetTimeouts method in Appium Base Driver

Best JavaScript code snippet using appium-base-driver

Run Appium Base Driver automation tests on LambdaTest cloud grid

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

protocol-converter.js

Source: protocol-converter.js Github

copy
1import _ from 'lodash';
2import { logger, util } from 'appium-support';
3import { duplicateKeys } from '../basedriver/helpers';
4import {
5  MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY, PROTOCOLS
6} from '../constants';
7import { formatStatus } from '../protocol/helpers';
8
9const log = logger.getLogger('Protocol Converter');
10
11
12export const COMMAND_URLS_CONFLICTS = [
13  {
14    commandNames: ['execute', 'executeAsync'],
15    jsonwpConverter: (url) => url.replace(/\/execute.*/,
16      url.includes('async') ? '/execute_async' : '/execute'),
17    w3cConverter: (url) => url.replace(/\/execute.*/,
18      url.includes('async') ? '/execute/async' : '/execute/sync'),
19  },
20  {
21    commandNames: ['getElementScreenshot'],
22    jsonwpConverter: (url) => url.replace(/\/element\/([^/]+)\/screenshot$/,
23      '/screenshot/$1'),
24    w3cConverter: (url) => url.replace(/\/screenshot\/([^/]+)/,
25      '/element/$1/screenshot'),
26  },
27  {
28    commandNames: ['getWindowHandles', 'getWindowHandle'],
29    jsonwpConverter (url) {
30      return /\/window$/.test(url)
31        ? url.replace(/\/window$/, '/window_handle')
32        : url.replace(/\/window\/handle(s?)$/, '/window_handle$1');
33    },
34    w3cConverter (url) {
35      return /\/window_handle$/.test(url)
36        ? url.replace(/\/window_handle$/, '/window')
37        : url.replace(/\/window_handles$/, '/window/handles');
38    },
39  },
40  {
41    commandNames: ['getProperty'],
42    jsonwpConverter: (w3cUrl) => {
43      const w3cPropertyRegex = /\/element\/([^/]+)\/property\/([^/]+)/;
44      const jsonwpUrl = w3cUrl.replace(w3cPropertyRegex, '/element/$1/attribute/$2');
45      log.info(`Converting W3C '${w3cUrl}' to '${jsonwpUrl}'`);
46      return jsonwpUrl;
47    },
48    w3cConverter: (jsonwpUrl) => jsonwpUrl // Don't convert JSONWP URL to W3C. W3C accepts /attribute and /property
49  }
50];
51
52const {MJSONWP, W3C} = PROTOCOLS;
53
54
55class ProtocolConverter {
56  constructor (proxyFunc) {
57    this.proxyFunc = proxyFunc;
58    this._downstreamProtocol = null;
59  }
60
61  set downstreamProtocol (value) {
62    this._downstreamProtocol = value;
63  }
64
65  get downstreamProtocol () {
66    return this._downstreamProtocol;
67  }
68
69  /**
70   * W3C /timeouts can take as many as 3 timeout types at once, MJSONWP /timeouts only takes one
71   * at a time. So if we're using W3C and proxying to MJSONWP and there's more than one timeout type
72   * provided in the request, we need to do 3 proxies and combine the result
73   *
74   * @param {Object} body Request body
75   * @return {Array} Array of W3C + MJSONWP compatible timeout objects
76   */
77  getTimeoutRequestObjects (body) {
78    if (this.downstreamProtocol === W3C && _.has(body, 'ms') && _.has(body, 'type')) {
79      const typeToW3C = (x) => x === 'page load' ? 'pageLoad' : x;
80      return [{
81        [typeToW3C(body.type)]: body.ms,
82      }];
83    }
84
85    if (this.downstreamProtocol === MJSONWP && (!_.has(body, 'ms') || !_.has(body, 'type'))) {
86      const typeToJSONWP = (x) => x === 'pageLoad' ? 'page load' : x;
87      return _.toPairs(body)
88        // Only transform the entry if ms value is a valid positive float number
89        .filter((pair) => /^\d+(?:[.,]\d*?)?$/.test(`${pair[1]}`))
90        .map(function (pair) {
91          return {
92            type: typeToJSONWP(pair[0]),
93            ms: pair[1],
94          };
95        });
96    }
97
98    return [body];
99  }
100
101  /**
102   * Proxy an array of timeout objects and merge the result
103   * @param {String} url Endpoint url
104   * @param {String} method Endpoint method
105   * @param {Object} body Request body
106   */
107  async proxySetTimeouts (url, method, body) {
108    let response, resBody;
109
110    const timeoutRequestObjects = this.getTimeoutRequestObjects(body);
111    log.debug(`Will send the following request bodies to /timeouts: ${JSON.stringify(timeoutRequestObjects)}`);
112    for (const timeoutObj of timeoutRequestObjects) {
113      [response, resBody] = await this.proxyFunc(url, method, timeoutObj);
114
115      // If we got a non-MJSONWP response, return the result, nothing left to do
116      if (this.downstreamProtocol !== MJSONWP) {
117        return [response, resBody];
118      }
119
120      // If we got an error, return the error right away
121      if (response.statusCode >= 400) {
122        return [response, resBody];
123      }
124
125      // ...Otherwise, continue to the next timeouts call
126    }
127    return [response, resBody];
128  }
129
130  async proxySetWindow (url, method, body) {
131    const bodyObj = util.safeJsonParse(body);
132    if (_.isPlainObject(bodyObj)) {
133      if (this.downstreamProtocol === W3C && _.has(bodyObj, 'name') && !_.has(bodyObj, 'handle')) {
134        log.debug(`Copied 'name' value '${bodyObj.name}' to 'handle' as per W3C spec`);
135        return await this.proxyFunc(url, method, {
136          ...bodyObj,
137          handle: bodyObj.name,
138        });
139      }
140      if (this.downstreamProtocol === MJSONWP && _.has(bodyObj, 'handle') && !_.has(bodyObj, 'name')) {
141        log.debug(`Copied 'handle' value '${bodyObj.handle}' to 'name' as per JSONWP spec`);
142        return await this.proxyFunc(url, method, {
143          ...bodyObj,
144          name: bodyObj.handle,
145        });
146      }
147    }
148
149    return await this.proxyFunc(url, method, body);
150  }
151
152  async proxySetValue (url, method, body) {
153    const bodyObj = util.safeJsonParse(body);
154    if (_.isPlainObject(bodyObj) && (util.hasValue(bodyObj.text) || util.hasValue(bodyObj.value))) {
155      let {text, value} = bodyObj;
156      if (util.hasValue(text) && !util.hasValue(value)) {
157        value = _.isString(text)
158          ? [...text]
159          : (_.isArray(text) ? text : []);
160        log.debug(`Added 'value' property ${JSON.stringify(value)} to 'setValue' request body`);
161      } else if (!util.hasValue(text) && util.hasValue(value)) {
162        text = _.isArray(value)
163          ? value.join('')
164          : (_.isString(value) ? value : '');
165        log.debug(`Added 'text' property ${JSON.stringify(text)} to 'setValue' request body`);
166      }
167      return await this.proxyFunc(url, method, Object.assign({}, bodyObj, {
168        text,
169        value,
170      }));
171    }
172
173    return await this.proxyFunc(url, method, body);
174  }
175
176  async proxySetFrame (url, method, body) {
177    const bodyObj = util.safeJsonParse(body);
178    return _.has(bodyObj, 'id') && _.isPlainObject(bodyObj.id)
179      ? await this.proxyFunc(url, method, {
180        ...bodyObj,
181        id: duplicateKeys(bodyObj.id, MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY),
182      })
183      : await this.proxyFunc(url, method, body);
184  }
185
186  async proxyPerformActions (url, method, body) {
187    const bodyObj = util.safeJsonParse(body);
188    return _.isPlainObject(bodyObj)
189      ? await this.proxyFunc(url, method, duplicateKeys(bodyObj, MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY))
190      : await this.proxyFunc(url, method, body);
191  }
192
193  /**
194   * Handle "crossing" endpoints for the case
195   * when upstream and downstream drivers operate different protocols
196   *
197   * @param {string} commandName
198   * @param {string} url
199   * @param {string} method
200   * @param {?string|object} body
201   * @returns The proxyfying result as [response, responseBody] tuple
202   */
203  async convertAndProxy (commandName, url, method, body) {
204    if (!this.downstreamProtocol) {
205      // Patch calls with GENERIC protocol
206      // to preserve the backward compatibility
207      const [res, resBodyObj] = await this.proxyFunc(url, method, body);
208      return [res, formatStatus(resBodyObj, res.statusCode)];
209    }
210
211    // Same url, but different arguments
212    switch (commandName) {
213      case 'timeouts':
214        return await this.proxySetTimeouts(url, method, body);
215      case 'setWindow':
216        return await this.proxySetWindow(url, method, body);
217      case 'setValue':
218        return await this.proxySetValue(url, method, body);
219      case 'performActions':
220        return await this.proxyPerformActions(url, method, body);
221      case 'setFrame':
222        return await this.proxySetFrame(url, method, body);
223      default:
224        break;
225    }
226
227    // Same arguments, but different URLs
228    for (const {commandNames, jsonwpConverter, w3cConverter} of COMMAND_URLS_CONFLICTS) {
229      if (!commandNames.includes(commandName)) {
230        continue;
231      }
232
233      const rewrittenUrl = this.downstreamProtocol === MJSONWP
234        ? jsonwpConverter(url)
235        : w3cConverter(url);
236      if (rewrittenUrl === url) {
237        log.debug(`Did not know how to rewrite the original URL '${url}' ` +
238          `for ${this.downstreamProtocol} protocol`);
239        break;
240      }
241      log.info(`Rewrote the original URL '${url}' to '${rewrittenUrl}' ` +
242        `for ${this.downstreamProtocol} protocol`);
243      return await this.proxyFunc(rewrittenUrl, method, body);
244    }
245
246    // No matches found. Proceed normally
247    return await this.proxyFunc(url, method, body);
248  }
249}
250
251export default ProtocolConverter;
252
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 Base 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)