@appium/fake-driver 6.0.2 → 6.1.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 (112) hide show
  1. package/LICENSE +201 -0
  2. package/build/lib/commands/alert.d.ts +10 -13
  3. package/build/lib/commands/alert.d.ts.map +1 -1
  4. package/build/lib/commands/alert.js +39 -46
  5. package/build/lib/commands/alert.js.map +1 -1
  6. package/build/lib/commands/contexts.d.ts +9 -13
  7. package/build/lib/commands/contexts.d.ts.map +1 -1
  8. package/build/lib/commands/contexts.js +55 -62
  9. package/build/lib/commands/contexts.js.map +1 -1
  10. package/build/lib/commands/element.d.ts +23 -26
  11. package/build/lib/commands/element.d.ts.map +1 -1
  12. package/build/lib/commands/element.js +100 -89
  13. package/build/lib/commands/element.js.map +1 -1
  14. package/build/lib/commands/find.d.ts +14 -17
  15. package/build/lib/commands/find.d.ts.map +1 -1
  16. package/build/lib/commands/find.js +66 -63
  17. package/build/lib/commands/find.js.map +1 -1
  18. package/build/lib/commands/general.d.ts +25 -28
  19. package/build/lib/commands/general.d.ts.map +1 -1
  20. package/build/lib/commands/general.js +90 -75
  21. package/build/lib/commands/general.js.map +1 -1
  22. package/build/lib/desired-caps.d.ts +14 -0
  23. package/build/lib/desired-caps.d.ts.map +1 -0
  24. package/build/lib/desired-caps.js +16 -0
  25. package/build/lib/desired-caps.js.map +1 -0
  26. package/build/lib/doctor/common.d.ts +11 -0
  27. package/build/lib/doctor/common.d.ts.map +1 -0
  28. package/build/lib/doctor/common.js +25 -0
  29. package/build/lib/doctor/common.js.map +1 -0
  30. package/build/lib/doctor/fake1.d.ts +3 -0
  31. package/build/lib/doctor/fake1.d.ts.map +1 -0
  32. package/build/lib/doctor/fake1.js +6 -0
  33. package/build/lib/doctor/fake1.js.map +1 -0
  34. package/build/lib/doctor/fake2.d.ts +3 -0
  35. package/build/lib/doctor/fake2.d.ts.map +1 -0
  36. package/build/lib/doctor/fake2.js +6 -0
  37. package/build/lib/doctor/fake2.js.map +1 -0
  38. package/build/lib/driver.d.ts +128 -156
  39. package/build/lib/driver.d.ts.map +1 -1
  40. package/build/lib/driver.js +146 -154
  41. package/build/lib/driver.js.map +1 -1
  42. package/build/lib/fake-app.d.ts +37 -45
  43. package/build/lib/fake-app.d.ts.map +1 -1
  44. package/build/lib/fake-app.js +57 -34
  45. package/build/lib/fake-app.js.map +1 -1
  46. package/build/lib/fake-driver-schema.d.ts +16 -11
  47. package/build/lib/fake-driver-schema.d.ts.map +1 -1
  48. package/build/lib/fake-driver-schema.js +2 -17
  49. package/build/lib/fake-driver-schema.js.map +1 -1
  50. package/build/lib/fake-element.d.ts +27 -26
  51. package/build/lib/fake-element.d.ts.map +1 -1
  52. package/build/lib/fake-element.js +19 -19
  53. package/build/lib/fake-element.js.map +1 -1
  54. package/build/lib/index.d.ts +2 -3
  55. package/build/lib/index.d.ts.map +1 -1
  56. package/build/lib/index.js +2 -6
  57. package/build/lib/index.js.map +1 -1
  58. package/build/lib/logger.d.ts +1 -2
  59. package/build/lib/logger.d.ts.map +1 -1
  60. package/build/lib/logger.js +2 -2
  61. package/build/lib/logger.js.map +1 -1
  62. package/build/lib/scripts/fake-error.d.ts.map +1 -1
  63. package/build/lib/scripts/fake-error.js.map +1 -1
  64. package/build/lib/scripts/fake-stdin.d.ts.map +1 -1
  65. package/build/lib/scripts/fake-stdin.js.map +1 -1
  66. package/build/lib/scripts/fake-success.d.ts.map +1 -1
  67. package/build/lib/scripts/fake-success.js +3 -6
  68. package/build/lib/scripts/fake-success.js.map +1 -1
  69. package/build/lib/server.d.ts +2 -1
  70. package/build/lib/server.d.ts.map +1 -1
  71. package/build/lib/server.js +3 -5
  72. package/build/lib/server.js.map +1 -1
  73. package/build/lib/types.d.ts +1 -1
  74. package/build/lib/types.d.ts.map +1 -1
  75. package/lib/commands/alert.ts +31 -61
  76. package/lib/commands/contexts.ts +50 -73
  77. package/lib/commands/element.ts +122 -135
  78. package/lib/commands/find.ts +100 -115
  79. package/lib/commands/general.ts +122 -127
  80. package/lib/desired-caps.ts +16 -0
  81. package/lib/doctor/common.ts +26 -0
  82. package/lib/doctor/fake1.ts +3 -0
  83. package/lib/doctor/fake2.ts +3 -0
  84. package/lib/driver.ts +321 -0
  85. package/lib/fake-app.ts +234 -0
  86. package/lib/fake-driver-schema.ts +43 -0
  87. package/lib/fake-element.ts +128 -0
  88. package/lib/{index.js → index.ts} +5 -9
  89. package/lib/logger.ts +3 -0
  90. package/lib/scripts/{fake-success.js → fake-success.ts} +1 -1
  91. package/lib/{server.js → server.ts} +3 -4
  92. package/lib/types.ts +1 -1
  93. package/package.json +11 -14
  94. package/tsconfig.json +2 -1
  95. package/build/lib/commands/index.d.ts +0 -14
  96. package/build/lib/commands/index.d.ts.map +0 -1
  97. package/build/lib/commands/index.js +0 -16
  98. package/build/lib/commands/index.js.map +0 -1
  99. package/build/lib/commands/mixin.d.ts +0 -11
  100. package/build/lib/commands/mixin.d.ts.map +0 -1
  101. package/build/lib/commands/mixin.js +0 -16
  102. package/build/lib/commands/mixin.js.map +0 -1
  103. package/lib/commands/index.ts +0 -14
  104. package/lib/commands/mixin.ts +0 -13
  105. package/lib/driver.js +0 -356
  106. package/lib/fake-app.js +0 -190
  107. package/lib/fake-driver-schema.js +0 -35
  108. package/lib/fake-element.js +0 -117
  109. package/lib/logger.js +0 -5
  110. package/test/fixtures/app.xml +0 -38
  111. /package/lib/scripts/{fake-error.js → fake-error.ts} +0 -0
  112. /package/lib/scripts/{fake-stdin.js → fake-stdin.ts} +0 -0
@@ -1,161 +1,146 @@
1
1
  import _ from 'lodash';
2
- import {Element} from '@appium/types';
2
+ import type {Element} from '@appium/types';
3
3
  import {errors} from 'appium/driver';
4
- import {FakeElement} from '../fake-element';
5
- import {FakeDriver} from '../driver';
4
+ import {FakeElement, type XmlNodeLike} from '../fake-element';
5
+ import type {FakeDriver} from '../driver';
6
6
  import {util} from 'appium/support';
7
- import {mixin} from './mixin';
8
7
 
9
8
  const {W3C_WEB_ELEMENT_IDENTIFIER} = util;
10
9
 
11
- async function findElOrEls<Ctx = any>(
12
- this: FakeDriver<any>,
10
+ /** Find an existing element id in elMap for the same underlying node (reference equality). */
11
+ export function getExistingElementForNode(
12
+ this: FakeDriver,
13
+ node: FakeElement
14
+ ): string | null {
15
+ for (const [id, el] of _.toPairs(this.elMap)) {
16
+ if (el.node === node.node) {
17
+ return id;
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+
23
+ /** Accepts either a FakeElement (reuse existing id) or a raw XmlNodeLike from xpath. */
24
+ export function wrapNewEl(
25
+ this: FakeDriver,
26
+ obj: FakeElement | XmlNodeLike
27
+ ): Element {
28
+ const node: XmlNodeLike = _.has(obj, 'node') && (obj as FakeElement).node
29
+ ? (obj as FakeElement).node
30
+ : (obj as XmlNodeLike);
31
+
32
+ if (_.has(obj, 'node')) {
33
+ const existingElId = this.getExistingElementForNode(obj as FakeElement);
34
+ if (existingElId) {
35
+ return {ELEMENT: existingElId, [W3C_WEB_ELEMENT_IDENTIFIER]: existingElId};
36
+ }
37
+ } else {
38
+ // raw node: reuse id if we already have an element for this node
39
+ for (const [id, el] of _.toPairs(this.elMap)) {
40
+ if (el.node === node) {
41
+ return {ELEMENT: id, [W3C_WEB_ELEMENT_IDENTIFIER]: id};
42
+ }
43
+ }
44
+ }
45
+
46
+ this.maxElId++;
47
+ const maxElId = this.maxElId.toString();
48
+ this.elMap[maxElId] = new FakeElement(node, this.appModel);
49
+ return {ELEMENT: maxElId, [W3C_WEB_ELEMENT_IDENTIFIER]: maxElId};
50
+ }
51
+
52
+ async function findElOrElsImpl<Ctx = unknown>(
53
+ this: FakeDriver,
13
54
  strategy: string,
14
55
  selector: string,
15
56
  mult: true,
16
57
  context?: Ctx
17
58
  ): Promise<Element[]>;
18
- async function findElOrEls<Ctx = any>(
19
- this: FakeDriver<any>,
59
+ async function findElOrElsImpl<Ctx = unknown>(
60
+ this: FakeDriver,
20
61
  strategy: string,
21
62
  selector: string,
22
63
  mult: false,
23
64
  context?: Ctx
24
65
  ): Promise<Element>;
25
- async function findElOrEls<Ctx = any>(
26
- this: FakeDriver<any>,
66
+ async function findElOrElsImpl<Ctx = unknown>(
67
+ this: FakeDriver,
27
68
  strategy: string,
28
69
  selector: string,
29
70
  mult: boolean,
30
71
  context?: Ctx
31
72
  ): Promise<Element | Element[]> {
32
- const qMap = {
73
+ // Map WebDriver locator strategy to FakeApp query method name.
74
+ const qMap: Record<string, 'xpathQuery' | 'idQuery' | 'classQuery' | 'cssQuery'> = {
33
75
  xpath: 'xpathQuery',
34
76
  id: 'idQuery',
35
77
  'accessibility id': 'idQuery',
36
78
  'class name': 'classQuery',
37
79
  'tag name': 'classQuery',
38
80
  'css selector': 'cssQuery',
39
- } as Record<string, keyof FakeDriver['appModel']>;
40
- // TODO this error checking should probably be part of MJSONWP?
81
+ };
41
82
  if (!_.includes(_.keys(qMap), strategy)) {
42
83
  throw new errors.UnknownCommandError();
43
84
  }
44
85
  if (selector === 'badsel') {
45
86
  throw new errors.InvalidSelectorError();
46
87
  }
47
- const els = this.appModel[qMap[strategy]](selector, context);
88
+ const methodName = qMap[strategy];
89
+ const raw = (this.appModel[methodName] as (sel: string, ctx?: unknown) => unknown).call(
90
+ this.appModel,
91
+ selector,
92
+ context
93
+ );
94
+ const els = _.isArray(raw) ? raw : raw ? [raw] : [];
48
95
 
49
- let retval: Element | Element[];
50
96
  if (els.length) {
51
97
  if (mult) {
52
- const allEls: Element[] = [];
53
- for (const el of els) {
54
- allEls.push(this.wrapNewEl(el));
55
- }
56
- retval = allEls;
57
- } else {
58
- retval = this.wrapNewEl(els[0]);
98
+ return els.map((el) => this.wrapNewEl(el as XmlNodeLike));
59
99
  }
60
- } else if (mult) {
61
- retval = [];
62
- } else {
63
- throw new errors.NoSuchElementError();
100
+ return this.wrapNewEl(els[0] as XmlNodeLike);
101
+ }
102
+ if (mult) {
103
+ return [];
64
104
  }
65
- return retval;
105
+ throw new errors.NoSuchElementError();
66
106
  }
67
107
 
68
- interface FakeDriverFindMixin {
69
- getExistingElementForNode(node: FakeElement): string | null;
70
- wrapNewEl(obj: FakeElement): Element;
71
-
72
- findElOrEls(
73
- this: FakeDriver,
74
- strategy: string,
75
- selector: string,
76
- mult: true,
77
- context?: any
78
- ): Promise<Element[]>;
79
- findElOrEls(
80
- this: FakeDriver,
81
- strategy: string,
82
- selector: string,
83
- mult: false,
84
- context?: any
85
- ): Promise<Element>;
86
- findElement(strategy: string, selector: string): Promise<Element>;
87
- findElements(strategy: string, selector: string): Promise<Element[]>;
88
- findElementFromElement(elementId: string, strategy: string, selector: string): Promise<Element>;
89
- findElementsFromElement(
90
- elementId: string,
91
- strategy: string,
92
- selector: string
93
- ): Promise<Element[]>;
94
- }
108
+ export const findElOrEls = findElOrElsImpl;
95
109
 
96
- declare module '../driver' {
97
- interface FakeDriver extends FakeDriverFindMixin {}
110
+ export async function findElement(
111
+ this: FakeDriver,
112
+ strategy: string,
113
+ selector: string
114
+ ): Promise<Element> {
115
+ return this.findElOrEls(strategy, selector, false);
98
116
  }
99
117
 
100
- const FindMixin: FakeDriverFindMixin = {
101
- getExistingElementForNode(this: FakeDriver, node) {
102
- for (const [id, el] of _.toPairs(this.elMap)) {
103
- if (el.node === node) {
104
- return id;
105
- }
106
- }
107
- return null;
108
- },
109
-
110
- wrapNewEl(this: FakeDriver, obj: FakeElement): Element {
111
- // first check and see if we already have a ref to this element
112
- const existingElId = this.getExistingElementForNode(obj);
113
- if (existingElId) {
114
- return {ELEMENT: existingElId, [W3C_WEB_ELEMENT_IDENTIFIER]: existingElId};
115
- }
116
-
117
- // otherwise add the element to the map
118
- this.maxElId++;
119
- const maxElId = this.maxElId.toString();
120
- this.elMap[maxElId] = new FakeElement(obj, this.appModel);
121
- return {ELEMENT: maxElId, [W3C_WEB_ELEMENT_IDENTIFIER]: maxElId};
122
- },
123
-
124
- findElOrEls,
118
+ // Protocol passes (strategy, selector, elementId) for find-from-element routes.
125
119
 
126
- /**
127
- * This should override whatever's in ExternalDriver
128
- * @param {string} strategy Strategy
129
- * @param {string} selector Selector
130
- * @this {FakeDriver}
131
- */
132
- async findElement(this: FakeDriver, strategy: string, selector: string) {
133
- return this.findElOrEls(strategy, selector, false);
134
- },
135
-
136
- async findElements(this: FakeDriver, strategy: string, selector: string) {
137
- return this.findElOrEls(strategy, selector, true);
138
- },
139
-
140
- async findElementFromElement(
141
- this: FakeDriver,
142
- strategy: string,
143
- selector: string,
144
- elementId: string
145
- ) {
146
- const el = this.getElement(elementId);
147
- return this.findElOrEls(strategy, selector, false, el.xmlFragment);
148
- },
120
+ export async function findElements(
121
+ this: FakeDriver,
122
+ strategy: string,
123
+ selector: string
124
+ ): Promise<Element[]> {
125
+ return this.findElOrEls(strategy, selector, true);
126
+ }
149
127
 
150
- async findElementsFromElement(
151
- this: FakeDriver,
152
- strategy: string,
153
- selector: string,
154
- elementId: string
155
- ) {
156
- const el = this.getElement(elementId);
157
- return this.findElOrEls(strategy, selector, true, el.xmlFragment);
158
- },
159
- };
128
+ export async function findElementFromElement(
129
+ this: FakeDriver,
130
+ strategy: string,
131
+ selector: string,
132
+ elementId: string
133
+ ): Promise<Element> {
134
+ const el = this.getElement(elementId);
135
+ return this.findElOrEls(strategy, selector, false, el.xmlFragment);
136
+ }
160
137
 
161
- mixin(FindMixin);
138
+ export async function findElementsFromElement(
139
+ this: FakeDriver,
140
+ strategy: string,
141
+ selector: string,
142
+ elementId: string
143
+ ): Promise<Element[]> {
144
+ const el = this.getElement(elementId);
145
+ return this.findElOrEls(strategy, selector, true, el.xmlFragment);
146
+ }
@@ -1,128 +1,123 @@
1
- import {ActionSequence, Location, Rect, Size} from '@appium/types';
1
+ import type {ActionSequence, Location, Rect, Size, Orientation} from '@appium/types';
2
2
  import {errors} from 'appium/driver';
3
- import {FakeDriver} from '../driver';
4
- import {mixin} from './mixin';
5
- import type {Orientation} from '../driver';
6
-
7
- const ORIENTATIONS = new Set(['LANDSCAPE', 'PORTRAIT']);
8
-
9
- interface FakeDriverGeneralMixin {
10
- title(): Promise<string>;
11
- keys(value: string | string[]): Promise<void>;
12
- setGeoLocation(location: Location): Promise<Location>;
13
- getGeoLocation(): Promise<Location>;
14
- getPageSource(): Promise<string>;
15
- getOrientation(): Promise<string>;
16
- setOrientation(orientation: Orientation): Promise<void>;
17
- getScreenshot(): Promise<string>;
18
- getWindowSize(): Promise<Size>;
19
- getWindowRect(): Promise<Rect>;
20
- performActions(actions: ActionSequence[]): Promise<void>;
21
- releaseActions(): Promise<void>;
22
- mobileShake(): Promise<void>;
23
- doubleClick(): Promise<void>;
24
- execute(script: string, args: any[]): Promise<any>;
25
- fakeAddition(a: number, b: number, c?: number): Promise<number>;
26
- getLog(type: string): Promise<any>;
27
- getUrl(): Promise<string>;
28
-
29
- bidiNavigate(context: string, url: string): Promise<void>;
30
- }
31
-
32
- declare module '../driver' {
33
- interface FakeDriver extends FakeDriverGeneralMixin {}
34
- }
35
-
36
- const GeneralMixin: FakeDriverGeneralMixin = {
37
- async title(this: FakeDriver) {
38
- this.assertWebviewContext();
39
- return this.appModel.title;
40
- },
41
-
42
- async keys(this: FakeDriver, value: string | string[]) {
43
- if (!this.focusedElId) {
44
- throw new errors.InvalidElementStateError();
45
- }
46
- await this.setValue(value, this.focusedElId);
47
- },
48
-
49
- async setGeoLocation(this: FakeDriver, location: Location) {
50
- // TODO test this adequately once WD bug is fixed
51
- this.appModel.lat = location.latitude;
52
- this.appModel.long = location.longitude;
53
- return location;
54
- },
55
-
56
- async getGeoLocation(this: FakeDriver) {
57
- return this.appModel.currentGeoLocation;
58
- },
59
-
60
- async getPageSource(this: FakeDriver) {
61
- return this.appModel.rawXml;
62
- },
63
-
64
- async getOrientation(this: FakeDriver) {
65
- return this.appModel.orientation;
66
- },
67
-
68
- async setOrientation(this: FakeDriver, o: Orientation) {
69
- if (!ORIENTATIONS.has(o)) {
70
- throw new errors.UnknownError('Orientation must be LANDSCAPE or PORTRAIT');
71
- }
72
- this.appModel.orientation = o;
73
- },
74
-
75
- async getScreenshot(this: FakeDriver) {
76
- return this.appModel.getScreenshot();
77
- },
78
-
79
- async getWindowSize(this: FakeDriver) {
80
- return {width: this.appModel.width, height: this.appModel.height};
81
- },
82
-
83
- async getWindowRect(this: FakeDriver) {
84
- return {width: this.appModel.width, height: this.appModel.height, x: 0, y: 0};
85
- },
86
-
87
- async performActions(this: FakeDriver, actions: ActionSequence[]) {
88
- this.appModel.actionLog.push(actions);
89
- },
90
-
91
- async releaseActions(this: FakeDriver) {},
92
-
93
- async getLog(this: FakeDriver, type: string): Promise<ActionSequence[][]> {
94
- switch (type) {
95
- case 'actions':
96
- return this.appModel.actionLog;
97
- default:
98
- throw new Error(`Don't understand log type '${type}'`);
99
- }
100
- },
101
-
102
- async mobileShake(this: FakeDriver) {
103
- this.shook = true;
104
- },
105
-
106
- async doubleClick(this: FakeDriver) {},
107
-
108
- async execute(this: FakeDriver, script: string, args: any[]) {
109
- return await this.executeMethod(script, args);
110
- },
111
-
112
- /**
113
- * Add two or maybe even three numbers
114
- */
115
- async fakeAddition(this: FakeDriver, num1: number, num2: number, num3 = 0) {
116
- return num1 + num2 + (num3 ?? 0);
117
- },
118
-
119
- async getUrl() {
120
- return this.url;
121
- },
122
-
123
- async bidiNavigate(context: string, url: string) {
124
- this.url = url;
125
- },
126
- };
127
-
128
- mixin(GeneralMixin);
3
+ import type {FakeDriver} from '../driver';
4
+
5
+ const ORIENTATIONS = new Set<string>(['LANDSCAPE', 'PORTRAIT']);
6
+
7
+ /** Requires webview context (title comes from active document). */
8
+ export async function title(this: FakeDriver): Promise<string> {
9
+ this.assertWebviewContext();
10
+ return this.appModel.title;
11
+ }
12
+
13
+ export async function keys(
14
+ this: FakeDriver,
15
+ value: string | string[]
16
+ ): Promise<void> {
17
+ if (!this.focusedElId) {
18
+ throw new errors.InvalidElementStateError();
19
+ }
20
+ await this.setValue(value, this.focusedElId);
21
+ }
22
+
23
+ export async function setGeoLocation(
24
+ this: FakeDriver,
25
+ location: Location
26
+ ): Promise<Location> {
27
+ this.appModel.lat = location.latitude;
28
+ this.appModel.long = location.longitude;
29
+ return location;
30
+ }
31
+
32
+ export async function getGeoLocation(this: FakeDriver): Promise<Location> {
33
+ return this.appModel.currentGeoLocation;
34
+ }
35
+
36
+ export async function getPageSource(this: FakeDriver): Promise<string> {
37
+ return this.appModel.rawXml;
38
+ }
39
+
40
+ export async function getOrientation(this: FakeDriver): Promise<string> {
41
+ return this.appModel.orientation;
42
+ }
43
+
44
+ export async function setOrientation(
45
+ this: FakeDriver,
46
+ o: Orientation
47
+ ): Promise<void> {
48
+ if (!ORIENTATIONS.has(o)) {
49
+ throw new errors.UnknownError('Orientation must be LANDSCAPE or PORTRAIT');
50
+ }
51
+ this.appModel.orientation = o;
52
+ }
53
+
54
+ export async function getScreenshot(this: FakeDriver): Promise<string> {
55
+ return this.appModel.getScreenshot();
56
+ }
57
+
58
+ export async function getWindowSize(this: FakeDriver): Promise<Size> {
59
+ return {width: this.appModel.width, height: this.appModel.height};
60
+ }
61
+
62
+ export async function getWindowRect(this: FakeDriver): Promise<Rect> {
63
+ return {width: this.appModel.width, height: this.appModel.height, x: 0, y: 0};
64
+ }
65
+
66
+ export async function performActions(
67
+ this: FakeDriver,
68
+ actions: ActionSequence[]
69
+ ): Promise<void> {
70
+ this.appModel.actionLog.push(actions);
71
+ }
72
+
73
+ export async function releaseActions(this: FakeDriver): Promise<void> {}
74
+
75
+ /** Supported log types: 'actions'. TODO: add more log types if needed for tests. */
76
+ export async function getLog(
77
+ this: FakeDriver,
78
+ type: string
79
+ ): Promise<ActionSequence[][]> {
80
+ switch (type) {
81
+ case 'actions':
82
+ return this.appModel.actionLog;
83
+ default:
84
+ throw new Error(`Don't understand log type '${type}'`);
85
+ }
86
+ }
87
+
88
+ export async function mobileShake(this: FakeDriver): Promise<void> {
89
+ this.shook = true;
90
+ }
91
+
92
+ export async function doubleClick(this: FakeDriver): Promise<void> {}
93
+
94
+ export async function execute(
95
+ this: FakeDriver,
96
+ script: string,
97
+ args: any[]
98
+ ): Promise<any> {
99
+ return await this.executeMethod(script, args);
100
+ }
101
+
102
+ export async function fakeAddition(
103
+ this: FakeDriver,
104
+ num1: number,
105
+ num2: number,
106
+ num3 = 0
107
+ ): Promise<number> {
108
+ return num1 + num2 + (num3 ?? 0);
109
+ }
110
+
111
+ /** Get current URL. Returns empty string until bidiNavigate (or equivalent) sets one. @see https://w3c.github.io/webdriver/#get-current-url */
112
+ export async function getUrl(this: FakeDriver): Promise<string> {
113
+ return this.url ?? '';
114
+ }
115
+
116
+ /** Set current URL (used by Bidi browsingContext.navigate). */
117
+ export async function bidiNavigate(
118
+ this: FakeDriver,
119
+ context: string,
120
+ url: string
121
+ ): Promise<void> {
122
+ this.url = url;
123
+ }
@@ -0,0 +1,16 @@
1
+ import type {Constraints} from '@appium/types';
2
+
3
+ export const desiredCapConstraints = {
4
+ app: {
5
+ presence: true,
6
+ isString: true,
7
+ },
8
+ uniqueApp: {
9
+ isBoolean: true,
10
+ },
11
+ runClock: {
12
+ isBoolean: true,
13
+ },
14
+ } as const satisfies Constraints;
15
+
16
+ export type FakeDriverConstraints = typeof desiredCapConstraints;
@@ -0,0 +1,26 @@
1
+ import {doctor} from 'appium/support';
2
+ import type {IDoctorCheck, AppiumLogger, DoctorCheckResult} from '@appium/types';
3
+
4
+ export class EnvVarAndPathCheck implements IDoctorCheck {
5
+ log!: AppiumLogger;
6
+
7
+ constructor(private readonly varName: string) {}
8
+
9
+ async diagnose(): Promise<DoctorCheckResult> {
10
+ return doctor.ok(
11
+ `${this.varName} environment variable is always set because it's fake`
12
+ );
13
+ }
14
+
15
+ async fix(): Promise<string> {
16
+ return `Make sure the environment variable ${this.varName} is properly configured for the Appium server process`;
17
+ }
18
+
19
+ hasAutofix(): boolean {
20
+ return false;
21
+ }
22
+
23
+ isOptional(): boolean {
24
+ return false;
25
+ }
26
+ }
@@ -0,0 +1,3 @@
1
+ import {EnvVarAndPathCheck} from './common';
2
+
3
+ export const fakeCheck1 = new EnvVarAndPathCheck('FAKE1');
@@ -0,0 +1,3 @@
1
+ import {EnvVarAndPathCheck} from './common';
2
+
3
+ export const fakeCheck2 = new EnvVarAndPathCheck('FAKE2');