@appium/base-driver 8.2.4 → 8.4.0

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 (206) hide show
  1. package/build/lib/basedriver/capabilities.d.ts +80 -0
  2. package/build/lib/basedriver/capabilities.d.ts.map +1 -0
  3. package/build/lib/basedriver/capabilities.js +12 -13
  4. package/build/lib/basedriver/commands/event.d.ts +9 -0
  5. package/build/lib/basedriver/commands/event.d.ts.map +1 -0
  6. package/build/lib/basedriver/commands/event.js +21 -23
  7. package/build/lib/basedriver/commands/find.d.ts +11 -0
  8. package/build/lib/basedriver/commands/find.d.ts.map +1 -0
  9. package/build/lib/basedriver/commands/find.js +41 -43
  10. package/build/lib/basedriver/commands/index.d.ts +8 -0
  11. package/build/lib/basedriver/commands/index.d.ts.map +1 -0
  12. package/build/lib/basedriver/commands/index.js +17 -16
  13. package/build/lib/basedriver/commands/log.d.ts +12 -0
  14. package/build/lib/basedriver/commands/log.d.ts.map +1 -0
  15. package/build/lib/basedriver/commands/log.js +23 -30
  16. package/build/lib/basedriver/commands/session.d.ts +11 -0
  17. package/build/lib/basedriver/commands/session.d.ts.map +1 -0
  18. package/build/lib/basedriver/commands/session.js +21 -158
  19. package/build/lib/basedriver/commands/settings.d.ts +10 -0
  20. package/build/lib/basedriver/commands/settings.d.ts.map +1 -0
  21. package/build/lib/basedriver/commands/settings.js +18 -22
  22. package/build/lib/basedriver/commands/timeout.d.ts +8 -0
  23. package/build/lib/basedriver/commands/timeout.d.ts.map +1 -0
  24. package/build/lib/basedriver/commands/timeout.js +118 -144
  25. package/build/lib/basedriver/core.d.ts +235 -0
  26. package/build/lib/basedriver/core.d.ts.map +1 -0
  27. package/build/lib/basedriver/core.js +283 -0
  28. package/build/lib/basedriver/desired-caps.d.ts +5 -0
  29. package/build/lib/basedriver/desired-caps.d.ts.map +1 -0
  30. package/build/lib/basedriver/desired-caps.js +2 -4
  31. package/build/lib/basedriver/device-settings.d.ts +32 -0
  32. package/build/lib/basedriver/device-settings.d.ts.map +1 -0
  33. package/build/lib/basedriver/device-settings.js +33 -15
  34. package/build/lib/basedriver/driver.d.ts +83 -0
  35. package/build/lib/basedriver/driver.d.ts.map +1 -0
  36. package/build/lib/basedriver/driver.js +104 -257
  37. package/build/lib/basedriver/helpers.d.ts +132 -0
  38. package/build/lib/basedriver/helpers.d.ts.map +1 -0
  39. package/build/lib/basedriver/helpers.js +24 -10
  40. package/build/lib/basedriver/logger.d.ts +3 -0
  41. package/build/lib/basedriver/logger.d.ts.map +1 -0
  42. package/build/lib/basedriver/logger.js +2 -4
  43. package/build/lib/constants.d.ts +9 -0
  44. package/build/lib/constants.d.ts.map +1 -0
  45. package/build/lib/constants.js +2 -4
  46. package/build/lib/express/crash.d.ts +3 -0
  47. package/build/lib/express/crash.d.ts.map +1 -0
  48. package/build/lib/express/crash.js +2 -4
  49. package/build/lib/express/express-logging.d.ts +3 -0
  50. package/build/lib/express/express-logging.d.ts.map +1 -0
  51. package/build/lib/express/express-logging.js +3 -5
  52. package/build/lib/express/idempotency.d.ts +2 -0
  53. package/build/lib/express/idempotency.d.ts.map +1 -0
  54. package/build/lib/express/idempotency.js +3 -5
  55. package/build/lib/express/logger.d.ts +3 -0
  56. package/build/lib/express/logger.d.ts.map +1 -0
  57. package/build/lib/express/logger.js +2 -4
  58. package/build/lib/express/middleware.d.ts +9 -0
  59. package/build/lib/express/middleware.d.ts.map +1 -0
  60. package/build/lib/express/middleware.js +2 -4
  61. package/build/lib/express/server.d.ts +10 -0
  62. package/build/lib/express/server.d.ts.map +1 -0
  63. package/build/lib/express/server.js +2 -4
  64. package/build/lib/express/static.d.ts +6 -0
  65. package/build/lib/express/static.d.ts.map +1 -0
  66. package/build/lib/express/static.js +2 -4
  67. package/build/lib/express/websocket.d.ts +64 -0
  68. package/build/lib/express/websocket.d.ts.map +1 -0
  69. package/build/lib/express/websocket.js +2 -4
  70. package/build/lib/helpers/capabilities.d.ts +13 -0
  71. package/build/lib/helpers/capabilities.d.ts.map +1 -0
  72. package/build/lib/helpers/capabilities.js +77 -0
  73. package/build/lib/index.d.ts +183 -0
  74. package/build/lib/index.d.ts.map +1 -0
  75. package/build/lib/index.js +41 -25
  76. package/build/lib/jsonwp-proxy/protocol-converter.d.ts +48 -0
  77. package/build/lib/jsonwp-proxy/protocol-converter.d.ts.map +1 -0
  78. package/build/lib/jsonwp-proxy/protocol-converter.js +19 -15
  79. package/build/lib/jsonwp-proxy/proxy.d.ts +41 -0
  80. package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -0
  81. package/build/lib/jsonwp-proxy/proxy.js +20 -15
  82. package/build/lib/jsonwp-status/status.d.ts +159 -0
  83. package/build/lib/jsonwp-status/status.d.ts.map +1 -0
  84. package/build/lib/jsonwp-status/status.js +2 -4
  85. package/build/lib/protocol/errors.d.ts +310 -0
  86. package/build/lib/protocol/errors.d.ts.map +1 -0
  87. package/build/lib/protocol/errors.js +82 -5
  88. package/build/lib/protocol/helpers.d.ts +22 -0
  89. package/build/lib/protocol/helpers.d.ts.map +1 -0
  90. package/build/lib/protocol/helpers.js +2 -4
  91. package/build/lib/protocol/index.d.ts +16 -0
  92. package/build/lib/protocol/index.d.ts.map +1 -0
  93. package/build/lib/protocol/index.js +8 -10
  94. package/build/lib/protocol/protocol.d.ts +11 -0
  95. package/build/lib/protocol/protocol.d.ts.map +1 -0
  96. package/build/lib/protocol/protocol.js +38 -35
  97. package/build/lib/protocol/routes.d.ts +6 -0
  98. package/build/lib/protocol/routes.d.ts.map +1 -0
  99. package/build/lib/protocol/routes.js +84 -4
  100. package/build/lib/protocol/validators.d.ts +8 -0
  101. package/build/lib/protocol/validators.d.ts.map +1 -0
  102. package/build/lib/protocol/validators.js +2 -4
  103. package/build/test/basedriver/README.md +5 -0
  104. package/build/test/basedriver/driver-e2e-tests.js +2 -4
  105. package/build/test/basedriver/driver-tests.js +41 -19
  106. package/build/test/basedriver/index.js +2 -4
  107. package/build/test/e2e/basedriver/driver.e2e.spec.js +15 -0
  108. package/build/test/e2e/basedriver/helpers.e2e.spec.js +192 -0
  109. package/build/test/e2e/basedriver/websockets.e2e.spec.js +82 -0
  110. package/build/test/e2e/express/server.e2e.spec.js +159 -0
  111. package/build/test/e2e/jsonwp-proxy/proxy.e2e.spec.js +59 -0
  112. package/build/test/e2e/protocol/fake-driver.js +163 -0
  113. package/build/test/e2e/protocol/helpers.js +25 -0
  114. package/build/test/e2e/protocol/protocol.e2e.spec.js +1186 -0
  115. package/build/test/helpers.js +2 -4
  116. package/build/test/unit/basedriver/capabilities.spec.js +672 -0
  117. package/build/test/unit/basedriver/capability.spec.js +353 -0
  118. package/build/test/unit/basedriver/commands/event.spec.js +110 -0
  119. package/build/test/unit/basedriver/commands/log.spec.js +92 -0
  120. package/build/test/unit/basedriver/driver.spec.js +15 -0
  121. package/build/test/unit/basedriver/helpers.spec.js +151 -0
  122. package/build/test/unit/basedriver/timeout.spec.js +135 -0
  123. package/build/test/unit/express/server.spec.js +155 -0
  124. package/build/test/unit/express/static.spec.js +26 -0
  125. package/build/test/unit/jsonwp-proxy/mock-request.js +91 -0
  126. package/build/test/unit/jsonwp-proxy/protocol-converter.spec.js +171 -0
  127. package/build/test/unit/jsonwp-proxy/proxy.spec.js +292 -0
  128. package/build/test/unit/jsonwp-proxy/url.spec.js +165 -0
  129. package/build/test/unit/jsonwp-status/status.spec.js +34 -0
  130. package/build/test/unit/protocol/errors.spec.js +390 -0
  131. package/build/test/unit/protocol/routes.spec.js +80 -0
  132. package/build/test/unit/protocol/validator.spec.js +149 -0
  133. package/build/tsconfig.tsbuildinfo +1 -0
  134. package/lib/basedriver/capabilities.js +49 -10
  135. package/lib/basedriver/commands/event.js +49 -31
  136. package/lib/basedriver/commands/find.js +107 -45
  137. package/lib/basedriver/commands/index.js +25 -19
  138. package/lib/basedriver/commands/log.js +59 -34
  139. package/lib/basedriver/commands/session.js +39 -142
  140. package/lib/basedriver/commands/settings.js +32 -14
  141. package/lib/basedriver/commands/timeout.js +153 -154
  142. package/lib/basedriver/core.js +497 -0
  143. package/lib/basedriver/desired-caps.js +1 -1
  144. package/lib/basedriver/device-settings.js +57 -13
  145. package/lib/basedriver/driver.js +277 -375
  146. package/lib/basedriver/helpers.js +31 -13
  147. package/lib/express/express-logging.js +1 -1
  148. package/lib/express/idempotency.js +1 -1
  149. package/lib/helpers/capabilities.js +84 -0
  150. package/lib/index.js +17 -13
  151. package/lib/jsonwp-proxy/protocol-converter.js +14 -13
  152. package/lib/jsonwp-proxy/proxy.js +16 -12
  153. package/lib/protocol/errors.js +42 -42
  154. package/lib/protocol/index.js +4 -4
  155. package/lib/protocol/protocol.js +35 -32
  156. package/lib/protocol/routes.js +69 -1
  157. package/package.json +37 -24
  158. package/test/basedriver/README.md +5 -0
  159. package/test/basedriver/driver-e2e-tests.js +1 -1
  160. package/test/basedriver/driver-tests.js +43 -9
  161. package/build/lib/protocol/sessions-cache.js +0 -88
  162. package/build/test/basedriver/capabilities-specs.js +0 -632
  163. package/build/test/basedriver/capability-specs.js +0 -396
  164. package/build/test/basedriver/commands/event-specs.js +0 -112
  165. package/build/test/basedriver/commands/log-specs.js +0 -80
  166. package/build/test/basedriver/driver-e2e-specs.js +0 -17
  167. package/build/test/basedriver/driver-specs.js +0 -17
  168. package/build/test/basedriver/helpers-e2e-specs.js +0 -194
  169. package/build/test/basedriver/helpers-specs.js +0 -153
  170. package/build/test/basedriver/timeout-specs.js +0 -139
  171. package/build/test/basedriver/websockets-e2e-specs.js +0 -84
  172. package/build/test/express/server-e2e-specs.js +0 -156
  173. package/build/test/express/server-specs.js +0 -151
  174. package/build/test/express/static-specs.js +0 -23
  175. package/build/test/jsonwp-proxy/mock-request.js +0 -93
  176. package/build/test/jsonwp-proxy/protocol-converter-specs.js +0 -173
  177. package/build/test/jsonwp-proxy/proxy-e2e-specs.js +0 -61
  178. package/build/test/jsonwp-proxy/proxy-specs.js +0 -294
  179. package/build/test/jsonwp-proxy/url-specs.js +0 -167
  180. package/build/test/jsonwp-status/status-specs.js +0 -36
  181. package/build/test/protocol/errors-specs.js +0 -388
  182. package/build/test/protocol/fake-driver.js +0 -168
  183. package/build/test/protocol/helpers.js +0 -27
  184. package/build/test/protocol/protocol-e2e-specs.js +0 -1182
  185. package/build/test/protocol/routes-specs.js +0 -82
  186. package/build/test/protocol/validator-specs.js +0 -151
  187. package/index.d.ts +0 -386
  188. package/lib/protocol/sessions-cache.js +0 -74
  189. package/test/basedriver/capabilities-specs.js +0 -505
  190. package/test/basedriver/capability-specs.js +0 -409
  191. package/test/basedriver/commands/event-specs.js +0 -74
  192. package/test/basedriver/commands/log-specs.js +0 -70
  193. package/test/basedriver/driver-e2e-specs.js +0 -8
  194. package/test/basedriver/driver-specs.js +0 -8
  195. package/test/basedriver/fixtures/BadZippedApp.zip +0 -1
  196. package/test/basedriver/fixtures/FakeAndroidApp.apk +0 -1
  197. package/test/basedriver/fixtures/FakeAndroidApp.asd +0 -0
  198. package/test/basedriver/fixtures/FakeIOSApp.app +0 -1
  199. package/test/basedriver/fixtures/FakeIOSApp.app.zip +0 -0
  200. package/test/basedriver/fixtures/FakeIOSApp.ipa +0 -0
  201. package/test/basedriver/fixtures/custom-element-finder-bad.js +0 -5
  202. package/test/basedriver/fixtures/custom-element-finder.js +0 -29
  203. package/test/basedriver/helpers-e2e-specs.js +0 -187
  204. package/test/basedriver/helpers-specs.js +0 -137
  205. package/test/basedriver/timeout-specs.js +0 -133
  206. package/test/basedriver/websockets-e2e-specs.js +0 -75
@@ -1,74 +0,0 @@
1
- import LRU from 'lru-cache';
2
- import { logger } from '@appium/support';
3
- import { PROTOCOLS } from '../constants';
4
-
5
-
6
- const GENERIC_PROTOCOL = 'GENERIC';
7
- const mjsonwpLog = logger.getLogger('MJSONWP');
8
- const w3cLog = logger.getLogger('W3C');
9
- const genericProtocolLog = logger.getLogger(GENERIC_PROTOCOL);
10
-
11
-
12
- class SessionsCache {
13
- constructor (max) {
14
- this._cache = new LRU({ max });
15
- }
16
-
17
- getLogger (sessionId, protocol) {
18
- if (sessionId) {
19
- if (this._cache.has(sessionId)) {
20
- const value = this._cache.get(sessionId);
21
- if (value.logger) {
22
- return value.logger;
23
- }
24
- protocol = protocol || value.protocol;
25
- }
26
- // Always create a new logger instance for ids
27
- // that are not in the current sessions list,
28
- // so we can still see such ids as prefixes
29
- return logger.getLogger(`${protocol || GENERIC_PROTOCOL} ` +
30
- `(${sessionId.substring(0, Math.min(sessionId.length, 8))})`);
31
- }
32
-
33
- // Fall back to protocol name-only logger if session id is unknown
34
- switch (protocol) {
35
- case PROTOCOLS.W3C:
36
- return w3cLog;
37
- case PROTOCOLS.MJSONWP:
38
- return mjsonwpLog;
39
- default:
40
- return genericProtocolLog;
41
- }
42
- }
43
-
44
- getProtocol (sessionId) {
45
- return (this._cache.get(sessionId) || {}).protocol;
46
- }
47
-
48
- putSession (sessionId, value) {
49
- if (sessionId && value) {
50
- this._cache.set(sessionId, {
51
- protocol: value,
52
- // We don't want to cache the logger instance for each random session id in the cache
53
- // in order to save memory. Instead we only cache loggers for valid ids that
54
- // are returned by `createSession` call and reset them after `deleteSession` is called
55
- logger: this.getLogger(sessionId, value),
56
- });
57
- }
58
- return value;
59
- }
60
-
61
- resetLogger (sessionId) {
62
- if (this._cache.has(sessionId)) {
63
- this._cache.get(sessionId).logger = null;
64
- }
65
- }
66
- }
67
-
68
- // This cache is useful when a session gets terminated
69
- // and removed from the sessions list in the umbrella driver,
70
- // but the client still tries to send a command to this session id.
71
- // So we know how to properly wrap the error message for it
72
- const SESSIONS_CACHE = new SessionsCache(100);
73
-
74
- export default SESSIONS_CACHE;
@@ -1,505 +0,0 @@
1
- import { parseCaps, validateCaps, mergeCaps, processCapabilities, findNonPrefixedCaps,
2
- promoteAppiumOptions, APPIUM_OPTS_CAP, stripAppiumPrefixes } from '../../lib/basedriver/capabilities';
3
- import _ from 'lodash';
4
- import { desiredCapabilityConstraints } from '../../lib/basedriver/desired-caps';
5
-
6
-
7
- describe('caps', function () {
8
-
9
- // Tests based on: https://www.w3.org/TR/webdriver/#dfn-validate-caps
10
- describe('#validateCaps', function () {
11
- it('returns invalid argument error if "capability" is not a JSON object (1)', function () {
12
- for (let arg of [undefined, null, 1, true, 'string']) {
13
- (function () { validateCaps(arg); }).should.throw(/must be a JSON object/);
14
- }
15
- });
16
-
17
- it('returns result {} by default if caps is empty object and no constraints provided (2)', function () {
18
- validateCaps({}).should.deep.equal({});
19
- });
20
-
21
- describe('throws errors if constraints are not met', function () {
22
- it('returns invalid argument error if "present" constraint not met on property', function () {
23
- (() => validateCaps({}, {foo: {presence: true}})).should.throw(/'foo' can't be blank/);
24
- });
25
-
26
- it('returns the capability that was passed in if "skipPresenceConstraint" is false', function () {
27
- validateCaps({}, {foo: {presence: true}}, {skipPresenceConstraint: true}).should.deep.equal({});
28
- });
29
-
30
- it('returns invalid argument error if "isString" constraint not met on property', function () {
31
- (() => validateCaps({foo: 1}, {foo: {isString: true}})).should.throw(/'foo' must be of type string/);
32
- });
33
-
34
- it('returns invalid argument error if "isNumber" constraint not met on property', function () {
35
- (() => validateCaps({foo: 'bar'}, {foo: {isNumber: true}})).should.throw(/'foo' must be of type number/);
36
- });
37
-
38
- it('returns invalid argument error if "isBoolean" constraint not met on property', function () {
39
- (() => validateCaps({foo: 'bar'}, {foo: {isBoolean: true}})).should.throw(/'foo' must be of type boolean/);
40
- });
41
-
42
- it('returns invalid argument error if "inclusion" constraint not met on property', function () {
43
- (() => validateCaps({foo: '3'}, {foo: {inclusionCaseInsensitive: ['1', '2']}})).should.throw(/'foo' 3 not part of 1,2/);
44
- });
45
-
46
- it('returns invalid argument error if "inclusionCaseInsensitive" constraint not met on property', function () {
47
- (() => validateCaps({foo: 'a'}, {foo: {inclusion: ['A', 'B', 'C']}})).should.throw(/'foo' a is not included in the list/);
48
- });
49
- });
50
-
51
- it('should not throw errors if constraints are met', function () {
52
- let caps = {
53
- number: 1,
54
- string: 'string',
55
- present: 'present',
56
- extra: 'extra',
57
- };
58
-
59
- let constraints = {
60
- number: {isNumber: true},
61
- string: {isString: true},
62
- present: {presence: true},
63
- notPresent: {presence: false},
64
- };
65
-
66
- validateCaps(caps, constraints).should.deep.equal(caps);
67
- });
68
- });
69
-
70
- // Tests based on: https://www.w3.org/TR/webdriver/#dfn-merging-caps
71
- describe('#mergeCaps', function () {
72
- it('returns a result that is {} by default (1)', function () {
73
- mergeCaps().should.deep.equal({});
74
- });
75
-
76
- it('returns a result that matches primary by default (2, 3)', function () {
77
- mergeCaps({hello: 'world'}).should.deep.equal({hello: 'world'});
78
- });
79
-
80
- it('returns invalid argument error if primary and secondary have matching properties (4)', function () {
81
- (() => mergeCaps({hello: 'world'}, {hello: 'whirl'})).should.throw(/property 'hello' should not exist on both primary [\w\W]* and secondary [\w\W]*/);
82
- });
83
-
84
- it('returns a result with keys from primary and secondary together', function () {
85
- let primary = {
86
- a: 'a',
87
- b: 'b',
88
- };
89
- let secondary = {
90
- c: 'c',
91
- d: 'd',
92
- };
93
- mergeCaps(primary, secondary).should.deep.equal({
94
- a: 'a', b: 'b', c: 'c', d: 'd',
95
- });
96
- });
97
- });
98
-
99
- // Tests based on: https://www.w3.org/TR/webdriver/#processing-capabilities
100
- describe('#parseCaps', function () {
101
- let caps;
102
-
103
- beforeEach(function () {
104
- caps = {};
105
- });
106
-
107
- it('should return invalid argument if no caps object provided', function () {
108
- (() => parseCaps()).should.throw(/must be a JSON object/);
109
- });
110
-
111
- it('sets "requiredCaps" to property named "alwaysMatch" (2)', function () {
112
- caps.alwaysMatch = {'appium:hello': 'world'};
113
- parseCaps(caps).requiredCaps.should.deep.equal(caps.alwaysMatch);
114
- });
115
-
116
- it('sets "requiredCaps" to empty JSON object if "alwaysMatch" is not an object (2.1)', function () {
117
- parseCaps(caps).requiredCaps.should.deep.equal({});
118
- });
119
-
120
- it('returns invalid argument error if "requiredCaps" don\'t match "constraints" (2.2)', function () {
121
- caps.alwaysMatch = {'appium:foo': 1};
122
- (() => parseCaps(caps, {foo: {isString: true}})).should.throw(/'foo' must be of type string/);
123
- });
124
-
125
- it('sets "allFirstMatchCaps" to property named "firstMatch" (3)', function () {
126
- parseCaps({}, [{}]).allFirstMatchCaps.should.deep.equal([{}]);
127
- });
128
-
129
- it('sets "allFirstMatchCaps" to [{}] if "firstMatch" is undefined (3.1)', function () {
130
- parseCaps({}).allFirstMatchCaps.should.deep.equal([{}]);
131
- });
132
-
133
- it('returns invalid argument error if "firstMatch" is not an array and is not undefined (3.2)', function () {
134
- for (let arg of [null, 1, true, 'string']) {
135
- caps.firstMatch = arg;
136
- (function () { parseCaps(caps); }).should.throw(/must be a JSON array or undefined/);
137
- }
138
- });
139
-
140
- it('has "validatedFirstMatchCaps" property that is empty by default if no valid firstMatch caps were found (4)', function () {
141
- parseCaps(caps, {foo: {presence: true}}).validatedFirstMatchCaps.should.deep.equal([]);
142
- });
143
-
144
- describe('returns a "validatedFirstMatchCaps" array (5)', function () {
145
- it('that equals "firstMatch" if firstMatch is one empty object and there are no constraints', function () {
146
- caps.firstMatch = [{}];
147
- parseCaps(caps).validatedFirstMatchCaps.should.deep.equal(caps.firstMatch);
148
- });
149
-
150
- it('returns "null" matchedCaps if nothing matches', function () {
151
- caps.firstMatch = [{}];
152
- should.equal(parseCaps(caps, {foo: {presence: true}}).matchedCaps, null);
153
- });
154
-
155
- it(`should return capabilities if presence constraint is matched in at least one of the 'firstMatch' capabilities objects`, function () {
156
- caps.alwaysMatch = {
157
- 'appium:foo': 'bar',
158
- };
159
- caps.firstMatch = [{
160
- 'appium:hello': 'world',
161
- }, {
162
- 'appium:goodbye': 'world',
163
- }];
164
- parseCaps(caps, {goodbye: {presence: true}}).matchedCaps.should.deep.equal({
165
- foo: 'bar',
166
- goodbye: 'world',
167
- });
168
- });
169
-
170
- it(`throws invalid argument if presence constraint is not met on any capabilities`, function () {
171
- caps.alwaysMatch = {
172
- 'appium:foo': 'bar',
173
- };
174
- caps.firstMatch = [{
175
- 'appium:hello': 'world',
176
- }, {
177
- 'appium:goodbye': 'world',
178
- }];
179
- should.equal(parseCaps(caps, {someAttribute: {presence: true}}).matchedCaps, null);
180
- });
181
-
182
- it('that equals firstMatch if firstMatch contains two objects that pass the provided constraints', function () {
183
- caps.alwaysMatch = {
184
- 'appium:foo': 'bar'
185
- };
186
- caps.firstMatch = [
187
- {'appium:foo': 'bar1'},
188
- {'appium:foo': 'bar2'},
189
- ];
190
-
191
- let constraints = {
192
- foo: {
193
- presence: true,
194
- isString: true,
195
- }
196
- };
197
-
198
- parseCaps(caps, constraints).validatedFirstMatchCaps.should.deep.equal(caps.firstMatch);
199
- });
200
-
201
- it('returns no vendor prefix error if the firstMatch[2] does not have it because of no bject', function () {
202
- caps.alwaysMatch = {};
203
- caps.firstMatch = [{'appium:foo': 'bar'}, 'foo'];
204
- (() => parseCaps(caps, {})).should.throw(/All non-standard capabilities should have a vendor prefix/);
205
- });
206
- });
207
-
208
- describe('returns a matchedCaps object (6)', function () {
209
- beforeEach(function () {
210
- caps.alwaysMatch = {'appium:hello': 'world'};
211
- });
212
-
213
- it('which is same as alwaysMatch if firstMatch array is not provided', function () {
214
- parseCaps(caps).matchedCaps.should.deep.equal({hello: 'world'});
215
- });
216
-
217
- it('merges caps together', function () {
218
- caps.firstMatch = [{'appium:foo': 'bar'}];
219
- parseCaps(caps).matchedCaps.should.deep.equal({hello: 'world', foo: 'bar'});
220
- });
221
-
222
- it('with merged caps', function () {
223
- caps.firstMatch = [{'appium:hello': 'bar', 'appium:foo': 'foo'}, {'appium:foo': 'bar'}];
224
- parseCaps(caps).matchedCaps.should.deep.equal({hello: 'world', foo: 'bar'});
225
- });
226
- });
227
- });
228
-
229
- describe('#processCaps', function () {
230
- it('should return "alwaysMatch" if "firstMatch" and "constraints" were not provided', function () {
231
- processCapabilities({}).should.deep.equal({});
232
- });
233
-
234
- it('should return merged caps', function () {
235
- processCapabilities({
236
- alwaysMatch: {'appium:hello': 'world'},
237
- firstMatch: [{'appium:foo': 'bar'}]
238
- }).should.deep.equal({hello: 'world', foo: 'bar'});
239
- });
240
-
241
- it('should strip out the "appium:" prefix for non-standard capabilities', function () {
242
- processCapabilities({
243
- alwaysMatch: {'appium:hello': 'world'},
244
- firstMatch: [{'appium:foo': 'bar'}]
245
- }).should.deep.equal({hello: 'world', foo: 'bar'});
246
- });
247
-
248
- it('should still accept prefixed caps even if they are standard capabilities (https://www.w3.org/TR/webdriver/#dfn-table-of-standard-capabilities)', function () {
249
- processCapabilities({
250
- alwaysMatch: {'appium:platformName': 'Whatevz'},
251
- firstMatch: [{'appium:browserName': 'Anything'}],
252
- }).should.deep.equal({platformName: 'Whatevz', browserName: 'Anything'});
253
- });
254
-
255
- it('should prefer standard caps that are non-prefixed to prefixed', function () {
256
- processCapabilities({
257
- alwaysMatch: {'appium:platformName': 'Foo', 'platformName': 'Bar'},
258
- firstMatch: [{'appium:browserName': 'FOO', 'browserName': 'BAR'}],
259
- }).should.deep.equal({platformName: 'Bar', browserName: 'BAR'});
260
- });
261
- it('should throw exception if duplicates in alwaysMatch and firstMatch', function () {
262
- (() => processCapabilities({
263
- alwaysMatch: {'platformName': 'Fake', 'appium:fakeCap': 'foobar'},
264
- firstMatch: [{'appium:platformName': 'bar'}],
265
- })).should.throw(/should not exist on both primary/);
266
- });
267
-
268
- it('should not throw an exception if presence constraint is not met on a firstMatch capability', function () {
269
- const caps = processCapabilities({
270
- alwaysMatch: {'platformName': 'Fake', 'appium:fakeCap': 'foobar'},
271
- firstMatch: [{'appium:foo': 'bar'}],
272
- }, {
273
- platformName: {
274
- presence: true,
275
- },
276
- fakeCap: {
277
- presence: true
278
- },
279
- });
280
-
281
- caps.platformName.should.equal('Fake');
282
- caps.fakeCap.should.equal('foobar');
283
- caps.foo.should.equal('bar');
284
- });
285
-
286
- it('should throw an exception if no matching caps were found', function () {
287
- (() => processCapabilities({
288
- alwaysMatch: {'platformName': 'Fake', 'appium:fakeCap': 'foobar'},
289
- firstMatch: [{'appium:foo': 'bar'}],
290
- }, {
291
- platformName: {
292
- presence: true,
293
- },
294
- fakeCap: {
295
- presence: true
296
- },
297
- missingCap: {
298
- presence: true,
299
- },
300
- })).should.throw(/'missingCap' can't be blank/);
301
- });
302
-
303
- describe('validate Appium constraints', function () {
304
- const constraints = {...desiredCapabilityConstraints};
305
- const expectedMatchingCaps = {'platformName': 'Fake', 'automationName': 'Fake', 'deviceName': 'Fake'};
306
-
307
- let matchingCaps;
308
- let caps;
309
-
310
- beforeEach(function () {
311
- matchingCaps = {
312
- 'platformName': 'Fake',
313
- 'appium:automationName': 'Fake',
314
- 'appium:deviceName': 'Fake'
315
- };
316
- });
317
-
318
- it('should validate when alwaysMatch has the proper caps', function () {
319
- caps = {
320
- alwaysMatch: matchingCaps,
321
- firstMatch: [{}],
322
- };
323
- processCapabilities(caps, constraints).should.deep.equal(expectedMatchingCaps);
324
- });
325
-
326
-
327
- it('should validate when firstMatch[0] has the proper caps', function () {
328
- caps = {
329
- alwaysMatch: {},
330
- firstMatch: [matchingCaps],
331
- };
332
- processCapabilities(caps, constraints).should.deep.equal(expectedMatchingCaps);
333
- });
334
-
335
- it('should validate when alwaysMatch and firstMatch[0] have the proper caps when merged together', function () {
336
- caps = {
337
- alwaysMatch: _.omit(matchingCaps, ['appium:deviceName']),
338
- firstMatch: [{'appium:deviceName': 'Fake'}],
339
- };
340
- processCapabilities(caps, constraints).should.deep.equal(expectedMatchingCaps);
341
- });
342
-
343
- it('should validate when automationName is omitted', function () {
344
- caps = {
345
- alwaysMatch: _.omit(matchingCaps, ['appium:automationName']),
346
- };
347
- processCapabilities(caps, constraints).should.deep.equal(_.omit(expectedMatchingCaps, 'automationName'));
348
- });
349
-
350
- it('should pass if first element in "firstMatch" does validate and second element does not', function () {
351
- caps = {
352
- alwaysMatch: {},
353
- firstMatch: [
354
- matchingCaps,
355
- {'appium:badCaps': 'badCaps'},
356
- ],
357
- };
358
- processCapabilities(caps, constraints).should.deep.equal(expectedMatchingCaps);
359
- });
360
-
361
- it('should pass if first element in "firstMatch" does not validate and second element does', function () {
362
- caps = {
363
- alwaysMatch: {},
364
- firstMatch: [
365
- {'appium:badCaps': 'badCaps'},
366
- matchingCaps,
367
- ],
368
- };
369
- processCapabilities(caps, constraints).should.deep.equal(expectedMatchingCaps);
370
- });
371
-
372
- it('should fail when bad parameters are passed in more than one firstMatch capability', function () {
373
- caps = {
374
- alwaysMatch: {},
375
- firstMatch: [{
376
- 'appium:bad': 'params',
377
- }, {
378
- 'appium:more': 'bad-params',
379
- }],
380
- };
381
- (() => processCapabilities(caps, constraints)).should.throw(/Could not find matching capabilities/);
382
- });
383
- });
384
- });
385
- describe('.findNonPrefixedCaps', function () {
386
- it('should find alwaysMatch caps with no prefix', function () {
387
- findNonPrefixedCaps({alwaysMatch: {
388
- 'non-standard': 'dummy',
389
- }}).should.eql(['non-standard']);
390
- });
391
- it('should not find a standard cap in alwaysMatch', function () {
392
- findNonPrefixedCaps({alwaysMatch: {
393
- 'platformName': 'Any',
394
- }}).should.eql([]);
395
- });
396
- it('should find firstMatch caps with no prefix', function () {
397
- findNonPrefixedCaps({alwaysMatch: {}, firstMatch: [{
398
- 'non-standard': 'dummy',
399
- }]}).should.eql(['non-standard']);
400
- });
401
- it('should not find a standard cap in prefix', function () {
402
- findNonPrefixedCaps({alwaysMatch: {}, firstMatch: [{
403
- 'platformName': 'Any',
404
- }]}).should.eql([]);
405
- });
406
- it('should find firstMatch caps in second item of firstMatch array', function () {
407
- findNonPrefixedCaps({alwaysMatch: {}, firstMatch: [{}, {
408
- 'non-standard': 'dummy',
409
- }]}).should.eql(['non-standard']);
410
- });
411
- it('should remove duplicates from alwaysMatch and firstMatch', function () {
412
- findNonPrefixedCaps({alwaysMatch: {
413
- 'non-standard': 'something',
414
- }, firstMatch: [{
415
- 'non-standard': 'dummy',
416
- }]}).should.eql(['non-standard']);
417
- });
418
- it('should remove duplicates from firstMatch', function () {
419
- findNonPrefixedCaps({firstMatch: [{
420
- 'non-standard': 'dummy',
421
- }, {
422
- 'non-standard': 'dummy 2',
423
- }]}).should.eql(['non-standard']);
424
- });
425
- it('should remove duplicates and keep standard capabilities', function () {
426
- const alwaysMatch = {
427
- platformName: 'Fake',
428
- nonStandardOne: 'non-standard',
429
- nonStandardTwo: 'non-standard',
430
- };
431
- const firstMatch = [
432
- {nonStandardThree: 'non-standard', nonStandardFour: 'non-standard', browserName: 'FakeBrowser'},
433
- {nonStandardThree: 'non-standard', nonStandardFour: 'non-standard', nonStandardFive: 'non-standard', browserVersion: 'whateva'},
434
- ];
435
- findNonPrefixedCaps({alwaysMatch, firstMatch}).should.eql(['nonStandardOne', 'nonStandardTwo', 'nonStandardThree', 'nonStandardFour', 'nonStandardFive']);
436
- });
437
- });
438
-
439
- describe('#promoteAppiumOptions', function () {
440
- const appiumCaps = {
441
- 'appium:platformVersion': '14.4',
442
- 'appium:deviceName': 'iPhone 11',
443
- 'appium:app': '/foo/bar.app.zip',
444
- 'appium:automationName': 'XCUITest',
445
- };
446
- const nonAppiumCaps = {
447
- platformName: 'iOS',
448
- };
449
- const appiumUnprefixedCaps = _.clone(appiumCaps);
450
- stripAppiumPrefixes(appiumUnprefixedCaps);
451
- const simpleCaps = {
452
- ...nonAppiumCaps,
453
- ...appiumUnprefixedCaps,
454
- };
455
- it('should do nothing to caps that dont include the options', function () {
456
- promoteAppiumOptions(simpleCaps).should.eql(simpleCaps);
457
- });
458
- it('should promote options', function () {
459
- const caps = {
460
- ...nonAppiumCaps,
461
- [APPIUM_OPTS_CAP]: {
462
- ...appiumUnprefixedCaps,
463
- }
464
- };
465
- promoteAppiumOptions(caps).should.eql(simpleCaps);
466
- });
467
- it('should get rid of prefixes if caps inside options are prefixed', function () {
468
- const caps = {
469
- ...nonAppiumCaps,
470
- [APPIUM_OPTS_CAP]: {
471
- ...appiumCaps,
472
- }
473
- };
474
- promoteAppiumOptions(caps).should.eql(simpleCaps);
475
- });
476
- it('should preserve non-appium vendor prefixes', function () {
477
- const googCaps = {'goog:chromeOptions': {foo: 'bar'}};
478
- const caps = {
479
- ...nonAppiumCaps,
480
- [APPIUM_OPTS_CAP]: {
481
- ...appiumCaps,
482
- ...googCaps,
483
- },
484
- };
485
- promoteAppiumOptions(caps).should.eql({
486
- ...simpleCaps,
487
- ...googCaps,
488
- });
489
- });
490
- it('should overwrite caps found on the top level', function () {
491
- const caps = {
492
- ...nonAppiumCaps,
493
- foo: 'bar',
494
- [APPIUM_OPTS_CAP]: {
495
- ...appiumCaps,
496
- foo: 'baz',
497
- }
498
- };
499
- promoteAppiumOptions(caps).should.eql({
500
- ...simpleCaps,
501
- foo: 'baz',
502
- });
503
- });
504
- });
505
- });