mirror of
https://github.com/appium/appium.git
synced 2026-10-28 04:14:00 +08:00
260 lines
8.4 KiB
JavaScript
260 lines
8.4 KiB
JavaScript
import _ from 'lodash';
|
|
import chai from 'chai';
|
|
import chaiAsPromised from 'chai-as-promised';
|
|
import B from 'bluebird';
|
|
|
|
const should = chai.should();
|
|
chai.use(chaiAsPromised);
|
|
|
|
// wrap these tests in a function so we can export the tests and re-use them
|
|
// for actual driver implementations
|
|
function baseDriverUnitTests (DriverClass, defaultCaps = {}) {
|
|
describe('BaseDriver', () => {
|
|
|
|
let d;
|
|
beforeEach(() => {
|
|
d = new DriverClass();
|
|
});
|
|
|
|
it('should return an empty status object', async () => {
|
|
let status = await d.getStatus();
|
|
status.should.eql({});
|
|
});
|
|
|
|
it('should return a sessionId from createSession', async () => {
|
|
let [sessId] = await d.createSession(defaultCaps);
|
|
should.exist(sessId);
|
|
sessId.should.be.a('string');
|
|
sessId.length.should.be.above(5);
|
|
});
|
|
|
|
it('should not be able to start two sessions without closing the first', async () => {
|
|
await d.createSession(defaultCaps);
|
|
await d.createSession(defaultCaps).should.eventually.be.rejectedWith('session');
|
|
});
|
|
|
|
it('should be able to delete a session', async () => {
|
|
let sessionId1 = await d.createSession(defaultCaps);
|
|
await d.deleteSession();
|
|
should.equal(d.sessionId, null);
|
|
let sessionId2 = await d.createSession(defaultCaps);
|
|
sessionId1.should.not.eql(sessionId2);
|
|
});
|
|
|
|
it('should get the current session', async () => {
|
|
let [, caps] = await d.createSession(defaultCaps);
|
|
caps.should.equal(await d.getSession());
|
|
});
|
|
|
|
it('should return sessions if no session exists', async () => {
|
|
let sessions = await d.getSessions();
|
|
sessions.length.should.equal(0);
|
|
});
|
|
|
|
it('should return sessions', async () => {
|
|
let caps = _.clone(defaultCaps);
|
|
caps.a = 'cap';
|
|
await d.createSession(caps);
|
|
let sessions = await d.getSessions();
|
|
|
|
sessions.length.should.equal(1);
|
|
sessions[0].should.eql({
|
|
id: d.sessionId,
|
|
capabilities: caps
|
|
});
|
|
});
|
|
|
|
it('should fulfill an unexpected driver quit promise', async () => {
|
|
// make a command that will wait a bit so we can crash while it's running
|
|
d.getStatus = async function () {
|
|
await B.delay(100);
|
|
}.bind(d);
|
|
let cmdPromise = d.executeCommand('getStatus');
|
|
await B.delay(0);
|
|
d.startUnexpectedShutdown(new Error('We crashed'));
|
|
await cmdPromise.should.be.rejectedWith(/We crashed/);
|
|
await d.onUnexpectedShutdown.should.be.rejectedWith(/We crashed/);
|
|
});
|
|
|
|
it('should not allow commands in middle of unexpected shutdown', async () => {
|
|
// make a command that will wait a bit so we can crash while it's running
|
|
d.oldDeleteSession = d.deleteSession;
|
|
d.deleteSession = async function () {
|
|
await B.delay(100);
|
|
await this.oldDeleteSession();
|
|
}.bind(d);
|
|
let caps = _.clone(defaultCaps);
|
|
await d.createSession(caps);
|
|
d.startUnexpectedShutdown(new Error('We crashed'));
|
|
await d.onUnexpectedShutdown.should.be.rejectedWith(/We crashed/);
|
|
await d.executeCommand('getSession').should.be.rejectedWith(/shut down/);
|
|
});
|
|
|
|
it('should allow new commands after done shutting down', async () => {
|
|
// make a command that will wait a bit so we can crash while it's running
|
|
d.oldDeleteSession = d.deleteSession;
|
|
d.deleteSession = async function () {
|
|
await B.delay(100);
|
|
await this.oldDeleteSession();
|
|
}.bind(d);
|
|
let caps = _.clone(defaultCaps);
|
|
await d.createSession(caps);
|
|
d.startUnexpectedShutdown(new Error('We crashed'));
|
|
await d.onUnexpectedShutdown.should.be.rejectedWith(/We crashed/);
|
|
await d.executeCommand('getSession').should.be.rejectedWith(/shut down/);
|
|
await B.delay(100);
|
|
await d.executeCommand('createSession', caps);
|
|
await d.deleteSession();
|
|
});
|
|
|
|
it('should have a method to get driver for a session', async () => {
|
|
let [sessId] = await d.createSession(defaultCaps);
|
|
d.driverForSession(sessId).should.eql(d);
|
|
});
|
|
|
|
describe('command queue', () => {
|
|
let d = new DriverClass();
|
|
|
|
let waitMs = 10;
|
|
d.getStatus = async function () {
|
|
await B.delay(waitMs);
|
|
return Date.now();
|
|
}.bind(d);
|
|
|
|
d.getSessions = async function () {
|
|
await B.delay(waitMs);
|
|
throw new Error('multipass');
|
|
}.bind(d);
|
|
|
|
afterEach(() => {
|
|
d.clearNewCommandTimeout();
|
|
});
|
|
|
|
it('should queue commands and.executeCommand/respond in the order received', async () => {
|
|
let numCmds = 10;
|
|
let cmds = [];
|
|
for (let i = 0; i < numCmds; i++) {
|
|
cmds.push(d.executeCommand('getStatus'));
|
|
}
|
|
let results = await B.all(cmds);
|
|
for (let i = 1; i < numCmds; i++) {
|
|
if (results[i] <= results[i - 1]) {
|
|
throw new Error('Got result out of order');
|
|
}
|
|
}
|
|
});
|
|
|
|
it('should handle errors correctly when queuing', async () => {
|
|
let numCmds = 10;
|
|
let cmds = [];
|
|
for (let i = 0; i < numCmds; i++) {
|
|
if (i === 5) {
|
|
cmds.push(d.executeCommand('getSessions'));
|
|
} else {
|
|
cmds.push(d.executeCommand('getStatus'));
|
|
}
|
|
}
|
|
let results = await B.settle(cmds);
|
|
for (let i = 1; i < 5; i++) {
|
|
if (results[i].value() <= results[i - 1].value()) {
|
|
throw new Error('Got result out of order');
|
|
}
|
|
}
|
|
results[5].reason().message.should.contain('multipass');
|
|
for (let i = 7; i < numCmds; i++) {
|
|
if (results[i].value() <= results[i - 1].value()) {
|
|
throw new Error('Got result out of order');
|
|
}
|
|
}
|
|
});
|
|
|
|
it('should not care if queue empties for a bit', async () => {
|
|
let numCmds = 10;
|
|
let cmds = [];
|
|
for (let i = 0; i < numCmds; i++) {
|
|
cmds.push(d.executeCommand('getStatus'));
|
|
}
|
|
let results = await B.all(cmds);
|
|
cmds = [];
|
|
for (let i = 0; i < numCmds; i++) {
|
|
cmds.push(d.executeCommand('getStatus'));
|
|
}
|
|
results = await B.all(cmds);
|
|
for (let i = 1; i < numCmds; i++) {
|
|
if (results[i] <= results[i - 1]) {
|
|
throw new Error('Got result out of order');
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('timeouts', () => {
|
|
before(async () => {
|
|
await d.createSession(defaultCaps);
|
|
});
|
|
describe('command', () => {
|
|
it('should exist by default', async () => {
|
|
d.newCommandTimeoutMs.should.equal(60000);
|
|
});
|
|
it('should be settable through `timeouts`', async () => {
|
|
await d.timeouts('command', 20);
|
|
d.newCommandTimeoutMs.should.equal(20);
|
|
});
|
|
});
|
|
describe('implicit', () => {
|
|
it('should not exist by default', async () => {
|
|
d.implicitWaitMs.should.equal(0);
|
|
});
|
|
it('should be settable through `timeouts`', async () => {
|
|
await d.timeouts('implicit', 20);
|
|
d.implicitWaitMs.should.equal(20);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('proxying', () => {
|
|
let sessId;
|
|
beforeEach(async () => {
|
|
[sessId] = await d.createSession(defaultCaps);
|
|
});
|
|
describe('#proxyActive', () => {
|
|
it('should exist', () => {
|
|
d.proxyActive.should.be.an.instanceof(Function);
|
|
});
|
|
it('should return false', () => {
|
|
d.proxyActive(sessId).should.be.false;
|
|
});
|
|
it('should throw an error when sessionId is wrong', () => {
|
|
(() => { d.proxyActive('aaa'); }).should.throw;
|
|
});
|
|
});
|
|
|
|
describe('#getProxyAvoidList', () => {
|
|
it('should exist', () => {
|
|
d.getProxyAvoidList.should.be.an.instanceof(Function);
|
|
});
|
|
it('should return an array', () => {
|
|
d.getProxyAvoidList(sessId).should.be.an.instanceof(Array);
|
|
});
|
|
it('should throw an error when sessionId is wrong', () => {
|
|
(() => { d.getProxyAvoidList('aaa'); }).should.throw;
|
|
});
|
|
});
|
|
|
|
describe('#canProxy', () => {
|
|
it('should have a #canProxy method', () => {
|
|
d.canProxy.should.be.an.instanceof(Function);
|
|
});
|
|
it('should return false from #canProxy', () => {
|
|
d.canProxy(sessId).should.be.false;
|
|
});
|
|
it('should throw an error when sessionId is wrong', () => {
|
|
(() => { d.canProxy(); }).should.throw;
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
export default baseDriverUnitTests;
|