@xenon-device-management/xenon 1.1.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 +446 -0
- package/lib/package.json +207 -0
- package/lib/public/assets/Layouts-7IT8aFLI.js +11 -0
- package/lib/public/assets/Layouts-DPMls9vh.css +1 -0
- package/lib/public/assets/ai-settings-BbnfgdEx.js +11 -0
- package/lib/public/assets/apps-CRMrI4_p.js +16 -0
- package/lib/public/assets/apps-CcM77dgg.css +1 -0
- package/lib/public/assets/badge-B1nKs8zj.css +1 -0
- package/lib/public/assets/badge-CSvl5xIU.js +11 -0
- package/lib/public/assets/button-CJlKn4PZ.css +1 -0
- package/lib/public/assets/button-CvLaGFYj.js +26 -0
- package/lib/public/assets/calendar-6w-D6Oaw.js +6 -0
- package/lib/public/assets/clock-DcdeWBPr.js +6 -0
- package/lib/public/assets/cpu-DiSoXT9n.js +6 -0
- package/lib/public/assets/device-explorer-CajM63OJ.js +193 -0
- package/lib/public/assets/device-explorer-CxdUAoTL.css +1 -0
- package/lib/public/assets/index-ByQwMN5T.js +174 -0
- package/lib/public/assets/index-C1DBaoSh.js +1 -0
- package/lib/public/assets/index-qzCez_kk.css +1 -0
- package/lib/public/assets/lock-B23ibZmo.js +6 -0
- package/lib/public/assets/maintenance-settings-CirzA6yG.js +6 -0
- package/lib/public/assets/mouse-pointer-2-Cz76SHFb.js +6 -0
- package/lib/public/assets/plus-BBwlIevt.js +6 -0
- package/lib/public/assets/session-dashboard-C2k7FFv_.css +1 -0
- package/lib/public/assets/session-dashboard-HPDtwPOZ.js +62 -0
- package/lib/public/assets/settings-DrZsZwdc.js +1 -0
- package/lib/public/assets/trash-2-DQpvzJec.js +6 -0
- package/lib/public/assets/useSocket-Dxsqae2a.js +16 -0
- package/lib/public/assets/webhook-settings-CDPgsgkb.css +1 -0
- package/lib/public/assets/webhook-settings-Cp-B4Nrw.js +1 -0
- package/lib/public/assets/zap-DovP6iow.js +6 -0
- package/lib/public/favicon.ico +0 -0
- package/lib/public/favicon.png +0 -0
- package/lib/public/favicon.svg +9 -0
- package/lib/public/index.html +46 -0
- package/lib/public/logo.svg +17 -0
- package/lib/public/logo192.png +0 -0
- package/lib/public/logo512.png +0 -0
- package/lib/public/manifest.json +25 -0
- package/lib/public/robots.txt +3 -0
- package/lib/schema.json +348 -0
- package/lib/src/InternalHttpClient.js +212 -0
- package/lib/src/PluginContext.js +29 -0
- package/lib/src/XenonCapabilityManager.js +199 -0
- package/lib/src/app/index.js +167 -0
- package/lib/src/app/routers/apps.js +79 -0
- package/lib/src/app/routers/config.js +131 -0
- package/lib/src/app/routers/control.js +835 -0
- package/lib/src/app/routers/dashboard.js +301 -0
- package/lib/src/app/routers/grid.js +352 -0
- package/lib/src/app/routers/reservation.js +190 -0
- package/lib/src/app/routers/webhook.js +83 -0
- package/lib/src/app/swagger-docs.js +203 -0
- package/lib/src/app/swagger.js +366 -0
- package/lib/src/chromeUtils.js +148 -0
- package/lib/src/commands/handle.js +19 -0
- package/lib/src/commands/index.js +8 -0
- package/lib/src/config.js +73 -0
- package/lib/src/dashboard/asset-manager.js +84 -0
- package/lib/src/dashboard/commands.js +284 -0
- package/lib/src/dashboard/event-manager.js +699 -0
- package/lib/src/dashboard/services/app-service.js +134 -0
- package/lib/src/dashboard/services/failure-analysis-service.js +173 -0
- package/lib/src/dashboard/services/session-service.js +113 -0
- package/lib/src/data-service/CircuitBreaker.js +83 -0
- package/lib/src/data-service/config-service.js +155 -0
- package/lib/src/data-service/db.js +122 -0
- package/lib/src/data-service/device-service.js +320 -0
- package/lib/src/data-service/device-store.interface.js +2 -0
- package/lib/src/data-service/device-store.js +345 -0
- package/lib/src/data-service/pending-sessions-service.js +25 -0
- package/lib/src/data-service/pluginArgs.js +25 -0
- package/lib/src/data-service/prisma-service.js +31 -0
- package/lib/src/data-service/prisma-store.js +385 -0
- package/lib/src/data-service/queue-service.js +150 -0
- package/lib/src/data-service/web-config-service.js +130 -0
- package/lib/src/device-managers/AndroidDeviceManager.js +1155 -0
- package/lib/src/device-managers/ChromeDriverManager.js +68 -0
- package/lib/src/device-managers/HealthMonitorService.js +325 -0
- package/lib/src/device-managers/IOSDeviceManager.js +351 -0
- package/lib/src/device-managers/NodeDevices.js +82 -0
- package/lib/src/device-managers/android/AndroidStreamService.js +370 -0
- package/lib/src/device-managers/android/DeviceLockManager.js +45 -0
- package/lib/src/device-managers/cloud/CapabilityManager.js +26 -0
- package/lib/src/device-managers/cloud/Devices.js +86 -0
- package/lib/src/device-managers/iOSTracker.js +44 -0
- package/lib/src/device-managers/index.js +89 -0
- package/lib/src/device-managers/ios/IOSDiscoveryService.js +268 -0
- package/lib/src/device-managers/ios/IOSStreamService.js +893 -0
- package/lib/src/device-managers/ios/WDAClient.js +866 -0
- package/lib/src/device-utils.js +663 -0
- package/lib/src/enums/Capabilities.js +8 -0
- package/lib/src/enums/Cloud.js +11 -0
- package/lib/src/enums/Platform.js +9 -0
- package/lib/src/enums/SessionType.js +9 -0
- package/lib/src/enums/SocketEvents.js +15 -0
- package/lib/src/helpers/UniversalMjpegProxy.js +273 -0
- package/lib/src/helpers/index.js +229 -0
- package/lib/src/index.js +95 -0
- package/lib/src/interceptors/CommandInterceptor.js +524 -0
- package/lib/src/interfaces/ICloudManager.js +2 -0
- package/lib/src/interfaces/IDevice.js +2 -0
- package/lib/src/interfaces/IDeviceFilterOptions.js +2 -0
- package/lib/src/interfaces/IDeviceManager.js +2 -0
- package/lib/src/interfaces/IOptions.js +2 -0
- package/lib/src/interfaces/IPluginArgs.js +55 -0
- package/lib/src/interfaces/ISessionCapability.js +2 -0
- package/lib/src/logger.js +225 -0
- package/lib/src/plugin.js +244 -0
- package/lib/src/prisma.js +12 -0
- package/lib/src/profiling/AndroidAppProfiler.js +213 -0
- package/lib/src/proxy/wd-command-proxy.js +221 -0
- package/lib/src/scripts/generate-database-migration.js +59 -0
- package/lib/src/scripts/initialize-database.js +55 -0
- package/lib/src/scripts/install-go-ios.js +66 -0
- package/lib/src/scripts/prepare-prisma.js +89 -0
- package/lib/src/services/AICommandService.js +143 -0
- package/lib/src/services/AIService.js +466 -0
- package/lib/src/services/CleanupService.js +141 -0
- package/lib/src/services/EventBus.js +74 -0
- package/lib/src/services/InspectorService.js +395 -0
- package/lib/src/services/MetricsService.js +134 -0
- package/lib/src/services/NetworkConditioningService.js +173 -0
- package/lib/src/services/NotificationService.js +163 -0
- package/lib/src/services/RequestLogService.js +252 -0
- package/lib/src/services/ResourceIsolationService.js +122 -0
- package/lib/src/services/SecurityService.js +120 -0
- package/lib/src/services/ServerManager.js +284 -0
- package/lib/src/services/SessionHeartbeatService.js +158 -0
- package/lib/src/services/SessionLifecycleService.js +572 -0
- package/lib/src/services/SocketClient.js +71 -0
- package/lib/src/services/SocketServer.js +87 -0
- package/lib/src/services/TracingService.js +132 -0
- package/lib/src/services/VideoPipelineService.js +220 -0
- package/lib/src/services/healing/FuzzyXmlHealingProvider.js +333 -0
- package/lib/src/services/healing/HealEtalonService.js +98 -0
- package/lib/src/services/healing/HealedLocatorGenerator.js +132 -0
- package/lib/src/services/healing/HealingOrchestrator.js +165 -0
- package/lib/src/services/healing/LlmHealingProvider.js +77 -0
- package/lib/src/services/healing/OcrHealingProvider.js +119 -0
- package/lib/src/services/healing/ResilioTreeHealingProvider.js +100 -0
- package/lib/src/services/healing/VisualAiHealingProvider.js +90 -0
- package/lib/src/services/healing/types.js +12 -0
- package/lib/src/services/omni-vision/OmniVisionService.js +718 -0
- package/lib/src/services/omni-vision/VisionAssertionService.js +68 -0
- package/lib/src/sessions/CloudSession.js +42 -0
- package/lib/src/sessions/LocalSession.js +313 -0
- package/lib/src/sessions/RemoteSession.js +287 -0
- package/lib/src/sessions/SessionManager.js +238 -0
- package/lib/src/sessions/XenonSession.js +44 -0
- package/lib/src/types/CLIArgs.js +2 -0
- package/lib/src/types/CloudArgs.js +2 -0
- package/lib/src/types/CloudSchema.js +131 -0
- package/lib/src/types/DeviceType.js +2 -0
- package/lib/src/types/DeviceUpdate.js +2 -0
- package/lib/src/types/IOSDevice.js +2 -0
- package/lib/src/types/Platform.js +2 -0
- package/lib/src/types/SessionStatus.js +11 -0
- package/lib/src/validators/CapabilityValidator.js +93 -0
- package/lib/test/e2e/android/conf.spec.js +43 -0
- package/lib/test/e2e/android/conf2.spec.js +44 -0
- package/lib/test/e2e/android/conf3.spec.js +44 -0
- package/lib/test/e2e/e2ehelper.js +113 -0
- package/lib/test/e2e/hubnode/forward-request.spec.js +224 -0
- package/lib/test/e2e/hubnode/hubnode.spec.js +214 -0
- package/lib/test/e2e/ios/conf1.spec.js +39 -0
- package/lib/test/e2e/ios/conf2.spec.js +39 -0
- package/lib/test/e2e/plugin-harness.js +236 -0
- package/lib/test/e2e/plugin.spec.js +97 -0
- package/lib/test/e2e/telemetry_verification.spec.js +83 -0
- package/lib/test/e2e/video-recording-test.spec.js +63 -0
- package/lib/test/helpers/test-container.js +112 -0
- package/lib/test/integration/androidDevices.spec.js +137 -0
- package/lib/test/integration/cliArgs.js +73 -0
- package/lib/test/integration/ios/01iOSSimulator.spec.js +291 -0
- package/lib/test/integration/ios/02iOSDevices.spec.js +75 -0
- package/lib/test/integration/testHelpers.js +74 -0
- package/lib/test/unit/AndroidDeviceManager.spec.js +178 -0
- package/lib/test/unit/ChromeDriverManager.spec.js +26 -0
- package/lib/test/unit/CleanupService.spec.js +21 -0
- package/lib/test/unit/DeviceModel.spec.js +157 -0
- package/lib/test/unit/FuzzyXmlHealingProvider.test.js +294 -0
- package/lib/test/unit/GetAdbOriginal.js +42 -0
- package/lib/test/unit/HealingCascade.test.js +128 -0
- package/lib/test/unit/IOSDeviceManager.spec.js +261 -0
- package/lib/test/unit/RemoteIOs.spec.js +78 -0
- package/lib/test/unit/ResilioTreeHealingProvider.test.js +96 -0
- package/lib/test/unit/commands.spec.js +27 -0
- package/lib/test/unit/config.spec.js +27 -0
- package/lib/test/unit/device-service.spec.js +307 -0
- package/lib/test/unit/device-utils.spec.js +313 -0
- package/lib/test/unit/fixtures/device.config.js +4 -0
- package/lib/test/unit/fixtures/devices.js +89 -0
- package/lib/test/unit/helpers.spec.js +62 -0
- package/lib/test/unit/omni-vision.spec.js +100 -0
- package/lib/test/unit/plugin.spec.js +133 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +207 -0
- package/prisma/data.db +0 -0
- package/prisma/dev.db +0 -0
- package/prisma/dev.db-journal +0 -0
- package/prisma/migrations/20231011074725_initial_tables/migration.sql +47 -0
- package/prisma/migrations/20231226115334_update_session_log/migration.sql +2 -0
- package/prisma/migrations/20251204113710_add_video_recording_enabled/migration.sql +29 -0
- package/prisma/migrations/20251204132449_add_log_table/migration.sql +11 -0
- package/prisma/migrations/20251205050111_add_profiling_support/migration.sql +47 -0
- package/prisma/migrations/20251205050947_add_is_error_field/migration.sql +24 -0
- package/prisma/migrations/20260126201337_add_app_model/migration.sql +18 -0
- package/prisma/migrations/20260130115722_add_performance_trace_and_xenon_sync/migration.sql +2 -0
- package/prisma/migrations/20260130135114_add_device_models/migration.sql +57 -0
- package/prisma/migrations/20260130140655_make_systemport_optional/migration.sql +45 -0
- package/prisma/migrations/20260130140932_make_device_fields_optional/migration.sql +45 -0
- package/prisma/migrations/20260130141040_final_schema_fix/migration.sql +45 -0
- package/prisma/migrations/20260130143234_add_device_health_fields/migration.sql +4 -0
- package/prisma/migrations/20260130144921_add_failure_category/migration.sql +2 -0
- package/prisma/migrations/20260131151456_add_webhook_config/migration.sql +10 -0
- package/prisma/migrations/20260201094507_add_device_tags/migration.sql +11 -0
- package/prisma/migrations/20260201103410_add_managed_process/migration.sql +15 -0
- package/prisma/migrations/20260201140637_add_web_config/migration.sql +22 -0
- package/prisma/migrations/20260201162232_add_session_progress/migration.sql +2 -0
- package/prisma/migrations/20260201174231_add_total_healed_count/migration.sql +2 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +210 -0
- package/schema.json +348 -0
- package/scripts/build-xenon.sh +32 -0
- package/scripts/dev/debug-gemini.ts +44 -0
- package/scripts/generate-types-from-schema.js +86 -0
- package/scripts/install-compatible-driver.js +39 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
require("reflect-metadata");
|
|
49
|
+
const chai_1 = __importStar(require("chai"));
|
|
50
|
+
const db_1 = require("../../src/data-service/db");
|
|
51
|
+
const device_utils_1 = require("../../src/device-utils");
|
|
52
|
+
const IPluginArgs_1 = require("../../src/interfaces/IPluginArgs");
|
|
53
|
+
const ip_1 = __importDefault(require("ip"));
|
|
54
|
+
const async_wait_until_1 = __importDefault(require("async-wait-until"));
|
|
55
|
+
const device_service_1 = require("../../src/data-service/device-service");
|
|
56
|
+
const chai_as_promised_1 = __importDefault(require("chai-as-promised"));
|
|
57
|
+
const test_container_1 = require("../helpers/test-container");
|
|
58
|
+
chai_1.default.use(chai_as_promised_1.default);
|
|
59
|
+
const pluginArgs = Object.assign({}, IPluginArgs_1.DefaultPluginArgs, {
|
|
60
|
+
remote: [`http://${ip_1.default.address()}:4723`],
|
|
61
|
+
skipChromeDownload: true,
|
|
62
|
+
platform: 'android',
|
|
63
|
+
});
|
|
64
|
+
describe('Android Test', () => {
|
|
65
|
+
let deviceManager;
|
|
66
|
+
before(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
67
|
+
(yield db_1.XenonDatabase.DeviceModel).removeDataOnly();
|
|
68
|
+
deviceManager = (0, test_container_1.createTestXenonManager)(pluginArgs);
|
|
69
|
+
// adb devices should return devices
|
|
70
|
+
(0, chai_1.expect)(deviceManager.getDevices()).to.eventually.have.length.greaterThan(0, 'No devices detected. Is adb running? Is there at least one device connected?');
|
|
71
|
+
}));
|
|
72
|
+
it('Allocate free device and verify the device state is busy in db', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
73
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
74
|
+
yield deviceManager.getDevices();
|
|
75
|
+
const hub = pluginArgs.hub;
|
|
76
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp, hub);
|
|
77
|
+
yield (0, device_utils_1.cleanPendingSessions)(0);
|
|
78
|
+
yield (0, device_service_1.unblockDeviceMatchingFilter)({});
|
|
79
|
+
const capabilities = {
|
|
80
|
+
alwaysMatch: {
|
|
81
|
+
platformName: 'android',
|
|
82
|
+
'appium:app': '/Downloads/VodQA.apk',
|
|
83
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
84
|
+
'appium:deviceRetryInterval': 100,
|
|
85
|
+
},
|
|
86
|
+
firstMatch: [{}],
|
|
87
|
+
};
|
|
88
|
+
const devices = yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 1000, 1000, pluginArgs);
|
|
89
|
+
const allDeviceIds = (yield db_1.XenonDatabase.DeviceModel)
|
|
90
|
+
.chain()
|
|
91
|
+
.find({ udid: devices.udid })
|
|
92
|
+
.data();
|
|
93
|
+
(0, chai_1.expect)(allDeviceIds[0].busy).to.be.true;
|
|
94
|
+
}));
|
|
95
|
+
it.skip('Allocate second free device and verify both the device state is busy in db', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
96
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
97
|
+
deviceManager = (0, test_container_1.createTestXenonManager)(Object.assign({}, pluginArgs, { platform: 'android' }));
|
|
98
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp);
|
|
99
|
+
const capabilities = {
|
|
100
|
+
alwaysMatch: {
|
|
101
|
+
platformName: 'android',
|
|
102
|
+
'appium:app': '/Downloads/VodQA.apk',
|
|
103
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
104
|
+
'appium:deviceRetryInterval': 100,
|
|
105
|
+
},
|
|
106
|
+
firstMatch: [{}],
|
|
107
|
+
};
|
|
108
|
+
// wait until there are two devices and both are not offline
|
|
109
|
+
let devices;
|
|
110
|
+
(0, async_wait_until_1.default)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
111
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp);
|
|
112
|
+
devices = yield deviceManager.getDevices();
|
|
113
|
+
return devices.length === 2 && devices.every((device) => !device.offline);
|
|
114
|
+
}));
|
|
115
|
+
yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 1000, 1000, pluginArgs);
|
|
116
|
+
const allDeviceIds = (yield db_1.XenonDatabase.DeviceModel).chain().find().data();
|
|
117
|
+
allDeviceIds.forEach((device) => (0, chai_1.expect)(device.busy).to.be.true);
|
|
118
|
+
}));
|
|
119
|
+
it('Finding a device should throw error when all devices are busy', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
120
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
121
|
+
deviceManager = (0, test_container_1.createTestXenonManager)(pluginArgs);
|
|
122
|
+
const hub = pluginArgs.hub;
|
|
123
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp, hub);
|
|
124
|
+
const capabilities = {
|
|
125
|
+
alwaysMatch: {
|
|
126
|
+
platformName: 'android',
|
|
127
|
+
'appium:app': '/Downloads/VodQA.apk',
|
|
128
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
129
|
+
'appium:deviceRetryInterval': 100,
|
|
130
|
+
},
|
|
131
|
+
firstMatch: [{}],
|
|
132
|
+
};
|
|
133
|
+
yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 1000, 1000, pluginArgs).catch((error) => (0, chai_1.expect)(error)
|
|
134
|
+
.to.be.an('error')
|
|
135
|
+
.with.property('message', 'Device is busy or blocked.. Device request: {"platform":"android"}'));
|
|
136
|
+
}));
|
|
137
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serverCliArgs = void 0;
|
|
4
|
+
exports.serverCliArgs = {
|
|
5
|
+
subcommand: 'server',
|
|
6
|
+
address: '0.0.0.0',
|
|
7
|
+
allow_cors: undefined,
|
|
8
|
+
allow_insecure: undefined,
|
|
9
|
+
basePath: '/wd/hub',
|
|
10
|
+
callback_address: undefined,
|
|
11
|
+
callback_port: undefined,
|
|
12
|
+
debug_log_spacing: undefined,
|
|
13
|
+
default_capabilities: undefined,
|
|
14
|
+
deny_insecure: undefined,
|
|
15
|
+
keepAliveTimeout: 800,
|
|
16
|
+
local_timezone: undefined,
|
|
17
|
+
log: undefined,
|
|
18
|
+
log_filters: undefined,
|
|
19
|
+
log_level: undefined,
|
|
20
|
+
log_no_colors: undefined,
|
|
21
|
+
log_timestamp: undefined,
|
|
22
|
+
long_stacktrace: undefined,
|
|
23
|
+
no_perms_check: undefined,
|
|
24
|
+
nodeconfig: undefined,
|
|
25
|
+
port: 31337,
|
|
26
|
+
relaxed_security: undefined,
|
|
27
|
+
session_override: undefined,
|
|
28
|
+
strict_caps: undefined,
|
|
29
|
+
tmp: undefined,
|
|
30
|
+
trace_dir: undefined,
|
|
31
|
+
use_drivers: undefined,
|
|
32
|
+
usePlugins: ['xenon'],
|
|
33
|
+
webhook: undefined,
|
|
34
|
+
driver_xcuitest_webdriveragent_port: undefined,
|
|
35
|
+
plugin_device_farm_platform: undefined,
|
|
36
|
+
plugin_device_farm_android_device_type: undefined,
|
|
37
|
+
plugin: {
|
|
38
|
+
'xenon': {
|
|
39
|
+
iosDeviceType: 'simulated',
|
|
40
|
+
platform: 'ios',
|
|
41
|
+
androidDeviceType: 'both',
|
|
42
|
+
skipChromeDownload: true,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
plugin_device_farm_hub: undefined,
|
|
46
|
+
plugin_device_farm_adb_remote: undefined,
|
|
47
|
+
plugin_device_farm_skip_chrome_download: undefined,
|
|
48
|
+
plugin_device_farm_max_sessions: undefined,
|
|
49
|
+
plugin_device_farm_cloud: undefined,
|
|
50
|
+
plugin_device_farm_derived_data_path: undefined,
|
|
51
|
+
shell: undefined,
|
|
52
|
+
showBuildInfo: undefined,
|
|
53
|
+
showConfig: undefined,
|
|
54
|
+
configFile: './server-config.json',
|
|
55
|
+
extraArgs: [],
|
|
56
|
+
allowCors: false,
|
|
57
|
+
allowInsecure: [],
|
|
58
|
+
callbackPort: 4723,
|
|
59
|
+
debugLogSpacing: false,
|
|
60
|
+
denyInsecure: [],
|
|
61
|
+
localTimezone: false,
|
|
62
|
+
loglevel: 'debug',
|
|
63
|
+
logNoColors: false,
|
|
64
|
+
logTimestamp: false,
|
|
65
|
+
longStacktrace: false,
|
|
66
|
+
noPermsCheck: false,
|
|
67
|
+
relaxedSecurityEnabled: false,
|
|
68
|
+
sessionOverride: false,
|
|
69
|
+
strictCaps: false,
|
|
70
|
+
useDrivers: [],
|
|
71
|
+
driver: { xcuitest: { wdaLocalPort: 8100 } },
|
|
72
|
+
tmpDir: '/var/folders/fr/l_lyyktd2l3dq2yq3x3qdmbw0000gn/T',
|
|
73
|
+
};
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
|
+
var m = o[Symbol.asyncIterator], i;
|
|
14
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
15
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
|
+
};
|
|
18
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
require("reflect-metadata");
|
|
23
|
+
const chai_1 = require("chai");
|
|
24
|
+
const device_utils_1 = require("../../../src/device-utils");
|
|
25
|
+
const db_1 = require("../../../src/data-service/db");
|
|
26
|
+
const node_simctl_1 = __importDefault(require("node-simctl"));
|
|
27
|
+
const pluginArgs_1 = require("../../../src/data-service/pluginArgs");
|
|
28
|
+
const cliArgs_1 = require("../cliArgs");
|
|
29
|
+
const ip_1 = __importDefault(require("ip"));
|
|
30
|
+
const IPluginArgs_1 = require("../../../src/interfaces/IPluginArgs");
|
|
31
|
+
const device_service_1 = require("../../../src/data-service/device-service");
|
|
32
|
+
const lodash_1 = require("lodash");
|
|
33
|
+
const test_container_1 = require("../../helpers/test-container");
|
|
34
|
+
const simctl = new node_simctl_1.default();
|
|
35
|
+
const name = 'My Device Name';
|
|
36
|
+
const pluginArgs = Object.assign({}, IPluginArgs_1.DefaultPluginArgs, {
|
|
37
|
+
remote: [`http://${ip_1.default.address()}:4723`],
|
|
38
|
+
iosDeviceType: 'both',
|
|
39
|
+
platform: 'ios',
|
|
40
|
+
});
|
|
41
|
+
function markSimulatorsAsBooted() {
|
|
42
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
const deviceModel = yield db_1.XenonDatabase.DeviceModel;
|
|
44
|
+
// mark simulators as booted
|
|
45
|
+
deviceModel.findAndUpdate({ platform: 'ios', deviceType: 'simulator' }, (device) => {
|
|
46
|
+
device.state = 'Booted';
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function initDeviceFarm(iosDeviceType) {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
53
|
+
const deviceManager = (0, test_container_1.createTestXenonManager)(Object.assign({}, pluginArgs, {
|
|
54
|
+
iosDeviceType: iosDeviceType,
|
|
55
|
+
maxSessions: 1,
|
|
56
|
+
}));
|
|
57
|
+
(0, chai_1.expect)(deviceManager.getMaxSessionCount()).to.be.eql(1);
|
|
58
|
+
const hub = pluginArgs.hub;
|
|
59
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp, hub);
|
|
60
|
+
yield markSimulatorsAsBooted();
|
|
61
|
+
yield (0, device_service_1.unblockDeviceMatchingFilter)({});
|
|
62
|
+
yield (0, device_utils_1.cleanPendingSessions)(0);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
describe('Max sessions CLI argument test', () => {
|
|
66
|
+
before('Add Args', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
67
|
+
(yield db_1.XenonDatabase.DeviceModel).removeDataOnly();
|
|
68
|
+
yield (0, pluginArgs_1.addCLIArgs)(cliArgs_1.serverCliArgs);
|
|
69
|
+
}));
|
|
70
|
+
beforeEach('Release devices', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
|
+
yield initDeviceFarm('simulated');
|
|
72
|
+
}));
|
|
73
|
+
it('Allocate first device without issue', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
74
|
+
const capabilities = {
|
|
75
|
+
alwaysMatch: {
|
|
76
|
+
platformName: 'iOS',
|
|
77
|
+
'appium:app': '/Downloads/VodQA.app',
|
|
78
|
+
'appium:iPhoneOnly': true,
|
|
79
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
80
|
+
'appium:deviceRetryInterval': 100,
|
|
81
|
+
},
|
|
82
|
+
firstMatch: [{}],
|
|
83
|
+
};
|
|
84
|
+
const device = yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 6000, 1000, pluginArgs);
|
|
85
|
+
const allDeviceIds = (yield db_1.XenonDatabase.DeviceModel)
|
|
86
|
+
.chain()
|
|
87
|
+
.find({ udid: device.udid })
|
|
88
|
+
.data();
|
|
89
|
+
(0, chai_1.expect)(allDeviceIds[0].busy).to.be.true;
|
|
90
|
+
}));
|
|
91
|
+
it('Should throw error if the app does not match with device type', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
92
|
+
const capabilities = {
|
|
93
|
+
alwaysMatch: {
|
|
94
|
+
platformName: 'iOS',
|
|
95
|
+
'appium:app': '/Downloads/VodQA.ipa',
|
|
96
|
+
'appium:iPhoneOnly': true,
|
|
97
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
98
|
+
'appium:deviceRetryInterval': 100,
|
|
99
|
+
},
|
|
100
|
+
firstMatch: [{}],
|
|
101
|
+
};
|
|
102
|
+
yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 6000, 100, Object.assign({}, pluginArgs, { iosDeviceType: 'simulated' })).catch((error) => (0, chai_1.expect)(error)
|
|
103
|
+
.to.be.an('error')
|
|
104
|
+
.with.property('message', 'iosDeviceType value is set to "simulated" but app provided is not suitable for simulator device.'));
|
|
105
|
+
}));
|
|
106
|
+
it('Throw error when all sessions occupied', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
107
|
+
var _a, e_1, _b, _c;
|
|
108
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
109
|
+
const deviceManager = (0, test_container_1.createTestXenonManager)(Object.assign({}, pluginArgs, {
|
|
110
|
+
iosDeviceType: 'simulated',
|
|
111
|
+
maxSessions: 1,
|
|
112
|
+
}));
|
|
113
|
+
// set all devices to busy
|
|
114
|
+
const allDevices = yield deviceManager.getDevices();
|
|
115
|
+
try {
|
|
116
|
+
for (var _d = true, allDevices_1 = __asyncValues(allDevices), allDevices_1_1; allDevices_1_1 = yield allDevices_1.next(), _a = allDevices_1_1.done, !_a; _d = true) {
|
|
117
|
+
_c = allDevices_1_1.value;
|
|
118
|
+
_d = false;
|
|
119
|
+
const _device = _c;
|
|
120
|
+
(yield db_1.XenonDatabase.DeviceModel)
|
|
121
|
+
.chain()
|
|
122
|
+
.find({ platform: 'ios' })
|
|
123
|
+
.update((device) => {
|
|
124
|
+
device.busy = true;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
129
|
+
finally {
|
|
130
|
+
try {
|
|
131
|
+
if (!_d && !_a && (_b = allDevices_1.return)) yield _b.call(allDevices_1);
|
|
132
|
+
}
|
|
133
|
+
finally { if (e_1) throw e_1.error; }
|
|
134
|
+
}
|
|
135
|
+
const capabilities = {
|
|
136
|
+
alwaysMatch: {
|
|
137
|
+
platformName: 'iOS',
|
|
138
|
+
'appium:app': '/Downloads/VodQA.app',
|
|
139
|
+
'appium:iPhoneOnly': true,
|
|
140
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
141
|
+
'appium:deviceRetryInterval': 100,
|
|
142
|
+
},
|
|
143
|
+
firstMatch: [{}],
|
|
144
|
+
};
|
|
145
|
+
yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 6000, 1000, pluginArgs).catch((error) => (0, chai_1.expect)(error)
|
|
146
|
+
.to.be.an('error')
|
|
147
|
+
.with.property('message', 'Device is busy or blocked.. Device request: {"platform":"ios","name":"iPhone","deviceType":"simulator"}'));
|
|
148
|
+
}));
|
|
149
|
+
});
|
|
150
|
+
describe('IOS Simulator Test', () => {
|
|
151
|
+
beforeEach('Release devices', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
152
|
+
yield (0, device_service_1.unblockDeviceMatchingFilter)({});
|
|
153
|
+
}));
|
|
154
|
+
it('Should find free iPhone simulator when app path has .app extension and set busy status to true', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
155
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
156
|
+
const deviceManager = (0, test_container_1.createTestXenonManager)(pluginArgs);
|
|
157
|
+
const hub = pluginArgs.hub;
|
|
158
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp, hub);
|
|
159
|
+
yield markSimulatorsAsBooted();
|
|
160
|
+
yield (0, device_service_1.unblockDeviceMatchingFilter)({});
|
|
161
|
+
yield (0, device_utils_1.cleanPendingSessions)(0);
|
|
162
|
+
const capabilities = {
|
|
163
|
+
alwaysMatch: {
|
|
164
|
+
platformName: 'iOS',
|
|
165
|
+
'appium:app': '/Downloads/VodQA.app',
|
|
166
|
+
'appium:iPhoneOnly': true,
|
|
167
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
168
|
+
'appium:deviceRetryInterval': 100,
|
|
169
|
+
},
|
|
170
|
+
firstMatch: [{}],
|
|
171
|
+
};
|
|
172
|
+
// console.log('devices: ', await deviceManager.getDevices())
|
|
173
|
+
const device = yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 6000, 1000, pluginArgs);
|
|
174
|
+
const allocatedSimulator = (yield db_1.XenonDatabase.DeviceModel)
|
|
175
|
+
.chain()
|
|
176
|
+
.find({ udid: device.udid })
|
|
177
|
+
.data();
|
|
178
|
+
const foundSimulator = allocatedSimulator[0];
|
|
179
|
+
(0, chai_1.expect)(foundSimulator.busy).to.be.true;
|
|
180
|
+
(0, chai_1.expect)(foundSimulator.name).to.match(/^iPhone/);
|
|
181
|
+
(0, chai_1.expect)(foundSimulator.wdaLocalPort).to.match(/[0-9]/);
|
|
182
|
+
}));
|
|
183
|
+
it('Should find free iPad simulator when app path has .app extension and set busy status to true', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
184
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
185
|
+
const deviceManager = (0, test_container_1.createTestXenonManager)(pluginArgs);
|
|
186
|
+
const hub = pluginArgs.hub;
|
|
187
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp, hub);
|
|
188
|
+
yield markSimulatorsAsBooted();
|
|
189
|
+
yield (0, device_service_1.unblockDeviceMatchingFilter)({});
|
|
190
|
+
yield (0, device_utils_1.cleanPendingSessions)(0);
|
|
191
|
+
const capabilities = {
|
|
192
|
+
alwaysMatch: {
|
|
193
|
+
platformName: 'iOS',
|
|
194
|
+
'appium:app': '/Downloads/VodQA.app',
|
|
195
|
+
'appium:iPadOnly': true,
|
|
196
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
197
|
+
'appium:deviceRetryInterval': 100,
|
|
198
|
+
},
|
|
199
|
+
firstMatch: [{}],
|
|
200
|
+
};
|
|
201
|
+
// console.log('devices: ', await deviceManager.getDevices())
|
|
202
|
+
const device = yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 6000, 1000, pluginArgs);
|
|
203
|
+
const allocatedSimulator = (yield db_1.XenonDatabase.DeviceModel)
|
|
204
|
+
.chain()
|
|
205
|
+
.find({ udid: device.udid })
|
|
206
|
+
.data();
|
|
207
|
+
const foundSimulator = allocatedSimulator[0];
|
|
208
|
+
(0, chai_1.expect)(foundSimulator.busy).to.be.true;
|
|
209
|
+
(0, chai_1.expect)(foundSimulator.name).to.match(/^iPad/);
|
|
210
|
+
(0, chai_1.expect)(foundSimulator.wdaLocalPort).to.match(/[0-9]/);
|
|
211
|
+
}));
|
|
212
|
+
it('Should find free Apple TV simulator and set busy status to true', function () {
|
|
213
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
214
|
+
if (process.env.CI) {
|
|
215
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
216
|
+
const deviceManager = (0, test_container_1.createTestXenonManager)(pluginArgs);
|
|
217
|
+
const hub = pluginArgs.hub;
|
|
218
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp, hub);
|
|
219
|
+
yield markSimulatorsAsBooted();
|
|
220
|
+
yield (0, device_service_1.unblockDeviceMatchingFilter)({});
|
|
221
|
+
yield (0, device_utils_1.cleanPendingSessions)(0);
|
|
222
|
+
const capabilities = {
|
|
223
|
+
alwaysMatch: {
|
|
224
|
+
platformName: 'tvOS',
|
|
225
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
226
|
+
'appium:deviceRetryInterval': 100,
|
|
227
|
+
},
|
|
228
|
+
firstMatch: [{}],
|
|
229
|
+
};
|
|
230
|
+
const device = yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 6000, 1000, pluginArgs);
|
|
231
|
+
const allocatedSimulator = (yield db_1.XenonDatabase.DeviceModel)
|
|
232
|
+
.chain()
|
|
233
|
+
.find({ udid: device.udid })
|
|
234
|
+
.data();
|
|
235
|
+
const foundSimulator = allocatedSimulator[0];
|
|
236
|
+
(0, chai_1.expect)(foundSimulator.busy).to.be.true;
|
|
237
|
+
(0, chai_1.expect)(foundSimulator.name).to.match(/^Apple TV/);
|
|
238
|
+
(0, chai_1.expect)(foundSimulator.wdaLocalPort).to.match(/[0-9]/);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
this.skip();
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
describe('Boot simulator test', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
247
|
+
before('Boot simulator', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
248
|
+
const list = yield simctl.list();
|
|
249
|
+
const version = list.runtimes[0].version;
|
|
250
|
+
const devices = (0, lodash_1.flatten)(Object.keys(list.devices).map((key) => list.devices[key]));
|
|
251
|
+
//console.log('devices: ', devices);
|
|
252
|
+
// find device is isAvailable=true
|
|
253
|
+
const availableDevices = devices.filter((device) => device.isAvailable);
|
|
254
|
+
//console.log('availableDevices: ', availableDevices);
|
|
255
|
+
// find device name starts with iPhone
|
|
256
|
+
const iphone = availableDevices.find((device) => device.name.startsWith('iPhone'));
|
|
257
|
+
simctl.udid = yield simctl.createDevice(name, iphone.name, version);
|
|
258
|
+
yield simctl.bootDevice();
|
|
259
|
+
yield simctl.startBootMonitor({ timeout: 160000 });
|
|
260
|
+
}));
|
|
261
|
+
beforeEach('Release devices', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
262
|
+
yield (0, device_service_1.unblockDeviceMatchingFilter)({});
|
|
263
|
+
}));
|
|
264
|
+
it('Should pick Booted simulator when app path has .app', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
265
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
266
|
+
const deviceManager = (0, test_container_1.createTestXenonManager)(pluginArgs);
|
|
267
|
+
const hub = pluginArgs.hub;
|
|
268
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp, hub);
|
|
269
|
+
const capabilities = {
|
|
270
|
+
alwaysMatch: {
|
|
271
|
+
platformName: 'iOS',
|
|
272
|
+
'appium:app': '/Downloads/VodQA.app',
|
|
273
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
274
|
+
'appium:deviceRetryInterval': 100,
|
|
275
|
+
},
|
|
276
|
+
firstMatch: [{}],
|
|
277
|
+
};
|
|
278
|
+
const devices = yield deviceManager.getDevices();
|
|
279
|
+
console.log('devices: ', devices);
|
|
280
|
+
const device = yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 6000, 1000, pluginArgs);
|
|
281
|
+
const allocatedSimulator = (yield db_1.XenonDatabase.DeviceModel)
|
|
282
|
+
.chain()
|
|
283
|
+
.find({ udid: device.udid })
|
|
284
|
+
.data();
|
|
285
|
+
(0, chai_1.expect)(allocatedSimulator[0].state).to.be.equal('Booted');
|
|
286
|
+
}));
|
|
287
|
+
after('Delete simulator', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
288
|
+
if (simctl.udid)
|
|
289
|
+
yield simctl.deleteDevice(simctl.udid);
|
|
290
|
+
}));
|
|
291
|
+
}));
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
require("reflect-metadata");
|
|
16
|
+
const chai_1 = require("chai");
|
|
17
|
+
const ip_1 = __importDefault(require("ip"));
|
|
18
|
+
const device_utils_1 = require("../../../src/device-utils");
|
|
19
|
+
const db_1 = require("../../../src/data-service/db");
|
|
20
|
+
const IPluginArgs_1 = require("../../../src/interfaces/IPluginArgs");
|
|
21
|
+
const device_service_1 = require("../../../src/data-service/device-service");
|
|
22
|
+
const test_container_1 = require("../../helpers/test-container");
|
|
23
|
+
const pluginArgs = Object.assign({}, IPluginArgs_1.DefaultPluginArgs, {
|
|
24
|
+
remote: [`http://${ip_1.default.address()}:4723`],
|
|
25
|
+
iosDeviceType: 'both',
|
|
26
|
+
platform: 'ios',
|
|
27
|
+
});
|
|
28
|
+
describe('IOS Test', () => {
|
|
29
|
+
beforeEach('Release devices', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
+
// unblock all otherwise it will stuck on max session count
|
|
31
|
+
yield (0, device_service_1.unblockDeviceMatchingFilter)({});
|
|
32
|
+
}));
|
|
33
|
+
it('Throw error when no device is found for given capabilities', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
35
|
+
(yield db_1.XenonDatabase.CLIArgs)
|
|
36
|
+
.chain()
|
|
37
|
+
.find()
|
|
38
|
+
.update(function (d) {
|
|
39
|
+
d.plugin['xenon'].iosDeviceType = 'real';
|
|
40
|
+
});
|
|
41
|
+
const deviceManager = (0, test_container_1.createTestXenonManager)(pluginArgs);
|
|
42
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp);
|
|
43
|
+
const capabilities = {
|
|
44
|
+
alwaysMatch: {
|
|
45
|
+
platformName: 'iOS',
|
|
46
|
+
'appium:app': '/Downloads/VodQA.ipa',
|
|
47
|
+
'appium:iPhoneOnly': true,
|
|
48
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
49
|
+
'appium:deviceRetryInterval': 100,
|
|
50
|
+
},
|
|
51
|
+
firstMatch: [{}],
|
|
52
|
+
};
|
|
53
|
+
yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 6000, 1000, pluginArgs).catch((error) => (0, chai_1.expect)(error)
|
|
54
|
+
.to.be.an('error')
|
|
55
|
+
.with.property('message', 'No device matching request.. Device request: {"platform":"ios","name":"iPhone","deviceType":"real"}'));
|
|
56
|
+
}));
|
|
57
|
+
it('Should throw error if the IPA does not match with device type real', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
59
|
+
const deviceManager = (0, test_container_1.createTestXenonManager)(pluginArgs);
|
|
60
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp);
|
|
61
|
+
const capabilities = {
|
|
62
|
+
alwaysMatch: {
|
|
63
|
+
platformName: 'iOS',
|
|
64
|
+
'appium:app': '/Downloads/VodQA.zip',
|
|
65
|
+
'appium:iPhoneOnly': true,
|
|
66
|
+
'appium:deviceAvailabilityTimeout': 1800,
|
|
67
|
+
'appium:deviceRetryInterval': 100,
|
|
68
|
+
},
|
|
69
|
+
firstMatch: [{}],
|
|
70
|
+
};
|
|
71
|
+
yield (0, device_utils_1.allocateDeviceForSession)(capabilities, 6000, 1000, pluginArgs).catch((error) => (0, chai_1.expect)(error)
|
|
72
|
+
.to.be.an('error')
|
|
73
|
+
.with.property('message', 'iosDeviceType value is set to "real" but app provided is not suitable for real device.'));
|
|
74
|
+
}));
|
|
75
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.updateDevice = exports.unblockDevice = exports.blockDevice = exports.simulators = exports.androidDevices = exports.sessionId = exports.deviceState = void 0;
|
|
46
|
+
exports.findFreeDevice = findFreeDevice;
|
|
47
|
+
const ramda_1 = require("ramda");
|
|
48
|
+
const device = __importStar(require("../../src/Devices"));
|
|
49
|
+
const deviceState = (device) => (0, ramda_1.pipe)((0, ramda_1.find)((0, ramda_1.propEq)('udid', device)), (0, ramda_1.prop)('busy'));
|
|
50
|
+
exports.deviceState = deviceState;
|
|
51
|
+
const sessionId = (device) => (0, ramda_1.pipe)((0, ramda_1.find)((0, ramda_1.propEq)('udid', device)), (0, ramda_1.prop)('sessionId'));
|
|
52
|
+
exports.sessionId = sessionId;
|
|
53
|
+
function findFreeDevice(firstMatch, cliArgs) {
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
yield device.fetchDevices(cliArgs);
|
|
56
|
+
return device.getFreeDevice(firstMatch);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const androidDevices = () => device.listAllAndroidDevices();
|
|
60
|
+
exports.androidDevices = androidDevices;
|
|
61
|
+
const simulators = () => device.listiOSSimulators();
|
|
62
|
+
exports.simulators = simulators;
|
|
63
|
+
exports.blockDevice = (0, ramda_1.curry)((devices, freeDevice, platform) => {
|
|
64
|
+
device.blockDevice(freeDevice, platform);
|
|
65
|
+
return devices();
|
|
66
|
+
});
|
|
67
|
+
exports.unblockDevice = (0, ramda_1.curry)((devices, freeDevice, platform) => {
|
|
68
|
+
device.unblockDevice(freeDevice, platform);
|
|
69
|
+
return devices();
|
|
70
|
+
});
|
|
71
|
+
exports.updateDevice = (0, ramda_1.curry)((devices, freeDevice, sessionId) => {
|
|
72
|
+
device.updateDevice(freeDevice, sessionId);
|
|
73
|
+
return devices();
|
|
74
|
+
});
|