@appium/base-driver 9.15.0 → 9.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/build/lib/basedriver/commands/execute.d.ts.map +1 -1
  2. package/build/lib/basedriver/commands/execute.js +24 -2
  3. package/build/lib/basedriver/commands/execute.js.map +1 -1
  4. package/build/lib/basedriver/driver.d.ts +7 -1
  5. package/build/lib/basedriver/driver.d.ts.map +1 -1
  6. package/build/lib/basedriver/driver.js +8 -0
  7. package/build/lib/basedriver/driver.js.map +1 -1
  8. package/build/lib/express/server.d.ts +23 -17
  9. package/build/lib/express/server.d.ts.map +1 -1
  10. package/build/lib/express/server.js +15 -3
  11. package/build/lib/express/server.js.map +1 -1
  12. package/build/lib/index.d.ts +1 -0
  13. package/build/lib/index.d.ts.map +1 -1
  14. package/build/lib/index.js +4 -1
  15. package/build/lib/index.js.map +1 -1
  16. package/build/lib/jsonwp-proxy/proxy.d.ts +15 -3
  17. package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
  18. package/build/lib/jsonwp-proxy/proxy.js +43 -50
  19. package/build/lib/jsonwp-proxy/proxy.js.map +1 -1
  20. package/build/lib/protocol/bidi-commands.js +3 -2
  21. package/build/lib/protocol/bidi-commands.js.map +1 -1
  22. package/build/lib/protocol/index.d.ts +3 -1
  23. package/build/lib/protocol/index.d.ts.map +1 -1
  24. package/build/lib/protocol/index.js +3 -1
  25. package/build/lib/protocol/index.js.map +1 -1
  26. package/build/lib/protocol/protocol.d.ts +5 -3
  27. package/build/lib/protocol/protocol.d.ts.map +1 -1
  28. package/build/lib/protocol/protocol.js +10 -11
  29. package/build/lib/protocol/protocol.js.map +1 -1
  30. package/build/lib/protocol/routes.d.ts +639 -604
  31. package/build/lib/protocol/routes.d.ts.map +1 -1
  32. package/build/lib/protocol/routes.js +399 -355
  33. package/build/lib/protocol/routes.js.map +1 -1
  34. package/lib/basedriver/commands/execute.ts +27 -2
  35. package/lib/basedriver/driver.ts +10 -0
  36. package/lib/express/server.js +24 -6
  37. package/lib/index.js +3 -0
  38. package/lib/jsonwp-proxy/proxy.js +52 -58
  39. package/lib/protocol/bidi-commands.js +1 -3
  40. package/lib/protocol/index.js +4 -0
  41. package/lib/protocol/protocol.js +5 -6
  42. package/lib/protocol/routes.js +410 -365
  43. package/package.json +6 -11
@@ -4,6 +4,12 @@ import _ from 'lodash';
4
4
  import {util} from '@appium/support';
5
5
  import {PROTOCOLS, DEFAULT_BASE_PATH} from '../constants';
6
6
  import {match} from 'path-to-regexp';
7
+ import { LRUCache } from 'lru-cache';
8
+
9
+ /** @type {LRUCache<string, string>} */
10
+ const COMMAND_NAMES_CACHE = new LRUCache({
11
+ max: 1024,
12
+ });
7
13
 
8
14
  const SET_ALERT_TEXT_PAYLOAD_PARAMS = {
9
15
  validate: (jsonObj) =>
@@ -22,6 +28,12 @@ const SET_ALERT_TEXT_PAYLOAD_PARAMS = {
22
28
  * @satisfies {import('@appium/types').MethodMap<import('../basedriver/driver').BaseDriver>}
23
29
  */
24
30
  export const METHOD_MAP = /** @type {const} */ ({
31
+
32
+ //
33
+ // W3C WebDriver (and deprecated MJSONWP that will be removed in Appium 3)
34
+ // https://www.w3.org/TR/webdriver1/
35
+ // https://www.w3.org/TR/webdriver2/
36
+ //
25
37
  '/status': {
26
38
  GET: {command: 'getStatus'},
27
39
  },
@@ -29,6 +41,7 @@ export const METHOD_MAP = /** @type {const} */ ({
29
41
  POST: {
30
42
  command: 'createSession',
31
43
  payloadParams: {
44
+ // TODO: Appium 3 will accept only 'capabilities'.
32
45
  validate: (jsonObj) =>
33
46
  !jsonObj.capabilities &&
34
47
  !jsonObj.desiredCapabilities &&
@@ -37,11 +50,8 @@ export const METHOD_MAP = /** @type {const} */ ({
37
50
  },
38
51
  },
39
52
  },
40
- '/sessions': {
41
- GET: {command: 'getSessions'},
42
- },
43
53
  '/session/:sessionId': {
44
- GET: {command: 'getSession'},
54
+ GET: {command: 'getSession', deprecated: true},
45
55
  DELETE: {command: 'deleteSession'},
46
56
  },
47
57
  '/session/:sessionId/timeouts': {
@@ -59,7 +69,7 @@ export const METHOD_MAP = /** @type {const} */ ({
59
69
  return 'W3C protocol expects any of script, pageLoad or implicit to be set';
60
70
  }
61
71
  } else {
62
- // MJSONWP
72
+ // TODO: Remove in Appium 3
63
73
  if (!util.hasValue(jsonObj.type) || !util.hasValue(jsonObj.ms)) {
64
74
  return 'MJSONWP protocol requires type and ms';
65
75
  }
@@ -69,25 +79,6 @@ export const METHOD_MAP = /** @type {const} */ ({
69
79
  },
70
80
  },
71
81
  },
72
- '/session/:sessionId/timeouts/async_script': {
73
- POST: {command: 'asyncScriptTimeout', payloadParams: {required: ['ms']}, deprecated: true},
74
- },
75
- '/session/:sessionId/timeouts/implicit_wait': {
76
- POST: {command: 'implicitWait', payloadParams: {required: ['ms']}, deprecated: true},
77
- },
78
- // JSONWP
79
- '/session/:sessionId/window_handle': {
80
- GET: {command: 'getWindowHandle'},
81
- },
82
- // W3C
83
- '/session/:sessionId/window/handle': {
84
- GET: {command: 'getWindowHandle'},
85
- },
86
- // JSONWP
87
- '/session/:sessionId/window_handles': {
88
- GET: {command: 'getWindowHandles'},
89
- },
90
- // W3C
91
82
  '/session/:sessionId/window/handles': {
92
83
  GET: {command: 'getWindowHandles'},
93
84
  },
@@ -104,39 +95,10 @@ export const METHOD_MAP = /** @type {const} */ ({
104
95
  '/session/:sessionId/refresh': {
105
96
  POST: {command: 'refresh'},
106
97
  },
107
- // MJSONWP
108
- '/session/:sessionId/execute': {
109
- POST: {command: 'execute', payloadParams: {required: ['script', 'args']}},
110
- },
111
- // MJSONWP
112
- '/session/:sessionId/execute_async': {
113
- POST: {
114
- command: 'executeAsync',
115
- payloadParams: {required: ['script', 'args']},
116
- },
117
- },
98
+
118
99
  '/session/:sessionId/screenshot': {
119
100
  GET: {command: 'getScreenshot'},
120
101
  },
121
- '/session/:sessionId/ime/available_engines': {
122
- GET: {command: 'availableIMEEngines', deprecated: true},
123
- },
124
- '/session/:sessionId/ime/active_engine': {
125
- GET: {command: 'getActiveIMEEngine', deprecated: true},
126
- },
127
- '/session/:sessionId/ime/activated': {
128
- GET: {command: 'isIMEActivated', deprecated: true},
129
- },
130
- '/session/:sessionId/ime/deactivate': {
131
- POST: {command: 'deactivateIMEEngine', deprecated: true},
132
- },
133
- '/session/:sessionId/ime/activate': {
134
- POST: {
135
- command: 'activateIMEEngine',
136
- payloadParams: {required: ['engine']},
137
- deprecated: true,
138
- },
139
- },
140
102
  '/session/:sessionId/frame': {
141
103
  POST: {command: 'setFrame', payloadParams: {required: ['id']}},
142
104
  },
@@ -148,6 +110,7 @@ export const METHOD_MAP = /** @type {const} */ ({
148
110
  POST: {
149
111
  command: 'setWindow',
150
112
  payloadParams: {
113
+ // TODO: Appium 3 will only accept 'handle'. 'name' will be ginored.
151
114
  optional: ['name', 'handle'],
152
115
  // Return both values to match W3C and JSONWP protocols
153
116
  makeArgs: (jsonObj) => {
@@ -167,15 +130,17 @@ export const METHOD_MAP = /** @type {const} */ ({
167
130
  },
168
131
  DELETE: {command: 'closeWindow'},
169
132
  },
170
- '/session/:sessionId/window/:windowhandle/size': {
171
- GET: {command: 'getWindowSize', deprecated: true},
133
+ '/session/:sessionId/window/maximize': {
134
+ POST: {command: 'maximizeWindow'},
172
135
  },
173
- '/session/:sessionId/window/:windowhandle/position': {
174
- POST: {deprecated: true},
175
- GET: {deprecated: true},
136
+ '/session/:sessionId/window/minimize': {
137
+ POST: {command: 'minimizeWindow'},
176
138
  },
177
- '/session/:sessionId/window/:windowhandle/maximize': {
178
- POST: {command: 'maximizeWindow'},
139
+ '/session/:sessionId/window/fullscreen': {
140
+ POST: {command: 'fullScreenWindow'},
141
+ },
142
+ '/session/:sessionId/window/new': {
143
+ POST: {command: 'createNewWindow', payloadParams: {optional: ['type']}},
179
144
  },
180
145
  '/session/:sessionId/cookie': {
181
146
  GET: {command: 'getCookies'},
@@ -206,7 +171,7 @@ export const METHOD_MAP = /** @type {const} */ ({
206
171
  },
207
172
  '/session/:sessionId/element/active': {
208
173
  GET: {command: 'active'}, // W3C: https://w3c.github.io/webdriver/webdriver-spec.html#dfn-get-active-element
209
- POST: {command: 'active'},
174
+ POST: {command: 'active', deprecated: true},
210
175
  },
211
176
  '/session/:sessionId/element/:elementId': {
212
177
  GET: {},
@@ -226,9 +191,6 @@ export const METHOD_MAP = /** @type {const} */ ({
226
191
  '/session/:sessionId/element/:elementId/click': {
227
192
  POST: {command: 'click'},
228
193
  },
229
- '/session/:sessionId/element/:elementId/submit': {
230
- POST: {command: 'submit', deprecated: true},
231
- },
232
194
  '/session/:sessionId/element/:elementId/text': {
233
195
  GET: {command: 'getText'},
234
196
  },
@@ -240,6 +202,7 @@ export const METHOD_MAP = /** @type {const} */ ({
240
202
  !util.hasValue(jsonObj.value) &&
241
203
  !util.hasValue(jsonObj.text) &&
242
204
  'we require one of "text" or "value" params',
205
+ // TODO: Appium 3 will accept only 'value'.
243
206
  optional: ['value', 'text'],
244
207
  // override the default argument constructor because of the special
245
208
  // logic here. Basically we want to accept either a value (old JSONWP)
@@ -250,9 +213,6 @@ export const METHOD_MAP = /** @type {const} */ ({
250
213
  },
251
214
  },
252
215
  },
253
- '/session/:sessionId/keys': {
254
- POST: {command: 'keys', payloadParams: {required: ['value']}, deprecated: true},
255
- },
256
216
  '/session/:sessionId/element/:elementId/name': {
257
217
  GET: {command: 'getName'},
258
218
  },
@@ -268,21 +228,9 @@ export const METHOD_MAP = /** @type {const} */ ({
268
228
  '/session/:sessionId/element/:elementId/attribute/:name': {
269
229
  GET: {command: 'getAttribute'},
270
230
  },
271
- '/session/:sessionId/element/:elementId/equals/:otherId': {
272
- GET: {command: 'equalsElement', deprecated: true},
273
- },
274
231
  '/session/:sessionId/element/:elementId/displayed': {
275
232
  GET: {command: 'elementDisplayed'},
276
233
  },
277
- '/session/:sessionId/element/:elementId/location': {
278
- GET: {command: 'getLocation', deprecated: true},
279
- },
280
- '/session/:sessionId/element/:elementId/location_in_view': {
281
- GET: {command: 'getLocationInView', deprecated: true},
282
- },
283
- '/session/:sessionId/element/:elementId/size': {
284
- GET: {command: 'getSize', deprecated: true},
285
- },
286
234
  '/session/:sessionId/element/:elementId/shadow': {
287
235
  GET: {command: 'elementShadowRoot'},
288
236
  },
@@ -301,12 +249,8 @@ export const METHOD_MAP = /** @type {const} */ ({
301
249
  '/session/:sessionId/element/:elementId/css/:propertyName': {
302
250
  GET: {command: 'getCssProperty'},
303
251
  },
304
- '/session/:sessionId/orientation': {
305
- GET: {command: 'getOrientation'},
306
- POST: {
307
- command: 'setOrientation',
308
- payloadParams: {required: ['orientation']},
309
- },
252
+ '/session/:sessionId/element/:elementId/property/:name': {
253
+ GET: {command: 'getProperty'},
310
254
  },
311
255
  // w3c v2 https://www.w3.org/TR/webdriver2/#get-computed-role
312
256
  'session/:sessionId/element/:elementId/computedrole': {
@@ -316,10 +260,336 @@ export const METHOD_MAP = /** @type {const} */ ({
316
260
  'session/:sessionId/element/:elementId/computedlabel': {
317
261
  GET: {command: 'getComputedLabel'},
318
262
  },
263
+ '/session/:sessionId/actions': {
264
+ POST: {command: 'performActions', payloadParams: {required: ['actions']}},
265
+ DELETE: {command: 'releaseActions'},
266
+ },
267
+ '/session/:sessionId/alert/text': {
268
+ GET: {command: 'getAlertText'},
269
+ POST: {
270
+ command: 'setAlertText',
271
+ payloadParams: SET_ALERT_TEXT_PAYLOAD_PARAMS,
272
+ },
273
+ },
274
+ '/session/:sessionId/alert/accept': {
275
+ POST: {command: 'postAcceptAlert'},
276
+ },
277
+ '/session/:sessionId/alert/dismiss': {
278
+ POST: {command: 'postDismissAlert'},
279
+ },
280
+ '/session/:sessionId/element/:elementId/rect': {
281
+ GET: {command: 'getElementRect'},
282
+ },
283
+ '/session/:sessionId/execute/sync': {
284
+ POST: {command: 'execute', payloadParams: {required: ['script', 'args']}},
285
+ },
286
+ '/session/:sessionId/execute/async': {
287
+ POST: {
288
+ command: 'executeAsync',
289
+ payloadParams: {required: ['script', 'args']},
290
+ },
291
+ },
292
+ '/session/:sessionId/element/:elementId/screenshot': {
293
+ GET: {command: 'getElementScreenshot'},
294
+ },
295
+ '/session/:sessionId/window/rect': {
296
+ GET: {command: 'getWindowRect'},
297
+ POST: {
298
+ command: 'setWindowRect',
299
+ payloadParams: {optional: ['x', 'y', 'width', 'height']},
300
+ },
301
+ },
302
+
303
+ //
304
+ // Appium specific
305
+ //
306
+ '/session/:sessionId/ime/available_engines': {
307
+ GET: {command: 'availableIMEEngines'},
308
+ },
309
+ '/session/:sessionId/ime/active_engine': {
310
+ GET: {command: 'getActiveIMEEngine'},
311
+ },
312
+ '/session/:sessionId/ime/activated': {
313
+ GET: {command: 'isIMEActivated'},
314
+ },
315
+ '/session/:sessionId/ime/deactivate': {
316
+ POST: {command: 'deactivateIMEEngine'},
317
+ },
318
+ '/session/:sessionId/ime/activate': {
319
+ POST: {command: 'activateIMEEngine', payloadParams: {required: ['engine']}},
320
+ },
319
321
  '/session/:sessionId/rotation': {
320
322
  GET: {command: 'getRotation'},
321
323
  POST: {command: 'setRotation', payloadParams: {required: ['x', 'y', 'z']}},
322
324
  },
325
+ '/session/:sessionId/location': {
326
+ GET: {command: 'getGeoLocation'},
327
+ POST: {command: 'setGeoLocation', payloadParams: {required: ['location']}},
328
+ },
329
+ '/session/:sessionId/orientation': {
330
+ GET: {command: 'getOrientation'},
331
+ POST: {
332
+ command: 'setOrientation',
333
+ payloadParams: {required: ['orientation']}
334
+ },
335
+ },
336
+ '/session/:sessionId/context': {
337
+ GET: {command: 'getCurrentContext'},
338
+ POST: {command: 'setContext', payloadParams: {required: ['name']}},
339
+ },
340
+ '/session/:sessionId/contexts': {
341
+ GET: {command: 'getContexts'},
342
+ },
343
+ '/session/:sessionId/network_connection': {
344
+ GET: {command: 'getNetworkConnection'},
345
+ POST: {
346
+ command: 'setNetworkConnection',
347
+ payloadParams: {unwrap: 'parameters', required: ['type']},
348
+ },
349
+ },
350
+ '/session/:sessionId/receive_async_response': {
351
+ POST: {
352
+ command: 'receiveAsyncResponse',
353
+ payloadParams: {required: ['status', 'value']},
354
+ },
355
+ },
356
+ '/appium/sessions': {
357
+ GET: {command: 'getAppiumSessions'},
358
+ },
359
+ '/session/:sessionId/appium/capabilities': {
360
+ GET: {command: 'getAppiumSessionCapabilities'}
361
+ },
362
+ '/session/:sessionId/appium/device/system_time': {
363
+ GET: {command: 'getDeviceTime', payloadParams: {optional: ['format']}},
364
+ POST: {command: 'getDeviceTime', payloadParams: {optional: ['format']}},
365
+ },
366
+ // #region Applications Management
367
+ '/session/:sessionId/appium/device/install_app': {
368
+ POST: {
369
+ command: 'installApp',
370
+ payloadParams: {
371
+ required: ['appPath'],
372
+ optional: ['options'],
373
+ },
374
+ },
375
+ },
376
+ '/session/:sessionId/appium/device/activate_app': {
377
+ POST: {
378
+ command: 'activateApp',
379
+ payloadParams: {
380
+ required: [['appId'], ['bundleId']],
381
+ optional: ['options'],
382
+ },
383
+ },
384
+ },
385
+ '/session/:sessionId/appium/device/remove_app': {
386
+ POST: {
387
+ command: 'removeApp',
388
+ payloadParams: {
389
+ required: [['appId'], ['bundleId']],
390
+ optional: ['options'],
391
+ },
392
+ },
393
+ },
394
+ '/session/:sessionId/appium/device/terminate_app': {
395
+ POST: {
396
+ command: 'terminateApp',
397
+ payloadParams: {
398
+ required: [['appId'], ['bundleId']],
399
+ optional: ['options'],
400
+ },
401
+ },
402
+ },
403
+ '/session/:sessionId/appium/device/app_installed': {
404
+ POST: {
405
+ command: 'isAppInstalled',
406
+ payloadParams: {
407
+ required: [['appId'], ['bundleId']],
408
+ },
409
+ },
410
+ },
411
+ '/session/:sessionId/appium/device/app_state': {
412
+ GET: {
413
+ command: 'queryAppState',
414
+ payloadParams: {
415
+ required: [['appId'], ['bundleId']],
416
+ },
417
+ },
418
+ POST: {
419
+ command: 'queryAppState',
420
+ payloadParams: {
421
+ required: [['appId'], ['bundleId']],
422
+ },
423
+ deprecated: true,
424
+ },
425
+ },
426
+ // #endregion
427
+ '/session/:sessionId/appium/device/hide_keyboard': {
428
+ POST: {
429
+ command: 'hideKeyboard',
430
+ payloadParams: {optional: ['strategy', 'key', 'keyCode', 'keyName']},
431
+ },
432
+ },
433
+ '/session/:sessionId/appium/device/is_keyboard_shown': {
434
+ GET: {command: 'isKeyboardShown'},
435
+ },
436
+ '/session/:sessionId/appium/device/push_file': {
437
+ POST: {command: 'pushFile', payloadParams: {required: ['path', 'data']}},
438
+ },
439
+ '/session/:sessionId/appium/device/pull_file': {
440
+ POST: {command: 'pullFile', payloadParams: {required: ['path']}},
441
+ },
442
+ '/session/:sessionId/appium/device/pull_folder': {
443
+ POST: {command: 'pullFolder', payloadParams: {required: ['path']}},
444
+ },
445
+ '/session/:sessionId/appium/settings': {
446
+ POST: {command: 'updateSettings', payloadParams: {required: ['settings']}},
447
+ GET: {command: 'getSettings'},
448
+ },
449
+ '/session/:sessionId/appium/events': {
450
+ POST: {command: 'getLogEvents', payloadParams: {optional: ['type']}},
451
+ },
452
+ '/session/:sessionId/appium/log_event': {
453
+ POST: {
454
+ command: 'logCustomEvent',
455
+ payloadParams: {required: ['vendor', 'event']},
456
+ },
457
+ },
458
+ // #region Inspector
459
+ '/session/:sessionId/appium/commands': {
460
+ GET: {command: 'listCommands'},
461
+ },
462
+ '/session/:sessionId/appium/extensions': {
463
+ GET: {command: 'listExtensions'},
464
+ },
465
+ // #endregion
466
+
467
+ //
468
+ // 3rd party vendor/protcol support
469
+ //
470
+ // #region Selenium/Chromium browsers
471
+ '/session/:sessionId/se/log': {
472
+ POST: {command: 'getLog', payloadParams: {required: ['type']}},
473
+ },
474
+ '/session/:sessionId/se/log/types': {
475
+ GET: {command: 'getLogTypes'},
476
+ },
477
+ // #endregion
478
+
479
+ // #region chromium devtools
480
+ // https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/server/http_handler.cc
481
+ '/session/:sessionId/:vendor/cdp/execute': {
482
+ POST: {command: 'executeCdp', payloadParams: {required: ['cmd', 'params']}},
483
+ },
484
+ // #endregion
485
+
486
+ // #region Webauthn
487
+ // https://www.w3.org/TR/webauthn-2/#sctn-automation-add-virtual-authenticator
488
+ '/session/:sessionId/webauthn/authenticator': {
489
+ POST: {
490
+ command: 'addVirtualAuthenticator',
491
+ payloadParams: {
492
+ required: ['protocol', 'transport'],
493
+ optional: ['hasResidentKey', 'hasUserVerification', 'isUserConsenting', 'isUserVerified'],
494
+ },
495
+ },
496
+ },
497
+ '/session/:sessionId/webauthn/authenticator/:authenticatorId': {
498
+ DELETE: {
499
+ command: 'removeVirtualAuthenticator',
500
+ },
501
+ },
502
+ '/session/:sessionId/webauthn/authenticator/:authenticatorId/credential': {
503
+ POST: {
504
+ command: 'addAuthCredential',
505
+ payloadParams: {
506
+ required: ['credentialId', 'isResidentCredential', 'rpId', 'privateKey'],
507
+ optional: ['userHandle', 'signCount'],
508
+ },
509
+ },
510
+ },
511
+ '/session/:sessionId/webauthn/authenticator/:authenticatorId/credentials': {
512
+ GET: {command: 'getAuthCredential'},
513
+ DELETE: {command: 'removeAllAuthCredentials'},
514
+ },
515
+ '/session/:sessionId/webauthn/authenticator/:authenticatorId/credentials/:credentialId': {
516
+ DELETE: {command: 'removeAuthCredential'},
517
+ },
518
+ '/session/:sessionId/webauthn/authenticator/:authenticatorId/uv': {
519
+ POST: {
520
+ command: 'setUserAuthVerified',
521
+ payloadParams: {
522
+ required: ['isUserVerified'],
523
+ },
524
+ },
525
+ },
526
+ // #endregion
527
+
528
+ //
529
+ // Endpoints deprecated entirely
530
+ //
531
+ // #region MJSONWP
532
+ '/sessions': {
533
+ GET: {command: 'getSessions', deprecated: true},
534
+ },
535
+ '/session/:sessionId/timeouts/async_script': {
536
+ POST: {command: 'asyncScriptTimeout', payloadParams: {required: ['ms']}, deprecated: true},
537
+ },
538
+ '/session/:sessionId/timeouts/implicit_wait': {
539
+ POST: {command: 'implicitWait', payloadParams: {required: ['ms']}, deprecated: true},
540
+ },
541
+ '/session/:sessionId/window_handle': {
542
+ GET: {command: 'getWindowHandle', deprecated: true},
543
+ },
544
+ // Only 'window/handles' exists in W3C WebDriver spec.
545
+ '/session/:sessionId/window/handle': {
546
+ GET: {command: 'getWindowHandle', deprecated: true},
547
+ },
548
+ '/session/:sessionId/window_handles': {
549
+ GET: {command: 'getWindowHandles', deprecated: true},
550
+ },
551
+ '/session/:sessionId/execute': {
552
+ POST: {
553
+ command: 'execute',
554
+ payloadParams: {required: ['script', 'args']},
555
+ deprecated: true
556
+ },
557
+ },
558
+ '/session/:sessionId/execute_async': {
559
+ POST: {
560
+ command: 'executeAsync',
561
+ payloadParams: {required: ['script', 'args']},
562
+ deprecated: true
563
+ },
564
+ },
565
+ '/session/:sessionId/window/:windowhandle/size': {
566
+ GET: {command: 'getWindowSize', deprecated: true},
567
+ },
568
+ '/session/:sessionId/window/:windowhandle/position': {
569
+ POST: {deprecated: true},
570
+ GET: {deprecated: true},
571
+ },
572
+ '/session/:sessionId/window/:windowhandle/maximize': {
573
+ POST: {command: 'maximizeWindow', deprecated: true},
574
+ },
575
+ '/session/:sessionId/element/:elementId/submit': {
576
+ POST: {command: 'submit', deprecated: true},
577
+ },
578
+ '/session/:sessionId/keys': {
579
+ POST: {command: 'keys', payloadParams: {required: ['value']}, deprecated: true},
580
+ },
581
+ '/session/:sessionId/element/:elementId/equals/:otherId': {
582
+ GET: {command: 'equalsElement', deprecated: true},
583
+ },
584
+ '/session/:sessionId/element/:elementId/location': {
585
+ GET: {command: 'getLocation', deprecated: true},
586
+ },
587
+ '/session/:sessionId/element/:elementId/location_in_view': {
588
+ GET: {command: 'getLocationInView', deprecated: true},
589
+ },
590
+ '/session/:sessionId/element/:elementId/size': {
591
+ GET: {command: 'getSize', deprecated: true},
592
+ },
323
593
  '/session/:sessionId/moveto': {
324
594
  POST: {
325
595
  command: 'moveTo',
@@ -355,11 +625,7 @@ export const METHOD_MAP = /** @type {const} */ ({
355
625
  POST: {deprecated: true},
356
626
  },
357
627
  '/session/:sessionId/touch/doubleclick': {
358
- POST: {},
359
- },
360
- '/session/:sessionId/actions': {
361
- POST: {command: 'performActions', payloadParams: {required: ['actions']}},
362
- DELETE: {command: 'releaseActions'},
628
+ POST: {deprecated: true},
363
629
  },
364
630
  '/session/:sessionId/touch/longclick': {
365
631
  POST: {
@@ -377,10 +643,6 @@ export const METHOD_MAP = /** @type {const} */ ({
377
643
  deprecated: true,
378
644
  },
379
645
  },
380
- '/session/:sessionId/location': {
381
- GET: {command: 'getGeoLocation'},
382
- POST: {command: 'setGeoLocation', payloadParams: {required: ['location']}},
383
- },
384
646
  '/session/:sessionId/local_storage': {
385
647
  GET: {deprecated: true},
386
648
  POST: {deprecated: true},
@@ -405,46 +667,32 @@ export const METHOD_MAP = /** @type {const} */ ({
405
667
  '/session/:sessionId/session_storage/size': {
406
668
  GET: {deprecated: true},
407
669
  },
408
- // Selenium 4 clients
409
- '/session/:sessionId/se/log': {
410
- POST: {command: 'getLog', payloadParams: {required: ['type']}},
411
- },
412
- // Selenium 4 clients
413
- '/session/:sessionId/se/log/types': {
414
- GET: {command: 'getLogTypes'},
415
- },
416
- // mjsonwire, appium clients
417
- '/session/:sessionId/log': {
418
- POST: {command: 'getLog', payloadParams: {required: ['type']}},
670
+ '/session/:sessionId/application_cache/status': {
671
+ GET: {deprecated: true},
419
672
  },
420
- // mjsonwire, appium clients
421
- '/session/:sessionId/log/types': {
422
- GET: {command: 'getLogTypes'},
673
+ '/session/:sessionId/alert_text': {
674
+ GET: {command: 'getAlertText', deprecated: true},
675
+ POST: {
676
+ command: 'setAlertText',
677
+ payloadParams: SET_ALERT_TEXT_PAYLOAD_PARAMS,
678
+ deprecated: true
679
+ },
423
680
  },
424
- '/session/:sessionId/application_cache/status': {
425
- GET: {},
681
+ '/session/:sessionId/accept_alert': {
682
+ POST: {command: 'postAcceptAlert', deprecated: true},
426
683
  },
427
-
428
- //
429
- // mjsonwire
430
- //
431
- '/session/:sessionId/context': {
432
- GET: {command: 'getCurrentContext'},
433
- POST: {command: 'setContext', payloadParams: {required: ['name']}},
684
+ '/session/:sessionId/dismiss_alert': {
685
+ POST: {command: 'postDismissAlert', deprecated: true},
434
686
  },
435
- '/session/:sessionId/contexts': {
436
- GET: {command: 'getContexts'},
687
+ // Pre-W3C endpoint for element screenshot
688
+ '/session/:sessionId/screenshot/:elementId': {
689
+ GET: {command: 'getElementScreenshot', deprecated: true},
437
690
  },
691
+ // #endregion
692
+ // #region Appium specific
438
693
  '/session/:sessionId/element/:elementId/pageIndex': {
439
694
  GET: {command: 'getPageIndex', deprecated: true},
440
695
  },
441
- '/session/:sessionId/network_connection': {
442
- GET: {command: 'getNetworkConnection'},
443
- POST: {
444
- command: 'setNetworkConnection',
445
- payloadParams: {unwrap: 'parameters', required: ['type']},
446
- },
447
- },
448
696
  '/session/:sessionId/touch/perform': {
449
697
  POST: {
450
698
  command: 'performTouch',
@@ -459,19 +707,9 @@ export const METHOD_MAP = /** @type {const} */ ({
459
707
  deprecated: true,
460
708
  },
461
709
  },
462
- '/session/:sessionId/receive_async_response': {
463
- POST: {
464
- command: 'receiveAsyncResponse',
465
- payloadParams: {required: ['status', 'value']},
466
- },
467
- },
468
710
  '/session/:sessionId/appium/device/shake': {
469
711
  POST: {command: 'mobileShake', deprecated: true},
470
712
  },
471
- '/session/:sessionId/appium/device/system_time': {
472
- GET: {command: 'getDeviceTime', payloadParams: {optional: ['format']}},
473
- POST: {command: 'getDeviceTime', payloadParams: {optional: ['format']}},
474
- },
475
713
  '/session/:sessionId/appium/device/lock': {
476
714
  POST: {command: 'lock', payloadParams: {optional: ['seconds']}, deprecated: true},
477
715
  },
@@ -575,85 +813,6 @@ export const METHOD_MAP = /** @type {const} */ ({
575
813
  '/session/:sessionId/appium/device/current_package': {
576
814
  GET: {command: 'getCurrentPackage', deprecated: true},
577
815
  },
578
- //region Applications Management
579
- '/session/:sessionId/appium/device/install_app': {
580
- POST: {
581
- command: 'installApp',
582
- payloadParams: {
583
- required: ['appPath'],
584
- optional: ['options'],
585
- },
586
- },
587
- },
588
- '/session/:sessionId/appium/device/activate_app': {
589
- POST: {
590
- command: 'activateApp',
591
- payloadParams: {
592
- required: [['appId'], ['bundleId']],
593
- optional: ['options'],
594
- },
595
- },
596
- },
597
- '/session/:sessionId/appium/device/remove_app': {
598
- POST: {
599
- command: 'removeApp',
600
- payloadParams: {
601
- required: [['appId'], ['bundleId']],
602
- optional: ['options'],
603
- },
604
- },
605
- },
606
- '/session/:sessionId/appium/device/terminate_app': {
607
- POST: {
608
- command: 'terminateApp',
609
- payloadParams: {
610
- required: [['appId'], ['bundleId']],
611
- optional: ['options'],
612
- },
613
- },
614
- },
615
- '/session/:sessionId/appium/device/app_installed': {
616
- POST: {
617
- command: 'isAppInstalled',
618
- payloadParams: {
619
- required: [['appId'], ['bundleId']],
620
- },
621
- },
622
- },
623
- '/session/:sessionId/appium/device/app_state': {
624
- GET: {
625
- command: 'queryAppState',
626
- payloadParams: {
627
- required: [['appId'], ['bundleId']],
628
- },
629
- },
630
- POST: {
631
- command: 'queryAppState',
632
- payloadParams: {
633
- required: [['appId'], ['bundleId']],
634
- },
635
- deprecated: true,
636
- },
637
- },
638
- //endregion
639
- '/session/:sessionId/appium/device/hide_keyboard': {
640
- POST: {
641
- command: 'hideKeyboard',
642
- payloadParams: {optional: ['strategy', 'key', 'keyCode', 'keyName']},
643
- },
644
- },
645
- '/session/:sessionId/appium/device/is_keyboard_shown': {
646
- GET: {command: 'isKeyboardShown'},
647
- },
648
- '/session/:sessionId/appium/device/push_file': {
649
- POST: {command: 'pushFile', payloadParams: {required: ['path', 'data']}},
650
- },
651
- '/session/:sessionId/appium/device/pull_file': {
652
- POST: {command: 'pullFile', payloadParams: {required: ['path']}},
653
- },
654
- '/session/:sessionId/appium/device/pull_folder': {
655
- POST: {command: 'pullFolder', payloadParams: {required: ['path']}},
656
- },
657
816
  '/session/:sessionId/appium/device/toggle_airplane_mode': {
658
817
  POST: {command: 'toggleFlightMode', deprecated: true},
659
818
  },
@@ -743,10 +902,6 @@ export const METHOD_MAP = /** @type {const} */ ({
743
902
  deprecated: true,
744
903
  },
745
904
  },
746
- '/session/:sessionId/appium/settings': {
747
- POST: {command: 'updateSettings', payloadParams: {required: ['settings']}},
748
- GET: {command: 'getSettings'},
749
- },
750
905
  '/session/:sessionId/appium/receive_async_response': {
751
906
  POST: {
752
907
  command: 'receiveAsyncResponse',
@@ -754,94 +909,6 @@ export const METHOD_MAP = /** @type {const} */ ({
754
909
  deprecated: true,
755
910
  },
756
911
  },
757
- '/session/:sessionId/appium/events': {
758
- POST: {command: 'getLogEvents', payloadParams: {optional: ['type']}},
759
- },
760
- '/session/:sessionId/appium/log_event': {
761
- POST: {
762
- command: 'logCustomEvent',
763
- payloadParams: {required: ['vendor', 'event']},
764
- },
765
- },
766
-
767
- /*
768
- * The W3C spec has some changes to the wire protocol.
769
- * https://w3c.github.io/webdriver/webdriver-spec.html
770
- * Begin to add those changes here, keeping the old version
771
- * since clients still implement them.
772
- */
773
- // MJSONWP
774
- '/session/:sessionId/alert_text': {
775
- GET: {command: 'getAlertText'},
776
- POST: {
777
- command: 'setAlertText',
778
- payloadParams: SET_ALERT_TEXT_PAYLOAD_PARAMS,
779
- },
780
- },
781
- // MJSONWP
782
- '/session/:sessionId/accept_alert': {
783
- POST: {command: 'postAcceptAlert'},
784
- },
785
- // MJSONWP
786
- '/session/:sessionId/dismiss_alert': {
787
- POST: {command: 'postDismissAlert'},
788
- },
789
- // https://w3c.github.io/webdriver/webdriver-spec.html#user-prompts
790
- '/session/:sessionId/alert/text': {
791
- GET: {command: 'getAlertText'},
792
- POST: {
793
- command: 'setAlertText',
794
- payloadParams: SET_ALERT_TEXT_PAYLOAD_PARAMS,
795
- },
796
- },
797
- '/session/:sessionId/alert/accept': {
798
- POST: {command: 'postAcceptAlert'},
799
- },
800
- '/session/:sessionId/alert/dismiss': {
801
- POST: {command: 'postDismissAlert'},
802
- },
803
- // https://w3c.github.io/webdriver/webdriver-spec.html#get-element-rect
804
- '/session/:sessionId/element/:elementId/rect': {
805
- GET: {command: 'getElementRect'},
806
- },
807
- '/session/:sessionId/execute/sync': {
808
- POST: {command: 'execute', payloadParams: {required: ['script', 'args']}},
809
- },
810
- '/session/:sessionId/execute/async': {
811
- POST: {
812
- command: 'executeAsync',
813
- payloadParams: {required: ['script', 'args']},
814
- },
815
- },
816
- // Pre-W3C endpoint for element screenshot
817
- '/session/:sessionId/screenshot/:elementId': {
818
- GET: {command: 'getElementScreenshot'},
819
- },
820
- '/session/:sessionId/element/:elementId/screenshot': {
821
- GET: {command: 'getElementScreenshot'},
822
- },
823
- '/session/:sessionId/window/rect': {
824
- GET: {command: 'getWindowRect'},
825
- POST: {
826
- command: 'setWindowRect',
827
- payloadParams: {optional: ['x', 'y', 'width', 'height']},
828
- },
829
- },
830
- '/session/:sessionId/window/maximize': {
831
- POST: {command: 'maximizeWindow'},
832
- },
833
- '/session/:sessionId/window/minimize': {
834
- POST: {command: 'minimizeWindow'},
835
- },
836
- '/session/:sessionId/window/fullscreen': {
837
- POST: {command: 'fullScreenWindow'},
838
- },
839
- '/session/:sessionId/window/new': {
840
- POST: {command: 'createNewWindow', payloadParams: {optional: ['type']}},
841
- },
842
- '/session/:sessionId/element/:elementId/property/:name': {
843
- GET: {command: 'getProperty'},
844
- },
845
912
  '/session/:sessionId/appium/device/set_clipboard': {
846
913
  POST: {
847
914
  command: 'setClipboard',
@@ -861,61 +928,15 @@ export const METHOD_MAP = /** @type {const} */ ({
861
928
  deprecated: true,
862
929
  },
863
930
  },
864
-
865
- // chromium devtools
866
- // https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/server/http_handler.cc
867
- '/session/:sessionId/:vendor/cdp/execute': {
868
- POST: {command: 'executeCdp', payloadParams: {required: ['cmd', 'params']}},
869
- },
870
-
871
- //region Webauthn
872
- // https://www.w3.org/TR/webauthn-2/#sctn-automation-add-virtual-authenticator
873
-
874
- '/session/:sessionId/webauthn/authenticator': {
875
- POST: {
876
- command: 'addVirtualAuthenticator',
877
- payloadParams: {
878
- required: ['protocol', 'transport'],
879
- optional: ['hasResidentKey', 'hasUserVerification', 'isUserConsenting', 'isUserVerified'],
880
- },
881
- },
882
- },
883
-
884
- '/session/:sessionId/webauthn/authenticator/:authenticatorId': {
885
- DELETE: {
886
- command: 'removeVirtualAuthenticator',
887
- },
888
- },
889
-
890
- '/session/:sessionId/webauthn/authenticator/:authenticatorId/credential': {
891
- POST: {
892
- command: 'addAuthCredential',
893
- payloadParams: {
894
- required: ['credentialId', 'isResidentCredential', 'rpId', 'privateKey'],
895
- optional: ['userHandle', 'signCount'],
896
- },
897
- },
898
- },
899
-
900
- '/session/:sessionId/webauthn/authenticator/:authenticatorId/credentials': {
901
- GET: {command: 'getAuthCredential'},
902
- DELETE: {command: 'removeAllAuthCredentials'},
903
- },
904
-
905
- '/session/:sessionId/webauthn/authenticator/:authenticatorId/credentials/:credentialId': {
906
- DELETE: {command: 'removeAuthCredential'},
931
+ // #endregion
932
+ // #region JSONWP
933
+ '/session/:sessionId/log': {
934
+ POST: {command: 'getLog', payloadParams: {required: ['type']}, deprecated: true},
907
935
  },
908
-
909
- '/session/:sessionId/webauthn/authenticator/:authenticatorId/uv': {
910
- POST: {
911
- command: 'setUserAuthVerified',
912
- payloadParams: {
913
- required: ['isUserVerified'],
914
- },
915
- },
936
+ '/session/:sessionId/log/types': {
937
+ GET: {command: 'getLogTypes', deprecated: true},
916
938
  },
917
-
918
- //endregion
939
+ // #endregion
919
940
  });
920
941
 
921
942
  // driver command names
@@ -926,7 +947,7 @@ export const ALL_COMMANDS = _.flatMap(_.values(METHOD_MAP).map(_.values))
926
947
  /**
927
948
  *
928
949
  * @param {string} endpoint
929
- * @param {import('@appium/types').HTTPMethod} method
950
+ * @param {import('@appium/types').HTTPMethod} [method]
930
951
  * @param {string} [basePath=DEFAULT_BASE_PATH]
931
952
  * @returns {string|undefined}
932
953
  */
@@ -944,23 +965,47 @@ export function routeToCommandName(endpoint, method, basePath = DEFAULT_BASE_PAT
944
965
  throw new Error(`'${endpoint}' cannot be translated to a command name: ${err.message}`);
945
966
  }
946
967
 
968
+ const normalizedMethod = _.toUpper(method);
969
+ const cacheKey = toCommandNameCacheKey(normalizedPathname, normalizedMethod);
970
+ if (COMMAND_NAMES_CACHE.has(cacheKey)) {
971
+ return COMMAND_NAMES_CACHE.get(cacheKey) || undefined;
972
+ }
973
+
947
974
  /** @type {string[]} */
948
975
  const possiblePathnames = [];
949
976
  if (!normalizedPathname.startsWith('/session/')) {
950
977
  possiblePathnames.push(`/session/any-session-id${normalizedPathname}`);
951
978
  }
952
979
  possiblePathnames.push(normalizedPathname);
953
- const normalizedMethod = _.toUpper(method);
954
980
  for (const [routePath, routeSpec] of _.toPairs(METHOD_MAP)) {
955
981
  const routeMatcher = match(routePath);
956
982
  if (possiblePathnames.some((pp) => routeMatcher(pp))) {
957
- const commandName = routeSpec?.[normalizedMethod]?.command;
983
+ const commandForAnyMethod = () => _.first(
984
+ (_.keys(routeSpec) ?? []).map((key) => routeSpec[key]?.command)
985
+ );
986
+ const commandName = normalizedMethod
987
+ ? routeSpec?.[normalizedMethod]?.command
988
+ : commandForAnyMethod();
958
989
  if (commandName) {
990
+ COMMAND_NAMES_CACHE.set(cacheKey, commandName);
959
991
  return commandName;
960
992
  }
961
993
  }
962
994
  }
995
+ // storing an empty string means we did not find any match for this set of arguments
996
+ // and we want to cache this result
997
+ COMMAND_NAMES_CACHE.set(cacheKey, '');
998
+ }
999
+
1000
+ /**
1001
+ *
1002
+ * @param {string} endpoint
1003
+ * @param {string} [method]
1004
+ * @returns {string}
1005
+ */
1006
+ function toCommandNameCacheKey(endpoint, method) {
1007
+ return `${endpoint}:${method ?? ''}`;
963
1008
  }
964
1009
 
965
1010
  // driver commands that do not require a session to already exist
966
- export const NO_SESSION_ID_COMMANDS = ['createSession', 'getStatus', 'getSessions'];
1011
+ export const NO_SESSION_ID_COMMANDS = ['createSession', 'getStatus', 'getSessions', 'getAppiumSessions'];