@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,518 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StepExecutor = void 0;
|
|
4
|
+
const healer_1 = require("../healing/healer");
|
|
5
|
+
const selector_resolver_1 = require("./selector-resolver");
|
|
6
|
+
/**
|
|
7
|
+
* Executa passos de teste parseados usando AdbExecutor.
|
|
8
|
+
*
|
|
9
|
+
* Resolve seletores (resourceId, text, xpath) para coordenadas
|
|
10
|
+
* via UI dump e executa acoes via ADB.
|
|
11
|
+
*
|
|
12
|
+
* Quando o self-healing esta habilitado, tenta encontrar
|
|
13
|
+
* elementos por estrategias alternativas quando o seletor falha.
|
|
14
|
+
*/
|
|
15
|
+
class StepExecutor {
|
|
16
|
+
adb;
|
|
17
|
+
logs = [];
|
|
18
|
+
healer;
|
|
19
|
+
healingAttempts = [];
|
|
20
|
+
options;
|
|
21
|
+
resolvers = (0, selector_resolver_1.createResolverChain)();
|
|
22
|
+
constructor(adb, options) {
|
|
23
|
+
this.adb = adb;
|
|
24
|
+
this.healer = new healer_1.Healer(adb);
|
|
25
|
+
this.options = options || {};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Executa um unico passo de teste.
|
|
29
|
+
* Resolve seletores para coordenadas usando UI dump quando necessario.
|
|
30
|
+
*/
|
|
31
|
+
async executeStep(step) {
|
|
32
|
+
try {
|
|
33
|
+
switch (step.action) {
|
|
34
|
+
case 'tap':
|
|
35
|
+
return await this.executeTap(step);
|
|
36
|
+
case 'long_press':
|
|
37
|
+
return await this.executeLongPress(step);
|
|
38
|
+
case 'swipe':
|
|
39
|
+
return await this.executeSwipe(step);
|
|
40
|
+
case 'type_text':
|
|
41
|
+
return await this.executeTypeText(step);
|
|
42
|
+
case 'press_key':
|
|
43
|
+
return await this.executePressKey(step);
|
|
44
|
+
case 'press_back':
|
|
45
|
+
await this.adb.pressBack();
|
|
46
|
+
this.log(`Voltar pressionado`);
|
|
47
|
+
return { success: true };
|
|
48
|
+
case 'press_home':
|
|
49
|
+
await this.adb.pressHome();
|
|
50
|
+
this.log(`Home pressionado`);
|
|
51
|
+
return { success: true };
|
|
52
|
+
case 'launch_app':
|
|
53
|
+
await this.adb.launchApp(step.params.packageName, step.params.activity);
|
|
54
|
+
this.log(`App iniciado: ${step.params.packageName}`);
|
|
55
|
+
return { success: true };
|
|
56
|
+
case 'wait':
|
|
57
|
+
await this.sleep(step.params.ms || 500);
|
|
58
|
+
this.log(`Aguardando ${step.params.ms || 500}ms`);
|
|
59
|
+
return { success: true };
|
|
60
|
+
case 'assert_element':
|
|
61
|
+
return await this.executeAssertElement(step);
|
|
62
|
+
case 'assert_text':
|
|
63
|
+
return await this.executeAssertText(step);
|
|
64
|
+
default:
|
|
65
|
+
this.log(`Acao desconhecida: ${step.action}`);
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
error: `Acao desconhecida: ${step.action}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
74
|
+
this.log(`Erro: ${message}`);
|
|
75
|
+
return { success: false, error: message };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* beforeEach: garante estado limpo antes da execucao.
|
|
80
|
+
* - Fecha dialogs abertos (back key)
|
|
81
|
+
* - Verifica se o app esta em foreground, relanca se nao estiver
|
|
82
|
+
* - Aguarda estabilizacao
|
|
83
|
+
*/
|
|
84
|
+
async beforeEach() {
|
|
85
|
+
const pkg = this.options.appPackage;
|
|
86
|
+
if (!pkg)
|
|
87
|
+
return;
|
|
88
|
+
this.log('[beforeEach] A preparar estado do dispositivo...');
|
|
89
|
+
// 1. Fechar qualquer dialog/popup aberto com back
|
|
90
|
+
try {
|
|
91
|
+
await this.adb.pressBack();
|
|
92
|
+
await this.sleep(500);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Ignora se falhar
|
|
96
|
+
}
|
|
97
|
+
// 2. Verificar se o app esta em foreground
|
|
98
|
+
try {
|
|
99
|
+
const output = this.adb.dumpUi();
|
|
100
|
+
const appInForeground = output.includes(`package="${pkg}"`);
|
|
101
|
+
if (!appInForeground) {
|
|
102
|
+
this.log(`[beforeEach] App ${pkg} nao esta em foreground, a relancar...`);
|
|
103
|
+
await this.adb.launchApp(pkg);
|
|
104
|
+
await this.sleep(3000);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this.log('[beforeEach] App em foreground OK');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Em caso de erro, tenta lancar o app
|
|
112
|
+
try {
|
|
113
|
+
await this.adb.launchApp(pkg);
|
|
114
|
+
await this.sleep(3000);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
this.log('[beforeEach] Falha ao lancar app');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// 3. Aguardar estabilizacao da UI
|
|
121
|
+
await this.sleep(500);
|
|
122
|
+
this.log('[beforeEach] Pronto');
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* afterEach: cleanup apos a execucao.
|
|
126
|
+
* - Captura screenshot do estado final
|
|
127
|
+
* - Em caso de falha, tenta fechar dialogs
|
|
128
|
+
* - Regista estado final no log
|
|
129
|
+
*/
|
|
130
|
+
async afterEach(success, screenshotPath) {
|
|
131
|
+
this.log(`[afterEach] Resultado: ${success ? 'PASSED' : 'FAILED'}`);
|
|
132
|
+
// 1. Screenshot do estado final (sempre, para evidencia)
|
|
133
|
+
if (!screenshotPath) {
|
|
134
|
+
try {
|
|
135
|
+
const path = `/tmp/testdroid-${success ? 'final' : 'failure'}-${Date.now()}.png`;
|
|
136
|
+
await this.adb.takeScreenshot(path);
|
|
137
|
+
screenshotPath = path;
|
|
138
|
+
this.log(`[afterEach] Screenshot salvo: ${path}`);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Ignora
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// 2. Em caso de falha, tentar recuperar estado limpo
|
|
145
|
+
if (!success) {
|
|
146
|
+
try {
|
|
147
|
+
// Fechar possiveis dialogs
|
|
148
|
+
await this.adb.pressBack();
|
|
149
|
+
await this.sleep(300);
|
|
150
|
+
await this.adb.pressBack();
|
|
151
|
+
await this.sleep(300);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// Ignora
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
this.log('[afterEach] Cleanup concluido');
|
|
158
|
+
return screenshotPath;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Executa todos os passos em sequencia.
|
|
162
|
+
* Inclui beforeEach (preparacao) e afterEach (cleanup).
|
|
163
|
+
* Para na primeira falha e retorna o resultado geral.
|
|
164
|
+
* Inclui tentativas de self-healing quando habilitado.
|
|
165
|
+
*/
|
|
166
|
+
async executeAll(steps, onStep) {
|
|
167
|
+
const startTime = Date.now();
|
|
168
|
+
this.logs = [];
|
|
169
|
+
this.healingAttempts = [];
|
|
170
|
+
let stepsPassed = 0;
|
|
171
|
+
let stepsFailed = 0;
|
|
172
|
+
let errorMessage;
|
|
173
|
+
let screenshotPath;
|
|
174
|
+
// === BEFORE EACH ===
|
|
175
|
+
await this.beforeEach();
|
|
176
|
+
for (let i = 0; i < steps.length; i++) {
|
|
177
|
+
const step = steps[i];
|
|
178
|
+
const result = await this.executeStep(step);
|
|
179
|
+
// Se houve healing neste passo, atualizar stepIndex
|
|
180
|
+
if (result.healingAttempt) {
|
|
181
|
+
result.healingAttempt.stepIndex = i;
|
|
182
|
+
if (this.options.testRunId) {
|
|
183
|
+
result.healingAttempt.testRunId = this.options.testRunId;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (onStep) {
|
|
187
|
+
onStep(i, step, result);
|
|
188
|
+
}
|
|
189
|
+
if (result.success) {
|
|
190
|
+
stepsPassed++;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
stepsFailed++;
|
|
194
|
+
errorMessage = `Passo ${i + 1}/${steps.length} falhou: ${result.error || 'Erro desconhecido'}`;
|
|
195
|
+
this.log(errorMessage);
|
|
196
|
+
// Tira screenshot na falha
|
|
197
|
+
try {
|
|
198
|
+
const path = `/tmp/testdroid-failure-${Date.now()}.png`;
|
|
199
|
+
await this.adb.takeScreenshot(path);
|
|
200
|
+
screenshotPath = path;
|
|
201
|
+
this.log(`Screenshot de falha salvo em: ${path}`);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Ignora se nao conseguir capturar screenshot
|
|
205
|
+
}
|
|
206
|
+
break; // Para na primeira falha
|
|
207
|
+
}
|
|
208
|
+
// Pausa curta entre passos para estabilidade
|
|
209
|
+
if (i < steps.length - 1 && step.action !== 'wait') {
|
|
210
|
+
await this.sleep(200);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// === AFTER EACH ===
|
|
214
|
+
const success = stepsFailed === 0;
|
|
215
|
+
screenshotPath = await this.afterEach(success, screenshotPath);
|
|
216
|
+
const duration = Date.now() - startTime;
|
|
217
|
+
const status = stepsFailed > 0 ? 'failed' : 'passed';
|
|
218
|
+
return {
|
|
219
|
+
status,
|
|
220
|
+
duration,
|
|
221
|
+
logs: this.logs.join('\n'),
|
|
222
|
+
errorMessage,
|
|
223
|
+
screenshotPath,
|
|
224
|
+
stepsTotal: steps.length,
|
|
225
|
+
stepsPassed,
|
|
226
|
+
stepsFailed,
|
|
227
|
+
healingAttempts: this.healingAttempts,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// --- Executores individuais ---
|
|
231
|
+
async executeTap(step) {
|
|
232
|
+
// Se temos coordenadas diretas, usa-las
|
|
233
|
+
if (step.params.x !== undefined &&
|
|
234
|
+
step.params.y !== undefined) {
|
|
235
|
+
await this.adb.tap(step.params.x, step.params.y);
|
|
236
|
+
this.log(`Toque em (${step.params.x}, ${step.params.y})`);
|
|
237
|
+
return { success: true };
|
|
238
|
+
}
|
|
239
|
+
// Se temos seletor, resolver via UI dump
|
|
240
|
+
if (step.params.selector) {
|
|
241
|
+
const coords = await this.resolveSelector(step.params.selector);
|
|
242
|
+
if (!coords) {
|
|
243
|
+
// Tentar self-healing
|
|
244
|
+
const healResult = await this.tryHeal(step.params.selector, step);
|
|
245
|
+
if (healResult)
|
|
246
|
+
return healResult;
|
|
247
|
+
return {
|
|
248
|
+
success: false,
|
|
249
|
+
error: `Elemento nao encontrado: ${step.params.selector}`,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
await this.adb.tap(coords.x, coords.y);
|
|
253
|
+
this.log(`Toque em "${step.params.selector}" (${coords.x}, ${coords.y})`);
|
|
254
|
+
return { success: true };
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
success: false,
|
|
258
|
+
error: 'Tap sem coordenadas ou seletor',
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
async executeLongPress(step) {
|
|
262
|
+
let x;
|
|
263
|
+
let y;
|
|
264
|
+
if (step.params.x !== undefined &&
|
|
265
|
+
step.params.y !== undefined) {
|
|
266
|
+
x = step.params.x;
|
|
267
|
+
y = step.params.y;
|
|
268
|
+
}
|
|
269
|
+
else if (step.params.selector) {
|
|
270
|
+
const coords = await this.resolveSelector(step.params.selector);
|
|
271
|
+
if (!coords) {
|
|
272
|
+
// Tentar self-healing
|
|
273
|
+
const healResult = await this.tryHeal(step.params.selector, step);
|
|
274
|
+
if (healResult)
|
|
275
|
+
return healResult;
|
|
276
|
+
return {
|
|
277
|
+
success: false,
|
|
278
|
+
error: `Elemento nao encontrado: ${step.params.selector}`,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
x = coords.x;
|
|
282
|
+
y = coords.y;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
return {
|
|
286
|
+
success: false,
|
|
287
|
+
error: 'LongPress sem coordenadas ou seletor',
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
// Simula long press com swipe de duracao longa na mesma posicao
|
|
291
|
+
await this.adb.swipe(x, y, x, y, 1000);
|
|
292
|
+
this.log(`Toque longo em (${x}, ${y})`);
|
|
293
|
+
return { success: true };
|
|
294
|
+
}
|
|
295
|
+
async executeSwipe(step) {
|
|
296
|
+
const { x1, y1, x2, y2 } = step.params;
|
|
297
|
+
if (x1 === undefined ||
|
|
298
|
+
y1 === undefined ||
|
|
299
|
+
x2 === undefined ||
|
|
300
|
+
y2 === undefined) {
|
|
301
|
+
return {
|
|
302
|
+
success: false,
|
|
303
|
+
error: 'Swipe sem coordenadas completas',
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
await this.adb.swipe(x1, y1, x2, y2, 300);
|
|
307
|
+
this.log(`Swipe de (${x1}, ${y1}) para (${x2}, ${y2})`);
|
|
308
|
+
return { success: true };
|
|
309
|
+
}
|
|
310
|
+
async executeTypeText(step) {
|
|
311
|
+
// Se tem seletor, tocar no elemento primeiro para focar
|
|
312
|
+
if (step.params.selector) {
|
|
313
|
+
const coords = await this.resolveSelector(step.params.selector);
|
|
314
|
+
if (!coords) {
|
|
315
|
+
// Tentar self-healing
|
|
316
|
+
const healResult = await this.tryHeal(step.params.selector, step);
|
|
317
|
+
if (healResult) {
|
|
318
|
+
// Se healing teve sucesso, o toque ja foi realizado via tryHeal
|
|
319
|
+
// Agora digitar o texto
|
|
320
|
+
if (healResult.success) {
|
|
321
|
+
await this.sleep(300);
|
|
322
|
+
const text = step.params.text || '';
|
|
323
|
+
await this.adb.typeText(text);
|
|
324
|
+
this.log(`Texto digitado: "${text}"`);
|
|
325
|
+
return healResult;
|
|
326
|
+
}
|
|
327
|
+
return healResult;
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
success: false,
|
|
331
|
+
error: `Elemento nao encontrado: ${step.params.selector}`,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
await this.adb.tap(coords.x, coords.y);
|
|
335
|
+
await this.sleep(300); // Aguarda o campo focar
|
|
336
|
+
}
|
|
337
|
+
const text = step.params.text || '';
|
|
338
|
+
await this.adb.typeText(text);
|
|
339
|
+
this.log(`Texto digitado: "${text}"`);
|
|
340
|
+
return { success: true };
|
|
341
|
+
}
|
|
342
|
+
async executePressKey(step) {
|
|
343
|
+
const keycode = step.params.keycode;
|
|
344
|
+
const key = step.params.key;
|
|
345
|
+
if (keycode !== undefined) {
|
|
346
|
+
await this.adb.pressKey(keycode);
|
|
347
|
+
this.log(`Tecla pressionada: keycode ${keycode}`);
|
|
348
|
+
return { success: true };
|
|
349
|
+
}
|
|
350
|
+
if (key) {
|
|
351
|
+
// Mapear nomes de tecla do Playwright para keycodes Android
|
|
352
|
+
const keyMap = {
|
|
353
|
+
Enter: 66,
|
|
354
|
+
Back: 4,
|
|
355
|
+
Home: 3,
|
|
356
|
+
Tab: 61,
|
|
357
|
+
Delete: 67,
|
|
358
|
+
Escape: 111,
|
|
359
|
+
Space: 62,
|
|
360
|
+
};
|
|
361
|
+
const code = keyMap[key];
|
|
362
|
+
if (code) {
|
|
363
|
+
await this.adb.pressKey(code);
|
|
364
|
+
this.log(`Tecla pressionada: ${key} (${code})`);
|
|
365
|
+
return { success: true };
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
success: false,
|
|
369
|
+
error: `Tecla desconhecida: ${key}`,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
success: false,
|
|
374
|
+
error: 'PressKey sem keycode ou nome de tecla',
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
async executeAssertElement(step) {
|
|
378
|
+
const selector = step.params.selector;
|
|
379
|
+
if (!selector) {
|
|
380
|
+
return {
|
|
381
|
+
success: false,
|
|
382
|
+
error: 'assert_element sem seletor',
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
const found = await this.resolveSelector(selector);
|
|
386
|
+
if (found) {
|
|
387
|
+
this.log(`Elemento encontrado: "${selector}"`);
|
|
388
|
+
return { success: true };
|
|
389
|
+
}
|
|
390
|
+
// Tentar self-healing
|
|
391
|
+
const healResult = await this.tryHeal(selector, step);
|
|
392
|
+
if (healResult)
|
|
393
|
+
return healResult;
|
|
394
|
+
return {
|
|
395
|
+
success: false,
|
|
396
|
+
error: `Elemento nao encontrado: "${selector}"`,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
async executeAssertText(step) {
|
|
400
|
+
const expectedText = step.params.text;
|
|
401
|
+
if (!expectedText) {
|
|
402
|
+
return {
|
|
403
|
+
success: false,
|
|
404
|
+
error: 'assert_text sem texto esperado',
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
const xml = this.adb.dumpUi();
|
|
408
|
+
if (!xml) {
|
|
409
|
+
return {
|
|
410
|
+
success: false,
|
|
411
|
+
error: 'Falha ao obter hierarquia UI',
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
if (xml.includes(`text="${expectedText}"`)) {
|
|
415
|
+
this.log(`Texto encontrado: "${expectedText}"`);
|
|
416
|
+
return { success: true };
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
success: false,
|
|
420
|
+
error: `Texto nao encontrado na tela: "${expectedText}"`,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
// --- Self-Healing ---
|
|
424
|
+
/**
|
|
425
|
+
* Tenta curar um seletor que falhou e re-executar a acao.
|
|
426
|
+
* Retorna null se healing esta desabilitado ou falhou.
|
|
427
|
+
*/
|
|
428
|
+
async tryHeal(failedSelector, step) {
|
|
429
|
+
if (this.options.noHeal)
|
|
430
|
+
return null;
|
|
431
|
+
const selectorType = healer_1.Healer.detectSelectorType(failedSelector);
|
|
432
|
+
this.log(`Self-healing: tentando curar seletor "${failedSelector}" (${selectorType})...`);
|
|
433
|
+
const healResult = await this.healer.heal(failedSelector, selectorType);
|
|
434
|
+
if (!healResult.healed || !healResult.attempt) {
|
|
435
|
+
this.log(`Self-healing: falhou - ${healResult.error || 'nenhuma alternativa encontrada'}`);
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
const attempt = healResult.attempt;
|
|
439
|
+
this.healingAttempts.push(attempt);
|
|
440
|
+
this.log(`Self-healing: elemento nao encontrado com '${attempt.originalSelector}', usando '${attempt.newSelector}' (confianca: ${attempt.confidence}%)`);
|
|
441
|
+
// Re-tentar com o novo seletor
|
|
442
|
+
const newCoords = await this.resolveSelector(attempt.newSelector);
|
|
443
|
+
if (!newCoords) {
|
|
444
|
+
this.log(`Self-healing: novo seletor '${attempt.newSelector}' tambem nao encontrou elemento`);
|
|
445
|
+
attempt.applied = false;
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
// Executar a acao com as novas coordenadas
|
|
449
|
+
switch (step.action) {
|
|
450
|
+
case 'tap':
|
|
451
|
+
await this.adb.tap(newCoords.x, newCoords.y);
|
|
452
|
+
this.log(`Toque (curado) em "${attempt.newSelector}" (${newCoords.x}, ${newCoords.y})`);
|
|
453
|
+
return {
|
|
454
|
+
success: true,
|
|
455
|
+
healed: true,
|
|
456
|
+
healingAttempt: attempt,
|
|
457
|
+
};
|
|
458
|
+
case 'long_press':
|
|
459
|
+
await this.adb.swipe(newCoords.x, newCoords.y, newCoords.x, newCoords.y, 1000);
|
|
460
|
+
this.log(`Toque longo (curado) em "${attempt.newSelector}" (${newCoords.x}, ${newCoords.y})`);
|
|
461
|
+
return {
|
|
462
|
+
success: true,
|
|
463
|
+
healed: true,
|
|
464
|
+
healingAttempt: attempt,
|
|
465
|
+
};
|
|
466
|
+
case 'type_text':
|
|
467
|
+
await this.adb.tap(newCoords.x, newCoords.y);
|
|
468
|
+
this.log(`Foco (curado) em "${attempt.newSelector}" (${newCoords.x}, ${newCoords.y})`);
|
|
469
|
+
return {
|
|
470
|
+
success: true,
|
|
471
|
+
healed: true,
|
|
472
|
+
healingAttempt: attempt,
|
|
473
|
+
};
|
|
474
|
+
case 'assert_element':
|
|
475
|
+
this.log(`Elemento (curado) encontrado: "${attempt.newSelector}"`);
|
|
476
|
+
return {
|
|
477
|
+
success: true,
|
|
478
|
+
healed: true,
|
|
479
|
+
healingAttempt: attempt,
|
|
480
|
+
};
|
|
481
|
+
default:
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
// --- Resolucao de seletores ---
|
|
486
|
+
/**
|
|
487
|
+
* Resolve um seletor (resourceId, texto, xpath) para coordenadas (x, y).
|
|
488
|
+
* Usa Chain of Responsibility: percorre a cadeia de resolvers ate encontrar
|
|
489
|
+
* um que consiga resolver o seletor.
|
|
490
|
+
*/
|
|
491
|
+
async resolveSelector(selector) {
|
|
492
|
+
const xml = this.adb.dumpUi();
|
|
493
|
+
if (!xml)
|
|
494
|
+
return null;
|
|
495
|
+
for (const resolver of this.resolvers) {
|
|
496
|
+
if (resolver.canResolve(selector)) {
|
|
497
|
+
const result = resolver.resolve(selector, this.adb, xml);
|
|
498
|
+
if (result)
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Adiciona entrada ao log.
|
|
506
|
+
*/
|
|
507
|
+
log(message) {
|
|
508
|
+
this.logs.push(`[${new Date().toISOString()}] ${message}`);
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Aguarda ms milissegundos.
|
|
512
|
+
*/
|
|
513
|
+
sleep(ms) {
|
|
514
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
exports.StepExecutor = StepExecutor;
|
|
518
|
+
//# sourceMappingURL=step-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-executor.js","sourceRoot":"","sources":["../../src/runner/step-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { TestStep } from './script-parser';
|
|
2
|
+
import { TestRunResult, OnStepCallback } from './step-executor';
|
|
3
|
+
/**
|
|
4
|
+
* Opcoes para execucao de um teste.
|
|
5
|
+
*/
|
|
6
|
+
export interface TestRunOptions {
|
|
7
|
+
/** Serial do dispositivo */
|
|
8
|
+
serial: string;
|
|
9
|
+
/** Caminho do arquivo de teste (.ts ou .js) */
|
|
10
|
+
testFile: string;
|
|
11
|
+
/** Package name do app */
|
|
12
|
+
appPackage: string;
|
|
13
|
+
/** Timeout em ms (padrao 60000) */
|
|
14
|
+
timeout?: number;
|
|
15
|
+
/** URL do backend para reportar resultado (opcional) */
|
|
16
|
+
reportTo?: string;
|
|
17
|
+
/** Desabilitar self-healing */
|
|
18
|
+
noHeal?: boolean;
|
|
19
|
+
/** ID da execucao (para tracking de healing) */
|
|
20
|
+
testRunId?: string;
|
|
21
|
+
/** URL do Appium server */
|
|
22
|
+
appiumUrl?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Modo de execucao do runner.
|
|
26
|
+
*/
|
|
27
|
+
export type ExecutionMode = 'adb' | 'appium';
|
|
28
|
+
/**
|
|
29
|
+
* Runner principal de testes.
|
|
30
|
+
*
|
|
31
|
+
* Suporta dois modos de execucao:
|
|
32
|
+
* - Modo A (adb): Executa via ADB direto - MVP, nao requer Appium
|
|
33
|
+
* - Modo B (appium): Executa via Appium/WebdriverIO - futuro
|
|
34
|
+
*
|
|
35
|
+
* O modo padrao e ADB (Modo A).
|
|
36
|
+
*/
|
|
37
|
+
export declare class TestRunner {
|
|
38
|
+
private parser;
|
|
39
|
+
private mode;
|
|
40
|
+
constructor(mode?: ExecutionMode);
|
|
41
|
+
/**
|
|
42
|
+
* Executa um arquivo de teste no dispositivo.
|
|
43
|
+
*
|
|
44
|
+
* 1. Verifica se o dispositivo esta conectado
|
|
45
|
+
* 2. Le e parseia o arquivo de teste
|
|
46
|
+
* 3. Executa os passos via ADB
|
|
47
|
+
* 4. Captura screenshot em caso de falha
|
|
48
|
+
* 5. Retorna resultado
|
|
49
|
+
*/
|
|
50
|
+
run(options: TestRunOptions, onStep?: OnStepCallback): Promise<TestRunResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Parseia o codigo de teste e retorna os passos sem executar.
|
|
53
|
+
* Util para preview / dry-run.
|
|
54
|
+
*/
|
|
55
|
+
parseTestFile(testFile: string): TestStep[];
|
|
56
|
+
/**
|
|
57
|
+
* Modo A: Execucao via ADB direto (MVP).
|
|
58
|
+
*
|
|
59
|
+
* Parseia o codigo gerado, extrai os passos,
|
|
60
|
+
* e executa cada um via AdbExecutor.
|
|
61
|
+
*/
|
|
62
|
+
private runAdbMode;
|
|
63
|
+
/**
|
|
64
|
+
* Modo B: Execucao via Appium/WebDriverIO.
|
|
65
|
+
*
|
|
66
|
+
* Requer Appium server rodando e WebdriverIO instalado.
|
|
67
|
+
* Conecta ao Appium, parseia o script, e executa cada passo
|
|
68
|
+
* com suporte a self-healing e callbacks onStep.
|
|
69
|
+
*/
|
|
70
|
+
private runAppiumMode;
|
|
71
|
+
/**
|
|
72
|
+
* Executa passos de teste sequencialmente via AppiumExecutor.
|
|
73
|
+
* Inclui self-healing e callbacks onStep.
|
|
74
|
+
*/
|
|
75
|
+
private executeAppiumSteps;
|
|
76
|
+
/**
|
|
77
|
+
* Cria um resultado de erro.
|
|
78
|
+
*/
|
|
79
|
+
private errorResult;
|
|
80
|
+
/**
|
|
81
|
+
* Promise que rejeita apos o timeout.
|
|
82
|
+
*/
|
|
83
|
+
private timeoutPromise;
|
|
84
|
+
/**
|
|
85
|
+
* Aguarda ms milissegundos.
|
|
86
|
+
*/
|
|
87
|
+
private sleep;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=test-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../../src/runner/test-runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAGL,aAAa,EACb,cAAc,EAEf,MAAM,iBAAiB,CAAC;AAKzB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE7C;;;;;;;;GAQG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,IAAI,CAAgB;gBAEhB,IAAI,GAAE,aAAqB;IAKvC;;;;;;;;OAQG;IACG,GAAG,CACP,OAAO,EAAE,cAAc,EACvB,MAAM,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC;IA8CzB;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE;IAK3C;;;;;OAKG;YACW,UAAU;IA+CxB;;;;;;OAMG;YACW,aAAa;IAsE3B;;;OAGG;YACW,kBAAkB;IAwEhC;;OAEG;IACH,OAAO,CAAC,WAAW;IAanB;;OAEG;IACH,OAAO,CAAC,cAAc;IAiBtB;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd"}
|