UNPKG

appium-xcuitest-driver

Version:

Appium driver for iOS using XCUITest for backend

358 lines 18.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const appium_xcode_1 = __importDefault(require("appium-xcode")); const driver_1 = require("appium/driver"); const lodash_1 = __importDefault(require("lodash")); const sinon_1 = require("sinon"); const driver_2 = require("../../lib/driver"); const utils = __importStar(require("../../lib/utils")); const helpers_1 = require("./helpers"); const real_device_management_1 = require("../../lib/device/real-device-management"); const node_net_1 = __importDefault(require("node:net")); const chai_1 = __importStar(require("chai")); const chai_as_promised_1 = __importDefault(require("chai-as-promised")); chai_1.default.use(chai_as_promised_1.default); const caps = { fistMatch: [{}], alwaysMatch: { platformName: 'iOS', 'appium:deviceName': 'iPhone 6', 'appium:app': '/foo.app', 'appium:platformVersion': '10.0', }, }; describe('XCUITestDriver', function () { let sandbox; beforeEach(function () { sandbox = (0, sinon_1.createSandbox)(); }); afterEach(function () { sandbox.restore(); }); describe('getDefaultUrl', function () { let driver; let realDevice; beforeEach(function () { driver = new driver_2.XCUITestDriver({}); realDevice = new real_device_management_1.RealDevice('1234'); // Mock _wda to avoid getter throwing error // For simulators, url.port should be undefined to allow wdaLocalPort to be used driver._wda = { url: { port: undefined }, }; }); it('real device', function () { driver._device = realDevice; // For real devices, wda.url.port should be used if available driver._wda = { url: { port: 8100 }, }; (0, chai_1.expect)(driver.getDefaultUrl()).eq('http://127.0.0.1:8100/health'); }); it('simulator with ipv4', function () { driver.opts.wdaLocalPort = 8111; (0, chai_1.expect)(driver.getDefaultUrl()).eq('http://127.0.0.1:8111/health'); }); it('simulator with ipv6', function () { driver.opts.address = '::1'; (0, chai_1.expect)(driver.getDefaultUrl()).eq('http://127.0.0.1:8100/health'); }); }); describe('driver commands', function () { describe('status', function () { /** @type {XCUITestDriver} */ let driver; /** @type {import('sinon').SinonStubbedMember<typeof JWProxy.prototype.command>} */ let jwproxyCommandSpy; beforeEach(function () { driver = new driver_2.XCUITestDriver({}); // fake the proxy to WDA const jwproxy = new driver_1.JWProxy(); jwproxyCommandSpy = sandbox.stub(jwproxy, 'command').resolves({ some: 'thing' }); driver._wda = { jwproxy, }; }); it('should not have wda status by default', async function () { const status = await driver.getStatus(); (0, chai_1.expect)(jwproxyCommandSpy.calledOnce).to.be.false; (0, chai_1.expect)(status.wda).to.be.undefined; }); it('should return wda status if cached', async function () { driver.cachedWdaStatus = {}; const status = await driver.getStatus(); (0, chai_1.expect)(jwproxyCommandSpy.called).to.be.false; (0, chai_1.expect)(status.wda).to.exist; }); }); describe('createSession', function () { let driver; let device; let realDevice; afterEach(async function () { await driver.deleteSession(); }); beforeEach(function () { driver = new driver_2.XCUITestDriver({}); device = { shutdown: lodash_1.default.noop, isRunning() { return true; }, stat() { return { state: 'Booted' }; }, getWebInspectorSocket() { return '/path/to/uds.socket'; }, setReduceTransparency: lodash_1.default.noop, setAutoFillPasswords: lodash_1.default.noop, reset: lodash_1.default.noop, }; const cacheMock = sandbox.mock(driver.appInfosCache); cacheMock.expects('extractBundleId').once().returns('bundle.id'); realDevice = null; sandbox .stub(driver, 'determineDevice') .callsFake(async () => ({ device, realDevice, udid: 'stuff' })); sandbox.stub(driver, 'configureApp'); sandbox.stub(driver, 'startLogCapture'); sandbox.stub(driver, 'startSim'); sandbox.stub(driver, 'startWdaSession'); sandbox.stub(driver, 'startWda'); sandbox.stub(driver, 'installAUT'); sandbox.stub(driver, 'connectToRemoteDebugger'); sandbox.stub(appium_xcode_1.default, 'getMaxIOSSDK').resolves('10.0'); sandbox.stub(utils, 'checkAppPresent'); sandbox.stub(utils, 'getAndCheckXcodeVersion').resolves({ versionString: '20.0', versionFloat: 20.0, major: 20, minor: 0, toString() { return '20.0'; }, }); }); it('should include server capabilities', async function () { this.timeout(helpers_1.MOCHA_LONG_TIMEOUT); const resCaps = await driver.createSession(null, null, lodash_1.default.cloneDeep(caps)); (0, chai_1.expect)(resCaps[1].javascriptEnabled).to.be.true; }); it('should call startLogCapture', async function () { this.timeout(helpers_1.MOCHA_LONG_TIMEOUT); const resCaps = await driver.createSession(null, null, lodash_1.default.merge({}, caps, { alwaysMatch: { 'appium:skipLogCapture': false, }, })); (0, chai_1.expect)(resCaps[1].javascriptEnabled).to.be.true; (0, chai_1.expect)(driver.startLogCapture.called).to.be.true; }); it('should not call startLogCapture', async function () { this.timeout(helpers_1.MOCHA_LONG_TIMEOUT); const resCaps = await driver.createSession(null, null, lodash_1.default.merge({}, caps, { alwaysMatch: { 'appium:skipLogCapture': true, }, })); (0, chai_1.expect)(resCaps[1].javascriptEnabled).to.be.true; (0, chai_1.expect)(driver.startLogCapture.called).to.be.false; }); it('should call setReduceTransparency for a simulator', async function () { this.timeout(helpers_1.MOCHA_LONG_TIMEOUT); device.simctl = true; delete device.devicectl; const spy = sandbox.stub(device, 'setReduceTransparency').resolves({ device, realDevice }); await driver.createSession(null, null, lodash_1.default.merge({}, caps, { alwaysMatch: { 'appium:reduceTransparency': true }, })); (0, chai_1.expect)(spy.calledOnce).to.be.true; (0, chai_1.expect)(spy.firstCall.args[0]).to.eql(true); }); it('should not call setReduceTransparency for a real device', async function () { this.timeout(helpers_1.MOCHA_LONG_TIMEOUT); delete device.simctl; device.devicectl = true; const spy = sandbox.stub(device, 'setReduceTransparency').resolves({ device, realDevice }); await driver.createSession(null, null, lodash_1.default.merge({}, caps, { alwaysMatch: { 'appium:reduceTransparency': true }, })); (0, chai_1.expect)(spy.notCalled).to.be.true; }); it('should call setAutoFillPasswords for a simulator', async function () { this.timeout(helpers_1.MOCHA_LONG_TIMEOUT); device.simctl = true; delete device.devicectl; const spy = sandbox.stub(device, 'setAutoFillPasswords').resolves({ device, realDevice }); await driver.createSession(null, null, lodash_1.default.merge({}, caps, { alwaysMatch: { 'appium:autoFillPasswords': true }, })); (0, chai_1.expect)(spy.calledOnce).to.be.true; (0, chai_1.expect)(spy.firstCall.args[0]).to.eql(true); }); it('should not call setAutoFillPasswords for a real device', async function () { this.timeout(helpers_1.MOCHA_LONG_TIMEOUT); delete device.simctl; device.devicectl = true; const spy = sandbox.stub(device, 'setAutoFillPasswords').resolves({ device, realDevice }); await driver.createSession(null, null, lodash_1.default.merge({}, caps, { alwaysMatch: { 'appium:setAutoFillPasswords': true }, })); (0, chai_1.expect)(spy.notCalled).to.be.true; }); it('should throw an error if mjpegServerPort is occupied', async function () { this.timeout(helpers_1.MOCHA_LONG_TIMEOUT); delete device.simctl; device.devicectl = true; const server = node_net_1.default.createServer(); await new Promise((resolve, reject) => { server.listen(9100, () => resolve()); server.on('error', reject); }); try { await (0, chai_1.expect)(driver.createSession(null, null, lodash_1.default.merge({}, caps, { alwaysMatch: { 'appium:mjpegServerPort': 9100 }, }))).to.be.rejectedWith(/mjpegServerPort.*port #9100 is occupied/); } finally { await new Promise((resolve, reject) => { server.close(resolve); server.on('error', reject); }); } }); }); describe('execute', function () { /** @type {XCUITestDriver} */ let driver; const deviceInfoResponse = { some: 'thing' }; beforeEach(function () { driver = new driver_2.XCUITestDriver({}); const jwproxy = new driver_1.JWProxy(); sandbox.stub(jwproxy, 'command').resolves(deviceInfoResponse); driver._wda = { jwproxy, }; }); it('should allow execute methods without whitespace', async function () { await (0, chai_1.expect)(driver.execute('mobile:deviceInfo')).to.eventually.eql(deviceInfoResponse); }); it('should allow execute methods with hella whitespace', async function () { await (0, chai_1.expect)(driver.execute('mobile: deviceInfo')).to.eventually.eql(deviceInfoResponse); }); it('should allow execute methods with leading/trailing whitespace', async function () { await (0, chai_1.expect)(driver.execute(' mobile: deviceInfo ')).to.eventually.eql(deviceInfoResponse); }); }); }); describe('installOtherApps', function () { /** @type {XCUITestDriver} */ let driver; beforeEach(function () { driver = new driver_2.XCUITestDriver({}); }); it('should install multiple apps from otherApps as string on on real devices', async function () { const RealDeviceManagementModule = require('../../lib/device/real-device-management'); sandbox.stub(RealDeviceManagementModule, 'installToRealDevice'); sandbox.stub(driver, 'isRealDevice').returns(true); sandbox.stub(driver.helpers, 'configureApp').resolves('/path/to/iosApp.app'); sandbox.mock(driver.appInfosCache) .expects('extractBundleId').resolves('bundle-id'); driver.opts.device = 'some-device'; driver.lifecycleData = { createSim: false }; await driver.installOtherApps('/path/to/iosApp.app'); (0, chai_1.expect)(driver.isRealDevice.calledOnce).to.be.true; (0, chai_1.expect)(driver.helpers.configureApp.calledOnce).to.be.true; (0, chai_1.expect)(RealDeviceManagementModule.installToRealDevice.calledOnceWithExactly('/path/to/iosApp.app', 'bundle-id', { skipUninstall: true, timeout: undefined })).to.be.true; }); it('should install multiple apps from otherApps as JSON array on on real devices', async function () { const RealDeviceManagementModule = require('../../lib/device/real-device-management'); sandbox.stub(RealDeviceManagementModule, 'installToRealDevice'); sandbox.stub(driver, 'isRealDevice').returns(true); const configureAppStub = sandbox.stub(driver.helpers, 'configureApp'); configureAppStub.onCall(0).resolves('/path/to/iosApp1.app'); configureAppStub.onCall(1).resolves('/path/to/iosApp2.app'); sandbox.stub(driver.appInfosCache, 'extractBundleId') .onCall(0).resolves('bundle-id') .onCall(1).resolves('bundle-id2'); driver.opts.device = 'some-device'; driver.lifecycleData = { createSim: false }; await driver.installOtherApps('["/path/to/iosApp1.app","/path/to/iosApp2.app"]'); (0, chai_1.expect)(driver.isRealDevice.calledTwice).to.be.true; (0, chai_1.expect)(driver.helpers.configureApp.calledTwice).to.be.true; (0, chai_1.expect)(RealDeviceManagementModule.installToRealDevice.calledWith('/path/to/iosApp1.app', 'bundle-id', { skipUninstall: true, timeout: undefined })).to.be.true; (0, chai_1.expect)(RealDeviceManagementModule.installToRealDevice.calledWith('/path/to/iosApp2.app', 'bundle-id2', { skipUninstall: true, timeout: undefined })).to.be.true; }); it('should install multiple apps from otherApps as string on simulators', async function () { const SimulatorManagementModule = require('../../lib/device/simulator-management'); sandbox.stub(SimulatorManagementModule, 'installToSimulator'); sandbox.stub(driver, 'isRealDevice').returns(false); sandbox.stub(driver.helpers, 'configureApp').resolves('/path/to/iosApp.app'); sandbox.mock(driver.appInfosCache) .expects('extractBundleId').resolves('bundle-id'); driver.opts.noReset = false; driver.opts.device = 'some-device'; driver.lifecycleData = { createSim: false }; await driver.installOtherApps('/path/to/iosApp.app'); (0, chai_1.expect)(driver.isRealDevice.calledOnce).to.be.true; (0, chai_1.expect)(driver.helpers.configureApp.calledOnce).to.be.true; (0, chai_1.expect)(SimulatorManagementModule.installToSimulator.calledOnceWithExactly('/path/to/iosApp.app', 'bundle-id', { newSimulator: false })).to.be.true; }); it('should install multiple apps from otherApps as JSON array on simulators', async function () { const SimulatorManagementModule = require('../../lib/device/simulator-management'); sandbox.stub(SimulatorManagementModule, 'installToSimulator'); sandbox.stub(driver, 'isRealDevice').returns(false); const configureAppStub = sandbox.stub(driver.helpers, 'configureApp'); configureAppStub.onCall(0).resolves('/path/to/iosApp1.app'); configureAppStub.onCall(1).resolves('/path/to/iosApp2.app'); sandbox.stub(driver.appInfosCache, 'extractBundleId') .onCall(0).resolves('bundle-id') .onCall(1).resolves('bundle-id2'); driver.opts.noReset = false; driver.lifecycleData = { createSim: false }; await driver.installOtherApps('["/path/to/iosApp1.app","/path/to/iosApp2.app"]'); (0, chai_1.expect)(driver.isRealDevice.calledTwice).to.be.true; (0, chai_1.expect)(driver.helpers.configureApp.calledTwice).to.be.true; (0, chai_1.expect)(SimulatorManagementModule.installToSimulator.calledWith('/path/to/iosApp1.app', 'bundle-id', { newSimulator: false })).to.be.true; (0, chai_1.expect)(SimulatorManagementModule.installToSimulator.calledWith('/path/to/iosApp2.app', 'bundle-id2', { newSimulator: false })).to.be.true; }); }); }); //# sourceMappingURL=driver-specs.js.map