@appium/fake-driver 5.2.0 → 5.2.2

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 (65) hide show
  1. package/LICENSE +1 -1
  2. package/build/lib/commands/alert.d.ts +12 -40
  3. package/build/lib/commands/alert.d.ts.map +1 -1
  4. package/build/lib/commands/alert.js +3 -23
  5. package/build/lib/commands/alert.js.map +1 -1
  6. package/build/lib/commands/contexts.d.ts +12 -42
  7. package/build/lib/commands/contexts.d.ts.map +1 -1
  8. package/build/lib/commands/contexts.js +8 -28
  9. package/build/lib/commands/contexts.js.map +1 -1
  10. package/build/lib/commands/element.d.ts +25 -74
  11. package/build/lib/commands/element.d.ts.map +1 -1
  12. package/build/lib/commands/element.js +24 -76
  13. package/build/lib/commands/element.js.map +1 -1
  14. package/build/lib/commands/find.d.ts +16 -44
  15. package/build/lib/commands/find.d.ts.map +1 -1
  16. package/build/lib/commands/find.js +21 -45
  17. package/build/lib/commands/find.js.map +1 -1
  18. package/build/lib/commands/general.d.ts +25 -88
  19. package/build/lib/commands/general.d.ts.map +1 -1
  20. package/build/lib/commands/general.js +3 -61
  21. package/build/lib/commands/general.js.map +1 -1
  22. package/build/lib/commands/index.d.ts +13 -5
  23. package/build/lib/commands/index.d.ts.map +1 -1
  24. package/build/lib/commands/index.js +13 -14
  25. package/build/lib/commands/index.js.map +1 -1
  26. package/build/lib/commands/mixin.d.ts +11 -0
  27. package/build/lib/commands/mixin.d.ts.map +1 -0
  28. package/build/lib/commands/mixin.js +17 -0
  29. package/build/lib/commands/mixin.js.map +1 -0
  30. package/build/lib/driver.d.ts +37 -111
  31. package/build/lib/driver.d.ts.map +1 -1
  32. package/build/lib/driver.js +11 -73
  33. package/build/lib/driver.js.map +1 -1
  34. package/build/lib/fake-app.d.ts +9 -7
  35. package/build/lib/fake-app.d.ts.map +1 -1
  36. package/build/lib/fake-app.js +2 -0
  37. package/build/lib/fake-app.js.map +1 -1
  38. package/build/lib/fake-element.d.ts +12 -4
  39. package/build/lib/fake-element.d.ts.map +1 -1
  40. package/build/lib/fake-element.js +11 -4
  41. package/build/lib/fake-element.js.map +1 -1
  42. package/build/lib/scripts/fake-error.d.ts +1 -0
  43. package/build/lib/scripts/fake-error.js +11 -1
  44. package/build/lib/scripts/fake-error.js.map +1 -1
  45. package/build/lib/scripts/fake-stdin.d.ts +2 -0
  46. package/build/lib/scripts/fake-stdin.d.ts.map +1 -0
  47. package/build/lib/scripts/fake-stdin.js +13 -0
  48. package/build/lib/scripts/fake-stdin.js.map +1 -0
  49. package/lib/commands/alert.ts +70 -0
  50. package/lib/commands/{contexts.js → contexts.ts} +26 -34
  51. package/lib/commands/element.ts +138 -0
  52. package/lib/commands/find.ts +137 -0
  53. package/lib/commands/general.ts +115 -0
  54. package/lib/commands/{index.js → index.ts} +14 -5
  55. package/lib/commands/mixin.ts +13 -0
  56. package/lib/driver.js +41 -78
  57. package/lib/fake-app.js +3 -3
  58. package/lib/fake-element.js +21 -6
  59. package/lib/scripts/fake-error.js +8 -1
  60. package/lib/scripts/fake-stdin.js +9 -0
  61. package/package.json +4 -3
  62. package/lib/commands/alert.js +0 -73
  63. package/lib/commands/element.js +0 -161
  64. package/lib/commands/find.js +0 -118
  65. package/lib/commands/general.js +0 -147
@@ -0,0 +1,70 @@
1
+ import {FakeDriver} from '../driver';
2
+ import {errors} from 'appium/driver';
3
+ import {mixin} from './mixin';
4
+
5
+ interface FakeDriverAlertMixin {
6
+ assertNoAlert(): void;
7
+ assertAlert(): void;
8
+
9
+ getAlertText(): Promise<string>;
10
+
11
+ setAlertText(text: string): Promise<void>;
12
+
13
+ postAcceptAlert(): Promise<void>;
14
+ postDismissAlert(): Promise<void>;
15
+ }
16
+
17
+ declare module '../driver' {
18
+ interface FakeDriver extends FakeDriverAlertMixin {}
19
+ }
20
+
21
+ const AlertMixin: FakeDriverAlertMixin = {
22
+ assertNoAlert(this: FakeDriver) {
23
+ if (this.appModel.hasAlert()) {
24
+ throw new errors.UnexpectedAlertOpenError();
25
+ }
26
+ },
27
+
28
+ assertAlert(this: FakeDriver) {
29
+ if (!this.appModel.hasAlert()) {
30
+ throw new errors.NoAlertOpenError();
31
+ }
32
+ },
33
+
34
+ /**
35
+ * Get the text of an alert
36
+ */
37
+ async getAlertText(this: FakeDriver) {
38
+ this.assertAlert();
39
+ return this.appModel.alertText();
40
+ },
41
+
42
+ /**
43
+ * Set the text of an alert
44
+ */
45
+ async setAlertText(this: FakeDriver, text: string) {
46
+ this.assertAlert();
47
+ try {
48
+ this.appModel.setAlertText(text);
49
+ } catch (e) {
50
+ throw new errors.InvalidElementStateError();
51
+ }
52
+ },
53
+
54
+ /**
55
+ * Accept an alert
56
+ */
57
+ async postAcceptAlert(this: FakeDriver) {
58
+ this.assertAlert();
59
+ this.appModel.handleAlert();
60
+ },
61
+
62
+ /**
63
+ * Dismiss an alert
64
+ */
65
+ async postDismissAlert(this: FakeDriver) {
66
+ return this.postAcceptAlert();
67
+ },
68
+ };
69
+
70
+ mixin(AlertMixin);
@@ -1,55 +1,53 @@
1
1
  import _ from 'lodash';
2
+ import {FakeDriver} from '../driver';
2
3
  import {errors} from 'appium/driver';
4
+ import {mixin} from './mixin';
5
+ interface FakeDriverContextsMixin {
6
+ getRawContexts(): Record<string, any>;
7
+ assertWebviewContext(): void;
8
+ getCurrentContext(): Promise<string>;
9
+ getContexts(): Promise<string[]>;
10
+ setContext(context: string): Promise<void>;
11
+ setFrame(frame: number | null): Promise<void>;
12
+ }
13
+ declare module '../driver' {
14
+ interface FakeDriver extends FakeDriverContextsMixin {}
15
+ }
3
16
 
4
- export default {
5
- /**
6
- * @this {FakeDriver}
7
- */
8
- getRawContexts() {
9
- let contexts = {NATIVE_APP: null, PROXY: null};
10
- let wvs = this.appModel?.getWebviews() ?? [];
17
+ const ContextsMixin: FakeDriverContextsMixin = {
18
+ getRawContexts(this: FakeDriver) {
19
+ const contexts = {NATIVE_APP: null, PROXY: null};
20
+ const wvs = this.appModel.getWebviews() ?? [];
11
21
  for (let i = 1; i < wvs.length + 1; i++) {
12
22
  contexts[`WEBVIEW_${i}`] = wvs[i - 1];
13
23
  }
14
24
  return contexts;
15
25
  },
16
26
 
17
- /**
18
- * @this {FakeDriver}
19
- */
20
- assertWebviewContext() {
27
+ assertWebviewContext(this: FakeDriver) {
21
28
  if (this.curContext === 'NATIVE_APP') {
22
29
  throw new errors.InvalidContextError();
23
30
  }
24
31
  },
25
32
 
26
- /**
27
- * @returns {Promise<string>}
28
- * @this {FakeDriver}
29
- */
30
- async getCurrentContext() {
33
+ async getCurrentContext(this: FakeDriver): Promise<string> {
31
34
  return this.curContext;
32
35
  },
33
36
 
34
37
  /**
35
38
  * Get the list of available contexts
36
- *
37
- * @returns {Promise<string[]>}
38
- * @this {FakeDriver}
39
39
  */
40
- async getContexts() {
40
+ async getContexts(this: FakeDriver) {
41
41
  return _.keys(this.getRawContexts());
42
42
  },
43
43
 
44
44
  /**
45
45
  * Set the current context
46
46
  *
47
- * @param {string} context - name of the context
48
- * @returns {Promise<void>}
49
- * @this {FakeDriver}
47
+ * @param context - name of the context
50
48
  */
51
- async setContext(context) {
52
- let contexts = this.getRawContexts();
49
+ async setContext(this: FakeDriver, context: string) {
50
+ const contexts = this.getRawContexts();
53
51
  if (context in contexts) {
54
52
  this.curContext = context;
55
53
  if (context === 'NATIVE_APP') {
@@ -68,17 +66,13 @@ export default {
68
66
 
69
67
  /**
70
68
  * Set the active frame
71
- *
72
- * @param {number} frameId
73
- * @returns {Promise<void>}
74
- * @this {FakeDriver}
75
69
  */
76
- async setFrame(frameId) {
70
+ async setFrame(this: FakeDriver, frameId: number | null) {
77
71
  this.assertWebviewContext();
78
72
  if (frameId === null) {
79
73
  this.appModel.deactivateFrame();
80
74
  } else {
81
- let nodes = this.appModel.xpathQuery(`//iframe[@id="${frameId}"]`);
75
+ const nodes = this.appModel.xpathQuery(`//iframe[@id="${frameId}"]`);
82
76
  if (!nodes.length) {
83
77
  throw new errors.NoSuchFrameError();
84
78
  }
@@ -87,6 +81,4 @@ export default {
87
81
  },
88
82
  };
89
83
 
90
- /**
91
- * @typedef {import('../driver').FakeDriver} FakeDriver
92
- */
84
+ mixin(ContextsMixin);
@@ -0,0 +1,138 @@
1
+ import _ from 'lodash';
2
+ import {errors} from 'appium/driver';
3
+ import {FakeDriver} from '../driver';
4
+ import {Position, Rect, Size} from '@appium/types';
5
+ import {FakeElement} from '../fake-element';
6
+ import {mixin} from './mixin';
7
+
8
+ interface FakeDriverElementsMixin {
9
+ getElements(elementIds: string[]): FakeElement[];
10
+ getElement(elementId: string): FakeElement;
11
+ getName(elementId: string): Promise<string>;
12
+ elementDisplayed(elementId: string): Promise<boolean>;
13
+ elementEnabled(elementId: string): Promise<boolean>;
14
+ elementSelected(elementId: string): Promise<boolean>;
15
+ setValue(keys: string | string[], value: string): Promise<void>;
16
+ getText(elementId: string): Promise<string>;
17
+ clear(elementId: string): Promise<void>;
18
+ click(elementId: string): Promise<void>;
19
+
20
+ getAttribute(elementId: string, attributeName: string): Promise<string>;
21
+ getElementRect(elementId: string): Promise<Rect>;
22
+ getSize(elementId: string): Promise<Size>;
23
+ equalsElement(elementId: string, otherElementId: string): Promise<boolean>;
24
+ getCssProperty(elementId: string, propertyName: string): Promise<string>;
25
+ getLocation(elementId: string): Promise<Position>;
26
+ getLocationInView(elementId: string): Promise<Position>;
27
+ }
28
+
29
+ declare module '../driver' {
30
+ interface FakeDriver extends FakeDriverElementsMixin {}
31
+ }
32
+
33
+ const ElementsMixin: FakeDriverElementsMixin = {
34
+ getElements(this: FakeDriver, elementIds: string[]) {
35
+ for (const elId of elementIds) {
36
+ if (!_.has(this.elMap, elId)) {
37
+ throw new errors.StaleElementReferenceError();
38
+ }
39
+ }
40
+ return elementIds.map((e) => this.elMap[e]);
41
+ },
42
+
43
+ getElement(this: FakeDriver, elementId: string) {
44
+ return this.getElements([elementId])[0];
45
+ },
46
+
47
+ async getName(this: FakeDriver, elementId: string) {
48
+ const el = this.getElement(elementId);
49
+ return el.tagName;
50
+ },
51
+
52
+ async elementDisplayed(this: FakeDriver, elementId: string) {
53
+ const el = this.getElement(elementId);
54
+ return el.isVisible();
55
+ },
56
+
57
+ async elementEnabled(this: FakeDriver, elementId: string) {
58
+ const el = this.getElement(elementId);
59
+ return el.isEnabled();
60
+ },
61
+
62
+ async elementSelected(this: FakeDriver, elementId: string) {
63
+ const el = this.getElement(elementId);
64
+ return el.isSelected();
65
+ },
66
+
67
+ async setValue(this: FakeDriver, keys: string | string[], elementId: string) {
68
+ let value = keys;
69
+ if (keys instanceof Array) {
70
+ value = keys.join('');
71
+ }
72
+ const el = this.getElement(elementId);
73
+ if (el.type !== 'MockInputField') {
74
+ throw new errors.InvalidElementStateError();
75
+ }
76
+ el.setAttr('value', value);
77
+ },
78
+
79
+ async getText(this: FakeDriver, elementId: string) {
80
+ const el = this.getElement(elementId);
81
+ return el.getAttr('value');
82
+ },
83
+
84
+ async clear(this: FakeDriver, elementId: string) {
85
+ await this.setValue('', elementId);
86
+ },
87
+
88
+ /**
89
+ * This comment should be displayed instead of the one from ExternalDriver
90
+ */
91
+ async click(this: FakeDriver, elementId: string) {
92
+ this.assertNoAlert();
93
+ const el = this.getElement(elementId);
94
+ if (!el.isVisible()) {
95
+ throw new errors.InvalidElementStateError();
96
+ }
97
+ el.click();
98
+ this.focusedElId = elementId;
99
+ },
100
+
101
+ async getAttribute(this: FakeDriver, attr: string, elementId: string) {
102
+ const el = this.getElement(elementId);
103
+ return el.getAttr(attr);
104
+ },
105
+
106
+ async getElementRect(this: FakeDriver, elementId: string) {
107
+ const el = this.getElement(elementId);
108
+ return el.getElementRect();
109
+ },
110
+
111
+ async getSize(this: FakeDriver, elementId: string) {
112
+ const el = this.getElement(elementId);
113
+ return el.getSize();
114
+ },
115
+
116
+ async equalsElement(this: FakeDriver, elementIdA: string, elementIdB: string) {
117
+ const el1 = this.getElement(elementIdA);
118
+ const el2 = this.getElement(elementIdB);
119
+ return el1.equals(el2);
120
+ },
121
+
122
+ async getCssProperty(this: FakeDriver, prop: string, elementId: string) {
123
+ this.assertWebviewContext();
124
+ const el = this.getElement(elementId);
125
+ return el.getCss(prop);
126
+ },
127
+
128
+ async getLocation(this: FakeDriver, elementId: string) {
129
+ const el = this.getElement(elementId);
130
+ return el.getLocation();
131
+ },
132
+
133
+ async getLocationInView(this: FakeDriver, elementId: string) {
134
+ return this.getLocation(elementId);
135
+ },
136
+ };
137
+
138
+ mixin(ElementsMixin);
@@ -0,0 +1,137 @@
1
+ import _ from 'lodash';
2
+ import {Element} from '@appium/types';
3
+ import {errors} from 'appium/driver';
4
+ import {FakeElement} from '../fake-element';
5
+ import {FakeDriver} from '../driver';
6
+ import {util} from '@appium/support';
7
+ import {mixin} from './mixin';
8
+
9
+ const {W3C_WEB_ELEMENT_IDENTIFIER} = util;
10
+ interface FakeDriverFindMixin {
11
+ getExistingElementForNode(node: FakeElement): string | null;
12
+ wrapNewEl(obj: FakeElement): Element;
13
+
14
+ findElOrEls<Many extends boolean, Ctx = any>(
15
+ this: FakeDriver,
16
+ strategy: string,
17
+ selector: string,
18
+ many: Many,
19
+ context?: Ctx
20
+ ): Promise<Many extends true ? Element[] : Element>;
21
+ findElement(strategy: string, selector: string): Promise<Element>;
22
+ findElements(strategy: string, selector: string): Promise<Element[]>;
23
+ findElementFromElement(elementId: string, strategy: string, selector: string): Promise<Element>;
24
+ findElementsFromElement(
25
+ elementId: string,
26
+ strategy: string,
27
+ selector: string
28
+ ): Promise<Element[]>;
29
+ }
30
+
31
+ declare module '../driver' {
32
+ interface FakeDriver extends FakeDriverFindMixin {}
33
+ }
34
+
35
+ const FindMixin: FakeDriverFindMixin = {
36
+ getExistingElementForNode(this: FakeDriver, node) {
37
+ for (const [id, el] of _.toPairs(this.elMap)) {
38
+ if (el.node === node) {
39
+ return id;
40
+ }
41
+ }
42
+ return null;
43
+ },
44
+
45
+ wrapNewEl(this: FakeDriver, obj: FakeElement): Element {
46
+ // first check and see if we already have a ref to this element
47
+ const existingElId = this.getExistingElementForNode(obj);
48
+ if (existingElId) {
49
+ return {ELEMENT: existingElId, [W3C_WEB_ELEMENT_IDENTIFIER]: existingElId};
50
+ }
51
+
52
+ // otherwise add the element to the map
53
+ this.maxElId++;
54
+ const maxElId = this.maxElId.toString();
55
+ this.elMap[maxElId] = new FakeElement(obj, this.appModel);
56
+ return {ELEMENT: maxElId, [W3C_WEB_ELEMENT_IDENTIFIER]: maxElId};
57
+ },
58
+
59
+ async findElOrEls<Many extends boolean, Ctx = any>(
60
+ this: FakeDriver,
61
+ strategy: string,
62
+ selector: string,
63
+ many: Many,
64
+ context: Ctx
65
+ ): Promise<Many extends true ? Element[] : Element> {
66
+ const qMap = {
67
+ xpath: 'xpathQuery',
68
+ id: 'idQuery',
69
+ 'accessibility id': 'idQuery',
70
+ 'class name': 'classQuery',
71
+ 'tag name': 'classQuery',
72
+ 'css selector': 'cssQuery',
73
+ } as Record<string, keyof FakeDriver['appModel']>;
74
+ // TODO this error checking should probably be part of MJSONWP?
75
+ if (!_.includes(_.keys(qMap), strategy)) {
76
+ throw new errors.UnknownCommandError();
77
+ }
78
+ if (selector === 'badsel') {
79
+ throw new errors.InvalidSelectorError();
80
+ }
81
+ const els = this.appModel[qMap[strategy]](selector, context);
82
+
83
+ let retval: Element | Element[];
84
+ if (els.length) {
85
+ if (many) {
86
+ const allEls: Element[] = [];
87
+ for (const el of els) {
88
+ allEls.push(this.wrapNewEl(el));
89
+ }
90
+ retval = allEls;
91
+ } else {
92
+ retval = this.wrapNewEl(els[0]);
93
+ }
94
+ } else if (many) {
95
+ retval = [];
96
+ } else {
97
+ throw new errors.NoSuchElementError();
98
+ }
99
+ return retval as Many extends true ? Element[] : Element;
100
+ },
101
+
102
+ /**
103
+ * This should override whatever's in ExternalDriver
104
+ * @param {string} strategy Strategy
105
+ * @param {string} selector Selector
106
+ * @this {FakeDriver}
107
+ */
108
+ async findElement(this: FakeDriver, strategy: string, selector: string) {
109
+ return this.findElOrEls(strategy, selector, false);
110
+ },
111
+
112
+ async findElements(this: FakeDriver, strategy: string, selector: string) {
113
+ return this.findElOrEls(strategy, selector, true);
114
+ },
115
+
116
+ async findElementFromElement(
117
+ this: FakeDriver,
118
+ strategy: string,
119
+ selector: string,
120
+ elementId: string
121
+ ) {
122
+ const el = this.getElement(elementId);
123
+ return this.findElOrEls(strategy, selector, false, el.xmlFragment);
124
+ },
125
+
126
+ async findElementsFromElement(
127
+ this: FakeDriver,
128
+ strategy: string,
129
+ selector: string,
130
+ elementId: string
131
+ ) {
132
+ const el = this.getElement(elementId);
133
+ return this.findElOrEls(strategy, selector, true, el.xmlFragment);
134
+ },
135
+ };
136
+
137
+ mixin(FindMixin);
@@ -0,0 +1,115 @@
1
+ import {ActionSequence, Location, Rect, Size} from '@appium/types';
2
+ import {errors} from 'appium/driver';
3
+ import {FakeDriver, Orientation} from '../driver';
4
+ import {mixin} from './mixin';
5
+
6
+ const ORIENTATIONS = new Set(['LANDSCAPE', 'PORTRAIT']);
7
+
8
+ interface FakeDriverGeneralMixin {
9
+ title(): Promise<string>;
10
+ keys(value: string | string[]): Promise<void>;
11
+ setGeoLocation(location: Location): Promise<void>;
12
+ getGeoLocation(): Promise<Location>;
13
+ getPageSource(): Promise<string>;
14
+ getOrientation(): Promise<string>;
15
+ setOrientation(orientation: Orientation): Promise<void>;
16
+ getScreenshot(): Promise<string>;
17
+ getWindowSize(): Promise<Size>;
18
+ getWindowRect(): Promise<Rect>;
19
+ performActions(actions: ActionSequence[]): Promise<void>;
20
+ releaseActions(): Promise<void>;
21
+ mobileShake(): Promise<void>;
22
+ doubleClick(): Promise<void>;
23
+ execute(script: string, args: any[]): Promise<any>;
24
+ fakeAddition(a: number, b: number, c?: number): Promise<number>;
25
+ getLog(type: string): Promise<unknown[]>;
26
+ }
27
+
28
+ declare module '../driver' {
29
+ interface FakeDriver extends FakeDriverGeneralMixin {}
30
+ }
31
+
32
+ const GeneralMixin: FakeDriverGeneralMixin = {
33
+ async title(this: FakeDriver) {
34
+ this.assertWebviewContext();
35
+ return this.appModel.title;
36
+ },
37
+
38
+ async keys(this: FakeDriver, value: string | string[]) {
39
+ if (!this.focusedElId) {
40
+ throw new errors.InvalidElementStateError();
41
+ }
42
+ await this.setValue(value, this.focusedElId);
43
+ },
44
+
45
+ async setGeoLocation(this: FakeDriver, location: Location) {
46
+ // TODO test this adequately once WD bug is fixed
47
+ this.appModel.lat = location.latitude;
48
+ this.appModel.long = location.longitude;
49
+ },
50
+
51
+ async getGeoLocation(this: FakeDriver) {
52
+ return this.appModel.currentGeoLocation;
53
+ },
54
+
55
+ async getPageSource(this: FakeDriver) {
56
+ return this.appModel.rawXml;
57
+ },
58
+
59
+ async getOrientation(this: FakeDriver) {
60
+ return this.appModel.orientation;
61
+ },
62
+
63
+ async setOrientation(this: FakeDriver, o: Orientation) {
64
+ if (!ORIENTATIONS.has(o)) {
65
+ throw new errors.UnknownError('Orientation must be LANDSCAPE or PORTRAIT');
66
+ }
67
+ this.appModel.orientation = o;
68
+ },
69
+
70
+ async getScreenshot(this: FakeDriver) {
71
+ return this.appModel.getScreenshot();
72
+ },
73
+
74
+ async getWindowSize(this: FakeDriver) {
75
+ return {width: this.appModel.width, height: this.appModel.height};
76
+ },
77
+
78
+ async getWindowRect(this: FakeDriver) {
79
+ return {width: this.appModel.width, height: this.appModel.height, x: 0, y: 0};
80
+ },
81
+
82
+ async performActions(this: FakeDriver, actions: ActionSequence[]) {
83
+ this.appModel.actionLog.push(actions);
84
+ },
85
+
86
+ async releaseActions(this: FakeDriver) {},
87
+
88
+ async getLog(this: FakeDriver, type: string): Promise<ActionSequence[][]> {
89
+ switch (type) {
90
+ case 'actions':
91
+ return this.appModel.actionLog;
92
+ default:
93
+ throw new Error(`Don't understand log type '${type}'`);
94
+ }
95
+ },
96
+
97
+ async mobileShake(this: FakeDriver) {
98
+ this.shook = true;
99
+ },
100
+
101
+ async doubleClick(this: FakeDriver) {},
102
+
103
+ async execute(this: FakeDriver, script: string, args: any[]) {
104
+ return await this.executeMethod(script, args);
105
+ },
106
+
107
+ /**
108
+ * Add two or maybe even three numbers
109
+ */
110
+ async fakeAddition(this: FakeDriver, num1: number, num2: number, num3 = 0) {
111
+ return num1 + num2 + (num3 ?? 0);
112
+ },
113
+ };
114
+
115
+ mixin(GeneralMixin);
@@ -1,8 +1,17 @@
1
- export {default as alert} from './alert';
2
- export {default as contexts} from './contexts';
3
- export {default as element} from './element';
4
- export {default as find} from './find';
5
- export {default as general} from './general';
1
+ /**
2
+ * Export all of the "stuff" from these mixin files. The mixins themselves are not exported,
3
+ * but any types/interfaces that they export (e.g., options objects for some command) are exported.
4
+ *
5
+ * Mixins must not use `Object.assign()` and are expected to use the `mixin` function in the sibling
6
+ * `mixin` module.
7
+ * @module
8
+ */
9
+
10
+ import './alert';
11
+ import './contexts';
12
+ import './element';
13
+ import './find';
14
+ import './general';
6
15
 
7
16
  /* // TODO:
8
17
  //rest.post('/wd/hub/session/:sessionId?/touch/click', controller.doClick);
@@ -0,0 +1,13 @@
1
+ import {FakeDriver} from '../driver';
2
+
3
+ /**
4
+ * This function assigns a mixin `T` to the `FakeDriver` class' prototype.
5
+ * While each mixin has its own interface which is (in isolation) unrelated to `FakeDriver`, the constraint
6
+ * on this generic type `T` is that it must be a partial of `FakeDriver`'s interface. This enforces
7
+ * that it does not conflict with the existing interface of `FakeDriver`. In that way, you can
8
+ * think of it as a type guard.
9
+ * @param mixin Mixin implementation
10
+ */
11
+ export function mixin<T extends Partial<FakeDriver>>(mixin: T): void {
12
+ Object.assign(FakeDriver.prototype, mixin);
13
+ }