devicely 2.2.13 → 2.2.14

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 (41) hide show
  1. package/bin/devicely.js +1 -1
  2. package/lib/advanced-logger.js +1 -1
  3. package/lib/androidDeviceDetection.js +1 -1
  4. package/lib/appMappings.js +1 -1
  5. package/lib/commanderService.js +1 -1
  6. package/lib/deviceDetection.js +1 -1
  7. package/lib/devices.js +1 -1
  8. package/lib/doctor.js +1 -1
  9. package/lib/encryption.js +1 -1
  10. package/lib/executor.js +1 -1
  11. package/lib/hybridAI.js +1 -1
  12. package/lib/intelligentLocatorService.js +1 -1
  13. package/lib/lightweightAI.js +1 -1
  14. package/lib/localBuiltInAI.js +1 -1
  15. package/lib/localBuiltInAI_backup.js +1 -1
  16. package/lib/localBuiltInAI_simple.js +1 -1
  17. package/lib/locatorStrategy.js +1 -1
  18. package/lib/logger-demo.js +1 -1
  19. package/lib/logger.js +1 -1
  20. package/lib/quick-start-logger.js +1 -1
  21. package/lib/scriptLoader.js +1 -1
  22. package/lib/server.js +1 -1
  23. package/lib/tensorflowAI.js +1 -1
  24. package/lib/tinyAI.js +1 -1
  25. package/lib/universalSessionManager.js +1 -1
  26. package/package.json +1 -1
  27. package/lib/.logging-backup/aiProviders.js.backup +0 -654
  28. package/lib/.logging-backup/appMappings.js.backup +0 -337
  29. package/lib/.logging-backup/commanderService.js.backup +0 -4427
  30. package/lib/.logging-backup/devices.js.backup +0 -54
  31. package/lib/.logging-backup/doctor.js.backup +0 -94
  32. package/lib/.logging-backup/encryption.js.backup +0 -61
  33. package/lib/.logging-backup/executor.js.backup +0 -104
  34. package/lib/.logging-backup/hybridAI.js.backup +0 -154
  35. package/lib/.logging-backup/intelligentLocatorService.js.backup +0 -1541
  36. package/lib/.logging-backup/locatorStrategy.js.backup +0 -342
  37. package/lib/.logging-backup/scriptLoader.js.backup +0 -13
  38. package/lib/.logging-backup/server.js.backup +0 -6298
  39. package/lib/.logging-backup/tensorflowAI.js.backup +0 -714
  40. package/lib/.logging-backup/universalSessionManager.js.backup +0 -370
  41. package/lib/.logging-enhanced-backup/server.js.enhanced-backup +0 -6298
@@ -1,342 +0,0 @@
1
- const Logger = require('./logger');
2
- const { execSync } = require('child_process');
3
-
4
- class LocatorStrategy {
5
- constructor() {
6
- this.logger = new Logger('LocatorStrategy');
7
- }
8
-
9
- /**
10
- * Capture element information at given coordinates
11
- * Returns all possible locators for the element
12
- */
13
- async captureElementLocators(device, x, y) {
14
- const locators = {
15
- coordinates: { x, y },
16
- timestamp: Date.now()
17
- };
18
-
19
- try {
20
- if (device.platform === 'Android') {
21
- return await this.captureAndroidElement(device, x, y);
22
- } else if (device.platform === 'iOS') {
23
- return await this.captureIOSElement(device, x, y);
24
- }
25
- } catch (error) {
26
- this.logger.error(`Failed to capture element locators: ${error.message}`);
27
- return locators;
28
- }
29
-
30
- return locators;
31
- }
32
-
33
- /**
34
- * Capture Android element using UIAutomator2
35
- */
36
- async captureAndroidElement(device, x, y) {
37
- try {
38
- // Use UIAutomator2 to get element at coordinates
39
- // This requires active UIAutomator2 session
40
- const dumpCommand = `adb -s ${device.udid || device.name} shell uiautomator dump /sdcard/window_dump.xml && adb -s ${device.udid || device.name} shell cat /sdcard/window_dump.xml`;
41
-
42
- const xmlDump = execSync(dumpCommand, {
43
- encoding: 'utf8',
44
- timeout: 10000
45
- });
46
-
47
- const element = this.findElementAtCoordinates(xmlDump, x, y);
48
-
49
- if (element) {
50
- return {
51
- xpath: this.buildXPath(element),
52
- resourceId: element.resourceId || null,
53
- contentDesc: element.contentDesc || null,
54
- text: element.text || null,
55
- className: element.className || null,
56
- index: element.index || 0,
57
- bounds: element.bounds || null,
58
- coordinates: { x, y },
59
- platform: 'Android'
60
- };
61
- }
62
- } catch (error) {
63
- this.logger.warn(`Android element capture failed: ${error.message}`);
64
- }
65
-
66
- return { coordinates: { x, y }, platform: 'Android' };
67
- }
68
-
69
- /**
70
- * Capture iOS element using WDA
71
- */
72
- async captureIOSElement(device, x, y) {
73
- try {
74
- // Use WDA to get element at coordinates
75
- // Requires active WDA session
76
- const sessionPort = device.wdaPort || 8100;
77
- const axios = require('axios');
78
-
79
- const response = await axios.get(`http://localhost:${sessionPort}/source`, {
80
- params: { format: 'json' },
81
- timeout: 5000
82
- });
83
-
84
- const pageSource = response.data;
85
- const element = this.findIOSElementAtCoordinates(pageSource, x, y);
86
-
87
- if (element) {
88
- return {
89
- xpath: this.buildIOSXPath(element),
90
- accessibilityId: element.name || element.label || null,
91
- accessibilityLabel: element.label || null,
92
- text: element.value || element.label || null,
93
- type: element.type || null,
94
- index: element.index || 0,
95
- bounds: element.rect || null,
96
- coordinates: { x, y },
97
- platform: 'iOS'
98
- };
99
- }
100
- } catch (error) {
101
- this.logger.warn(`iOS element capture failed: ${error.message}`);
102
- }
103
-
104
- return { coordinates: { x, y }, platform: 'iOS' };
105
- }
106
-
107
- /**
108
- * Find element at coordinates from XML dump
109
- */
110
- findElementAtCoordinates(xmlDump, x, y) {
111
- // Parse XML and find element whose bounds contain (x, y)
112
- // This is a simplified implementation
113
- const boundsRegex = /bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/g;
114
- const resourceIdRegex = /resource-id="([^"]*)"/;
115
- const textRegex = /text="([^"]*)"/;
116
- const contentDescRegex = /content-desc="([^"]*)"/;
117
- const classRegex = /class="([^"]*)"/;
118
-
119
- const lines = xmlDump.split('\n');
120
-
121
- for (const line of lines) {
122
- const boundsMatch = boundsRegex.exec(line);
123
- if (boundsMatch) {
124
- const [, left, top, right, bottom] = boundsMatch.map(Number);
125
-
126
- if (x >= left && x <= right && y >= top && y <= bottom) {
127
- return {
128
- resourceId: (resourceIdRegex.exec(line) || [])[1] || null,
129
- text: (textRegex.exec(line) || [])[1] || null,
130
- contentDesc: (contentDescRegex.exec(line) || [])[1] || null,
131
- className: (classRegex.exec(line) || [])[1] || null,
132
- bounds: { left, top, right, bottom }
133
- };
134
- }
135
- }
136
- }
137
-
138
- return null;
139
- }
140
-
141
- /**
142
- * Find iOS element at coordinates from page source
143
- */
144
- findIOSElementAtCoordinates(pageSource, x, y) {
145
- // Recursively search through WDA page source tree
146
- const findElement = (node) => {
147
- if (node.rect) {
148
- const { x: ex, y: ey, width, height } = node.rect;
149
- if (x >= ex && x <= (ex + width) && y >= ey && y <= (ey + height)) {
150
- return node;
151
- }
152
- }
153
-
154
- if (node.children) {
155
- for (const child of node.children) {
156
- const found = findElement(child);
157
- if (found) return found;
158
- }
159
- }
160
-
161
- return null;
162
- };
163
-
164
- return findElement(pageSource);
165
- }
166
-
167
- /**
168
- * Build XPath for Android element
169
- */
170
- buildXPath(element) {
171
- const parts = [];
172
-
173
- if (element.resourceId) {
174
- return `//*[@resource-id="${element.resourceId}"]`;
175
- }
176
-
177
- if (element.contentDesc) {
178
- return `//*[@content-desc="${element.contentDesc}"]`;
179
- }
180
-
181
- if (element.text) {
182
- return `//${element.className || '*'}[@text="${element.text}"]`;
183
- }
184
-
185
- if (element.className) {
186
- return `//${element.className}`;
187
- }
188
-
189
- return `//*`;
190
- }
191
-
192
- /**
193
- * Build XPath for iOS element
194
- */
195
- buildIOSXPath(element) {
196
- if (element.name) {
197
- return `//*[@name="${element.name}"]`;
198
- }
199
-
200
- if (element.label) {
201
- return `//${element.type || '*'}[@label="${element.label}"]`;
202
- }
203
-
204
- if (element.type) {
205
- return `//${element.type}`;
206
- }
207
-
208
- return `//*`;
209
- }
210
-
211
- /**
212
- * Execute action using specific locator strategy
213
- */
214
- async executeWithLocator(device, action, locator, input = null) {
215
- if (device.platform === 'Android') {
216
- return await this.executeAndroidAction(device, action, locator, input);
217
- } else if (device.platform === 'iOS') {
218
- return await this.executeIOSAction(device, action, locator, input);
219
- }
220
-
221
- throw new Error(`Unsupported platform: ${device.platform}`);
222
- }
223
-
224
- /**
225
- * Execute action on Android device
226
- */
227
- async executeAndroidAction(device, action, locator, input) {
228
- const deviceId = device.udid || device.name;
229
-
230
- try {
231
- switch (action) {
232
- case 'tap':
233
- return await this.androidTap(deviceId, locator);
234
- case 'swipe':
235
- return await this.androidSwipe(deviceId, locator);
236
- case 'type':
237
- return await this.androidType(deviceId, locator, input);
238
- case 'clear':
239
- return await this.androidClear(deviceId, locator);
240
- default:
241
- throw new Error(`Unsupported action: ${action}`);
242
- }
243
- } catch (error) {
244
- this.logger.error(`Android action failed: ${error.message}`);
245
- throw error;
246
- }
247
- }
248
-
249
- /**
250
- * Execute action on iOS device
251
- */
252
- async executeIOSAction(device, action, locator, input) {
253
- const sessionPort = device.wdaPort || 8100;
254
-
255
- try {
256
- switch (action) {
257
- case 'tap':
258
- return await this.iOSTap(sessionPort, locator);
259
- case 'swipe':
260
- return await this.iOSSwipe(sessionPort, locator);
261
- case 'type':
262
- return await this.iOSType(sessionPort, locator, input);
263
- case 'clear':
264
- return await this.iOSClear(sessionPort, locator);
265
- default:
266
- throw new Error(`Unsupported action: ${action}`);
267
- }
268
- } catch (error) {
269
- this.logger.error(`iOS action failed: ${error.message}`);
270
- throw error;
271
- }
272
- }
273
-
274
- // Android action implementations
275
- async androidTap(deviceId, locator) {
276
- if (locator.type === 'coordinates') {
277
- const { x, y } = locator.value;
278
- execSync(`adb -s ${deviceId} shell input tap ${x} ${y}`);
279
- } else if (locator.type === 'resource_id') {
280
- // Use UIAutomator2 to find and tap element
281
- execSync(`adb -s ${deviceId} shell input tap $(uiautomator dump | grep "${locator.value}")`);
282
- }
283
- return { success: true };
284
- }
285
-
286
- async androidSwipe(deviceId, locator) {
287
- const { x1, y1, x2, y2, duration = 300 } = locator.value;
288
- execSync(`adb -s ${deviceId} shell input swipe ${x1} ${y1} ${x2} ${y2} ${duration}`);
289
- return { success: true };
290
- }
291
-
292
- async androidType(deviceId, locator, text) {
293
- // First tap on element, then input text
294
- await this.androidTap(deviceId, locator);
295
- const escapedText = text.replace(/\s/g, '%s');
296
- execSync(`adb -s ${deviceId} shell input text "${escapedText}"`);
297
- return { success: true };
298
- }
299
-
300
- async androidClear(deviceId, locator) {
301
- // Select all and delete
302
- await this.androidTap(deviceId, locator);
303
- execSync(`adb -s ${deviceId} shell input keyevent KEYCODE_MOVE_END`);
304
- execSync(`adb -s ${deviceId} shell input keyevent --longpress KEYCODE_DEL`);
305
- return { success: true };
306
- }
307
-
308
- // iOS action implementations (using WDA HTTP API)
309
- async iOSTap(sessionPort, locator) {
310
- const axios = require('axios');
311
- if (locator.type === 'coordinates') {
312
- const { x, y } = locator.value;
313
- await axios.post(`http://localhost:${sessionPort}/wda/tap/0`, { x, y });
314
- }
315
- return { success: true };
316
- }
317
-
318
- async iOSSwipe(sessionPort, locator) {
319
- const axios = require('axios');
320
- const { x1, y1, x2, y2 } = locator.value;
321
- await axios.post(`http://localhost:${sessionPort}/wda/dragfromtoforduration`, {
322
- fromX: x1, fromY: y1, toX: x2, toY: y2, duration: 0.3
323
- });
324
- return { success: true };
325
- }
326
-
327
- async iOSType(sessionPort, locator, text) {
328
- const axios = require('axios');
329
- await this.iOSTap(sessionPort, locator);
330
- await axios.post(`http://localhost:${sessionPort}/wda/keys`, { value: [text] });
331
- return { success: true };
332
- }
333
-
334
- async iOSClear(sessionPort, locator) {
335
- const axios = require('axios');
336
- await this.iOSTap(sessionPort, locator);
337
- await axios.post(`http://localhost:${sessionPort}/wda/keys`, { value: [''] });
338
- return { success: true };
339
- }
340
- }
341
-
342
- module.exports = LocatorStrategy;
@@ -1,13 +0,0 @@
1
- const fs = require('fs');
2
- const { decrypt } = require('./encryption');
3
-
4
- /**
5
- * Decrypt encrypted shell script
6
- * Uses centralized encryption config for consistency
7
- */
8
- function decryptScript(encryptedFilePath) {
9
- const encryptedData = fs.readFileSync(encryptedFilePath, 'utf8');
10
- return decrypt(encryptedData);
11
- }
12
-
13
- module.exports = { decryptScript };