@appium/fake-driver 4.2.1 → 5.0.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 (68) hide show
  1. package/build/lib/commands/alert.d.ts +345 -13
  2. package/build/lib/commands/alert.d.ts.map +1 -1
  3. package/build/lib/commands/alert.js +80 -53
  4. package/build/lib/commands/alert.js.map +1 -0
  5. package/build/lib/commands/contexts.d.ts +359 -14
  6. package/build/lib/commands/contexts.d.ts.map +1 -1
  7. package/build/lib/commands/contexts.js +102 -86
  8. package/build/lib/commands/contexts.js.map +1 -0
  9. package/build/lib/commands/element.d.ts +326 -22
  10. package/build/lib/commands/element.d.ts.map +1 -1
  11. package/build/lib/commands/element.js +108 -123
  12. package/build/lib/commands/element.js.map +1 -0
  13. package/build/lib/commands/find.d.ts +338 -18
  14. package/build/lib/commands/find.d.ts.map +1 -1
  15. package/build/lib/commands/find.js +113 -107
  16. package/build/lib/commands/find.js.map +1 -0
  17. package/build/lib/commands/general.d.ts +364 -28
  18. package/build/lib/commands/general.d.ts.map +1 -1
  19. package/build/lib/commands/general.js +97 -106
  20. package/build/lib/commands/general.js.map +1 -0
  21. package/build/lib/commands/index.d.ts +1598 -2
  22. package/build/lib/commands/index.d.ts.map +1 -1
  23. package/build/lib/commands/index.js +97 -18
  24. package/build/lib/commands/index.js.map +1 -0
  25. package/build/lib/driver.d.ts +118 -36
  26. package/build/lib/driver.d.ts.map +1 -1
  27. package/build/lib/driver.js +170 -145
  28. package/build/lib/driver.js.map +1 -0
  29. package/build/lib/fake-app.d.ts +15 -6
  30. package/build/lib/fake-app.d.ts.map +1 -1
  31. package/build/lib/fake-app.js +155 -194
  32. package/build/lib/fake-app.js.map +1 -0
  33. package/build/lib/fake-driver-schema.js +34 -26
  34. package/build/lib/fake-driver-schema.js.map +1 -0
  35. package/build/lib/fake-element.js +87 -121
  36. package/build/lib/fake-element.js.map +1 -0
  37. package/build/lib/index.d.ts +4 -5
  38. package/build/lib/index.d.ts.map +1 -1
  39. package/build/lib/index.js +15 -36
  40. package/build/lib/index.js.map +1 -0
  41. package/build/lib/logger.d.ts +1 -1
  42. package/build/lib/logger.d.ts.map +1 -1
  43. package/build/lib/logger.js +5 -15
  44. package/build/lib/logger.js.map +1 -0
  45. package/build/lib/scripts/fake-error.js +1 -5
  46. package/build/lib/scripts/fake-error.js.map +1 -0
  47. package/build/lib/scripts/fake-success.js +8 -11
  48. package/build/lib/scripts/fake-success.js.map +1 -0
  49. package/build/lib/server.d.ts +1 -1
  50. package/build/lib/server.d.ts.map +1 -1
  51. package/build/lib/server.js +18 -27
  52. package/build/lib/server.js.map +1 -0
  53. package/build/lib/types.d.ts +36 -0
  54. package/build/lib/types.d.ts.map +1 -0
  55. package/build/lib/types.js +3 -0
  56. package/build/lib/types.js.map +1 -0
  57. package/build/tsconfig.tsbuildinfo +1 -1
  58. package/lib/commands/alert.js +74 -34
  59. package/lib/commands/contexts.js +90 -52
  60. package/lib/commands/element.js +111 -98
  61. package/lib/commands/find.js +101 -77
  62. package/lib/commands/general.js +106 -75
  63. package/lib/commands/index.js +13 -17
  64. package/lib/driver.js +103 -32
  65. package/lib/fake-app.js +20 -6
  66. package/lib/index.js +4 -7
  67. package/lib/types.ts +42 -0
  68. package/package.json +11 -12
@@ -1,64 +1,102 @@
1
1
  import _ from 'lodash';
2
2
  import {errors} from 'appium/driver';
3
3
 
4
- let commands = {},
5
- helpers = {},
6
- extensions = {};
7
-
8
- helpers.getRawContexts = function getRawContexts() {
9
- let contexts = {NATIVE_APP: null, PROXY: null};
10
- let wvs = this.appModel.getWebviews();
11
- for (let i = 1; i < wvs.length + 1; i++) {
12
- contexts[`WEBVIEW_${i}`] = wvs[i - 1];
13
- }
14
- return contexts;
15
- };
4
+ /**
5
+ *
6
+ * @template {Class<import('../types').IFakeDriver>} T
7
+ * @param {T} Base
8
+ */
9
+ export function ContextsMixin(Base) {
10
+ /**
11
+ * @implements {IContextsCommands}
12
+ */
13
+ class ContextsCommands extends Base {
14
+ getRawContexts() {
15
+ let contexts = {NATIVE_APP: null, PROXY: null};
16
+ let wvs = this.appModel?.getWebviews() ?? [];
17
+ for (let i = 1; i < wvs.length + 1; i++) {
18
+ contexts[`WEBVIEW_${i}`] = wvs[i - 1];
19
+ }
20
+ return contexts;
21
+ }
16
22
 
17
- helpers.assertWebviewContext = function assertWebviewContext() {
18
- if (this.curContext === 'NATIVE_APP') {
19
- throw new errors.InvalidContextError();
20
- }
21
- };
23
+ assertWebviewContext() {
24
+ if (this.curContext === 'NATIVE_APP') {
25
+ throw new errors.InvalidContextError();
26
+ }
27
+ }
22
28
 
23
- commands.getCurrentContext = async function getCurrentContext() {
24
- return this.curContext;
25
- };
29
+ /**
30
+ * Get the current appium context
31
+ *
32
+ * @returns {Promise<string>}
33
+ */
34
+ async getCurrentContext() {
35
+ return this.curContext;
36
+ }
26
37
 
27
- commands.getContexts = async function getContexts() {
28
- return _.keys(this.getRawContexts());
29
- };
38
+ /**
39
+ * Get the list of available contexts
40
+ *
41
+ * @returns {Promise<string[]>}
42
+ */
43
+ async getContexts() {
44
+ return _.keys(this.getRawContexts());
45
+ }
30
46
 
31
- commands.setContext = async function setContext(context) {
32
- let contexts = this.getRawContexts();
33
- if (_.includes(_.keys(contexts), context)) {
34
- this.curContext = context;
35
- if (context === 'NATIVE_APP') {
36
- this.appModel.deactivateWebview();
37
- this._proxyActive = false;
38
- } else if (context === 'PROXY') {
39
- this._proxyActive = true;
40
- } else {
41
- this.appModel.activateWebview(contexts[context]);
42
- this._proxyActive = false;
47
+ /**
48
+ * Set the current context
49
+ *
50
+ * @param {string} context - name of the context
51
+ * @returns {Promise<void>}
52
+ */
53
+ async setContext(context) {
54
+ let contexts = this.getRawContexts();
55
+ if (context in contexts) {
56
+ this.curContext = context;
57
+ if (context === 'NATIVE_APP') {
58
+ this.appModel.deactivateWebview();
59
+ this._proxyActive = false;
60
+ } else if (context === 'PROXY') {
61
+ this._proxyActive = true;
62
+ } else {
63
+ this.appModel.activateWebview(contexts[context]);
64
+ this._proxyActive = false;
65
+ }
66
+ } else {
67
+ throw new errors.NoSuchContextError();
68
+ }
43
69
  }
44
- } else {
45
- throw new errors.NoSuchContextError();
46
- }
47
- };
48
70
 
49
- commands.setFrame = async function setFrame(frameId) {
50
- this.assertWebviewContext();
51
- if (frameId === null) {
52
- this.appModel.deactivateFrame();
53
- } else {
54
- let nodes = this.appModel.xpathQuery(`//iframe[@id="${frameId}"]`);
55
- if (!nodes.length) {
56
- throw new errors.NoSuchFrameError();
71
+ /**
72
+ * Set the active frame
73
+ *
74
+ * @param {number} frameId
75
+ * @returns {Promise<void>}
76
+ */
77
+ async setFrame(frameId) {
78
+ this.assertWebviewContext();
79
+ if (frameId === null) {
80
+ this.appModel.deactivateFrame();
81
+ } else {
82
+ let nodes = this.appModel.xpathQuery(`//iframe[@id="${frameId}"]`);
83
+ if (!nodes.length) {
84
+ throw new errors.NoSuchFrameError();
85
+ }
86
+ this.appModel.activateFrame(nodes[0]);
87
+ }
57
88
  }
58
- this.appModel.activateFrame(nodes[0]);
59
89
  }
60
- };
61
90
 
62
- Object.assign(extensions, commands, helpers);
63
- export {commands, helpers};
64
- export default extensions;
91
+ return ContextsCommands;
92
+ }
93
+
94
+ /**
95
+ * @typedef {import('../driver').FakeDriverCore} FakeDriverCore
96
+ * @typedef {import('../types').IContextsCommands} IContextsCommands
97
+ */
98
+
99
+ /**
100
+ * @template T,[U={}],[V=Array<any>]
101
+ * @typedef {import('@appium/types').Class<T,U,V>} Class
102
+ */
@@ -1,103 +1,116 @@
1
1
  import _ from 'lodash';
2
2
  import {errors} from 'appium/driver';
3
3
 
4
- let commands = {},
5
- helpers = {},
6
- extensions = {};
7
-
8
- helpers.getElements = function getElements(elIds) {
9
- for (let elId of elIds) {
10
- if (!_.has(this.elMap, elId)) {
11
- throw new errors.StaleElementReferenceError();
4
+ /**
5
+ * @template {Class<import('../types').IContextsCommands & import('../types').IAlertCommands>} T
6
+ * @param {T} Base
7
+ */
8
+ export function ElementMixin(Base) {
9
+ /**
10
+ * @implements {IElementCommands}
11
+ */
12
+ class ElementCommands extends Base {
13
+ getElements(elIds) {
14
+ for (let elId of elIds) {
15
+ if (!_.has(this.elMap, elId)) {
16
+ throw new errors.StaleElementReferenceError();
17
+ }
18
+ }
19
+ return elIds.map((e) => this.elMap[e]);
12
20
  }
21
+
22
+ getElement(elId) {
23
+ return this.getElements([elId])[0];
24
+ }
25
+
26
+ async getName(elementId) {
27
+ let el = this.getElement(elementId);
28
+ return el.tagName;
29
+ }
30
+
31
+ async elementDisplayed(elementId) {
32
+ let el = this.getElement(elementId);
33
+ return el.isVisible();
34
+ }
35
+
36
+ async elementEnabled(elementId) {
37
+ let el = this.getElement(elementId);
38
+ return el.isEnabled();
39
+ }
40
+
41
+ async elementSelected(elementId) {
42
+ let el = this.getElement(elementId);
43
+ return el.isSelected();
44
+ }
45
+
46
+ async setValue(keys, elementId) {
47
+ let value = keys;
48
+ if (keys instanceof Array) {
49
+ value = keys.join('');
50
+ }
51
+ let el = this.getElement(elementId);
52
+ if (el.type !== 'MockInputField') {
53
+ throw new errors.InvalidElementStateError();
54
+ }
55
+ el.setAttr('value', value);
56
+ }
57
+
58
+ async getText(elementId) {
59
+ let el = this.getElement(elementId);
60
+ return el.getAttr('value');
61
+ }
62
+
63
+ async clear(elementId) {
64
+ await this.setValue('', elementId);
65
+ }
66
+
67
+ async click(elementId) {
68
+ this.assertNoAlert();
69
+ let el = this.getElement(elementId);
70
+ if (!el.isVisible()) {
71
+ throw new errors.InvalidElementStateError();
72
+ }
73
+ el.click();
74
+ this.focusedElId = elementId;
75
+ }
76
+
77
+ async getAttribute(attr, elementId) {
78
+ let el = this.getElement(elementId);
79
+ return el.getAttr(attr);
80
+ }
81
+ getElementRect(elementId) {
82
+ let el = this.getElement(elementId);
83
+ return el.getElementRect();
84
+ }
85
+ getSize(elementId) {
86
+ let el = this.getElement(elementId);
87
+ return el.getSize();
88
+ }
89
+
90
+ equalsElement(el1Id, el2Id) {
91
+ let el1 = this.getElement(el1Id);
92
+ let el2 = this.getElement(el2Id);
93
+ return el1.equals(el2);
94
+ }
95
+
96
+ async getCssProperty(prop, elementId) {
97
+ this.assertWebviewContext();
98
+ let el = this.getElement(elementId);
99
+ return el.getCss(prop);
100
+ }
101
+
102
+ getLocationInView = this.getLocation;
13
103
  }
14
- return elIds.map((e) => this.elMap[e]);
15
- };
16
-
17
- helpers.getElement = function getElement(elId) {
18
- return this.getElements([elId])[0];
19
- };
20
-
21
- commands.getName = async function getName(elementId) {
22
- let el = this.getElement(elementId);
23
- return el.tagName;
24
- };
25
-
26
- commands.elementDisplayed = async function elementDisplayed(elementId) {
27
- let el = this.getElement(elementId);
28
- return el.isVisible();
29
- };
30
-
31
- commands.elementEnabled = async function elementEnabled(elementId) {
32
- let el = this.getElement(elementId);
33
- return el.isEnabled();
34
- };
35
-
36
- commands.elementSelected = async function elementSelected(elementId) {
37
- let el = this.getElement(elementId);
38
- return el.isSelected();
39
- };
40
-
41
- commands.setValue = async function setValue(keys, elementId) {
42
- let value = keys;
43
- if (keys instanceof Array) {
44
- value = keys.join('');
45
- }
46
- let el = this.getElement(elementId);
47
- if (el.type !== 'MockInputField') {
48
- throw new errors.InvalidElementStateError();
49
- }
50
- el.setAttr('value', value);
51
- };
52
-
53
- commands.getText = async function getText(elementId) {
54
- let el = this.getElement(elementId);
55
- return el.getAttr('value');
56
- };
57
-
58
- commands.clear = async function clear(elementId) {
59
- await this.setValue('', elementId);
60
- };
61
-
62
- commands.click = async function click(elementId) {
63
- this.assertNoAlert();
64
- let el = this.getElement(elementId);
65
- if (!el.isVisible()) {
66
- throw new errors.InvalidElementStateError();
67
- }
68
- el.click();
69
- this.focusedElId = elementId;
70
- };
71
-
72
- commands.getAttribute = async function getAttribute(attr, elementId) {
73
- let el = this.getElement(elementId);
74
- return el.getAttr(attr);
75
- };
76
-
77
- commands.getElementRect = function getElementRect(elementId) {
78
- let el = this.getElement(elementId);
79
- return el.getElementRect();
80
- };
81
-
82
- commands.getSize = function getSize(elementId) {
83
- let el = this.getElement(elementId);
84
- return el.getSize();
85
- };
86
-
87
- commands.equalsElement = function equalsElement(el1Id, el2Id) {
88
- let el1 = this.getElement(el1Id);
89
- let el2 = this.getElement(el2Id);
90
- return el1.equals(el2);
91
- };
92
-
93
- commands.getLocationInView = commands.getLocation;
94
-
95
- commands.getCssProperty = async function getCssProperty(prop, elementId) {
96
- this.assertWebviewContext();
97
- let el = this.getElement(elementId);
98
- return el.getCss(prop);
99
- };
100
-
101
- Object.assign(extensions, commands, helpers);
102
- export {commands, helpers};
103
- export default extensions;
104
+
105
+ return ElementCommands;
106
+ }
107
+
108
+ /**
109
+ * @typedef {import('../driver').FakeDriverCore} FakeDriverCore
110
+ * @typedef {import('../types').IElementCommands} IElementCommands
111
+ */
112
+
113
+ /**
114
+ * @template T,[U={}],[V=Array<any>]
115
+ * @typedef {import('@appium/types').Class<T,U,V>} Class
116
+ */
@@ -2,92 +2,116 @@ import _ from 'lodash';
2
2
  import {errors} from 'appium/driver';
3
3
  import {FakeElement} from '../fake-element';
4
4
 
5
- let commands = {},
6
- helpers = {},
7
- extensions = {};
8
-
9
- helpers.getExistingElementForNode = function getExistingElementForNode(node) {
10
- for (let [id, el] of _.toPairs(this.elMap)) {
11
- if (el.node === node) {
12
- return id;
5
+ /**
6
+ * @template {Class<import('../types').IElementCommands>} T
7
+ * @param {T} Base
8
+ */
9
+ export function FindMixin(Base) {
10
+ /**
11
+ * @implements {IFindCommands}
12
+ */
13
+ class FindCommands extends Base {
14
+ getExistingElementForNode(node) {
15
+ for (let [id, el] of _.toPairs(this.elMap)) {
16
+ if (el.node === node) {
17
+ return id;
18
+ }
19
+ }
20
+ return null;
13
21
  }
14
- }
15
- return null;
16
- };
17
22
 
18
- helpers.wrapNewEl = function wrapNewEl(obj) {
19
- // first check and see if we already have a ref to this element
20
- let existingElId = this.getExistingElementForNode(obj);
21
- if (existingElId) {
22
- return {ELEMENT: existingElId};
23
- }
23
+ wrapNewEl(obj) {
24
+ // first check and see if we already have a ref to this element
25
+ let existingElId = this.getExistingElementForNode(obj);
26
+ if (existingElId) {
27
+ return {ELEMENT: existingElId};
28
+ }
24
29
 
25
- // otherwise add the element to the map
26
- this.maxElId++;
27
- this.elMap[this.maxElId.toString()] = new FakeElement(obj, this.appModel);
28
- return {ELEMENT: this.maxElId.toString()};
29
- };
30
+ // otherwise add the element to the map
31
+ this.maxElId++;
32
+ this.elMap[this.maxElId.toString()] = new FakeElement(obj, this.appModel);
33
+ return {ELEMENT: this.maxElId.toString()};
34
+ }
35
+ /**
36
+ * @template {boolean} Mult
37
+ * @template [Ctx=any]
38
+ * @param {string} strategy
39
+ * @param {string} selector
40
+ * @param {Mult} mult
41
+ * @param {Ctx} [context]
42
+ * @returns {Promise<Mult extends true ? Element[] : Element>}
43
+ */
44
+ async findElOrEls(strategy, selector, mult, context) {
45
+ let qMap = {
46
+ xpath: 'xpathQuery',
47
+ id: 'idQuery',
48
+ 'accessibility id': 'idQuery',
49
+ 'class name': 'classQuery',
50
+ 'tag name': 'classQuery',
51
+ 'css selector': 'cssQuery',
52
+ };
53
+ // TODO this error checking should probably be part of MJSONWP?
54
+ if (!_.includes(_.keys(qMap), strategy)) {
55
+ throw new errors.UnknownCommandError();
56
+ }
57
+ if (selector === 'badsel') {
58
+ throw new errors.InvalidSelectorError();
59
+ }
60
+ let els = this.appModel[qMap[strategy]](selector, context);
30
61
 
31
- helpers.findElOrEls = async function findElOrEls(strategy, selector, mult, ctx) {
32
- let qMap = {
33
- xpath: 'xpathQuery',
34
- id: 'idQuery',
35
- 'accessibility id': 'idQuery',
36
- 'class name': 'classQuery',
37
- 'tag name': 'classQuery',
38
- 'css selector': 'cssQuery',
39
- };
40
- // TODO this error checking should probably be part of MJSONWP?
41
- if (!_.includes(_.keys(qMap), strategy)) {
42
- throw new errors.UnknownCommandError();
43
- }
44
- if (selector === 'badsel') {
45
- throw new errors.InvalidSelectorError();
46
- }
47
- let els = this.appModel[qMap[strategy]](selector, ctx);
48
- if (els.length) {
49
- if (mult) {
50
- let allEls = [];
51
- for (let el of els) {
52
- allEls.push(this.wrapNewEl(el));
62
+ let retval;
63
+ if (els.length) {
64
+ if (mult) {
65
+ let allEls = [];
66
+ for (let el of els) {
67
+ allEls.push(this.wrapNewEl(el));
68
+ }
69
+ retval = allEls;
70
+ } else {
71
+ retval = this.wrapNewEl(els[0]);
72
+ }
73
+ } else if (mult) {
74
+ retval = [];
75
+ } else {
76
+ throw new errors.NoSuchElementError();
53
77
  }
54
- return allEls;
55
- } else {
56
- return this.wrapNewEl(els[0]);
78
+ return /** @type {Mult extends true ? Element[] : Element} */ (retval);
79
+ }
80
+
81
+ async findElement(strategy, selector) {
82
+ return this.findElOrEls(strategy, selector, false);
83
+ }
84
+
85
+ async findElements(strategy, selector) {
86
+ return this.findElOrEls(strategy, selector, true);
87
+ }
88
+
89
+ async findElementFromElement(strategy, selector, elementId) {
90
+ let el = this.getElement(elementId);
91
+ return this.findElOrEls(strategy, selector, false, el.xmlFragment);
92
+ }
93
+
94
+ async findElementsFromElement(strategy, selector, elementId) {
95
+ let el = this.getElement(elementId);
96
+ return this.findElOrEls(strategy, selector, true, el.xmlFragment);
57
97
  }
58
- } else if (mult) {
59
- return [];
60
- } else {
61
- throw new errors.NoSuchElementError();
62
98
  }
63
- };
64
99
 
65
- commands.findElement = async function findElement(strategy, selector) {
66
- return this.findElOrEls(strategy, selector, false);
67
- };
100
+ return FindCommands;
101
+ }
68
102
 
69
- commands.findElements = async function findElements(strategy, selector) {
70
- return this.findElOrEls(strategy, selector, true);
71
- };
103
+ /**
104
+ * @typedef {import('../driver').FakeDriverCore} FakeDriverCore
105
+ * @typedef {import('@appium/types').Element} Element
72
106
 
73
- commands.findElementFromElement = async function findElementFromElement(
74
- strategy,
75
- selector,
76
- elementId
77
- ) {
78
- let el = this.getElement(elementId);
79
- return this.findElOrEls(strategy, selector, false, el.xmlFragment);
80
- };
107
+ */
81
108
 
82
- commands.findElementsFromElement = async function findElementsFromElement(
83
- strategy,
84
- selector,
85
- elementId
86
- ) {
87
- let el = this.getElement(elementId);
88
- return this.findElOrEls(strategy, selector, true, el.xmlFragment);
89
- };
109
+ /**
110
+ * @template T,[U={}],[V=Array<any>]
111
+ * @typedef {import('@appium/types').Class<T,U,V>} Class
112
+ */
90
113
 
91
- Object.assign(extensions, commands, helpers);
92
- export {commands, helpers};
93
- export default extensions;
114
+ /**
115
+ * @template [Ctx=any]
116
+ * @typedef {import('@appium/types').IFindCommands<Ctx>} IFindCommands
117
+ */