UNPKG

webdriverio-automation

Version:

WebdriverIO-Automation android ios project

443 lines (398 loc) 15.5 kB
import _ from 'lodash'; import { server, routeConfiguringFunction, DeviceSettings, errors } from '../..'; import { W3C_ELEMENT_KEY, MJSONWP_ELEMENT_KEY } from '../../lib/protocol/protocol'; import request from 'request-promise'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import B from 'bluebird'; const should = chai.should(); const DEFAULT_ARGS = { address: 'localhost', port: 8181 }; chai.use(chaiAsPromised); function baseDriverE2ETests (DriverClass, defaultCaps = {}) { describe('BaseDriver (e2e)', function () { let baseServer, d = new DriverClass(DEFAULT_ARGS); before(async function () { baseServer = await server(routeConfiguringFunction(d), DEFAULT_ARGS.port); }); after(async function () { await baseServer.close(); }); function startSession (caps) { return request({ url: 'http://localhost:8181/wd/hub/session', method: 'POST', json: {desiredCapabilities: caps, requiredCapabilities: {}}, }); } function endSession (id) { return request({ url: `http://localhost:8181/wd/hub/session/${id}`, method: 'DELETE', json: true, simple: false }); } function getSession (id) { return request({ url: `http://localhost:8181/wd/hub/session/${id}`, method: 'GET', json: true, simple: false }); } describe('session handling', function () { it('should create session and retrieve a session id, then delete it', async function () { let res = await request({ url: 'http://localhost:8181/wd/hub/session', method: 'POST', json: {desiredCapabilities: defaultCaps, requiredCapabilities: {}}, simple: false, resolveWithFullResponse: true }); res.statusCode.should.equal(200); res.body.status.should.equal(0); should.exist(res.body.sessionId); res.body.value.should.eql(defaultCaps); res = await request({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}`, method: 'DELETE', json: true, simple: false, resolveWithFullResponse: true }); res.statusCode.should.equal(200); res.body.status.should.equal(0); should.equal(d.sessionId, null); }); }); it.skip('should throw NYI for commands not implemented', async function () { }); describe('command timeouts', function () { let originalFindElement, originalFindElements; function startTimeoutSession (timeout) { let caps = _.clone(defaultCaps); caps.newCommandTimeout = timeout; return startSession(caps); } before(function () { originalFindElement = d.findElement; d.findElement = function () { return 'foo'; }.bind(d); originalFindElements = d.findElements; d.findElements = async function () { await B.delay(200); return ['foo']; }.bind(d); }); after(function () { d.findElement = originalFindElement; d.findElements = originalFindElements; }); it('should set a default commandTimeout', async function () { let newSession = await startTimeoutSession(); d.newCommandTimeoutMs.should.be.above(0); await endSession(newSession.sessionId); }); it('should timeout on commands using commandTimeout cap', async function () { let newSession = await startTimeoutSession(0.25); await request({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}/element`, method: 'POST', json: {using: 'name', value: 'foo'}, }); await B.delay(400); let res = await request({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}`, method: 'GET', json: true, simple: false }); res.status.should.equal(6); should.equal(d.sessionId, null); res = await endSession(newSession.sessionId); res.status.should.equal(6); }); it('should not timeout with commandTimeout of false', async function () { let newSession = await startTimeoutSession(0.1); let start = Date.now(); let res = await request({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}/elements`, method: 'POST', json: {using: 'name', value: 'foo'}, }); (Date.now() - start).should.be.above(150); res.value.should.eql(['foo']); await endSession(newSession.sessionId); }); it('should not timeout with commandTimeout of 0', async function () { d.newCommandTimeoutMs = 2; let newSession = await startTimeoutSession(0); await request({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}/element`, method: 'POST', json: {using: 'name', value: 'foo'}, }); await B.delay(400); let res = await request({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}`, method: 'GET', json: true, simple: false }); res.status.should.equal(0); res = await endSession(newSession.sessionId); res.status.should.equal(0); d.newCommandTimeoutMs = 60 * 1000; }); it('should not timeout if its just the command taking awhile', async function () { let newSession = await startTimeoutSession(0.25); await request({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}/element`, method: 'POST', json: {using: 'name', value: 'foo'}, }); await B.delay(400); let res = await request({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}`, method: 'GET', json: true, simple: false }); res.status.should.equal(6); should.equal(d.sessionId, null); res = await endSession(newSession.sessionId); res.status.should.equal(6); }); it('should not have a timer running before or after a session', async function () { should.not.exist(d.noCommandTimer); let newSession = await startTimeoutSession(0.25); newSession.sessionId.should.equal(d.sessionId); should.exist(d.noCommandTimer); await endSession(newSession.sessionId); should.not.exist(d.noCommandTimer); }); }); describe('settings api', function () { before(function () { d.settings = new DeviceSettings({ignoreUnimportantViews: false}); }); it('should be able to get settings object', function () { d.settings.getSettings().ignoreUnimportantViews.should.be.false; }); it('should throw error when updateSettings method is not defined', async function () { await d.settings.update({ignoreUnimportantViews: true}).should.eventually .be.rejectedWith('onSettingsUpdate'); }); it('should throw error for invalid update object', async function () { await d.settings.update('invalid json').should.eventually .be.rejectedWith('JSON'); }); }); describe('unexpected exits', function () { it('should reject a current command when the driver crashes', async function () { d._oldGetStatus = d.getStatus; d.getStatus = async function () { await B.delay(5000); }.bind(d); let p = request({ url: 'http://localhost:8181/wd/hub/status', method: 'GET', json: true, simple: false }); // make sure that the request gets to the server before our shutdown await B.delay(100); d.startUnexpectedShutdown(new Error('Crashytimes')); let res = await p; res.status.should.equal(13); res.value.message.should.contain('Crashytimes'); await d.onUnexpectedShutdown.should.be.rejectedWith('Crashytimes'); d.getStatus = d._oldGetStatus; }); }); describe('event timings', function () { it('should not add timings if not using opt-in cap', async function () { let session = await startSession(defaultCaps); let res = await getSession(session.sessionId); should.not.exist(res.events); await endSession(session.sessionId); }); it('should add start session timings', async function () { let caps = Object.assign({}, defaultCaps, {eventTimings: true}); let session = await startSession(caps); let res = (await getSession(session.sessionId)).value; should.exist(res.events); should.exist(res.events.newSessionRequested); should.exist(res.events.newSessionStarted); res.events.newSessionRequested[0].should.be.a('number'); res.events.newSessionStarted[0].should.be.a('number'); await endSession(session.sessionId); }); }); describe('execute driver script', function () { // mock some methods on BaseDriver that aren't normally there except in // a fully blown driver let originalFindElement, sessionId; before(function () { d.allowInsecure = ['execute_driver_script']; originalFindElement = d.findElement; d.findElement = (function (strategy, selector) { if (strategy === 'accessibility id' && selector === 'amazing') { return {[W3C_ELEMENT_KEY]: 'element-id-1'}; } throw new errors.NoSuchElementError('not found'); }).bind(d); }); beforeEach(async function () { ({sessionId} = await startSession(defaultCaps)); }); after(function () { d.findElement = originalFindElement; }); afterEach(async function () { await endSession(sessionId); }); it('should not work unless the allowInsecure feature flag is set', async function () { d._allowInsecure = d.allowInsecure; d.allowInsecure = []; const script = `return 'foo'`; await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script, type: 'wd'}, }).should.eventually.be.rejectedWith(/allow-insecure/); await endSession(sessionId); d.allowInsecure = d._allowInsecure; }); it('should execute a webdriverio script in the context of session', async function () { const script = ` const timeouts = await driver.getTimeouts(); const status = await driver.status(); return [timeouts, status]; `; const res = await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script, type: 'webdriverio'}, }); const expectedTimeouts = {command: 250, implicit: 0}; const expectedStatus = {}; res.value.result.should.eql([expectedTimeouts, expectedStatus]); }); it('should fail with any script type other than webdriverio currently', async function () { const script = `return 'foo'`; await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script, type: 'wd'}, }).should.eventually.be.rejectedWith(/script type/); }); it('should execute a webdriverio script that returns elements correctly', async function () { const script = ` return await driver.$("~amazing"); `; const res = await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script}, }); res.value.result.should.eql({ [W3C_ELEMENT_KEY]: 'element-id-1', [MJSONWP_ELEMENT_KEY]: 'element-id-1' }); }); it('should execute a webdriverio script that returns elements in deep structure', async function () { const script = ` const el = await driver.$("~amazing"); return {element: el, elements: [el, el]}; `; const res = await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script}, }); const elObj = { [W3C_ELEMENT_KEY]: 'element-id-1', [MJSONWP_ELEMENT_KEY]: 'element-id-1' }; res.value.result.should.eql({element: elObj, elements: [elObj, elObj]}); }); it('should store and return logs to the user', async function () { const script = ` console.log("foo"); console.log("foo2"); console.warn("bar"); console.error("baz"); return null; `; const res = await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script}, }); res.value.logs.should.eql({log: ['foo', 'foo2'], warn: ['bar'], error: ['baz']}); }); it('should have appium specific commands available', async function () { const script = ` return typeof driver.lock; `; const res = await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script}, }); res.value.result.should.eql('function'); }); it('should correctly handle errors that happen in a webdriverio script', async function () { const script = ` return await driver.$("~notfound"); `; const res = await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script}, simple: false, }); res.should.eql({ sessionId, status: 13, value: {message: 'An unknown server-side error occurred while processing the command. Original error: Could not execute driver script. Original error was: Error: not found'} }); }); it('should correctly handle errors that happen when a script cannot be compiled', async function () { const script = ` return {; `; const res = await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script}, simple: false, }); res.should.eql({ sessionId, status: 13, value: {message: 'An unknown server-side error occurred while processing the command. Original error: Could not execute driver script. Original error was: Error: Unexpected token ;'} }); }); it('should be able to set a timeout on a driver script', async function () { const script = ` await Promise.delay(1000); return true; `; const res = await request({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: {script, timeout: 50}, simple: false, }); res.value.message.should.match(/.+50.+timeout.+/); }); }); }); } export default baseDriverE2ETests;