Files
appium/packages/base-driver/test/e2e/protocol/protocol.e2e.spec.js
T

1051 lines
34 KiB
JavaScript

import {server, routeConfiguringFunction, errors, JWProxy, BaseDriver} from '../../../lib';
import {FakeDriver} from './fake-driver';
import axios from 'axios';
import {createSandbox} from 'sinon';
import {StatusCodes as HTTPStatusCodes} from 'http-status-codes';
import {createProxyServer} from './helpers';
import {MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY} from '../../../lib/constants';
import {TEST_HOST, getTestPort} from '@appium/driver-test-support';
let port;
let baseUrl;
describe('Protocol', function () {
let sandbox;
let should;
beforeEach(function () {
sandbox = createSandbox();
});
afterEach(function () {
sandbox.restore();
});
before(async function () {
const chai = await import('chai');
const chaisAsPromised = await import('chai-as-promised');
chai.use(chaisAsPromised.default);
should = chai.should();
port = await getTestPort();
baseUrl = `http://${TEST_HOST}:${port}`;
});
//TODO: more tests!:
// Unknown commands should return 404
describe('direct to driver', function () {
let d = new FakeDriver();
it('should return response values directly from the driver', async function () {
(await d.setUrl('http://google.com')).should.contain('google');
});
});
describe('via express router', function () {
let mjsonwpServer;
let driver;
before(async function () {
driver = new FakeDriver();
driver.sessionId = 'foo';
mjsonwpServer = await server({
routeConfiguringFunction: routeConfiguringFunction(driver),
port,
});
});
after(async function () {
await mjsonwpServer.close();
});
it('should proxy to driver and return valid jsonwp response', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/url`,
method: 'POST',
data: {url: 'http://google.com'},
});
data.should.eql({
value: 'Navigated to: http://google.com',
sessionId: 'foo',
});
});
it('should assume requests without a Content-Type are json requests', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/url`,
method: 'POST',
data: {url: 'http://google.com'},
});
data.should.eql({
value: 'Navigated to: http://google.com',
sessionId: 'foo',
});
});
it('should respond to x-www-form-urlencoded as well as json requests', async function () {
const reqData = new URLSearchParams();
reqData.set('url', 'http://google.com');
const {data} = await axios({
url: `${baseUrl}/session/foo/url`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
data: reqData.toString(),
});
data.should.eql({
value: 'Navigated to: http://google.com',
sessionId: 'foo',
});
});
it('should include url request parameters for methods to use - sessionid', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/back`,
method: 'POST',
data: {},
});
data.should.eql({
value: 'foo',
sessionId: 'foo',
});
});
it('should include url request parameters for methods to use - elementid', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/element/bar/click`,
method: 'POST',
data: {},
});
data.value.should.eql(['bar', 'foo']);
});
it('should include url req params in the order: custom, element, session', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/element/bar/attribute/baz`,
});
data.value.should.eql(['baz', 'bar', 'foo']);
});
it('should respond with 400 Bad Request if parameters missing', async function () {
const {data, status} = await axios({
url: `${baseUrl}/session/foo/url`,
method: 'POST',
data: {},
validateStatus: null,
});
status.should.equal(400);
JSON.stringify(data).should.contain('url');
});
it('should reject requests with a badly formatted body and not crash', async function () {
await axios({
url: `${baseUrl}/session/foo/url`,
method: 'POST',
data: 'oh hello',
}).should.eventually.be.rejected;
const {data} = await axios({
url: `${baseUrl}/session/foo/url`,
method: 'POST',
data: {url: 'http://google.com'},
});
data.should.eql({
value: 'Navigated to: http://google.com',
sessionId: 'foo',
});
});
it('should get 404 for bad routes', async function () {
await axios({
url: `${baseUrl}/blargimarg`,
}).should.eventually.be.rejectedWith(/404/);
});
it('4xx responses should have content-type of application/json', async function () {
const {headers} = await axios({
url: `${baseUrl}/blargimargarita`,
validateStatus: null,
});
headers['content-type'].should.include('application/json');
});
it('should throw not yet implemented for unfilledout commands', async function () {
const {status, data} = await axios({
url: `${baseUrl}/session/foo/element/bar/location`,
validateStatus: null,
});
status.should.equal(405);
data.value.error.should.eql('unknown method');
data.value.message.should.eql('Method has not yet been implemented');
data.sessionId.should.eql('foo');
});
it('should throw not implemented for ignored commands', async function () {
const {status, data} = await axios({
url: `${baseUrl}/session/foo/buttonup`,
method: 'POST',
validateStatus: null,
data: {},
});
status.should.equal(405);
data.value.error.should.eql('unknown method');
data.value.message.should.eql('Method has not yet been implemented');
data.sessionId.should.eql('foo');
});
it('should get 400 for bad parameters', async function () {
await axios({
url: `${baseUrl}/session/foo/url`,
method: 'POST',
data: {},
}).should.eventually.be.rejectedWith(/400/);
});
it('should ignore special extra payload params in the right contexts', async function () {
await axios({
url: `${baseUrl}/session/foo/element/bar/value`,
method: 'POST',
data: {id: 'baz', sessionId: 'lol', value: ['a']},
});
await axios({
url: `${baseUrl}/session/foo/element/bar/value`,
method: 'POST',
data: {id: 'baz'},
}).should.eventually.be.rejectedWith(/400/);
// make sure adding the optional 'id' doesn't clobber a route where we
// have an actual required 'id'
await axios({
url: `${baseUrl}/session/foo/frame`,
method: 'POST',
data: {id: 'baz'},
});
});
it('should return the correct error even if driver does not throw', async function () {
const {status, data} = await axios({
url: `${baseUrl}/session/foo/appium/receive_async_response`,
method: 'POST',
data: {response: 'baz'},
validateStatus: null,
});
status.should.equal(500);
data.value.error.should.eql('unknown error');
data.value.message.should.eql(
'An unknown server-side error occurred while processing ' +
'the command. Original error: Mishandled Driver Error'
);
data.sessionId.should.eql('foo');
});
describe('w3c sendkeys migration', function () {
it('should accept value for sendkeys', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/element/bar/value`,
method: 'POST',
data: {value: 'text to type'},
});
data.value.should.eql(['text to type', 'bar']);
});
it('should accept text for sendkeys', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/element/bar/value`,
method: 'POST',
data: {text: 'text to type'},
});
data.value.should.eql(['text to type', 'bar']);
});
it('should accept value and text for sendkeys, and use value', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/element/bar/value`,
method: 'POST',
data: {value: 'text to type', text: 'text to ignore'},
});
data.value.should.eql(['text to type', 'bar']);
});
});
describe('multiple sets of arguments', function () {
describe('optional', function () {
it('should allow moveto with element', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/moveto`,
method: 'POST',
data: {element: '3'},
});
data.value.should.eql(['3', null, null]);
});
it('should allow moveto with xoffset/yoffset', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/moveto`,
method: 'POST',
data: {xoffset: 42, yoffset: 17},
});
data.value.should.eql([null, 42, 17]);
});
});
describe('required', function () {
it('should allow removeApp with appId', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/appium/device/remove_app`,
method: 'POST',
data: {appId: 42},
});
data.value.should.eql(42);
});
it('should allow removeApp with bundleId', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/appium/device/remove_app`,
method: 'POST',
data: {bundleId: 42},
});
data.value.should.eql(42);
});
});
});
describe('default param wrap', function () {
it('should wrap', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/touch/perform`,
method: 'POST',
data: [{action: 'tap', options: {element: '3'}}],
});
data.value.should.deep.equal([[{action: 'tap', options: {element: '3'}}], 'foo']);
});
it('should not wrap twice', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/touch/perform`,
method: 'POST',
data: {actions: [{action: 'tap', options: {element: '3'}}]},
});
data.value.should.deep.equal([[{action: 'tap', options: {element: '3'}}], 'foo']);
});
});
describe('create sessions via HTTP endpoint', function () {
let sessionId;
beforeEach(function () {
sessionId = null;
});
afterEach(async function () {
if (sessionId) {
await axios.delete(`${baseUrl}/session/${sessionId}`);
}
});
it('should not allow create session with desired caps (MJSONWP)', async function () {
const desiredCapabilities = {a: 'b'};
const {data} = await axios({
url: `${baseUrl}/session`,
method: 'POST',
data: {desiredCapabilities},
});
should.equal(data.value, null);
});
it('should fail to create session without capabilities', async function () {
await axios({
url: `${baseUrl}/session`,
method: 'POST',
data: {},
}).should.eventually.be.rejectedWith(/400/);
});
it('should allow create session with capabilities (W3C)', async function () {
const w3cCapabilities = {alwaysMatch: {'appium:e': 'f'}};
const {data} = await axios({
url: `${baseUrl}/session`,
method: 'POST',
data: {capabilities: w3cCapabilities},
});
should.not.exist(data.status);
should.not.exist(data.sessionId);
data.value.capabilities.should.eql(w3cCapabilities);
data.value.sessionId.should.exist;
sessionId = data.value.sessionId;
});
it('should raise an error if the driver does not support W3C yet', async function () {
const createSessionStub = sandbox
.stub(driver, 'createSession')
.callsFake(function (capabilities) {
driver.sessionId = null;
return BaseDriver.prototype.createSession.call(driver, capabilities);
});
try {
// let {status, value, sessionId} = await request({
await axios({
url: `${baseUrl}/session`,
method: 'POST',
data: {
capabilities: {
alwaysMatch: {
platformName: 'Fake',
'appium:deviceName': 'Fake',
},
firstMatch: [{}],
},
},
}).should.eventually.be.rejectedWith(/500/);
} finally {
createSessionStub.restore();
}
});
describe('w3c endpoints', function () {
let sessionUrl;
beforeEach(async function () {
// Start a W3C session
const {value} = (
await axios({
url: `${baseUrl}/session`,
method: 'POST',
data: {
capabilities: {
alwaysMatch: {
platformName: 'Fake',
'appium:deviceName': 'Commodore 64',
},
firstMatch: [{}],
},
},
})
).data;
sessionId = value.sessionId;
sessionUrl = `${baseUrl}/session/${sessionId}`;
});
it(`should throw 400 Bad Parameters exception if the parameters are bad`, async function () {
const {status, data} = await axios({
url: `${sessionUrl}/actions`,
method: 'POST',
validateStatus: null,
data: {
bad: 'params',
},
});
status.should.equal(400);
const {error: w3cError, message, stacktrace} = data.value;
message.should.match(/following required parameter/);
stacktrace.should.match(/protocol.js/);
w3cError.should.be.a.string;
w3cError.should.equal(errors.InvalidArgumentError.error());
});
it(`should throw 405 exception if the command hasn't been implemented yet`, async function () {
const {status, data} = await axios({
url: `${sessionUrl}/actions`,
method: 'POST',
validateStatus: null,
data: {
actions: [],
},
});
status.should.equal(405);
const {error: w3cError, message, stacktrace} = data.value;
message.should.match(/Method has not yet been implemented/);
stacktrace.should.match(/protocol.js/);
w3cError.should.be.a.string;
w3cError.should.equal(errors.NotYetImplementedError.error());
message.should.match(/Method has not yet been implemented/);
});
it(`should throw 500 Unknown Error if the command throws an unexpected exception`, async function () {
driver.performActions = () => {
throw new Error(`Didn't work`);
};
const {status, data} = await axios({
url: `${sessionUrl}/actions`,
method: 'POST',
validateStatus: null,
data: {
actions: [],
},
});
status.should.equal(500);
const {error: w3cError, message, stacktrace} = data.value;
stacktrace.should.match(/protocol.js/);
w3cError.should.be.a.string;
w3cError.should.equal(errors.UnknownError.error());
message.should.match(/Didn't work/);
delete driver.performActions;
});
it(`should translate element format from MJSONWP to W3C`, async function () {
const retValue = [
{
something: {
[MJSONWP_ELEMENT_KEY]: 'fooo',
other: 'bar',
},
},
{
[MJSONWP_ELEMENT_KEY]: 'bar',
},
'ignore',
];
const expectedValue = [
{
something: {
[MJSONWP_ELEMENT_KEY]: 'fooo',
[W3C_ELEMENT_KEY]: 'fooo',
other: 'bar',
},
},
{
[MJSONWP_ELEMENT_KEY]: 'bar',
[W3C_ELEMENT_KEY]: 'bar',
},
'ignore',
];
const findElementsBackup = driver.findElements;
driver.findElements = () => retValue;
const {data} = await axios.post(`${sessionUrl}/elements`, {
using: 'whatever',
value: 'whatever',
});
data.value.should.eql(expectedValue);
driver.findElements = findElementsBackup;
});
it(`should fail with a 408 error if it throws a TimeoutError exception`, async function () {
let setUrlStub = sandbox.stub(driver, 'setUrl').callsFake(function () {
throw new errors.TimeoutError();
});
const {status, data} = await axios({
url: `${sessionUrl}/url`,
method: 'POST',
validateStatus: null,
data: {
url: 'https://example.com/',
},
});
status.should.equal(408);
const {error: w3cError, message, stacktrace} = data.value;
stacktrace.should.match(/protocol.js/);
w3cError.should.be.a.string;
w3cError.should.equal(errors.TimeoutError.error());
message.should.match(/An operation did not complete before its timeout expired/);
setUrlStub.restore();
});
it(`should pass with 200 HTTP status code if the command returns a value`, async function () {
driver.performActions = (actions) => 'It works ' + actions.join('');
const {status, value, sessionId} = (
await axios.post(`${sessionUrl}/actions`, {
actions: ['a', 'b', 'c'],
})
).data;
should.not.exist(sessionId);
should.not.exist(status);
value.should.equal('It works abc');
delete driver.performActions;
});
describe('jwproxy', function () {
let port;
let server, jwproxy, app;
before(async function () {
port = await getTestPort(true);
});
beforeEach(function () {
const res = createProxyServer(sessionId, port);
server = res.server;
app = res.app;
jwproxy = new JWProxy({host: TEST_HOST, port});
jwproxy.sessionId = sessionId;
driver.performActions = async (actions) =>
await jwproxy.command('/perform-actions', 'POST', actions);
});
afterEach(async function () {
delete driver.performActions;
await server.close();
});
it('should work if a proxied request returns a response with status 200', async function () {
app.post('/session/:sessionId/perform-actions', (req, res) => {
res.json({
sessionId: req.params.sessionId,
value: req.body,
status: 0,
});
});
const {status, value, sessionId} = (
await axios.post(`${sessionUrl}/actions`, {
actions: [1, 2, 3],
})
).data;
value.should.eql([1, 2, 3]);
should.not.exist(status);
should.not.exist(sessionId);
});
it('should return error if a proxied request returns a MJSONWP error response', async function () {
app.post('/session/:sessionId/perform-actions', (req, res) => {
res.status(500).json({
sessionId,
status: 6,
value: 'A problem occurred',
});
});
const {status, data} = await axios({
url: `${sessionUrl}/actions`,
method: 'POST',
validateStatus: null,
data: {
actions: [1, 2, 3],
},
});
status.should.equal(HTTPStatusCodes.NOT_FOUND);
JSON.stringify(data).should.match(/A problem occurred/);
});
it('should return W3C error if a proxied request returns a W3C error response', async function () {
const error = new Error(`Some error occurred`);
error.w3cStatus = 414;
const executeCommandStub = sandbox.stub(driver, 'executeCommand').returns({
protocol: 'W3C',
error,
});
const {status, data} = await axios({
url: `${sessionUrl}/actions`,
method: 'POST',
validateStatus: null,
data: {actions: [1, 2, 3]},
});
status.should.equal(414);
const {error: w3cError, message: errMessage, stacktrace} = data.value;
w3cError.should.equal('unknown error');
stacktrace.should.match(/Some error occurred/);
errMessage.should.equal('Some error occurred');
executeCommandStub.restore();
});
it('should return error if a proxied request returns a MJSONWP error response but HTTP status code is 200', async function () {
app.post('/session/:sessionId/perform-actions', (req, res) => {
res.status(200).json({
sessionId: 'Fake Session Id',
status: 7,
value: 'A problem occurred',
});
});
const {status, data} = await axios({
url: `${sessionUrl}/actions`,
method: 'POST',
validateStatus: null,
data: {
actions: [1, 2, 3],
},
});
status.should.equal(HTTPStatusCodes.NOT_FOUND);
const {error: w3cError, message: errMessage, stacktrace} = data.value;
w3cError.should.equal('no such element');
errMessage.should.match(/A problem occurred/);
stacktrace.should.exist;
});
it('should return error if a proxied request returns a W3C error response', async function () {
app.post('/session/:sessionId/perform-actions', (req, res) => {
res.status(404).json({
value: {
error: 'no such element',
message: 'does not make a difference',
stacktrace: 'arbitrary stacktrace',
},
});
});
const {status, data} = await axios({
url: `${sessionUrl}/actions`,
method: 'POST',
validateStatus: null,
data: {
actions: [1, 2, 3],
},
});
status.should.equal(HTTPStatusCodes.NOT_FOUND);
const {error: w3cError, stacktrace} = data.value;
w3cError.should.equal('no such element');
stacktrace.should.match(/arbitrary stacktrace/);
});
it('should return an error if a proxied request returns a W3C error response', async function () {
app.post('/session/:sessionId/perform-actions', (req, res) => {
res.set('Connection', 'close');
res.status(444).json({
value: {
error: 'bogus error code',
message: 'does not make a difference',
stacktrace: 'arbitrary stacktrace',
},
});
});
const {status, data} = await axios({
url: `${sessionUrl}/actions`,
method: 'POST',
validateStatus: null,
data: {
actions: [1, 2, 3],
},
});
status.should.equal(HTTPStatusCodes.INTERNAL_SERVER_ERROR);
const {error: w3cError, stacktrace} = data.value;
w3cError.should.equal('unknown error');
stacktrace.should.match(/arbitrary stacktrace/);
});
});
});
});
it('should handle commands with no response values', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/forward`,
method: 'POST',
});
data.should.eql({
value: null,
sessionId: 'foo',
});
});
it('should allow empty string response values', async function () {
const {data} = await axios({
url: `${baseUrl}/session/foo/element/bar/text`,
});
data.should.eql({
value: '',
sessionId: 'foo',
});
});
it('should send 500 response and an Unknown object for rejected commands', async function () {
const {status, data} = await axios({
url: `${baseUrl}/session/foo/refresh`,
method: 'POST',
validateStatus: null,
});
status.should.equal(500);
data.value.error.should.eql('unknown error');
data.value.message.should.eql(
'An unknown server-side error occurred while processing ' +
'the command. Original error: Too Fresh!'
);
data.sessionId.should.eql('foo');
});
it('should not throw UnknownError when known', async function () {
const {status, data} = await axios({
url: `${baseUrl}/session/foo`,
validateStatus: null,
});
status.should.equal(404);
data.value.error.should.eql('invalid session id');
data.value.message.should.eql('A session is either terminated or not started');
data.sessionId.should.eql('foo');
});
});
describe('session Ids', function () {
let driver = new FakeDriver();
let mjsonwpServer;
before(async function () {
mjsonwpServer = await server({
routeConfiguringFunction: routeConfiguringFunction(driver),
port,
});
});
after(async function () {
await mjsonwpServer.close();
});
afterEach(function () {
driver.sessionId = null;
});
it('should return null SessionId for commands without sessionIds', async function () {
const {data} = await axios({
url: `${baseUrl}/status`,
});
should.equal(data.sessionId, null);
});
it('responds with the same session ID in the request', async function () {
let sessionId = 'Vader Sessions';
driver.sessionId = sessionId;
const {data} = await axios({
url: `${baseUrl}/session/${sessionId}/url`,
method: 'POST',
data: {url: 'http://google.com'},
});
should.exist(data.sessionId);
data.sessionId.should.eql(sessionId);
});
it('yells if no session exists', async function () {
let sessionId = 'Vader Sessions';
const {data, status} = await axios({
url: `${baseUrl}/session/${sessionId}/url`,
method: 'POST',
validateStatus: null,
data: {url: 'http://google.com'},
});
status.should.equal(404);
data.value.message.should.contain('session');
});
it('yells if invalid session is sent', async function () {
let sessionId = 'Vader Sessions';
driver.sessionId = 'recession';
const {data, status} = await axios({
url: `${baseUrl}/session/${sessionId}/url`,
method: 'POST',
validateStatus: null,
data: {url: 'http://google.com'},
});
status.should.equal(404);
data.value.message.should.contain('session');
});
it('should have session IDs in error responses', async function () {
let sessionId = 'Vader Sessions';
driver.sessionId = sessionId;
const {data, status} = await axios({
url: `${baseUrl}/session/${sessionId}/refresh`,
method: 'POST',
validateStatus: null,
});
status.should.equal(500);
data.value.error.should.eql('unknown error');
data.value.message.should.eql(
'An unknown server-side error occurred while processing ' +
'the command. Original error: Too Fresh!'
);
data.sessionId.should.eql('Vader Sessions');
});
it('should return a new session ID on create', async function () {
const {data} = await axios({
url: `${baseUrl}/session`,
method: 'POST',
data: {
capabilities: {
alwaysMatch: {'appium:greeting': 'hello'},
firstMatch: [{}],
},
},
});
should.exist(data.value.sessionId);
data.value.sessionId.indexOf('fakeSession_').should.equal(0);
data.value.capabilities.should.eql({
alwaysMatch: {'appium:greeting': 'hello'},
firstMatch: [{}],
});
});
});
describe('via drivers jsonwp proxy', function () {
let driver;
let sessionId = 'foo';
let mjsonwpServer;
beforeEach(async function () {
driver = new FakeDriver();
driver.sessionId = sessionId;
driver.proxyActive = () => true;
driver.canProxy = () => true;
mjsonwpServer = await server({
routeConfiguringFunction: routeConfiguringFunction(driver),
port,
extraMethodMap: FakeDriver.newMethodMap,
});
});
afterEach(async function () {
await mjsonwpServer.close();
});
it('should give a nice error if proxying is set but no proxy function exists', async function () {
driver.canProxy = () => false;
const {status, data} = await axios({
url: `${baseUrl}/session/${sessionId}/url`,
method: 'POST',
validateStatus: null,
data: {url: 'http://google.com'},
});
status.should.equal(500);
data.value.error.should.eql('unknown error');
data.value.message.should.eql(
'An unknown server-side error occurred while processing ' +
'the command. Original error: Trying to proxy to a ' +
'server but the driver is unable to proxy'
);
data.sessionId.should.eql('foo');
});
it('should pass on any errors in proxying', async function () {
// eslint-disable-next-line require-await
driver.proxyReqRes = async function () {
throw new Error('foo');
};
const {status, data} = await axios({
url: `${baseUrl}/session/${sessionId}/url`,
method: 'POST',
validateStatus: null,
data: {url: 'http://google.com'},
});
status.should.equal(500);
data.value.error.should.eql('unknown error');
data.value.message.should.eql(
'An unknown server-side error occurred while processing ' +
'the command. Original error: Could not proxy. Proxy error: foo'
);
data.sessionId.should.eql('foo');
});
it('should able to throw ProxyRequestError in proxying', async function () {
// eslint-disable-next-line require-await
driver.proxyReqRes = async function () {
let jsonwp = {
status: 35,
value: 'No such context found.',
sessionId: 'foo',
};
throw new errors.ProxyRequestError(`Could not proxy command to remote server. `, jsonwp);
};
const {status, data} = await axios({
url: `${baseUrl}/session/${sessionId}/url`,
method: 'POST',
validateStatus: null,
data: {url: 'http://google.com'},
});
status.should.equal(400);
data.value.error.should.eql('unknown error');
data.value.message.should.eql('No such context found.');
data.sessionId.should.eql('foo');
});
it('should let the proxy handle req/res', async function () {
// eslint-disable-next-line require-await
driver.proxyReqRes = async function (req, res) {
res.status(200).json({custom: 'data'});
};
const {status, data} = await axios({
url: `${baseUrl}/session/${sessionId}/url`,
method: 'POST',
data: {url: 'http://google.com'},
});
status.should.equal(200);
data.should.eql({custom: 'data'});
});
it('should avoid jsonwp proxying when path matches avoidance list', async function () {
driver.getProxyAvoidList = () => [['POST', new RegExp('^/session/[^/]+/url$')]];
const {status, data} = await axios({
url: `${baseUrl}/session/${sessionId}/url`,
method: 'POST',
data: {url: 'http://google.com'},
});
status.should.equal(200);
data.should.eql({
value: 'Navigated to: http://google.com',
sessionId,
});
});
it('should fail if avoid proxy list is malformed in some way', async function () {
async function badProxyAvoidanceList(list) {
driver.getProxyAvoidList = () => list;
const {status, data} = await axios({
url: `${baseUrl}/session/${sessionId}/url`,
method: 'POST',
validateStatus: null,
data: {url: 'http://google.com'},
});
status.should.equal(500);
data.value.message.should.contain('roxy');
}
const lists = ['foo', [['foo']], [['BAR', /lol/]], [['GET', 'foo']]];
for (let list of lists) {
await badProxyAvoidanceList(list);
}
});
it('should avoid proxying non-session commands even if not in the list', async function () {
driver.getProxyAvoidList = () => [['POST', new RegExp('')]];
const {status, data} = await axios({
url: `${baseUrl}/status`,
});
status.should.equal(200);
data.should.eql({
value: "I'm fine",
sessionId: null,
});
});
it('should avoid proxying deleteSession commands', async function () {
driver.getProxyAvoidList = () => [['POST', new RegExp('')]];
driver.sessionId.should.equal(sessionId);
const {status} = await axios.delete(`${baseUrl}/session/${sessionId}`);
status.should.equal(200);
should.not.exist(driver.sessionId);
driver.jwpProxyActive.should.be.false;
});
it('should avoid proxying when command spec specifies neverProxy', async function () {
const {status, data} = await axios({
url: `${baseUrl}/session/${sessionId}/noproxy`,
method: 'GET',
});
status.should.equal(200);
data.should.eql({
value: 'This was not proxied',
sessionId,
});
});
});
});