VulpesOS/gaia/tests/jsmarionette/client/marionette-client/test/marionette/client-test.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

1552 lines
37 KiB
JavaScript
Executable file

/* global DeviceInteraction, MockDriver, assert, exampleCmds, helper, setup */
'use strict';
suite('marionette/client', function() {
var subject, driver, cb, cbResponse,
device, Element, Client, Exception;
helper.require('element', function(obj) {
Element = obj;
});
helper.require('error', function(obj) {
Exception = obj;
});
helper.require('client', function(obj) {
Client = obj;
});
device = new DeviceInteraction(exampleCmds, function() {
return subject;
});
function commandCallback(error, value) {
commandCallback.error = error;
commandCallback.value = value;
}
setup(function() {
commandCallback.value = null;
driver = new MockDriver();
subject = new Client(driver);
cb = function() {
cbResponse = arguments;
};
});
suite('initialization', function() {
test('should save .driver', function() {
assert.strictEqual(subject.driver, driver);
});
suite('without driver', function() {
setup(function() {
subject = new Client(null, { lazy: true });
});
test('should not explode', function() {
assert.notOk(subject.driver);
});
});
});
suite('hooks', function() {
test('should not fail running missing hooks', function(done) {
subject.runHook('fakemissingyey', done);
});
test('should handle errors in hooks', function(done) {
var myErr = new Error('err');
// success
subject.addHook('test', function(complete) {
complete();
});
// failure
subject.addHook('test', function(complete) {
complete(myErr);
});
// after failure should not run
subject.addHook('test', function(complete) {
done(new Error('should not run hooks after error'));
});
subject.runHook('test', function(err) {
assert.strictEqual(err, myErr);
done();
});
});
suite('success', function() {
var called = [];
function logSuccess(name) {
return function(done) {
process.nextTick(function() {
called.push(name);
done();
});
};
}
setup(function() {
called.length = 0;
});
test('should handle adding a hook in a hook', function(done) {
var calledHook = false;
subject.addHook('test', function(hookOne) {
hookOne();
subject.addHook('test', function(hookTwo) {
calledHook = true;
hookTwo();
});
});
subject.runHook('test', function() {
assert.ok(calledHook);
done();
});
});
test('should run in context of client', function(done) {
subject.addHook('test', function(completeHook) {
assert.strictEqual(subject, this);
completeHook();
});
subject.runHook('test', done);
});
test('should run all hooks', function(done) {
subject.addHook('test', logSuccess('one'))
.addHook('test', logSuccess('two'))
.addHook('test', logSuccess('three'));
subject.runHook('test', function() {
assert.deepEqual(called, ['one', 'two', 'three']);
done();
});
});
});
});
suite('.plugin', function() {
test('should allow chaining', function() {
var one = {},
two = {};
function pluginOne() {
return one;
}
function pluginTwo() {
return two;
}
subject.plugin('one', pluginOne).
plugin('two', pluginTwo);
assert.strictEqual(subject.one, one);
assert.strictEqual(subject.two, two);
});
test('should invoke plugin without name', function() {
var calledPlugin;
var options = {};
function plugin(client, opts) {
assert.strictEqual(client, subject);
assert.strictEqual(opts, options);
calledPlugin = true;
}
subject.plugin(null, plugin, options);
assert.ok(calledPlugin);
});
test('should assign result to the given name', function() {
var myObj = {};
function plugin() {
return myObj;
}
subject.plugin('yey', plugin);
assert.strictEqual(subject.yey, myObj);
});
test('should work with .setup', function() {
var myObj = {};
function plugin() {}
plugin.setup = function() {
return myObj;
};
subject.plugin('woot', plugin);
assert.strictEqual(subject.woot, myObj);
});
});
suite('._handleCallback', function() {
var calledWith;
function usesCallback() {
test('should handle number errors', function() {
var calledWith, err;
err = {
status: 500,
message: 'foo',
stacktrace: 'bar'
};
subject._handleCallback(function() {
calledWith = arguments;
}, err, null);
assert.instanceOf(calledWith[0], Exception);
assert.include(calledWith[0].message, 'foo');
assert.include(calledWith[0].stack, 'bar');
});
test('should handle string errors', function() {
var calledWith, err;
err = {
status: 'no such element',
message: 'foo',
stacktrace: 'bar'
};
subject._handleCallback(function() {
calledWith = arguments;
}, err, null);
assert.instanceOf(calledWith[0], Exception);
assert.include(calledWith[0].message, 'foo');
assert.include(calledWith[0].stack, 'bar');
});
test('should use callback when provided', function(done) {
subject._handleCallback(function(err, val) {
assert.instanceOf(err, Exception);
assert.strictEqual(val, 2);
done();
}, {}, 2);
});
test('should call onScriptTimeout on script timeout', function(done) {
subject.onScriptTimeout = function(err) {
assert.strictEqual(err.type, 'ScriptTimeout');
done();
};
var err = {
error: 'script timeout',
message: 'foo',
stacktrace: 'bar'
};
subject._handleCallback(function() {}, err, null);
});
}
suite('with default', function() {
setup(function() {
calledWith = null;
subject.defaultCallback = function() {
calledWith = arguments;
};
});
test('should use default when no callback is provided', function() {
subject._handleCallback(null, 1, 2);
assert.instanceOf(calledWith[0], Exception);
assert.strictEqual(calledWith[1], 2);
});
usesCallback();
});
usesCallback();
});
suite('.searchMethods', function() {
test('should have a list of methods', function() {
assert.instanceOf(subject.searchMethods, Array);
assert.operator(subject.searchMethods.length, '>', 3);
});
});
suite('protocol 1 .send', function() {
suite('when session: is present', function() {
var result;
setup(function() {
subject.sessionId = 'session';
subject.actor = 'actor';
result = subject.send({name: 'newSession'});
});
test('should be chainable', function() {
assert.strictEqual(result, subject);
});
test('should add session to cmd', function() {
assert.deepEqual(driver.sent[0], {
to: subject.actor,
session: subject.sessionId,
name: 'newSession',
});
});
});
suite('when to: is not given', function() {
suite('with an actor', function() {
setup(function() {
subject.actor = 'foo';
subject.send({name: '_getActorId'}, cb);
});
test('should add to:', function() {
assert.deepEqual(driver.sent[0], {
to: 'foo',
name: '_getActorId',
});
});
});
suite('without an actor', function() {
setup(function() {
subject.send({name: '_getActorId'}, cb);
});
test('should add to', function() {
assert.deepEqual(driver.sent[0], {
to: 'root',
name: '_getActorId',
});
});
});
});
});
suite('protocol 2 .send', function() {
var result;
setup(function() {
subject.protocol = 2;
result = subject.send({name: 'get', parameters: {'url': 'about:blank'}});
});
test('should be chainable', function() {
assert.strictEqual(result, subject);
});
test('sends exact packet', function() {
assert.deepEqual(driver.sent[0], {
name: 'get',
parameters: {'url': 'about:blank'},
});
});
});
suite('.scope', function() {
suite('first subscope', function() {
var scope;
var options = {
scriptTimeout: 150,
searchTimeout: 175,
context: 'chrome'
};
setup(function() {
scope = subject.scope(options);
// trigger the new command.
scope.goUrl();
});
Object.keys(options).forEach(function(key) {
var value = options[key];
test('should update .' + key, function() {
assert.strictEqual(scope[key], value);
// has scoping changes
assert.strictEqual(scope._scope[key], value);
});
});
test('should update the ._scope when state changes in scoped',
function() {
scope.setScriptTimeout(250);
assert.strictEqual(scope._scope.scriptTimeout, 250);
});
test('should not update sibling scope', function() {
var sibling = subject.scope(options);
sibling.setScriptTimeout(999);
assert.strictEqual(sibling._scope.scriptTimeout, 999);
assert.notEqual(scope._scope.scriptTimeout, 999);
});
});
});
suite('.startSession protocol version 1', function() {
var result;
var desiredCapabilities = {desiredCapability: true};
setup(function(done) {
var firesHook = false;
subject.addHook('startSession', function(complete) {
firesHook = true;
complete();
});
result = subject.startSession(function() {
assert.ok(firesHook);
done();
}, desiredCapabilities);
device.shouldSend({parameters: {capabilities: desiredCapabilities}});
driver.respond(exampleCmds.getMarionetteIDResponse());
driver.respond(exampleCmds.newSessionResponseProto1());
});
test('should be chainable', function() {
assert.strictEqual(result, subject);
});
test('should have an actor property', function() {
assert.property(subject, 'actor');
assert.isNotNull(subject.actor);
});
test('should have a sessionId property', function() {
assert.property(subject, 'sessionId');
assert.isNotNull(subject.sessionId);
});
test('should have protocol version 1', function() {
assert.property(subject, 'protocol');
assert.strictEqual(subject.protocol, 1);
});
});
suite('.startSession protocol version 2', function() {
var result;
var response = exampleCmds.newSessionResponseProto2();
var desiredCapabilities = {desiredCapability: true};
setup(function(done) {
subject.protocol = 2;
var hookFired = false;
subject.addHook('startSession', function(done) {
hookFired = true;
done();
});
result = subject.startSession(function() {
cbResponse = arguments;
assert.ok(hookFired);
done();
}, desiredCapabilities);
device.
withProtocol(2).
shouldSend({
parameters: {capabilities: desiredCapabilities}
});
driver.respond(response);
});
test('should be chainable', function() {
assert.strictEqual(result, subject);
});
test('should have an empty actor property', function() {
assert.isNull(subject.actor);
});
test('should have sessionId property', function() {
assert.property(subject, 'sessionId');
assert.strictEqual(subject.sessionId, response.sessionId);
});
test('should have a capabilities property', function() {
assert.property(subject, 'capabilities');
assert.strictEqual(subject.capabilities, response.capabilities);
});
test('should send newSession', function() {
assert.strictEqual(driver.sent[0].name, 'newSession');
});
test('should send callback response', function() {
assert.deepEqual(cbResponse[1], response);
});
test('should have protocol version 2', function() {
assert.property(subject, 'protocol');
assert.strictEqual(subject.protocol, 2);
});
});
suite('._getActorId', function() {
device
.issues('_getActorId')
.shouldSend({name: 'getMarionetteID'})
.serverResponds('getMarionetteIDResponse')
.callbackReceives('id');
test('should save actor ID', function() {
var resp = exampleCmds.getMarionetteIDResponse();
assert.strictEqual(subject.actor, resp.id);
});
});
suite('._sendCommand', function() {
var cmd, response,
calledUnmarshal, result,
calledWith;
suite('on success', function() {
setup(function(done) {
cmd = exampleCmds.getUrl();
response = exampleCmds.getUrlResponse();
calledUnmarshal = false;
subject._unmarshalWebElement = function(value) {
calledUnmarshal = true;
assert.strictEqual(value, response);
return 'foo';
};
result = subject._sendCommand(cmd, function() {
calledWith = arguments;
done();
});
driver.respond(response);
});
test('should send given command and format the result', function() {
assert.strictEqual(result, subject);
});
test('should send command through _unmarshalWebElement', function() {
assert.strictEqual(calledUnmarshal, true);
assert.strictEqual(calledWith[1], 'foo');
});
});
suite('on number error from protocol 1', function() {
setup(function(done) {
calledWith = null;
cmd = exampleCmds.getUrl();
response = exampleCmds.numberError();
subject._sendCommand(cmd, function(err, data) {
calledWith = arguments;
done();
}, 'value');
driver.respond(response);
});
test('should pass error to callback', function() {
assert.ok(calledWith[0]);
assert.notOk(calledWith[1]);
});
});
suite('on string error from protocol 1', function() {
setup(function(done) {
calledWith = null;
cmd = exampleCmds.getUrl();
response = exampleCmds.stringError();
subject._sendCommand(cmd, function(err, data) {
calledWith = arguments;
done();
}, 'value');
driver.respond(response);
});
test('should pass error to callback', function() {
assert.ok(calledWith[0]);
assert.notOk(calledWith[1]);
});
});
suite('on modern error from protocol 2', function() {
setup(function(done) {
calledWith = null;
cmd = exampleCmds.getUrl();
response = exampleCmds.modernError();
subject._sendCommand(cmd, function(err, data) {
calledWith = arguments;
done();
}, 'value');
driver.respond(response);
});
test('should pass error to callback', function() {
assert.ok(calledWith[0]);
assert.notOk(calledWith[1]);
});
});
});
suite('.deleteSession', function() {
var result;
var callsClose;
setup(function(done) {
callsClose = false;
var callsHook = false;
subject.actor = '1';
subject.sessionId = 'session id';
subject.capabilities = {capability: true};
subject.driver.close = function() {
assert.strictEqual(callsHook, true);
callsClose = true;
};
subject.addHook('deleteSession', function(complete) {
callsHook = true;
complete();
process.nextTick(function() {
driver.respond(exampleCmds.ok());
});
});
result = subject.deleteSession(done);
});
test('should set actorId to null', function() {
assert.isNull(subject.actor);
});
test('should set sessionId to null', function() {
assert.isNull(subject.sessionId);
});
test('should set capabilities to null', function() {
assert.isNull(subject.capabilities);
});
test('should be chainable', function() {
assert.strictEqual(result, subject);
});
test('should close the connection', function() {
assert.strictEqual(callsClose, true);
});
});
suite('.setSearchTimeout', function() {
test('should have default .searchTimeout', function() {
assert.ok(subject.searchTimeout);
});
suite('after setting with protocol 1', function() {
device.
issues('setSearchTimeout', 50).
shouldSend({
name: 'setSearchTimeout',
parameters: {
ms: 50
}
}).
serverResponds('ok').
callbackReceives();
test('should set timeout', function() {
assert.strictEqual(subject.searchTimeout, 50);
});
});
suite('after setting with protocol 2', function() {
device.
withProtocol(2).
issues('setSearchTimeout', 50).
shouldSend({
name: 'setSearchTimeout',
parameters: {
ms: 50
}
}).
serverResponds('ok').
callbackReceives();
test('should set timeout', function() {
assert.strictEqual(subject.searchTimeout, 50);
});
});
});
suite('.sessionCapabilities with protocol 1', function() {
device.
withProtocol(1).
issues('sessionCapabilities').
shouldSend({
name: 'getSessionCapabilities'
}).
serverResponds('value').
callbackReceives('value');
});
suite('.sessionCapabilities with protocol 2', function() {
device.
withProtocol(2).
issues('sessionCapabilities').
shouldSend({
name: 'getSessionCapabilities'
}).
serverResponds('capabilities').
callbackReceives('capabilities');
});
suite('.getWindow', function() {
device.
issues('getWindow').
shouldSend({
name: 'getWindow'
}).
serverResponds('getWindowResponse').
callbackReceives('value');
});
suite('.setContext with protocol 1', function() {
test('should have a default context', function() {
assert.strictEqual(subject.context, 'content');
});
suite('after setting context', function() {
device.
issues('setContext', 'chrome').
shouldSend({
name: 'setContext',
parameters: {
value: 'chrome'
}
}).
serverResponds('ok').
callbackReceives();
test('should remember context', function() {
assert.strictEqual(subject.context, 'chrome');
});
});
});
suite('.setContext with protocol 2', function() {
test('should have a default context', function() {
assert.strictEqual(subject.context, 'content');
});
suite('after setting context', function() {
device.
withProtocol(2).
issues('setContext', 'chrome').
shouldSend({
name: 'setContext',
parameters: {
value: 'chrome'
}
}).
serverResponds('ok').
callbackReceives();
test('should remember context', function() {
assert.strictEqual(subject.context, 'chrome');
});
});
});
suite('.getWindows with protocol 1', function() {
device.
withProtocol(1).
issues('getWindows').
shouldSend({
name: 'getWindows'
}).
serverResponds('getWindowsResponseProto1').
callbackReceives('value');
});
suite('.getWindows with protocol 2', function() {
device.
withProtocol(2).
issues('getWindows').
shouldSend({
name: 'getWindows'
}).
serverResponds('getWindowsResponseProto2').
callbackReceives();
});
suite('.switchToWindow with protocol 1', function() {
device.
issues('switchToWindow', '1-b2g').
shouldSend({
name: 'switchToWindow',
parameters: {
value: '1-b2g'
}
}).
serverResponds('ok').
callbackReceives();
});
suite('.switchToWindow with protocol 2', function() {
device.
withProtocol(2).
issues('switchToWindow', '1-b2g').
shouldSend({
name: 'switchToWindow',
parameters: {
value: '1-b2g'
}
}).
serverResponds('ok').
callbackReceives();
});
suite('.getWindowType', function() {
device.
issues('getWindowType').
shouldSend({
name: 'getWindowType'
}).
serverResponds('value').
callbackReceives('value');
});
suite('.switchToFrame', function() {
suite('when given nothing', function() {
device.
issues('switchToFrame').
shouldSend({ name: 'switchToFrame' }).
serverResponds('ok').
callbackReceives();
});
suite('when given a callback', function() {
setup(function() {
subject.switchToFrame(commandCallback);
});
device.
shouldSend({
name: 'switchToFrame'
}).
serverResponds('ok').
callbackReceives();
});
suite('when given an element', function() {
var el;
setup(function() {
el = new Element('77', subject);
subject.switchToFrame(el, commandCallback);
});
device.
shouldSend({
name: 'switchToFrame',
parameters: {
element: '77'
}
}).
serverResponds('ok').
callbackReceives();
});
suite('when given an object with ELEMENT', function() {
var el;
setup(function() {
el = { ELEMENT: 'foo' };
subject.switchToFrame(el, commandCallback);
});
device.
shouldSend({
name: 'switchToFrame',
parameters: {
element: 'foo'
}
}).
serverResponds('ok').
callbackReceives();
});
suite('when switch to a frame with options', function() {
var el, options;
setup(function() {
el = { ELEMENT: 'foo' };
options = { focus: true };
subject.switchToFrame(el, options, commandCallback);
});
device.
shouldSend({
name: 'switchToFrame',
parameters: {
element: 'foo',
focus: true
}
}).
serverResponds('ok').
callbackReceives();
});
suite('when switch to a frame with multiple options', function() {
var el, options;
setup(function() {
el = {ELEMENT: 'foo'};
options = {
focus: true,
testOption: 'hi'
};
subject.switchToFrame(el, options, commandCallback);
});
device.
shouldSend({
name: 'switchToFrame',
parameters: {
element: 'foo',
focus: true,
testOption: 'hi'
}
}).
serverResponds('ok').
callbackReceives();
});
});
suite('.switchToShadowRoot', function() {
suite('when given nothing', function() {
device.
issues('switchToShadowRoot').
shouldSend({ name: 'switchToShadowRoot' }).
serverResponds('ok').
callbackReceives();
});
suite('when given a callback', function() {
setup(function() {
subject.switchToShadowRoot(commandCallback);
});
device.
shouldSend({
name: 'switchToShadowRoot'
}).
serverResponds('ok').
callbackReceives();
});
suite('when given an element', function() {
var el;
setup(function() {
el = new Element('78', subject);
subject.switchToShadowRoot(el, commandCallback);
});
device.
shouldSend({
name: 'switchToShadowRoot',
parameters: {
id: '78'
}
}).
serverResponds('ok').
callbackReceives();
});
});
suite('.importScript', function() {
device.
issues('importScript', 'foo').
shouldSend({
name: 'importScript',
parameters: {
script: 'foo'
}
}).
serverResponds('ok').
callbackReceives();
});
suite('.setScriptTimeout', function() {
test('should have a default timeout', function() {
assert.ok(subject.scriptTimeout);
});
suite('after setting timeout', function() {
device.
issues('setScriptTimeout', 100).
shouldSend({
name: 'setScriptTimeout',
parameters: {
ms: 100
}
}).
serverResponds('ok').
callbackReceives();
test('should update .scriptTimeout', function() {
assert.strictEqual(subject.scriptTimeout, 100);
});
test('driver should have gotten it', function() {
// this only work with the MockDevice.
assert.strictEqual(subject.driver.timeout, 100);
});
});
});
suite('.title', function() {
device.
issues('title').
shouldSend({
name: 'getTitle'
}).
serverResponds('value').
callbackReceives('value');
});
suite('.goUrl', function() {
device.
issues('goUrl', 'http://wow').
shouldSend({
name: 'goUrl',
parameters: {
url: 'http://wow'
}
}).
serverResponds('ok').
callbackReceives();
});
suite('.getUrl', function() {
device.
issues('getUrl').
shouldSend({
name: 'getUrl'
}).
serverResponds('getUrlResponse').
callbackReceives('value');
});
suite('.goForward', function() {
device.
issues('goForward').
shouldSend({
name: 'goForward'
}).
serverResponds('ok').
callbackReceives();
});
suite('.goBack', function() {
device.
issues('goBack').
shouldSend({
name: 'goBack'
}).
serverResponds('ok').
callbackReceives();
});
suite('script executing commands', function() {
var calledWith,
script = 'return null;';
setup(function() {
calledWith = null;
subject._executeScript = function() {
calledWith = arguments;
};
});
suite('.executeScript', function() {
test('should call _executeScript', function() {
subject.executeScript(script, commandCallback);
assert.deepEqual(calledWith, [
{
name: 'executeScript',
parameters: {
script: script,
args: null,
sandbox: 'default',
}
},
commandCallback
]);
});
test('should call _executeScript with arguments', function() {
subject.executeScript(script, ['foo'], commandCallback);
assert.deepEqual(calledWith, [
{
name: 'executeScript',
parameters: {
script: script,
args: ['foo'],
sandbox: 'default',
}
},
commandCallback
]);
});
test('should call _executeScript with custom sandbox', function() {
subject.executeScript(script, null, commandCallback, 'foo');
assert.deepEqual(calledWith, [
{
name: 'executeScript',
parameters: {
script: script,
args: null,
sandbox: 'foo',
}
},
commandCallback
]);
});
});
suite('.executeJsScript', function() {
setup(function() {
subject.executeJsScript(script, commandCallback);
});
test('should call _executeScript', function() {
assert.deepEqual(calledWith, [{
name: 'executeJSScript',
parameters: {
script: script,
timeout: true,
args: null,
sandbox: 'simpletest',
}
}, commandCallback]);
});
});
suite('.executeAsyncScript', function() {
test('should call _executeScript', function() {
subject.executeAsyncScript(script, commandCallback);
assert.deepEqual(calledWith, [
{
name: 'executeAsyncScript',
parameters: {
script: script,
args: null,
sandbox: 'default',
}
},
commandCallback
]);
});
test('should call _executeScript with arguments', function() {
subject.executeAsyncScript(script, ['foo'], commandCallback);
assert.deepEqual(calledWith, [
{
name: 'executeAsyncScript',
parameters: {
script: script,
args: ['foo'],
sandbox: 'default',
}
},
commandCallback
]);
});
test('should call _executeScript with custom sandbox', function() {
subject.executeAsyncScript(script, null, commandCallback, 'foo');
assert.deepEqual(calledWith, [
{
name: 'executeAsyncScript',
parameters: {
script: script,
args: null,
sandbox: 'foo',
}
},
commandCallback
]);
});
});
});
suite('.refresh', function() {
device.
issues('refresh').
serverResponds('ok').
shouldSend({ name: 'refresh' }).
callbackReceives();
});
suite('.log', function() {
device.
issues('log', 'wow', 'info').
shouldSend({ name: 'log', parameters: {value: 'wow', level: 'info' }}).
serverResponds('ok').
callbackReceives();
});
suite('.getLogs with protocol 1', function() {
device.
issues('getLogs').
shouldSend({name: 'getLogs'}).
serverResponds('getLogsResponseProto1').
callbackReceives('value');
});
suite('.getLogs with protocol 2', function() {
device.
withProtocol(2).
issues('getLogs').
shouldSend({name: 'getLogs'}).
serverResponds('getLogsResponseProto2').
callbackReceives();
});
suite('.pageSource', function() {
device.
issues('pageSource').
shouldSend({ name: 'getPageSource' }).
serverResponds('value').
callbackReceives('value');
});
suite('.screenshot', function() {
suite('without options', function() {
device.
issues('screenshot').
shouldSend({ name: 'screenShot' }).
serverResponds('screenshotResponse').
callbackReceives('value');
});
suite('with options', function() {
device.
issues('screenshot', {
name: 'untrusted',
element: { id: 33 },
highlights: [ { id: 23 }, { id: 99 } ],
}).
shouldSend({
name: 'screenShot',
parameters: {
id: 33,
highlights: [ 23, 99 ]
},
}).
serverResponds('screenshotResponse').
callbackReceives('value');
});
});
suite('._findElement', function() {
function receivesElement() {
var els;
suite('callback argument', function() {
setup(function() {
var value = device.commandCallback.value;
if (!(value instanceof Element) && !(value instanceof Array))
throw new Error(
'Result is not an array or an Element instance: ' + value);
if (value instanceof Array)
els = value;
else
els = [value];
});
test('should be an instance of Marionette.Element', function() {
els.forEach(function(el) {
assert.instanceOf(el, Element);
assert.strictEqual(el.client, subject);
assert.include(el.id, '{');
});
});
});
}
suite('with overriden Element', function() {
var MyElement;
setup(function() {
MyElement = function() {
Element.apply(this, arguments);
};
MyElement.prototype = { __proto__: Element.prototype };
subject.Element = MyElement;
});
device.
issues('_findElement', 'findElement', '#wow').
shouldSend({
name: 'findElement',
parameters: {
value: '#wow',
using: 'css selector'
}
}).
serverResponds('findElementResponse');
test('should return an instance of MyElement', function() {
var el = device.commandCallback.value;
assert.instanceOf(el, MyElement);
});
});
suite('simple find with defaults', function() {
device.
issues('_findElement', 'findElement', '#wow').
shouldSend({
name: 'findElement',
parameters: {
value: '#wow',
using: 'css selector'
}
}).
serverResponds('findElementResponse');
receivesElement();
});
suite('find with all options', function() {
device.
issues('_findElement', 'findElements', 'wow', 'class name', 1).
shouldSend({
name: 'findElements',
parameters: {
value: 'wow',
using: 'class name',
element: 1
}
}).
serverResponds('findElementResponse');
receivesElement();
});
suite('trying to find with invalid \'using\'', function() {
test('should fail', function() {
assert.throws(function() {
subject._findElement(
'findElement', 'wow', 'fake', function() {}
);
}, /invalid option for using/);
});
});
});
suite('element finders', function() {
var calledWith;
function delegatesToFind(type) {
suite('.' + type, function() {
setup(function() {
subject[type]('#query', commandCallback);
});
test('should call _findElement', function() {
assert.deepEqual(calledWith, [
type, '#query', commandCallback
]);
});
});
}
setup(function() {
subject._findElement = function() {
calledWith = arguments;
};
});
delegatesToFind('findElement');
delegatesToFind('findElements');
});
suite('._executeScript', function() {
var cmd = 'return window.location',
args = [{1: true}],
sandbox = 'default',
type = 'executeScript';
suite('with args', function() {
var request = {
name: type,
parameters: {
script: cmd,
args: args,
sandbox: sandbox
}
};
device.
issues('_executeScript', request).
shouldSend(request).
serverResponds('getUrlResponse').
callbackReceives('value');
});
suite('without args', function() {
var request = {
name: type,
parameters: {
script: cmd,
sandbox: sandbox
}
};
device.
issues('_executeScript', request).
shouldSend({
name: type,
parameters: {
script: cmd,
args: [],
sandbox: sandbox
}
}).
serverResponds('getUrlResponse').
callbackReceives('value');
});
});
suite('._newSession', function() {
var desiredCapabilities = {desiredCapability: true};
var response = exampleCmds.newSessionResponseProto1();
setup(function(done) {
subject._newSession(function() {
cbResponse = arguments;
done();
}, desiredCapabilities);
device.shouldSend({parameters: {capabilities: desiredCapabilities}});
driver.respond(response);
});
test('should send newSession', function() {
assert.strictEqual(driver.sent[0].name, 'newSession');
});
test('should save session ID', function() {
assert.strictEqual(subject.sessionId, response.value);
});
test('should send callback response', function() {
assert.deepEqual(cbResponse[1], response);
});
});
suite('._convertFunction', function() {
var result;
var fn = function() { return true; };
setup(function() {
result = subject._convertFunction(fn);
result = result.replace(/\n|\s/g, '');
});
test('should format function to call immediately', function() {
var expected;
expected = 'return (function() { return true;}.apply(this, arguments));';
expected = expected.replace(/\n|\s/g, '');
assert.strictEqual(result, expected);
});
test('should not format strings', function() {
assert.strictEqual(subject._convertFunction('foo'), 'foo');
});
});
suite('._unmarshalWebElement', function() {
var result;
suite('when it is an element', function() {
setup(function() {
result = subject._unmarshalWebElement({'ELEMENT': 'foo'});
});
test('should return an instance of element', function() {
assert.instanceOf(result, Element);
assert.strictEqual(result.id, 'foo');
});
});
suite('when it is not an element', function() {
var obj = {'foo': true};
setup(function() {
result = subject._unmarshalWebElement(obj);
});
test('should return same object', function() {
assert.strictEqual(result, obj);
});
});
});
suite('._prepareArguments', function() {
var args, result;
setup(function() {
args = [
new Element('{uuid}', subject),
'wow',
true
];
result = subject._prepareArguments(args);
});
test('should process Marionette.Element instances into uuids', function() {
assert.deepEqual(result, [
{'ELEMENT': '{uuid}'},
'wow',
true
]);
});
});
});