@testdroid-ai/cli 0.1.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.
- package/dist/adb/adb-path-resolver.d.ts +6 -0
- package/dist/adb/adb-path-resolver.d.ts.map +1 -0
- package/dist/adb/adb-path-resolver.js +93 -0
- package/dist/adb/adb-path-resolver.js.map +1 -0
- package/dist/adb/adb-shell.d.ts +29 -0
- package/dist/adb/adb-shell.d.ts.map +1 -0
- package/dist/adb/adb-shell.js +128 -0
- package/dist/adb/adb-shell.js.map +1 -0
- package/dist/adb/detector.d.ts +12 -0
- package/dist/adb/detector.d.ts.map +1 -0
- package/dist/adb/detector.js +44 -0
- package/dist/adb/detector.js.map +1 -0
- package/dist/adb/device-tracker.d.ts +23 -0
- package/dist/adb/device-tracker.d.ts.map +1 -0
- package/dist/adb/device-tracker.js +134 -0
- package/dist/adb/device-tracker.js.map +1 -0
- package/dist/adb/emulator-detector.d.ts +11 -0
- package/dist/adb/emulator-detector.d.ts.map +1 -0
- package/dist/adb/emulator-detector.js +54 -0
- package/dist/adb/emulator-detector.js.map +1 -0
- package/dist/appium/health-check.d.ts +6 -0
- package/dist/appium/health-check.d.ts.map +1 -0
- package/dist/appium/health-check.js +61 -0
- package/dist/appium/health-check.js.map +1 -0
- package/dist/appium/session-manager.d.ts +15 -0
- package/dist/appium/session-manager.d.ts.map +1 -0
- package/dist/appium/session-manager.js +82 -0
- package/dist/appium/session-manager.js.map +1 -0
- package/dist/auth/credential-store.d.ts +31 -0
- package/dist/auth/credential-store.d.ts.map +1 -0
- package/dist/auth/credential-store.js +154 -0
- package/dist/auth/credential-store.js.map +1 -0
- package/dist/auth/pairing-auth.d.ts +26 -0
- package/dist/auth/pairing-auth.d.ts.map +1 -0
- package/dist/auth/pairing-auth.js +177 -0
- package/dist/auth/pairing-auth.js.map +1 -0
- package/dist/auth/token-manager.d.ts +20 -0
- package/dist/auth/token-manager.d.ts.map +1 -0
- package/dist/auth/token-manager.js +101 -0
- package/dist/auth/token-manager.js.map +1 -0
- package/dist/commands/connect.d.ts +9 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +270 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/devices.d.ts +2 -0
- package/dist/commands/devices.d.ts.map +1 -0
- package/dist/commands/devices.js +52 -0
- package/dist/commands/devices.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +214 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/mirror.d.ts +2 -0
- package/dist/commands/mirror.d.ts.map +1 -0
- package/dist/commands/mirror.js +77 -0
- package/dist/commands/mirror.js.map +1 -0
- package/dist/commands/prompt.d.ts +12 -0
- package/dist/commands/prompt.d.ts.map +1 -0
- package/dist/commands/prompt.js +174 -0
- package/dist/commands/prompt.js.map +1 -0
- package/dist/commands/record.d.ts +7 -0
- package/dist/commands/record.d.ts.map +1 -0
- package/dist/commands/record.js +129 -0
- package/dist/commands/record.js.map +1 -0
- package/dist/commands/run.d.ts +16 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +271 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +50 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +32 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/healing/ai-adapter.d.ts +44 -0
- package/dist/healing/ai-adapter.d.ts.map +1 -0
- package/dist/healing/ai-adapter.js +87 -0
- package/dist/healing/ai-adapter.js.map +1 -0
- package/dist/healing/healer.d.ts +109 -0
- package/dist/healing/healer.d.ts.map +1 -0
- package/dist/healing/healer.js +475 -0
- package/dist/healing/healer.js.map +1 -0
- package/dist/healing/similarity.d.ts +63 -0
- package/dist/healing/similarity.d.ts.map +1 -0
- package/dist/healing/similarity.js +172 -0
- package/dist/healing/similarity.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/dist/recording/capture-strategies/capture-strategy.interface.d.ts +6 -0
- package/dist/recording/capture-strategies/capture-strategy.interface.d.ts.map +1 -0
- package/dist/recording/capture-strategies/capture-strategy.interface.js +3 -0
- package/dist/recording/capture-strategies/capture-strategy.interface.js.map +1 -0
- package/dist/recording/capture-strategies/getevent.strategy.d.ts +27 -0
- package/dist/recording/capture-strategies/getevent.strategy.d.ts.map +1 -0
- package/dist/recording/capture-strategies/getevent.strategy.js +163 -0
- package/dist/recording/capture-strategies/getevent.strategy.js.map +1 -0
- package/dist/recording/capture-strategies/key-capture.strategy.d.ts +16 -0
- package/dist/recording/capture-strategies/key-capture.strategy.d.ts.map +1 -0
- package/dist/recording/capture-strategies/key-capture.strategy.js +67 -0
- package/dist/recording/capture-strategies/key-capture.strategy.js.map +1 -0
- package/dist/recording/capture-strategies/logcat-capture.strategy.d.ts +32 -0
- package/dist/recording/capture-strategies/logcat-capture.strategy.d.ts.map +1 -0
- package/dist/recording/capture-strategies/logcat-capture.strategy.js +176 -0
- package/dist/recording/capture-strategies/logcat-capture.strategy.js.map +1 -0
- package/dist/recording/confidence-scorer.d.ts +13 -0
- package/dist/recording/confidence-scorer.d.ts.map +1 -0
- package/dist/recording/confidence-scorer.js +34 -0
- package/dist/recording/confidence-scorer.js.map +1 -0
- package/dist/recording/event-capture.d.ts +40 -0
- package/dist/recording/event-capture.d.ts.map +1 -0
- package/dist/recording/event-capture.js +168 -0
- package/dist/recording/event-capture.js.map +1 -0
- package/dist/recording/recorder.d.ts +32 -0
- package/dist/recording/recorder.d.ts.map +1 -0
- package/dist/recording/recorder.js +107 -0
- package/dist/recording/recorder.js.map +1 -0
- package/dist/runner/adb-executor.d.ts +116 -0
- package/dist/runner/adb-executor.d.ts.map +1 -0
- package/dist/runner/adb-executor.js +323 -0
- package/dist/runner/adb-executor.js.map +1 -0
- package/dist/runner/appium-executor.d.ts +35 -0
- package/dist/runner/appium-executor.d.ts.map +1 -0
- package/dist/runner/appium-executor.js +191 -0
- package/dist/runner/appium-executor.js.map +1 -0
- package/dist/runner/parse-strategies/appium-default.strategy.d.ts +12 -0
- package/dist/runner/parse-strategies/appium-default.strategy.d.ts.map +1 -0
- package/dist/runner/parse-strategies/appium-default.strategy.js +342 -0
- package/dist/runner/parse-strategies/appium-default.strategy.js.map +1 -0
- package/dist/runner/parse-strategies/index.d.ts +7 -0
- package/dist/runner/parse-strategies/index.d.ts.map +1 -0
- package/dist/runner/parse-strategies/index.js +14 -0
- package/dist/runner/parse-strategies/index.js.map +1 -0
- package/dist/runner/parse-strategies/java.strategy.d.ts +8 -0
- package/dist/runner/parse-strategies/java.strategy.d.ts.map +1 -0
- package/dist/runner/parse-strategies/java.strategy.js +170 -0
- package/dist/runner/parse-strategies/java.strategy.js.map +1 -0
- package/dist/runner/parse-strategies/maestro.strategy.d.ts +8 -0
- package/dist/runner/parse-strategies/maestro.strategy.d.ts.map +1 -0
- package/dist/runner/parse-strategies/maestro.strategy.js +105 -0
- package/dist/runner/parse-strategies/maestro.strategy.js.map +1 -0
- package/dist/runner/parse-strategies/python.strategy.d.ts +8 -0
- package/dist/runner/parse-strategies/python.strategy.d.ts.map +1 -0
- package/dist/runner/parse-strategies/python.strategy.js +140 -0
- package/dist/runner/parse-strategies/python.strategy.js.map +1 -0
- package/dist/runner/parse-strategies/robot.strategy.d.ts +8 -0
- package/dist/runner/parse-strategies/robot.strategy.d.ts.map +1 -0
- package/dist/runner/parse-strategies/robot.strategy.js +81 -0
- package/dist/runner/parse-strategies/robot.strategy.js.map +1 -0
- package/dist/runner/parse-strategies/types.d.ts +17 -0
- package/dist/runner/parse-strategies/types.d.ts.map +1 -0
- package/dist/runner/parse-strategies/types.js +3 -0
- package/dist/runner/parse-strategies/types.js.map +1 -0
- package/dist/runner/parse-strategies/utils.d.ts +39 -0
- package/dist/runner/parse-strategies/utils.d.ts.map +1 -0
- package/dist/runner/parse-strategies/utils.js +217 -0
- package/dist/runner/parse-strategies/utils.js.map +1 -0
- package/dist/runner/script-parser.d.ts +43 -0
- package/dist/runner/script-parser.d.ts.map +1 -0
- package/dist/runner/script-parser.js +68 -0
- package/dist/runner/script-parser.js.map +1 -0
- package/dist/runner/selector-resolver.d.ts +87 -0
- package/dist/runner/selector-resolver.d.ts.map +1 -0
- package/dist/runner/selector-resolver.js +206 -0
- package/dist/runner/selector-resolver.js.map +1 -0
- package/dist/runner/step-executor.d.ts +112 -0
- package/dist/runner/step-executor.d.ts.map +1 -0
- package/dist/runner/step-executor.js +518 -0
- package/dist/runner/step-executor.js.map +1 -0
- package/dist/runner/test-runner.d.ts +89 -0
- package/dist/runner/test-runner.d.ts.map +1 -0
- package/dist/runner/test-runner.js +320 -0
- package/dist/runner/test-runner.js.map +1 -0
- package/dist/scrcpy/launcher.d.ts +16 -0
- package/dist/scrcpy/launcher.d.ts.map +1 -0
- package/dist/scrcpy/launcher.js +87 -0
- package/dist/scrcpy/launcher.js.map +1 -0
- package/dist/services/device-poller.d.ts +10 -0
- package/dist/services/device-poller.d.ts.map +1 -0
- package/dist/services/device-poller.js +44 -0
- package/dist/services/device-poller.js.map +1 -0
- package/dist/services/execution-manager.d.ts +18 -0
- package/dist/services/execution-manager.d.ts.map +1 -0
- package/dist/services/execution-manager.js +185 -0
- package/dist/services/execution-manager.js.map +1 -0
- package/dist/services/recording-manager.d.ts +13 -0
- package/dist/services/recording-manager.d.ts.map +1 -0
- package/dist/services/recording-manager.js +234 -0
- package/dist/services/recording-manager.js.map +1 -0
- package/dist/setup/adb-installer.d.ts +8 -0
- package/dist/setup/adb-installer.d.ts.map +1 -0
- package/dist/setup/adb-installer.js +115 -0
- package/dist/setup/adb-installer.js.map +1 -0
- package/dist/setup/appium-installer.d.ts +8 -0
- package/dist/setup/appium-installer.d.ts.map +1 -0
- package/dist/setup/appium-installer.js +113 -0
- package/dist/setup/appium-installer.js.map +1 -0
- package/dist/setup/base-installer.d.ts +33 -0
- package/dist/setup/base-installer.d.ts.map +1 -0
- package/dist/setup/base-installer.js +170 -0
- package/dist/setup/base-installer.js.map +1 -0
- package/dist/setup/build-tools-installer.d.ts +8 -0
- package/dist/setup/build-tools-installer.d.ts.map +1 -0
- package/dist/setup/build-tools-installer.js +109 -0
- package/dist/setup/build-tools-installer.js.map +1 -0
- package/dist/setup/java-installer.d.ts +8 -0
- package/dist/setup/java-installer.d.ts.map +1 -0
- package/dist/setup/java-installer.js +132 -0
- package/dist/setup/java-installer.js.map +1 -0
- package/dist/setup/paths.d.ts +12 -0
- package/dist/setup/paths.d.ts.map +1 -0
- package/dist/setup/paths.js +90 -0
- package/dist/setup/paths.js.map +1 -0
- package/dist/setup/scrcpy-installer.d.ts +8 -0
- package/dist/setup/scrcpy-installer.d.ts.map +1 -0
- package/dist/setup/scrcpy-installer.js +143 -0
- package/dist/setup/scrcpy-installer.js.map +1 -0
- package/dist/setup/setup-manager.d.ts +18 -0
- package/dist/setup/setup-manager.d.ts.map +1 -0
- package/dist/setup/setup-manager.js +113 -0
- package/dist/setup/setup-manager.js.map +1 -0
- package/dist/ws/socket.d.ts +38 -0
- package/dist/ws/socket.d.ts.map +1 -0
- package/dist/ws/socket.js +91 -0
- package/dist/ws/socket.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../../src/healing/similarity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAiChE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAgB3D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAa/D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CAmBxD;AAWD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,SAAS,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,aAAa,GAAG,WAAW,CAAC;CAChE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,EAAE,EACrB,MAAM,EAAE;IACN,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACA,mBAAmB,EAAE,CA8DvB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Funcoes de similaridade para o motor de self-healing.
|
|
4
|
+
*
|
|
5
|
+
* Implementa Levenshtein distance sem dependencias externas
|
|
6
|
+
* para comparar seletores e encontrar elementos semelhantes.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.levenshteinDistance = levenshteinDistance;
|
|
10
|
+
exports.textSimilarity = textSimilarity;
|
|
11
|
+
exports.containsSimilarity = containsSimilarity;
|
|
12
|
+
exports.parseUiElements = parseUiElements;
|
|
13
|
+
exports.findSimilarElements = findSimilarElements;
|
|
14
|
+
/**
|
|
15
|
+
* Calcula a distancia de Levenshtein entre duas strings.
|
|
16
|
+
* Retorna o numero minimo de edicoes (insercoes, remocoes, substituicoes)
|
|
17
|
+
* necessarias para transformar `a` em `b`.
|
|
18
|
+
*/
|
|
19
|
+
function levenshteinDistance(a, b) {
|
|
20
|
+
const lenA = a.length;
|
|
21
|
+
const lenB = b.length;
|
|
22
|
+
// Caso base
|
|
23
|
+
if (lenA === 0)
|
|
24
|
+
return lenB;
|
|
25
|
+
if (lenB === 0)
|
|
26
|
+
return lenA;
|
|
27
|
+
// Matriz de distancias (otimizada para usar apenas 2 linhas)
|
|
28
|
+
let prevRow = new Array(lenB + 1);
|
|
29
|
+
let currRow = new Array(lenB + 1);
|
|
30
|
+
for (let j = 0; j <= lenB; j++) {
|
|
31
|
+
prevRow[j] = j;
|
|
32
|
+
}
|
|
33
|
+
for (let i = 1; i <= lenA; i++) {
|
|
34
|
+
currRow[0] = i;
|
|
35
|
+
for (let j = 1; j <= lenB; j++) {
|
|
36
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
37
|
+
currRow[j] = Math.min(prevRow[j] + 1, // remocao
|
|
38
|
+
currRow[j - 1] + 1, // insercao
|
|
39
|
+
prevRow[j - 1] + cost);
|
|
40
|
+
}
|
|
41
|
+
// Trocar linhas
|
|
42
|
+
[prevRow, currRow] = [currRow, prevRow];
|
|
43
|
+
}
|
|
44
|
+
return prevRow[lenB];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Calcula a similaridade entre duas strings (0-100).
|
|
48
|
+
* Baseado na distancia de Levenshtein normalizada.
|
|
49
|
+
*
|
|
50
|
+
* @returns Valor de 0 (completamente diferente) a 100 (identico)
|
|
51
|
+
*/
|
|
52
|
+
function textSimilarity(a, b) {
|
|
53
|
+
if (a === b)
|
|
54
|
+
return 100;
|
|
55
|
+
if (!a || !b)
|
|
56
|
+
return 0;
|
|
57
|
+
const aLower = a.toLowerCase();
|
|
58
|
+
const bLower = b.toLowerCase();
|
|
59
|
+
if (aLower === bLower)
|
|
60
|
+
return 95;
|
|
61
|
+
const distance = levenshteinDistance(aLower, bLower);
|
|
62
|
+
const maxLen = Math.max(aLower.length, bLower.length);
|
|
63
|
+
if (maxLen === 0)
|
|
64
|
+
return 100;
|
|
65
|
+
const similarity = ((maxLen - distance) / maxLen) * 100;
|
|
66
|
+
return Math.round(similarity);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Verifica se uma string contem a outra (match parcial).
|
|
70
|
+
* Retorna confianca de 0-100.
|
|
71
|
+
*/
|
|
72
|
+
function containsSimilarity(a, b) {
|
|
73
|
+
if (!a || !b)
|
|
74
|
+
return 0;
|
|
75
|
+
const aLower = a.toLowerCase();
|
|
76
|
+
const bLower = b.toLowerCase();
|
|
77
|
+
if (aLower.includes(bLower) || bLower.includes(aLower)) {
|
|
78
|
+
const shorter = Math.min(aLower.length, bLower.length);
|
|
79
|
+
const longer = Math.max(aLower.length, bLower.length);
|
|
80
|
+
return Math.round((shorter / longer) * 90);
|
|
81
|
+
}
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Extrai todos os elementos do XML do UI dump.
|
|
86
|
+
*/
|
|
87
|
+
function parseUiElements(xml) {
|
|
88
|
+
const elements = [];
|
|
89
|
+
const nodeRegex = /<node\s[^>]*>/g;
|
|
90
|
+
let match;
|
|
91
|
+
while ((match = nodeRegex.exec(xml)) !== null) {
|
|
92
|
+
const nodeStr = match[0];
|
|
93
|
+
elements.push({
|
|
94
|
+
nodeStr,
|
|
95
|
+
resourceId: extractAttr(nodeStr, 'resource-id'),
|
|
96
|
+
text: extractAttr(nodeStr, 'text'),
|
|
97
|
+
className: extractAttr(nodeStr, 'class'),
|
|
98
|
+
contentDesc: extractAttr(nodeStr, 'content-desc'),
|
|
99
|
+
bounds: extractAttr(nodeStr, 'bounds'),
|
|
100
|
+
clickable: extractAttr(nodeStr, 'clickable') === 'true',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return elements;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Extrai o valor de um atributo de um node XML.
|
|
107
|
+
*/
|
|
108
|
+
function extractAttr(nodeStr, attrName) {
|
|
109
|
+
const regex = new RegExp(`${attrName}="([^"]*)"`);
|
|
110
|
+
const match = nodeStr.match(regex);
|
|
111
|
+
return match ? match[1] : '';
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Encontra elementos similares ao alvo no UI dump.
|
|
115
|
+
* Retorna candidatos ordenados por confianca (maior primeiro).
|
|
116
|
+
*
|
|
117
|
+
* @param elements Lista de elementos do UI dump
|
|
118
|
+
* @param target Atributos do elemento original
|
|
119
|
+
* @returns Lista de matches ordenados por confianca
|
|
120
|
+
*/
|
|
121
|
+
function findSimilarElements(elements, target) {
|
|
122
|
+
const matches = [];
|
|
123
|
+
for (const element of elements) {
|
|
124
|
+
let bestConfidence = 0;
|
|
125
|
+
let bestMatchedBy = 'text';
|
|
126
|
+
// Comparar por resourceId
|
|
127
|
+
if (target.resourceId && element.resourceId) {
|
|
128
|
+
const sim = textSimilarity(target.resourceId, element.resourceId);
|
|
129
|
+
const containsSim = containsSimilarity(target.resourceId, element.resourceId);
|
|
130
|
+
const bestSim = Math.max(sim, containsSim);
|
|
131
|
+
if (bestSim > bestConfidence) {
|
|
132
|
+
bestConfidence = bestSim;
|
|
133
|
+
bestMatchedBy = 'resourceId';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Comparar por texto
|
|
137
|
+
if (target.text && element.text) {
|
|
138
|
+
const sim = textSimilarity(target.text, element.text);
|
|
139
|
+
if (sim > bestConfidence) {
|
|
140
|
+
bestConfidence = sim;
|
|
141
|
+
bestMatchedBy = 'text';
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Comparar por content-desc
|
|
145
|
+
if (target.contentDesc && element.contentDesc) {
|
|
146
|
+
const sim = textSimilarity(target.contentDesc, element.contentDesc);
|
|
147
|
+
if (sim > bestConfidence) {
|
|
148
|
+
bestConfidence = sim;
|
|
149
|
+
bestMatchedBy = 'contentDesc';
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Comparar por classe (bonus se mesma classe)
|
|
153
|
+
if (target.className && element.className === target.className) {
|
|
154
|
+
// Se ja tem match parcial, boost a confianca
|
|
155
|
+
if (bestConfidence > 0) {
|
|
156
|
+
bestConfidence = Math.min(100, bestConfidence + 10);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Apenas incluir se tem alguma similaridade relevante
|
|
160
|
+
if (bestConfidence >= 40) {
|
|
161
|
+
matches.push({
|
|
162
|
+
element,
|
|
163
|
+
confidence: bestConfidence,
|
|
164
|
+
matchedBy: bestMatchedBy,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Ordenar por confianca (maior primeiro)
|
|
169
|
+
matches.sort((a, b) => b.confidence - a.confidence);
|
|
170
|
+
return matches;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=similarity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"similarity.js","sourceRoot":"","sources":["../../src/healing/similarity.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
// Node.js version check
|
|
5
|
+
const [nodeMajor] = process.versions.node.split('.').map(Number);
|
|
6
|
+
if (nodeMajor < 20) {
|
|
7
|
+
console.error(`TestDroid requires Node.js >= 20. Current: ${process.version}`);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const commander_1 = require("commander");
|
|
11
|
+
const devices_1 = require("./commands/devices");
|
|
12
|
+
const mirror_1 = require("./commands/mirror");
|
|
13
|
+
const connect_1 = require("./commands/connect");
|
|
14
|
+
const record_1 = require("./commands/record");
|
|
15
|
+
const run_1 = require("./commands/run");
|
|
16
|
+
const prompt_1 = require("./commands/prompt");
|
|
17
|
+
const doctor_1 = require("./commands/doctor");
|
|
18
|
+
const status_1 = require("./commands/status");
|
|
19
|
+
const setup_1 = require("./commands/setup");
|
|
20
|
+
const program = new commander_1.Command();
|
|
21
|
+
program
|
|
22
|
+
.name('testdroid')
|
|
23
|
+
.description('TestDroid AI - CLI for mobile test automation')
|
|
24
|
+
.version('0.1.0');
|
|
25
|
+
program
|
|
26
|
+
.command('devices')
|
|
27
|
+
.description('List all connected Android devices')
|
|
28
|
+
.action(async () => {
|
|
29
|
+
await (0, devices_1.devicesCommand)();
|
|
30
|
+
});
|
|
31
|
+
program
|
|
32
|
+
.command('mirror [serial]')
|
|
33
|
+
.description('Mirror device screen via scrcpy')
|
|
34
|
+
.action(async (serial) => {
|
|
35
|
+
await (0, mirror_1.mirrorCommand)(serial);
|
|
36
|
+
});
|
|
37
|
+
program
|
|
38
|
+
.command('connect')
|
|
39
|
+
.description('Connect local devices to TestDroid server')
|
|
40
|
+
.option('--server <url>', 'Server URL')
|
|
41
|
+
.option('--token <token>', 'Auth token (legacy, prefer pairing)')
|
|
42
|
+
.option('--no-browser', 'Do not auto-open browser for pairing')
|
|
43
|
+
.option('--poll', 'Use polling instead of event-driven tracking')
|
|
44
|
+
.action(async (options) => {
|
|
45
|
+
await (0, connect_1.connectCommand)(options);
|
|
46
|
+
});
|
|
47
|
+
program
|
|
48
|
+
.command('doctor')
|
|
49
|
+
.description('Check prerequisites and system health')
|
|
50
|
+
.action(async () => {
|
|
51
|
+
await (0, doctor_1.doctorCommand)();
|
|
52
|
+
});
|
|
53
|
+
program
|
|
54
|
+
.command('setup')
|
|
55
|
+
.description('Install all dependencies (ADB, Java, Appium, scrcpy)')
|
|
56
|
+
.option('--check', 'Show installation status')
|
|
57
|
+
.option('--clean', 'Remove all installed dependencies')
|
|
58
|
+
.option('--component <name>', 'Install specific component (adb, java, appium, scrcpy)')
|
|
59
|
+
.action(async (options) => {
|
|
60
|
+
await (0, setup_1.setupCommand)(options);
|
|
61
|
+
});
|
|
62
|
+
program
|
|
63
|
+
.command('status')
|
|
64
|
+
.description('Show current session and connection status')
|
|
65
|
+
.action(async () => {
|
|
66
|
+
await (0, status_1.statusCommand)();
|
|
67
|
+
});
|
|
68
|
+
program
|
|
69
|
+
.command('record [serial]')
|
|
70
|
+
.description('Record touch events from an Android device')
|
|
71
|
+
.option('--output <file>', 'Output file path')
|
|
72
|
+
.option('--no-screenshots', 'Disable screenshot capture')
|
|
73
|
+
.option('--no-appium', 'Desabilitar auto-deteccao do Appium')
|
|
74
|
+
.option('--appium-url <url>', 'URL do servidor Appium (default: http://localhost:4723)')
|
|
75
|
+
.action(async (serial, options) => {
|
|
76
|
+
await (0, record_1.recordCommand)(serial, {
|
|
77
|
+
output: options?.output,
|
|
78
|
+
noScreenshots: options?.screenshots === false,
|
|
79
|
+
appium: options?.appium,
|
|
80
|
+
appiumUrl: options?.appiumUrl,
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
program
|
|
84
|
+
.command('run <file>')
|
|
85
|
+
.description('Execute a test file on a connected Android device')
|
|
86
|
+
.option('--serial <serial>', 'Device serial')
|
|
87
|
+
.option('--package <package>', 'Android app package name')
|
|
88
|
+
.option('--timeout <ms>', 'Timeout in milliseconds')
|
|
89
|
+
.option('--report-to <url>', 'Backend URL for result reporting')
|
|
90
|
+
.option('--no-heal', 'Disable selector self-healing')
|
|
91
|
+
.option('--appium-url <url>', 'URL do servidor Appium (default: http://localhost:4723)')
|
|
92
|
+
.action(async (file, options) => {
|
|
93
|
+
await (0, run_1.runCommand)(file, options);
|
|
94
|
+
});
|
|
95
|
+
program
|
|
96
|
+
.command('prompt <texto>')
|
|
97
|
+
.description('Generate test code from natural language description')
|
|
98
|
+
.option('--package <package>', 'Android app package name')
|
|
99
|
+
.option('--language <language>', 'Test language (appium-ts, appium-js, playwright)')
|
|
100
|
+
.option('--output <file>', 'Output file path')
|
|
101
|
+
.option('--url <url>', 'Backend server URL')
|
|
102
|
+
.option('--token <token>', 'Backend auth token')
|
|
103
|
+
.action(async (texto, options) => {
|
|
104
|
+
await (0, prompt_1.promptCommand)(texto, options);
|
|
105
|
+
});
|
|
106
|
+
program.parse(process.argv);
|
|
107
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture-strategy.interface.d.ts","sourceRoot":"","sources":["../../../src/recording/capture-strategies/capture-strategy.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,IAAI,IAAI,CAAC;CACd"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture-strategy.interface.js","sourceRoot":"","sources":["../../../src/recording/capture-strategies/capture-strategy.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RecordingEvent } from '@testdroid-ai/shared';
|
|
2
|
+
import { CaptureStrategy } from './capture-strategy.interface';
|
|
3
|
+
export declare class GeteventStrategy implements CaptureStrategy {
|
|
4
|
+
private serial;
|
|
5
|
+
private process;
|
|
6
|
+
private eventCount;
|
|
7
|
+
private screenSize;
|
|
8
|
+
private rawX;
|
|
9
|
+
private rawY;
|
|
10
|
+
private touchDown;
|
|
11
|
+
private touchStartCaptured;
|
|
12
|
+
private touchStartTime;
|
|
13
|
+
private touchStartX;
|
|
14
|
+
private touchStartY;
|
|
15
|
+
private inputMax;
|
|
16
|
+
constructor(serial: string);
|
|
17
|
+
setScreenSize(size: {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
}): void;
|
|
21
|
+
start(onEvent: (event: RecordingEvent) => void): Promise<void>;
|
|
22
|
+
stop(): void;
|
|
23
|
+
private detectInputRange;
|
|
24
|
+
private parseRawGetevent;
|
|
25
|
+
private emitGesture;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=getevent.strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getevent.strategy.d.ts","sourceRoot":"","sources":["../../../src/recording/capture-strategies/getevent.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAsB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,qBAAa,gBAAiB,YAAW,eAAe;IAe1C,OAAO,CAAC,MAAM;IAd1B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,UAAU,CAAiC;IAGnD,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAA0B;gBAEtB,MAAM,EAAE,MAAM;IAElC,aAAa,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAItD,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBpE,IAAI,IAAI,IAAI;IAWZ,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,gBAAgB;IA4CxB,OAAO,CAAC,WAAW;CA+CpB"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GeteventStrategy = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
class GeteventStrategy {
|
|
6
|
+
serial;
|
|
7
|
+
process = null;
|
|
8
|
+
eventCount = 0;
|
|
9
|
+
screenSize = { width: 1080, height: 2400 };
|
|
10
|
+
// getevent state
|
|
11
|
+
rawX = 0;
|
|
12
|
+
rawY = 0;
|
|
13
|
+
touchDown = false;
|
|
14
|
+
touchStartCaptured = false; // true once we've captured start position
|
|
15
|
+
touchStartTime = 0;
|
|
16
|
+
touchStartX = 0;
|
|
17
|
+
touchStartY = 0;
|
|
18
|
+
inputMax = { x: 32767, y: 32767 };
|
|
19
|
+
constructor(serial) {
|
|
20
|
+
this.serial = serial;
|
|
21
|
+
}
|
|
22
|
+
setScreenSize(size) {
|
|
23
|
+
this.screenSize = size;
|
|
24
|
+
}
|
|
25
|
+
async start(onEvent) {
|
|
26
|
+
this.eventCount = 0;
|
|
27
|
+
this.detectInputRange();
|
|
28
|
+
this.process = (0, child_process_1.spawn)('adb', ['-s', this.serial, 'shell', 'getevent', '-t'], {
|
|
29
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
30
|
+
});
|
|
31
|
+
let buffer = '';
|
|
32
|
+
this.process.stdout?.on('data', (data) => {
|
|
33
|
+
buffer += data.toString();
|
|
34
|
+
const lines = buffer.split('\n');
|
|
35
|
+
buffer = lines.pop() || '';
|
|
36
|
+
for (const line of lines) {
|
|
37
|
+
this.parseRawGetevent(line.trim(), onEvent);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
this.process.stderr?.on('data', () => { });
|
|
41
|
+
this.process.on('error', () => { });
|
|
42
|
+
}
|
|
43
|
+
stop() {
|
|
44
|
+
if (this.process) {
|
|
45
|
+
try {
|
|
46
|
+
this.process.kill('SIGKILL');
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// process may already be dead
|
|
50
|
+
}
|
|
51
|
+
this.process = null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
detectInputRange() {
|
|
55
|
+
try {
|
|
56
|
+
const output = (0, child_process_1.execFileSync)('adb', ['-s', this.serial, 'shell', 'getevent', '-lp'], { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 });
|
|
57
|
+
// Try multitouch first, fall back to single-touch (emulator virtio)
|
|
58
|
+
const xMax = output.match(/ABS_MT_POSITION_X[\s\S]*?max\s+(\d+)/)
|
|
59
|
+
|| output.match(/ABS_X[\s\S]*?max\s+(\d+)/);
|
|
60
|
+
const yMax = output.match(/ABS_MT_POSITION_Y[\s\S]*?max\s+(\d+)/)
|
|
61
|
+
|| output.match(/ABS_Y[\s\S]*?max\s+(\d+)/);
|
|
62
|
+
if (xMax)
|
|
63
|
+
this.inputMax.x = parseInt(xMax[1], 10);
|
|
64
|
+
if (yMax)
|
|
65
|
+
this.inputMax.y = parseInt(yMax[1], 10);
|
|
66
|
+
}
|
|
67
|
+
catch { }
|
|
68
|
+
}
|
|
69
|
+
parseRawGetevent(line, onEvent) {
|
|
70
|
+
if (!line || line.startsWith('add device'))
|
|
71
|
+
return;
|
|
72
|
+
const match = line.match(/\[\s*[\d.]+\]\s*\/dev\/input\/event\d+:\s*([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)/);
|
|
73
|
+
if (!match)
|
|
74
|
+
return;
|
|
75
|
+
const type = parseInt(match[1], 16);
|
|
76
|
+
const code = parseInt(match[2], 16);
|
|
77
|
+
// Parse as unsigned, then convert to signed 32-bit for tracking ID comparison
|
|
78
|
+
const rawValue = parseInt(match[3], 16);
|
|
79
|
+
const value = rawValue > 0x7fffffff ? rawValue - 0x100000000 : rawValue;
|
|
80
|
+
if (type === 3) {
|
|
81
|
+
// ABS_MT_POSITION_X (0x35) for multitouch, ABS_X (0x00) for emulator virtio
|
|
82
|
+
if (code === 0x35 || code === 0x00)
|
|
83
|
+
this.rawX = value;
|
|
84
|
+
// ABS_MT_POSITION_Y (0x36) for multitouch, ABS_Y (0x01) for emulator virtio
|
|
85
|
+
else if (code === 0x36 || code === 0x01)
|
|
86
|
+
this.rawY = value;
|
|
87
|
+
else if (code === 0x39) {
|
|
88
|
+
if (value === -1)
|
|
89
|
+
this.emitGesture(onEvent);
|
|
90
|
+
else if (!this.touchDown) {
|
|
91
|
+
this.touchDown = true;
|
|
92
|
+
this.touchStartCaptured = false; // will capture on next SYN_REPORT
|
|
93
|
+
this.touchStartTime = Date.now();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// BTN_TOUCH (0x14a), BTN_TOOL_FINGER (0x145), BTN_LEFT (0x110 — emulator mouse input)
|
|
97
|
+
}
|
|
98
|
+
else if (type === 1 && (code === 0x14a || code === 0x145 || code === 0x110)) {
|
|
99
|
+
if (value === 1 && !this.touchDown) {
|
|
100
|
+
this.touchDown = true;
|
|
101
|
+
this.touchStartCaptured = false;
|
|
102
|
+
this.touchStartTime = Date.now();
|
|
103
|
+
}
|
|
104
|
+
else if (value === 0) {
|
|
105
|
+
this.emitGesture(onEvent);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (type === 0 && code === 0 && value === 0) {
|
|
109
|
+
// SYN_REPORT — capture start position on first sync after touch down
|
|
110
|
+
if (this.touchDown && !this.touchStartCaptured) {
|
|
111
|
+
this.touchStartX = this.rawX;
|
|
112
|
+
this.touchStartY = this.rawY;
|
|
113
|
+
this.touchStartCaptured = true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
emitGesture(onEvent) {
|
|
118
|
+
if (!this.touchDown)
|
|
119
|
+
return;
|
|
120
|
+
this.touchDown = false;
|
|
121
|
+
const duration = Date.now() - this.touchStartTime;
|
|
122
|
+
const startX = Math.round((this.touchStartX / this.inputMax.x) * this.screenSize.width);
|
|
123
|
+
const startY = Math.round((this.touchStartY / this.inputMax.y) * this.screenSize.height);
|
|
124
|
+
const endX = Math.round((this.rawX / this.inputMax.x) * this.screenSize.width);
|
|
125
|
+
const endY = Math.round((this.rawY / this.inputMax.y) * this.screenSize.height);
|
|
126
|
+
// Calculate distance in SCREEN PIXELS (not raw input coords)
|
|
127
|
+
// Raw coords range is 0-32767 on emulators, so raw distance is misleading
|
|
128
|
+
const dxPx = endX - startX;
|
|
129
|
+
const dyPx = endY - startY;
|
|
130
|
+
const distancePx = Math.sqrt(dxPx * dxPx + dyPx * dyPx);
|
|
131
|
+
// Gesture classification:
|
|
132
|
+
// - Tap: short distance (<50px) + short duration (<400ms)
|
|
133
|
+
// Fingers naturally move 20-40px even on intentional taps
|
|
134
|
+
// - Long press: short distance (<50px) + long duration (>=400ms)
|
|
135
|
+
// - Swipe: large distance (>=50px)
|
|
136
|
+
let eventType;
|
|
137
|
+
if (distancePx < 50 && duration < 400)
|
|
138
|
+
eventType = 'tap';
|
|
139
|
+
else if (distancePx < 50)
|
|
140
|
+
eventType = 'long_press';
|
|
141
|
+
else
|
|
142
|
+
eventType = 'swipe';
|
|
143
|
+
const event = {
|
|
144
|
+
type: eventType,
|
|
145
|
+
timestamp: Date.now(),
|
|
146
|
+
x: startX,
|
|
147
|
+
y: startY,
|
|
148
|
+
gestureDetails: {
|
|
149
|
+
duration,
|
|
150
|
+
distance: Math.round(distancePx),
|
|
151
|
+
velocity: duration > 0 ? Math.round(distancePx / duration * 1000) : 0,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
if (eventType === 'swipe') {
|
|
155
|
+
event.endX = endX;
|
|
156
|
+
event.endY = endY;
|
|
157
|
+
}
|
|
158
|
+
this.eventCount++;
|
|
159
|
+
onEvent(event);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.GeteventStrategy = GeteventStrategy;
|
|
163
|
+
//# sourceMappingURL=getevent.strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getevent.strategy.js","sourceRoot":"","sources":["../../../src/recording/capture-strategies/getevent.strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RecordingEvent } from '@testdroid-ai/shared';
|
|
2
|
+
import { CaptureStrategy } from './capture-strategy.interface';
|
|
3
|
+
/**
|
|
4
|
+
* Captures hardware key events (Back, Home, etc.) via getevent.
|
|
5
|
+
* Runs in parallel with the main capture strategy.
|
|
6
|
+
* Only emits key events — does NOT capture touch/swipe.
|
|
7
|
+
*/
|
|
8
|
+
export declare class KeyCaptureStrategy implements CaptureStrategy {
|
|
9
|
+
private serial;
|
|
10
|
+
private process;
|
|
11
|
+
constructor(serial: string);
|
|
12
|
+
start(onEvent: (event: RecordingEvent) => void): Promise<void>;
|
|
13
|
+
stop(): void;
|
|
14
|
+
private parseLine;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=key-capture.strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-capture.strategy.d.ts","sourceRoot":"","sources":["../../../src/recording/capture-strategies/key-capture.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,eAAe;IAG5C,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,OAAO,CAA6B;gBAExB,MAAM,EAAE,MAAM;IAE5B,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBpE,IAAI,IAAI,IAAI;IAOZ,OAAO,CAAC,SAAS;CAsBlB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KeyCaptureStrategy = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
/**
|
|
6
|
+
* Captures hardware key events (Back, Home, etc.) via getevent.
|
|
7
|
+
* Runs in parallel with the main capture strategy.
|
|
8
|
+
* Only emits key events — does NOT capture touch/swipe.
|
|
9
|
+
*/
|
|
10
|
+
class KeyCaptureStrategy {
|
|
11
|
+
serial;
|
|
12
|
+
process = null;
|
|
13
|
+
constructor(serial) {
|
|
14
|
+
this.serial = serial;
|
|
15
|
+
}
|
|
16
|
+
async start(onEvent) {
|
|
17
|
+
// getevent -lt gives labeled events with timestamps
|
|
18
|
+
this.process = (0, child_process_1.spawn)('adb', [
|
|
19
|
+
'-s', this.serial, 'shell', 'getevent', '-lt',
|
|
20
|
+
], {
|
|
21
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
22
|
+
});
|
|
23
|
+
let buffer = '';
|
|
24
|
+
this.process.stdout?.on('data', (data) => {
|
|
25
|
+
buffer += data.toString();
|
|
26
|
+
const lines = buffer.split('\n');
|
|
27
|
+
buffer = lines.pop() || '';
|
|
28
|
+
for (const line of lines) {
|
|
29
|
+
this.parseLine(line.trim(), onEvent);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
this.process.stderr?.on('data', () => { });
|
|
33
|
+
this.process.on('error', () => { });
|
|
34
|
+
}
|
|
35
|
+
stop() {
|
|
36
|
+
if (this.process) {
|
|
37
|
+
try {
|
|
38
|
+
this.process.kill('SIGKILL');
|
|
39
|
+
}
|
|
40
|
+
catch { }
|
|
41
|
+
this.process = null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
parseLine(line, onEvent) {
|
|
45
|
+
// Format: [timestamp] /dev/input/eventN: EV_KEY KEY_BACK DOWN/UP
|
|
46
|
+
// We only care about KEY UP events (action completed)
|
|
47
|
+
if (!line.includes('EV_KEY'))
|
|
48
|
+
return;
|
|
49
|
+
if (!line.includes('UP'))
|
|
50
|
+
return;
|
|
51
|
+
let type = null;
|
|
52
|
+
if (line.includes('KEY_BACK')) {
|
|
53
|
+
type = 'back';
|
|
54
|
+
}
|
|
55
|
+
else if (line.includes('KEY_HOMEPAGE') || line.includes('KEY_HOME')) {
|
|
56
|
+
type = 'home';
|
|
57
|
+
}
|
|
58
|
+
if (!type)
|
|
59
|
+
return;
|
|
60
|
+
onEvent({
|
|
61
|
+
type,
|
|
62
|
+
timestamp: Date.now(),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.KeyCaptureStrategy = KeyCaptureStrategy;
|
|
67
|
+
//# sourceMappingURL=key-capture.strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-capture.strategy.js","sourceRoot":"","sources":["../../../src/recording/capture-strategies/key-capture.strategy.ts"],"names":[],"mappings":";;;AAAA,iDAAoD;AAIpD;;;;GAIG;AACH,MAAa,kBAAkB;IAGT;IAFZ,OAAO,GAAwB,IAAI,CAAC;IAE5C,YAAoB,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;IAAG,CAAC;IAEtC,KAAK,CAAC,KAAK,CAAC,OAAwC;QAClD,oDAAoD;QACpD,IAAI,CAAC,OAAO,GAAG,IAAA,qBAAK,EAAC,KAAK,EAAE;YAC1B,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK;SAC9C,EAAE;YACD,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC/C,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAC9C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,IAAY,EAAE,OAAwC;QACtE,iEAAiE;QACjE,sDAAsD;QAEtD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO;QACrC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO;QAEjC,IAAI,IAAI,GAA2B,IAAI,CAAC;QAExC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,IAAI,GAAG,MAAM,CAAC;QAChB,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACtE,IAAI,GAAG,MAAM,CAAC;QAChB,CAAC;QAED,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,OAAO,CAAC;YACN,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;IACL,CAAC;CACF;AAxDD,gDAwDC"}
|