appium-xcuitest-driver
Version:
Appium driver for iOS using XCUITest for backend
358 lines • 18.9 kB
JavaScript
;
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