appium-mcp 1.84.0 → 1.84.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 (100) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/command.d.ts +9 -0
  3. package/dist/command.d.ts.map +1 -1
  4. package/dist/command.js +29 -0
  5. package/dist/command.js.map +1 -1
  6. package/dist/tools/interactions/find.d.ts.map +1 -1
  7. package/dist/tools/interactions/find.js +2 -1
  8. package/dist/tools/interactions/find.js.map +1 -1
  9. package/package.json +2 -1
  10. package/server.json +2 -2
  11. package/src/command.ts +37 -0
  12. package/src/tools/interactions/find.ts +6 -1
  13. package/dist/tests/__mocks__/@appium/support.d.ts +0 -92
  14. package/dist/tests/__mocks__/@appium/support.d.ts.map +0 -1
  15. package/dist/tests/__mocks__/@appium/support.js +0 -66
  16. package/dist/tests/__mocks__/@appium/support.js.map +0 -1
  17. package/dist/tests/benchmark_model/benchmark_model.d.ts +0 -3
  18. package/dist/tests/benchmark_model/benchmark_model.d.ts.map +0 -1
  19. package/dist/tests/benchmark_model/benchmark_model.js +0 -617
  20. package/dist/tests/benchmark_model/benchmark_model.js.map +0 -1
  21. package/dist/tests/create-server.test.d.ts +0 -2
  22. package/dist/tests/create-server.test.d.ts.map +0 -1
  23. package/dist/tests/create-server.test.js +0 -586
  24. package/dist/tests/create-server.test.js.map +0 -1
  25. package/dist/tests/generate-all-locators.test.d.ts +0 -2
  26. package/dist/tests/generate-all-locators.test.d.ts.map +0 -1
  27. package/dist/tests/generate-all-locators.test.js +0 -136
  28. package/dist/tests/generate-all-locators.test.js.map +0 -1
  29. package/dist/tests/persistence.test.d.ts +0 -2
  30. package/dist/tests/persistence.test.d.ts.map +0 -1
  31. package/dist/tests/persistence.test.js +0 -116
  32. package/dist/tests/persistence.test.js.map +0 -1
  33. package/dist/tests/plugin.test.d.ts +0 -2
  34. package/dist/tests/plugin.test.d.ts.map +0 -1
  35. package/dist/tests/plugin.test.js +0 -399
  36. package/dist/tests/plugin.test.js.map +0 -1
  37. package/dist/tests/policy.test.d.ts +0 -2
  38. package/dist/tests/policy.test.d.ts.map +0 -1
  39. package/dist/tests/policy.test.js +0 -44
  40. package/dist/tests/policy.test.js.map +0 -1
  41. package/dist/tests/screenshot.test.d.ts +0 -2
  42. package/dist/tests/screenshot.test.d.ts.map +0 -1
  43. package/dist/tests/screenshot.test.js +0 -243
  44. package/dist/tests/screenshot.test.js.map +0 -1
  45. package/dist/tests/session-store.test.d.ts +0 -2
  46. package/dist/tests/session-store.test.d.ts.map +0 -1
  47. package/dist/tests/session-store.test.js +0 -459
  48. package/dist/tests/session-store.test.js.map +0 -1
  49. package/dist/tests/test-setup-wda.d.ts +0 -2
  50. package/dist/tests/test-setup-wda.d.ts.map +0 -1
  51. package/dist/tests/test-setup-wda.js +0 -199
  52. package/dist/tests/test-setup-wda.js.map +0 -1
  53. package/dist/tests/tools/evidence.test.d.ts +0 -2
  54. package/dist/tests/tools/evidence.test.d.ts.map +0 -1
  55. package/dist/tests/tools/evidence.test.js +0 -158
  56. package/dist/tests/tools/evidence.test.js.map +0 -1
  57. package/dist/tests/tools/gestures/ai-element.test.d.ts +0 -2
  58. package/dist/tests/tools/gestures/ai-element.test.d.ts.map +0 -1
  59. package/dist/tests/tools/gestures/ai-element.test.js +0 -114
  60. package/dist/tests/tools/gestures/ai-element.test.js.map +0 -1
  61. package/dist/tests/tools/gestures/swipe-scroll.test.d.ts +0 -2
  62. package/dist/tests/tools/gestures/swipe-scroll.test.d.ts.map +0 -1
  63. package/dist/tests/tools/gestures/swipe-scroll.test.js +0 -63
  64. package/dist/tests/tools/gestures/swipe-scroll.test.js.map +0 -1
  65. package/dist/tests/tools/interactions/webdriver-ai-element-rejection.test.d.ts +0 -2
  66. package/dist/tests/tools/interactions/webdriver-ai-element-rejection.test.d.ts.map +0 -1
  67. package/dist/tests/tools/interactions/webdriver-ai-element-rejection.test.js +0 -94
  68. package/dist/tests/tools/interactions/webdriver-ai-element-rejection.test.js.map +0 -1
  69. package/dist/tests/tools/llm-wording.test.d.ts +0 -2
  70. package/dist/tests/tools/llm-wording.test.d.ts.map +0 -1
  71. package/dist/tests/tools/llm-wording.test.js +0 -89
  72. package/dist/tests/tools/llm-wording.test.js.map +0 -1
  73. package/dist/tests/tools/session/device-info.test.d.ts +0 -2
  74. package/dist/tests/tools/session/device-info.test.d.ts.map +0 -1
  75. package/dist/tests/tools/session/device-info.test.js +0 -144
  76. package/dist/tests/tools/session/device-info.test.js.map +0 -1
  77. package/dist/tests/tools/session/file-transfer.test.d.ts +0 -2
  78. package/dist/tests/tools/session/file-transfer.test.d.ts.map +0 -1
  79. package/dist/tests/tools/session/file-transfer.test.js +0 -98
  80. package/dist/tests/tools/session/file-transfer.test.js.map +0 -1
  81. package/dist/tests/tools/session/session.test.d.ts +0 -2
  82. package/dist/tests/tools/session/session.test.d.ts.map +0 -1
  83. package/dist/tests/tools/session/session.test.js +0 -413
  84. package/dist/tests/tools/session/session.test.js.map +0 -1
  85. package/dist/tests/utils/collection.test.d.ts +0 -2
  86. package/dist/tests/utils/collection.test.d.ts.map +0 -1
  87. package/dist/tests/utils/collection.test.js +0 -87
  88. package/dist/tests/utils/collection.test.js.map +0 -1
  89. package/dist/tests/utils/paths.test.d.ts +0 -2
  90. package/dist/tests/utils/paths.test.d.ts.map +0 -1
  91. package/dist/tests/utils/paths.test.js +0 -21
  92. package/dist/tests/utils/paths.test.js.map +0 -1
  93. package/dist/tests/verify.test.d.ts +0 -2
  94. package/dist/tests/verify.test.d.ts.map +0 -1
  95. package/dist/tests/verify.test.js +0 -148
  96. package/dist/tests/verify.test.js.map +0 -1
  97. package/dist/tests/vision-finder.test.d.ts +0 -10
  98. package/dist/tests/vision-finder.test.d.ts.map +0 -1
  99. package/dist/tests/vision-finder.test.js +0 -420
  100. package/dist/tests/vision-finder.test.js.map +0 -1
@@ -1,136 +0,0 @@
1
- import { describe, test, expect } from '@jest/globals';
2
- import { generateAllElementLocators } from '../locators/generate-all-locators.js';
3
- describe('generateAllElementLocators', () => {
4
- // Sample XML for testing
5
- const sampleXML = `
6
- <hierarchy>
7
- <android.widget.FrameLayout resource-id="android:id/content">
8
- <android.widget.LinearLayout>
9
- <android.widget.TextView text="Hello World" resource-id="com.example:id/text_view" clickable="true" enabled="true" displayed="true" />
10
- <android.widget.Button text="Click Me" resource-id="com.example:id/button" clickable="true" enabled="true" displayed="true" />
11
- <android.widget.EditText text="" resource-id="com.example:id/edit_text" clickable="true" enabled="true" displayed="true" />
12
- </android.widget.LinearLayout>
13
- </android.widget.FrameLayout>
14
- </hierarchy>
15
- `;
16
- // Sample iOS XML for testing
17
- const sampleIOSXML = `
18
- <hierarchy>
19
- <XCUIElementTypeApplication>
20
- <XCUIElementTypeWindow>
21
- <XCUIElementTypeButton name="Click Me" enabled="true" visible="true" />
22
- <XCUIElementTypeTextField name="Enter text" enabled="true" visible="true" />
23
- <XCUIElementTypeStaticText name="Hello World" enabled="true" visible="true" />
24
- </XCUIElementTypeWindow>
25
- </XCUIElementTypeApplication>
26
- </hierarchy>
27
- `;
28
- test('should return an array when given valid XML', () => {
29
- // Call the function with the sample XML
30
- const result = generateAllElementLocators(sampleXML, true, 'uiautomator2');
31
- // Basic validation of the result
32
- expect(Array.isArray(result)).toBe(true);
33
- expect(result.length).toBeGreaterThan(0);
34
- // Verify the structure of the returned elements
35
- if (result.length > 0) {
36
- const element = result[0];
37
- expect(element).toHaveProperty('tagName');
38
- expect(element).toHaveProperty('locators');
39
- expect(element).toHaveProperty('text');
40
- expect(element).toHaveProperty('contentDesc');
41
- expect(element).toHaveProperty('resourceId');
42
- expect(element).toHaveProperty('clickable');
43
- expect(element).toHaveProperty('enabled');
44
- expect(element).toHaveProperty('displayed');
45
- }
46
- });
47
- test('should return an empty array when given invalid XML', () => {
48
- // Call the function with invalid XML (just a root element with no content)
49
- const result = generateAllElementLocators('<hierarchy></hierarchy>', true, 'uiautomator2');
50
- // Verify the result is an empty array or at least doesn't throw an error
51
- expect(Array.isArray(result)).toBe(true);
52
- expect(result.length).toBe(0);
53
- });
54
- test('should apply includeTagNames filter correctly', () => {
55
- // Call the function with filters
56
- const result = generateAllElementLocators(sampleXML, true, 'uiautomator2', {
57
- includeTagNames: ['android.widget.Button'],
58
- });
59
- // If the filter works, either the result will be empty (if no buttons found)
60
- // or all elements will be buttons
61
- if (result.length > 0) {
62
- expect(result.every((element) => element.tagName.includes('Button'))).toBe(true);
63
- }
64
- });
65
- test('should apply excludeTagNames filter correctly', () => {
66
- // Call the function with excludeTagNames filter
67
- const result = generateAllElementLocators(sampleXML, true, 'uiautomator2', {
68
- excludeTagNames: ['android.widget.Button'],
69
- });
70
- // Verify no Button elements are included
71
- expect(result.every((element) => !element.tagName.includes('Button'))).toBe(true);
72
- });
73
- test('should apply minAttributeCount filter correctly', () => {
74
- // Call the function with minAttributeCount filter
75
- const result = generateAllElementLocators(sampleXML, true, 'uiautomator2', {
76
- minAttributeCount: 3,
77
- });
78
- // All elements should have at least 3 attributes
79
- if (result.length > 0) {
80
- // We can't directly check the attributes count since we only have the processed elements
81
- // But we can verify that elements with fewer attributes are filtered out
82
- expect(result.length).toBeLessThanOrEqual(generateAllElementLocators(sampleXML, true, 'uiautomator2').length);
83
- }
84
- });
85
- test('should handle fetchableOnly filter for Android', () => {
86
- // Call the function with fetchableOnly filter
87
- const result = generateAllElementLocators(sampleXML, true, 'uiautomator2', {
88
- fetchableOnly: true,
89
- });
90
- // Verify the result contains only interactable elements
91
- if (result.length > 0) {
92
- const interactableTags = [
93
- 'EditText',
94
- 'Button',
95
- 'ImageButton',
96
- 'CheckBox',
97
- 'RadioButton',
98
- 'Switch',
99
- 'ToggleButton',
100
- 'TextView',
101
- ];
102
- expect(result.every((element) => interactableTags.some((tag) => element.tagName.includes(tag)) ||
103
- element.clickable === true)).toBe(true);
104
- }
105
- });
106
- test('should handle fetchableOnly filter for iOS', () => {
107
- // Call the function with fetchableOnly filter for iOS
108
- const result = generateAllElementLocators(sampleIOSXML, true, 'xcuitest', {
109
- fetchableOnly: true,
110
- });
111
- // Verify the result contains only interactable iOS elements
112
- if (result.length > 0) {
113
- const interactableTags = [
114
- 'XCUIElementTypeTextField',
115
- 'XCUIElementTypeSecureTextField',
116
- 'XCUIElementTypeButton',
117
- 'XCUIElementTypeImage',
118
- 'XCUIElementTypeSwitch',
119
- 'XCUIElementTypeStaticText',
120
- 'XCUIElementTypeTextView',
121
- 'XCUIElementTypeCell',
122
- 'XCUIElementTypeLink',
123
- ];
124
- expect(result.every((element) => interactableTags.some((tag) => element.tagName.includes(tag)))).toBe(true);
125
- }
126
- });
127
- test('should handle clickableOnly filter correctly', () => {
128
- // Call the function with clickableOnly filter
129
- const result = generateAllElementLocators(sampleXML, true, 'uiautomator2', {
130
- clickableOnly: true,
131
- });
132
- // Verify all elements are clickable
133
- expect(result.every((element) => element.clickable === true)).toBe(true);
134
- });
135
- });
136
- //# sourceMappingURL=generate-all-locators.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-all-locators.test.js","sourceRoot":"","sources":["../../src/tests/generate-all-locators.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=persistence.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"persistence.test.d.ts","sourceRoot":"","sources":["../../src/tests/persistence.test.ts"],"names":[],"mappings":""}
@@ -1,116 +0,0 @@
1
- import { afterEach, describe, expect, test } from '@jest/globals';
2
- import { createHash } from 'node:crypto';
3
- import { constants } from 'node:fs';
4
- import { access, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
5
- import os from 'node:os';
6
- import path from 'node:path';
7
- import { readAllPersistedSessions, } from '../persistence.js';
8
- const originalPersistencePath = process.env.APPIUM_MCP_PERSIST_REMOTE_SESSIONS_PATH;
9
- const tempDirs = [];
10
- afterEach(async () => {
11
- if (originalPersistencePath === undefined) {
12
- delete process.env.APPIUM_MCP_PERSIST_REMOTE_SESSIONS_PATH;
13
- }
14
- else {
15
- process.env.APPIUM_MCP_PERSIST_REMOTE_SESSIONS_PATH =
16
- originalPersistencePath;
17
- }
18
- await Promise.all(tempDirs.splice(0).map((dir) => rm(dir, { recursive: true, force: true })));
19
- });
20
- describe('readAllPersistedSessions', () => {
21
- test('skips a legacy file when the canonical hashed file also exists', async () => {
22
- const dir = await createTempPersistenceDir();
23
- const sessionId = 'session-123';
24
- const staleLegacy = persistedSession(sessionId, 'http://stale.example');
25
- const canonical = persistedSession(sessionId, 'http://valid.example');
26
- await writeSessionFile(dir, `${sessionId}.json`, staleLegacy);
27
- await writeSessionFile(dir, hashedSessionFilename(sessionId), canonical);
28
- const sessions = await readAllPersistedSessions();
29
- expect(sessions).toHaveLength(1);
30
- expect(sessions[0]).toMatchObject({
31
- sessionId,
32
- remoteServerUrl: 'http://valid.example',
33
- });
34
- await expectFileMissing(path.join(dir, `${sessionId}.json`));
35
- await expectCanonicalSession(dir, sessionId, 'http://valid.example');
36
- });
37
- test('removes a non-canonical duplicate when the canonical file also exists', async () => {
38
- const dir = await createTempPersistenceDir();
39
- const sessionId = 'session-456';
40
- const staleDuplicate = persistedSession(sessionId, 'http://stale.example');
41
- const canonical = persistedSession(sessionId, 'http://valid.example');
42
- await writeSessionFile(dir, 'duplicate-session.json', staleDuplicate);
43
- await writeSessionFile(dir, hashedSessionFilename(sessionId), canonical);
44
- const sessions = await readAllPersistedSessions();
45
- expect(sessions).toHaveLength(1);
46
- expect(sessions[0]).toMatchObject({
47
- sessionId,
48
- remoteServerUrl: 'http://valid.example',
49
- });
50
- await expectFileMissing(path.join(dir, 'duplicate-session.json'));
51
- await expectCanonicalSession(dir, sessionId, 'http://valid.example');
52
- });
53
- test('coalesces non-canonical duplicates when no canonical file exists yet', async () => {
54
- const dir = await createTempPersistenceDir();
55
- const sessionId = 'session-789';
56
- await writeSessionFile(dir, `${sessionId}.json`, persistedSession(sessionId, 'http://legacy.example'));
57
- await writeSessionFile(dir, 'duplicate-session.json', persistedSession(sessionId, 'http://duplicate.example'));
58
- const sessions = await readAllPersistedSessions();
59
- expect(sessions).toHaveLength(1);
60
- expect(sessions[0]?.sessionId).toBe(sessionId);
61
- expect(['http://legacy.example', 'http://duplicate.example']).toContain(sessions[0]?.remoteServerUrl);
62
- await expectFileMissing(path.join(dir, `${sessionId}.json`));
63
- await expectFileMissing(path.join(dir, 'duplicate-session.json'));
64
- await expectCanonicalSession(dir, sessionId, sessions[0].remoteServerUrl);
65
- });
66
- test('still migrates and returns a legacy file when no canonical file exists', async () => {
67
- const dir = await createTempPersistenceDir();
68
- const sessionId = 'legacy-session';
69
- const legacy = persistedSession(sessionId, 'http://legacy.example');
70
- await writeSessionFile(dir, `${sessionId}.json`, legacy);
71
- const sessions = await readAllPersistedSessions();
72
- expect(sessions).toHaveLength(1);
73
- expect(sessions[0]).toMatchObject({
74
- sessionId,
75
- remoteServerUrl: 'http://legacy.example',
76
- });
77
- await expectFileMissing(path.join(dir, `${sessionId}.json`));
78
- await expectCanonicalSession(dir, sessionId, 'http://legacy.example');
79
- });
80
- });
81
- async function createTempPersistenceDir() {
82
- const dir = await mkdtemp(path.join(os.tmpdir(), 'appium-mcp-sessions-'));
83
- tempDirs.push(dir);
84
- process.env.APPIUM_MCP_PERSIST_REMOTE_SESSIONS_PATH = dir;
85
- return dir;
86
- }
87
- async function writeSessionFile(dir, name, session) {
88
- await writeFile(path.join(dir, name), JSON.stringify(session, null, 2));
89
- }
90
- function persistedSession(sessionId, remoteServerUrl) {
91
- return {
92
- sessionId,
93
- remoteServerUrl,
94
- capabilities: { platformName: 'Android' },
95
- platform: 'Android',
96
- automationName: 'UiAutomator2',
97
- deviceName: 'Pixel',
98
- ownership: 'attached',
99
- };
100
- }
101
- function hashedSessionFilename(sessionId) {
102
- return `${createHash('sha256').update(sessionId).digest('hex')}.json`;
103
- }
104
- async function expectFileExists(filePath) {
105
- await expect(access(filePath, constants.F_OK)).resolves.toBeUndefined();
106
- }
107
- async function expectFileMissing(filePath) {
108
- await expect(access(filePath, constants.F_OK)).rejects.toThrow();
109
- }
110
- async function expectCanonicalSession(dir, sessionId, remoteServerUrl) {
111
- const filePath = path.join(dir, hashedSessionFilename(sessionId));
112
- await expectFileExists(filePath);
113
- const raw = await readFile(filePath, 'utf8');
114
- expect(JSON.parse(raw)).toMatchObject({ sessionId, remoteServerUrl });
115
- }
116
- //# sourceMappingURL=persistence.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"persistence.test.js","sourceRoot":"","sources":["../../src/tests/persistence.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=plugin.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin.test.d.ts","sourceRoot":"","sources":["../../src/tests/plugin.test.ts"],"names":[],"mappings":""}