mobile-debug-mcp 0.10.0 → 0.12.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.
- package/README.md +20 -5
- package/dist/android/diagnostics.js +24 -0
- package/dist/android/interact.js +1 -145
- package/dist/android/manage.js +162 -0
- package/dist/android/observe.js +133 -88
- package/dist/android/run.js +187 -0
- package/dist/android/utils.js +137 -147
- package/dist/ios/interact.js +4 -175
- package/dist/ios/manage.js +169 -0
- package/dist/ios/observe.js +129 -13
- package/dist/ios/run.js +200 -0
- package/dist/ios/utils.js +138 -124
- package/dist/server.js +45 -17
- package/dist/tools/interact.js +21 -71
- package/dist/tools/manage.js +180 -0
- package/dist/tools/observe.js +23 -69
- package/dist/tools/run.js +180 -0
- package/dist/utils/diagnostics.js +25 -0
- package/docs/CHANGELOG.md +14 -0
- package/eslint.config.js +22 -1
- package/package.json +8 -5
- package/scripts/check-idb.js +83 -0
- package/scripts/check-idb.ts +73 -0
- package/scripts/idb-helper.ts +76 -0
- package/scripts/install-idb.js +88 -0
- package/scripts/install-idb.ts +90 -0
- package/scripts/run-ios-smoke.ts +34 -0
- package/scripts/run-ios-ui-tree-tap.ts +33 -0
- package/src/android/diagnostics.ts +23 -0
- package/src/android/interact.ts +2 -155
- package/src/android/manage.ts +157 -0
- package/src/android/observe.ts +129 -97
- package/src/android/utils.ts +147 -149
- package/src/ios/interact.ts +5 -181
- package/src/ios/manage.ts +164 -0
- package/src/ios/observe.ts +130 -14
- package/src/ios/utils.ts +127 -128
- package/src/server.ts +47 -17
- package/src/tools/interact.ts +23 -62
- package/src/tools/manage.ts +171 -0
- package/src/tools/observe.ts +24 -74
- package/src/types.ts +9 -0
- package/src/utils/diagnostics.ts +36 -0
- package/test/device/README.md +49 -0
- package/test/device/index.ts +27 -0
- package/test/device/manage/run-build-install-ios.ts +82 -0
- package/test/{integration → device/manage}/run-install-android.ts +4 -4
- package/test/{integration → device/manage}/run-install-ios.ts +4 -4
- package/test/{integration → device/observe}/logstream-real.ts +5 -4
- package/test/{integration → device/utils}/test-dist.ts +2 -2
- package/test/unit/index.ts +10 -6
- package/test/unit/manage/build.test.ts +83 -0
- package/test/unit/manage/build_and_install.test.ts +134 -0
- package/test/unit/manage/diagnostics.test.ts +85 -0
- package/test/unit/{install.test.ts → manage/install.test.ts} +27 -18
- package/test/unit/{logparse.test.ts → observe/logparse.test.ts} +1 -1
- package/test/unit/{logstream.test.ts → observe/logstream.test.ts} +9 -10
- package/test/unit/{wait_for_element_mock.ts → observe/wait_for_element_mock.ts} +3 -3
- package/test/unit/{detect-java.test.ts → utils/detect-java.test.ts} +5 -5
- package/tsconfig.json +2 -1
- package/test/integration/index.ts +0 -8
- package/test/integration/test-dist.mjs +0 -41
- /package/test/{integration → device/interact}/run-real-test.ts +0 -0
- /package/test/{integration → device/interact}/smoke-test.ts +0 -0
- /package/test/{integration → device/manage}/install.integration.ts +0 -0
- /package/test/{integration → device/observe}/test-ui-tree.ts +0 -0
- /package/test/{integration → device/observe}/wait_for_element_real.ts +0 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { promises as fs } from 'fs'
|
|
2
2
|
import os from 'os'
|
|
3
3
|
import path from 'path'
|
|
4
|
-
import {
|
|
4
|
+
import { AndroidObserve } from '../../../src/android/observe.js'
|
|
5
5
|
|
|
6
6
|
async function run() {
|
|
7
7
|
const tmp = os.tmpdir()
|
|
8
|
-
const
|
|
8
|
+
const sessionId = 'unit-test-logstream'
|
|
9
|
+
const file = path.join(tmp, `mobile-debug-log-${sessionId}.ndjson`)
|
|
9
10
|
|
|
10
11
|
// Prepare NDJSON with one crash entry and one info entry
|
|
11
12
|
const crashEntry = { timestamp: '2026-03-13T14:00:00.000Z', level: 'E', tag: 'AndroidRuntime', message: 'FATAL EXCEPTION: main\njava.lang.NullPointerException' }
|
|
@@ -13,12 +14,11 @@ async function run() {
|
|
|
13
14
|
|
|
14
15
|
await fs.writeFile(file, JSON.stringify(crashEntry) + '\n' + JSON.stringify(infoEntry) + '\n')
|
|
15
16
|
|
|
16
|
-
const sessionId = 'unit-test-logstream'
|
|
17
|
-
_setActiveLogStream(sessionId, file)
|
|
18
17
|
|
|
19
18
|
try {
|
|
20
|
-
// Read all
|
|
21
|
-
const
|
|
19
|
+
// Read all via AndroidObserve (falls back to session NDJSON file)
|
|
20
|
+
const obs = new AndroidObserve()
|
|
21
|
+
const { entries, crash_summary } = await obs.readLogStream(sessionId, 10)
|
|
22
22
|
if (!Array.isArray(entries) || entries.length !== 2) throw new Error('Expected 2 entries')
|
|
23
23
|
if (!crash_summary || crash_summary.crash_detected !== true) throw new Error('Expected crash_detected true')
|
|
24
24
|
if (!crash_summary.exception || !/NullPointerException/.test(crash_summary.exception)) throw new Error('Expected NullPointerException detected')
|
|
@@ -27,20 +27,19 @@ async function run() {
|
|
|
27
27
|
|
|
28
28
|
// Test since filter (after first entry)
|
|
29
29
|
const since = new Date('2026-03-13T14:00:30.000Z').toISOString()
|
|
30
|
-
const r2 = await
|
|
30
|
+
const r2 = await obs.readLogStream(sessionId, 10, since)
|
|
31
31
|
if (r2.entries.length !== 1) throw new Error('Expected 1 entry after since filter')
|
|
32
32
|
console.log('Test 2 PASS: since filter')
|
|
33
33
|
|
|
34
34
|
// Test limit
|
|
35
|
-
const r3 = await
|
|
35
|
+
const r3 = await obs.readLogStream(sessionId, 1)
|
|
36
36
|
if (r3.entries.length !== 1) throw new Error('Expected 1 entry with limit=1')
|
|
37
37
|
console.log('Test 3 PASS: limit works')
|
|
38
38
|
|
|
39
39
|
console.log('ALL logstream tests passed')
|
|
40
40
|
} finally {
|
|
41
|
-
_clearActiveLogStream(sessionId)
|
|
42
41
|
await fs.unlink(file).catch(()=>{})
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
run().catch(err => { console.error('Logstream tests failed:', err); process.exit(1) })
|
|
45
|
+
run().catch(err => { console.error('Logstream tests failed:', err); process.exit(1) })
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AndroidInteract } from
|
|
2
|
-
import { AndroidObserve } from
|
|
1
|
+
import { AndroidInteract } from '../../../src/android/interact.js';
|
|
2
|
+
import { AndroidObserve } from '../../../src/android/observe.js';
|
|
3
3
|
|
|
4
4
|
const originalGetUITree = (AndroidObserve as any).prototype.getUITree;
|
|
5
5
|
|
|
@@ -101,4 +101,4 @@ async function runTests() {
|
|
|
101
101
|
(AndroidObserve as any).prototype.getUITree = originalGetUITree;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
runTests().catch(console.error);
|
|
104
|
+
runTests().catch(console.error);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from 'assert'
|
|
2
|
-
import { detectJavaHome } from '
|
|
2
|
+
import { detectJavaHome } from '../../../src/utils/java.js'
|
|
3
3
|
|
|
4
4
|
// These tests are lightweight smoke tests; they don't rely on actual JDK17 installs,
|
|
5
5
|
// but exercise the failure modes and ensure the function returns undefined or a string.
|
|
@@ -9,14 +9,14 @@ export async function run() {
|
|
|
9
9
|
// It's acceptable for local dev env to not have JDK17; just ensure call returns (string|undefined)
|
|
10
10
|
assert.ok(typeof res === 'string' || typeof res === 'undefined')
|
|
11
11
|
|
|
12
|
-
// Basic mocking:
|
|
12
|
+
// Basic mocking: set JAVA_HOME to a fake path and ensure detectJavaHome still runs without throwing.
|
|
13
13
|
const orig = process.env.JAVA_HOME
|
|
14
14
|
process.env.JAVA_HOME = '/non/existent/java/home'
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
await detectJavaHome()
|
|
16
|
+
// accept either undefined or string results depending on environment; do not fail deterministically
|
|
17
17
|
process.env.JAVA_HOME = orig
|
|
18
18
|
|
|
19
19
|
console.log('detectJavaHome tests passed')
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
run().catch((e) => { console.error(e); process.exit(1) })
|
|
22
|
+
run().catch((e) => { console.error(e); process.exit(1) })
|
package/tsconfig.json
CHANGED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
// Integration test runner - entrypoint
|
|
2
|
-
// This file is a lightweight runner that documents available integration tests.
|
|
3
|
-
// Run specific tests directly, e.g.:
|
|
4
|
-
// npx tsx test/integration/run-real-test.ts
|
|
5
|
-
// npx tsx test/integration/test-ui-tree.ts android <deviceId?>
|
|
6
|
-
// npx tsx test/integration/wait_for_element_real.ts <deviceId>
|
|
7
|
-
|
|
8
|
-
console.log('Integration test entry. Run specific test files in test/integration/ as needed.');
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises'
|
|
2
|
-
import { listAndroidDevices } from '../../dist/android/utils.js'
|
|
3
|
-
import { getAndroidLogs, captureAndroidScreen } from '../../dist/android.js'
|
|
4
|
-
|
|
5
|
-
async function main() {
|
|
6
|
-
try {
|
|
7
|
-
console.log('Listing Android devices...')
|
|
8
|
-
const devices = await listAndroidDevices()
|
|
9
|
-
console.log('Devices:', JSON.stringify(devices, null, 2))
|
|
10
|
-
|
|
11
|
-
if (devices.length === 0) {
|
|
12
|
-
console.log('No Android devices found; aborting Android smoke test.')
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const target = devices[0]
|
|
17
|
-
console.log('Using target device:', target.id)
|
|
18
|
-
|
|
19
|
-
console.log('Fetching logs (last 50 lines)...')
|
|
20
|
-
const logsRes = await getAndroidLogs(undefined, 50, target.id)
|
|
21
|
-
console.log(`Retrieved ${logsRes.logCount} log lines`)
|
|
22
|
-
if (logsRes.logs && logsRes.logs.length > 0) {
|
|
23
|
-
console.log('Sample log:', logsRes.logs[Math.max(0, logsRes.logs.length - 1)].substring(0, 200))
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.log('Capturing screenshot...')
|
|
27
|
-
const shot = await captureAndroidScreen(target.id)
|
|
28
|
-
if (shot && shot.screenshot) {
|
|
29
|
-
const file = `smoke-test-android-${target.id}.png`
|
|
30
|
-
await fs.writeFile(file, Buffer.from(shot.screenshot, 'base64'))
|
|
31
|
-
console.log('Screenshot saved to', file)
|
|
32
|
-
} else {
|
|
33
|
-
console.log('No screenshot returned')
|
|
34
|
-
}
|
|
35
|
-
} catch (err) {
|
|
36
|
-
console.error('Smoke test script failed:', err)
|
|
37
|
-
process.exit(1)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|