Bug 1336214 - Preserve stacktraces in Marionette errors; r=maja_zf

Since bug 1326534 we have discarded the original stacktrace from errors
originating inside Marionette.  This was due to faulty logic when
attempting to generate a new stacktrace when it was missing from a
propagated error.

This change simplifies WebDriver errors by making use of Error
inheritance.  The WebDriver error specific functions error.toJson and
error.fromJson has additionally been moved to WebDriverError.

MozReview-Commit-ID: C3Ns0H01LyG

--HG--
extra : rebase_source : 0c705054dae8c0647500bb90e9b970cc57e712c4
This commit is contained in:
Andreas Tolfsen 2017-02-10 18:36:52 +00:00
Родитель d9976f6943
Коммит 69d406c698
7 изменённых файлов: 288 добавлений и 281 удалений

Просмотреть файл

@ -32,12 +32,12 @@ this.assert = {};
* @return {string}
* Session ID.
*
* @throws {InvalidSessionIdError}
* @throws {InvalidSessionIDError}
* If |driver| does not have a session ID.
*/
assert.session = function (driver, msg = "") {
assert.that(sessionID => sessionID,
msg, InvalidSessionIdError)(driver.sessionId);
msg, InvalidSessionIDError)(driver.sessionId);
return driver.sessionId;
};

Просмотреть файл

@ -13,7 +13,7 @@ const ERRORS = new Set([
"InvalidArgumentError",
"InvalidElementStateError",
"InvalidSelectorError",
"InvalidSessionIdError",
"InvalidSessionIDError",
"JavaScriptError",
"NoAlertOpenError",
"NoSuchElementError",
@ -81,14 +81,15 @@ error.isWebDriverError = function (obj) {
};
/**
* Wraps an Error as a WebDriverError type. If the given error is already
* in the WebDriverError prototype chain, this function acts as a no-op.
* Wraps any error as a WebDriverError. If the given error is already in
* the WebDriverError prototype chain, this function returns it
* unmodified.
*/
error.wrap = function (err) {
if (error.isWebDriverError(err)) {
return err;
}
return new WebDriverError(`${err.name}: ${err.message}`, err.stacktrace);
return new WebDriverError(err);
};
/**
@ -96,7 +97,7 @@ error.wrap = function (err) {
* and reports error to the Browser Console.
*/
error.report = function (err) {
let msg = `Marionette threw an error: ${error.stringify(err)}`;
let msg = "Marionette threw an error: " + error.stringify(err);
dump(msg + "\n");
if (Cu.reportError) {
Cu.reportError(msg);
@ -144,260 +145,245 @@ error.pprint = function (strings, ...values) {
return res.join("");
};
/**
* Marshal a WebDriverError prototype to a JSON dictionary.
*
* @param {WebDriverError} err
* Error to serialise.
*
* @return {Object.<string, Object>}
* JSON dictionary with the keys "error", "message", and "stacktrace".
* @throws {TypeError}
* If error type is not serialisable.
*/
error.toJson = function (err) {
if (!error.isWebDriverError(err)) {
throw new TypeError(`Unserialisable error type: ${err}`);
}
let json = {
error: err.status,
message: err.message || "",
stacktrace: err.stack || "",
};
return json;
};
/**
* Unmarshal a JSON dictionary to a WebDriverError prototype.
*
* @param {Object.<string, string>} json
* JSON dictionary with the keys "error", "message", and "stacktrace".
*
* @return {WebDriverError}
* Deserialised error prototype.
*/
error.fromJson = function (json) {
if (!statusLookup.has(json.error)) {
throw new TypeError(`Undeserialisable error type: ${json.error}`);
}
let errCls = statusLookup.get(json.error);
let err = new errCls(json.message);
if ("stacktrace" in json) {
err.stack = json.stacktrace;
}
return err;
};
/**
* WebDriverError is the prototypal parent of all WebDriver errors.
* It should not be used directly, as it does not correspond to a real
* error in the specification.
*
* @param {(string|Error)=} err
* Optional string describing error situation or Error instance
* to propagate.
*/
this.WebDriverError = function (err) {
const proto = Error.call(this, err);
this.name = "WebDriverError";
this.status = "webdriver error";
class WebDriverError extends Error {
/**
* @param {(string|Error)=} x
* Optional string describing error situation or Error instance
* to propagate.
*/
constructor (x) {
super(x);
this.name = this.constructor.name;
this.status = "webdriver error";
if (error.isError(err)) {
this.message = err.message;
this.stack = err.stack;
} else {
this.message = err;
this.stack = proto.stack;
// Error's ctor does not preserve x' stack
if (error.isError(x)) {
this.stack = x.stack;
}
}
};
WebDriverError.prototype = Object.create(Error.prototype);
this.ElementNotAccessibleError = function (msg) {
WebDriverError.call(this, msg);
this.name = "ElementNotAccessibleError";
this.status = "element not accessible";
};
ElementNotAccessibleError.prototype = Object.create(WebDriverError.prototype);
toJSON () {
return {
error: this.status,
message: this.message || "",
stacktrace: this.stack || "",
}
}
this.ElementNotVisibleError = function (msg) {
WebDriverError.call(this, msg);
this.name = "ElementNotVisibleError";
this.status = "element not visible";
};
ElementNotVisibleError.prototype = Object.create(WebDriverError.prototype);
static fromJSON (json) {
if (typeof json.error == "undefined") {
let s = JSON.stringify(json);
throw new TypeError("Undeserialisable error type: " + s);
}
if (!STATUSES.has(json.error)) {
throw new TypeError("Not of WebDriverError descent: " + json.error);
}
this.InsecureCertificateError = function (msg) {
WebDriverError.call(this, msg);
this.name = "InsecureCertificateError";
this.status = "insecure certificate";
};
InsecureCertificateError.prototype = Object.create(WebDriverError.prototype);
let cls = STATUSES.get(json.error);
let err = new cls();
if ("message" in json) {
err.message = json.message;
}
if ("stacktrace" in json) {
err.stack = json.stacktrace;
}
return err;
}
}
this.InvalidArgumentError = function (msg) {
WebDriverError.call(this, msg);
this.name = "InvalidArgumentError";
this.status = "invalid argument";
};
InvalidArgumentError.prototype = Object.create(WebDriverError.prototype);
class ElementNotAccessibleError extends WebDriverError {
constructor (message) {
super(message);
this.status = "element not accessible";
}
}
this.InvalidElementStateError = function (msg) {
WebDriverError.call(this, msg);
this.name = "InvalidElementStateError";
this.status = "invalid element state";
};
InvalidElementStateError.prototype = Object.create(WebDriverError.prototype);
class ElementNotVisibleError extends WebDriverError {
constructor (message) {
super(message);
this.status = "element not visible";
}
}
this.InvalidSelectorError = function (msg) {
WebDriverError.call(this, msg);
this.name = "InvalidSelectorError";
this.status = "invalid selector";
};
InvalidSelectorError.prototype = Object.create(WebDriverError.prototype);
class InsecureCertificateError extends WebDriverError {
constructor (message) {
super(message);
this.status = "insecure certificate";
}
}
this.InvalidSessionIdError = function (msg) {
WebDriverError.call(this, msg);
this.name = "InvalidSessionIdError";
this.status = "invalid session id";
};
InvalidSessionIdError.prototype = Object.create(WebDriverError.prototype);
class InvalidArgumentError extends WebDriverError {
constructor (message) {
super(message);
this.status = "invalid argument";
}
}
class InvalidElementStateError extends WebDriverError {
constructor (message) {
super(message);
this.status = "invalid element state";
}
}
class InvalidSelectorError extends WebDriverError {
constructor (message) {
super(message);
this.status = "invalid selector";
}
}
class InvalidSessionIDError extends WebDriverError {
constructor (message) {
super(message);
this.status = "invalid session id";
}
}
/**
* Creates an error message for a JavaScript error thrown during
* executeScript or executeAsyncScript.
*
* @param {Error} err
* An Error object passed to a catch block or a message.
* @param {string=} fnName
* The name of the function to use in the stack trace message
* (e.g. execute_script).
* @param {string=} file
* The filename of the test file containing the Marionette
* command that caused this error to occur.
* @param {number=} line
* The line number of the above test file.
* @param {string=} script
* The JS script being executed in text form.
* Creates a richly annotated error for an error situation that occurred
* whilst evaluating injected scripts.
*/
this.JavaScriptError = function (
err, fnName = null, file = null, line = null, script = null) {
let msg = String(err);
let trace = "";
class JavaScriptError extends WebDriverError {
/**
* @param {(string|Error)} x
* An Error object instance or a string describing the error
* situation.
* @param {string=} fnName
* Name of the function to use in the stack trace message.
* @param {string=} file
* Filename of the test file on the client.
* @param {number=} line
* Line number of |file|.
* @param {string=} script
* Script being executed, in text form.
*/
constructor (
x,
fnName = undefined,
file = undefined,
line = undefined,
script = undefined) {
let msg = String(x);
let trace = "";
if (fnName) {
trace += fnName;
if (file) {
trace += ` @${file}`;
if (line) {
trace += `, line ${line}`;
if (fnName) {
trace += fnName;
if (file) {
trace += ` @${file}`;
if (line) {
trace += `, line ${line}`;
}
}
}
}
if (typeof err == "object" && "name" in err && "stack" in err) {
let jsStack = err.stack.split("\n");
let match = jsStack[0].match(/:(\d+):\d+$/);
let jsLine = match ? parseInt(match[1]) : 0;
if (script) {
let src = script.split("\n")[jsLine];
trace += "\n" +
"inline javascript, line " + jsLine + "\n" +
"src: \"" + src + "\"";
if (error.isError(x)) {
let jsStack = x.stack.split("\n");
let match = jsStack[0].match(/:(\d+):\d+$/);
let jsLine = match ? parseInt(match[1]) : 0;
if (script) {
let src = script.split("\n")[jsLine];
trace += "\n" +
`inline javascript, line ${jsLine}\n` +
`src: "${src}"`;
}
trace += "\nStack:\n" + x.stack;
}
trace += "\nStack:\n" + String(err.stack);
super(msg);
this.status = "javascript error";
this.stack = trace;
}
}
WebDriverError.call(this, msg);
this.name = "JavaScriptError";
this.status = "javascript error";
this.stack = trace;
};
JavaScriptError.prototype = Object.create(WebDriverError.prototype);
class NoAlertOpenError extends WebDriverError {
constructor (message) {
super(message);
this.status = "no such alert";
}
}
this.NoAlertOpenError = function (msg) {
WebDriverError.call(this, msg);
this.name = "NoAlertOpenError";
this.status = "no such alert";
};
NoAlertOpenError.prototype = Object.create(WebDriverError.prototype);
class NoSuchElementError extends WebDriverError {
constructor (message) {
super(message);
this.status = "no such element";
}
}
this.NoSuchElementError = function (msg) {
WebDriverError.call(this, msg);
this.name = "NoSuchElementError";
this.status = "no such element";
};
NoSuchElementError.prototype = Object.create(WebDriverError.prototype);
class NoSuchFrameError extends WebDriverError {
constructor (message) {
super(message);
this.status = "no such frame";
}
}
this.NoSuchFrameError = function (msg) {
WebDriverError.call(this, msg);
this.name = "NoSuchFrameError";
this.status = "no such frame";
};
NoSuchFrameError.prototype = Object.create(WebDriverError.prototype);
class NoSuchWindowError extends WebDriverError {
constructor (message) {
super(message);
this.status = "no such window";
}
}
this.NoSuchWindowError = function (msg) {
WebDriverError.call(this, msg);
this.name = "NoSuchWindowError";
this.status = "no such window";
};
NoSuchWindowError.prototype = Object.create(WebDriverError.prototype);
class ScriptTimeoutError extends WebDriverError {
constructor (message) {
super(message);
this.status = "script timeout";
}
}
this.ScriptTimeoutError = function (msg) {
WebDriverError.call(this, msg);
this.name = "ScriptTimeoutError";
this.status = "script timeout";
};
ScriptTimeoutError.prototype = Object.create(WebDriverError.prototype);
class SessionNotCreatedError extends WebDriverError {
constructor (message) {
super(message);
this.status = "session not created";
}
}
this.SessionNotCreatedError = function (msg) {
WebDriverError.call(this, msg);
this.name = "SessionNotCreatedError";
this.status = "session not created";
};
SessionNotCreatedError.prototype = Object.create(WebDriverError.prototype);
class StaleElementReferenceError extends WebDriverError {
constructor (message) {
super(message);
this.status = "stale element reference";
}
}
this.StaleElementReferenceError = function (msg) {
WebDriverError.call(this, msg);
this.name = "StaleElementReferenceError";
this.status = "stale element reference";
};
StaleElementReferenceError.prototype = Object.create(WebDriverError.prototype);
class TimeoutError extends WebDriverError {
constructor (message) {
super(message);
this.status = "timeout";
}
}
this.TimeoutError = function (msg) {
WebDriverError.call(this, msg);
this.name = "TimeoutError";
this.status = "timeout";
};
TimeoutError.prototype = Object.create(WebDriverError.prototype);
class UnableToSetCookieError extends WebDriverError {
constructor (message) {
super(message);
this.status = "unable to set cookie";
}
}
this.UnableToSetCookieError = function (msg) {
WebDriverError.call(this, msg);
this.name = "UnableToSetCookieError";
this.status = "unable to set cookie";
};
UnableToSetCookieError.prototype = Object.create(WebDriverError.prototype);
class UnknownCommandError extends WebDriverError {
constructor (message) {
super(message);
this.status = "unknown command";
}
}
this.UnknownCommandError = function (msg) {
WebDriverError.call(this, msg);
this.name = "UnknownCommandError";
this.status = "unknown command";
};
UnknownCommandError.prototype = Object.create(WebDriverError.prototype);
class UnknownError extends WebDriverError {
constructor (message) {
super(message);
this.status = "unknown error";
}
}
this.UnknownError = function (msg) {
WebDriverError.call(this, msg);
this.name = "UnknownError";
this.status = "unknown error";
};
UnknownError.prototype = Object.create(WebDriverError.prototype);
this.UnsupportedOperationError = function (msg) {
WebDriverError.call(this, msg);
this.name = "UnsupportedOperationError";
this.status = "unsupported operation";
};
UnsupportedOperationError.prototype = Object.create(WebDriverError.prototype);
class UnsupportedOperationError extends WebDriverError {
constructor (message) {
super(message);
this.status = "unsupported operation";
}
}
const STATUSES = new Map([
["element not accessible", ElementNotAccessibleError],

Просмотреть файл

@ -254,15 +254,12 @@ this.Response = class {
* propagated.
*/
sendError(err) {
let wd = error.isWebDriverError(err);
let we = wd ? err : new WebDriverError(err.message);
this.error = error.toJson(we);
this.error = error.wrap(err).toJSON();
this.body = null;
this.send();
// propagate errors that are implementation problems
if (!wd) {
// propagate errors which are implementation problems
if (!error.isWebDriverError(err)) {
throw err;
}
}

Просмотреть файл

@ -114,7 +114,7 @@ proxy.AsyncMessageChannel = class {
break;
case proxy.AsyncMessageChannel.ReplyType.Error:
let err = error.fromJson(msg.json.data);
let err = WebDriverError.fromJSON(msg.json.data);
reject(err);
break;
@ -172,16 +172,24 @@ proxy.AsyncMessageChannel = class {
this.sendReply_(uuid, proxy.AsyncMessageChannel.ReplyType.Ok);
} else if (error.isError(obj)) {
let err = error.wrap(obj);
let serr = error.toJson(err);
this.sendReply_(uuid, proxy.AsyncMessageChannel.ReplyType.Error, serr);
this.sendReply_(uuid, proxy.AsyncMessageChannel.ReplyType.Error, err);
} else {
this.sendReply_(uuid, proxy.AsyncMessageChannel.ReplyType.Value, obj);
}
}
sendReply_(uuid, type, data = undefined) {
let path = proxy.AsyncMessageChannel.makePath(uuid);
let msg = {type: type, data: data};
const path = proxy.AsyncMessageChannel.makePath(uuid);
let payload;
if (data && typeof data.toJSON == "function") {
payload = data.toJSON();
} else {
payload = data;
}
const msg = {type: type, data: payload};
// here sendAsync is actually the content frame's
// sendAsyncMessage(path, message) global
this.sendAsync(path, msg);

Просмотреть файл

@ -12,7 +12,7 @@ Cu.import("chrome://marionette/content/error.js");
add_test(function test_session() {
assert.session({sessionId: "foo"});
for (let typ of [null, undefined, ""]) {
Assert.throws(() => assert.session({sessionId: typ}), InvalidSessionIdError);
Assert.throws(() => assert.session({sessionId: typ}), InvalidSessionIDError);
}
run_next_test();

Просмотреть файл

@ -43,6 +43,7 @@ add_test(function test_isWebDriverError() {
ok(error.isWebDriverError(new WebDriverError()));
ok(error.isWebDriverError(new InvalidArgumentError()));
ok(error.isWebDriverError(new JavaScriptError()));
run_next_test();
});
@ -88,23 +89,20 @@ add_test(function test_stringify() {
run_next_test();
});
add_test(function test_toJson() {
Assert.throws(() => error.toJson(new Error()),
/Unserialisable error type: [object Error]/);
add_test(function test_toJSON() {
let e0 = new WebDriverError();
let e0s = error.toJson(e0);
let e0s = e0.toJSON();
equal(e0s.error, "webdriver error");
equal(e0s.message, "");
equal(e0s.stacktrace, e0.stack);
let e1 = new WebDriverError("a");
let e1s = error.toJson(e1);
let e1s = e1.toJSON();
equal(e1s.message, e1.message);
equal(e1s.stacktrace, e1.stack);
let e2 = new JavaScriptError("first", "second", "third", "fourth");
let e2s = error.toJson(e2);
let e2s = e2.toJSON();
equal(e2.status, e2s.error);
equal(e2.message, e2s.message);
ok(e2s.stacktrace.match(/second/));
@ -114,29 +112,47 @@ add_test(function test_toJson() {
run_next_test();
});
add_test(function test_fromJson() {
Assert.throws(() => error.fromJson({error: "foo"}),
/Undeserialisable error type: foo/);
Assert.throws(() => error.fromJson({error: "Error"}),
/Undeserialisable error type: Error/);
Assert.throws(() => error.fromJson({}),
/Undeserialisable error type: undefined/);
add_test(function test_fromJSON() {
Assert.throws(() => WebDriverError.fromJSON({error: "foo"}),
/Not of WebDriverError descent/);
Assert.throws(() => WebDriverError.fromJSON({error: "Error"}),
/Not of WebDriverError descent/);
Assert.throws(() => WebDriverError.fromJSON({}),
/Undeserialisable error type/);
Assert.throws(() => WebDriverError.fromJSON(undefined),
/TypeError/);
// stacks will be different
let e1 = new WebDriverError("1");
let e1r = error.fromJson({error: "webdriver error", message: "1"});
let e1r = WebDriverError.fromJSON({error: "webdriver error", message: "1"});
ok(e1r instanceof WebDriverError);
equal(e1r.name, e1.name);
equal(e1r.status, e1.status);
equal(e1r.message, e1.message);
// stacks will be different
let e2 = new InvalidArgumentError("2");
let e2r = error.fromJson({error: "invalid argument", message: "2"});
let e2r = WebDriverError.fromJSON({error: "invalid argument", message: "2"});
ok(e2r instanceof WebDriverError);
ok(e2r instanceof InvalidArgumentError);
equal(e2r.name, e2.name);
equal(e2r.status, e2.status);
equal(e2r.message, e2.message);
let e3 = new JavaScriptError("first", "second", "third", "fourth");
let e3s = error.toJson(e3);
deepEqual(e3, error.fromJson(e3s));
// test stacks
let e3j = {error: "no such element", message: "3", stacktrace: "4"};
let e3r = WebDriverError.fromJSON(e3j);
ok(e3r instanceof WebDriverError);
ok(e3r instanceof NoSuchElementError);
equal(e3r.name, "NoSuchElementError");
equal(e3r.status, e3j.error);
equal(e3r.message, e3j.message);
equal(e3r.stack, e3j.stacktrace);
// parity with toJSON
let e4 = new JavaScriptError("first", "second", "third", "fourth");
let e4s = e4.toJSON();
deepEqual(e4, WebDriverError.fromJSON(e4s));
run_next_test();
});
@ -146,7 +162,7 @@ add_test(function test_WebDriverError() {
equal("WebDriverError", err.name);
equal("foo", err.message);
equal("webdriver error", err.status);
equal(Error.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -156,7 +172,7 @@ add_test(function test_ElementNotAccessibleError() {
equal("ElementNotAccessibleError", err.name);
equal("foo", err.message);
equal("element not accessible", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -166,7 +182,7 @@ add_test(function test_ElementNotVisibleError() {
equal("ElementNotVisibleError", err.name);
equal("foo", err.message);
equal("element not visible", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -176,7 +192,7 @@ add_test(function test_InvalidArgumentError() {
equal("InvalidArgumentError", err.name);
equal("foo", err.message);
equal("invalid argument", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -186,7 +202,7 @@ add_test(function test_InvalidElementStateError() {
equal("InvalidElementStateError", err.name);
equal("foo", err.message);
equal("invalid element state", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -196,17 +212,17 @@ add_test(function test_InvalidSelectorError() {
equal("InvalidSelectorError", err.name);
equal("foo", err.message);
equal("invalid selector", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
add_test(function test_InvalidSessionIdError() {
let err = new InvalidSessionIdError("foo");
equal("InvalidSessionIdError", err.name);
add_test(function test_InvalidSessionIDError() {
let err = new InvalidSessionIDError("foo");
equal("InvalidSessionIDError", err.name);
equal("foo", err.message);
equal("invalid session id", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -216,7 +232,7 @@ add_test(function test_JavaScriptError() {
equal("JavaScriptError", err.name);
equal("foo", err.message);
equal("javascript error", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
equal("undefined", new JavaScriptError(undefined).message);
// TODO(ato): Bug 1240550
@ -234,7 +250,7 @@ add_test(function test_NoAlertOpenError() {
equal("NoAlertOpenError", err.name);
equal("foo", err.message);
equal("no such alert", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -244,7 +260,7 @@ add_test(function test_NoSuchElementError() {
equal("NoSuchElementError", err.name);
equal("foo", err.message);
equal("no such element", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -254,7 +270,7 @@ add_test(function test_NoSuchFrameError() {
equal("NoSuchFrameError", err.name);
equal("foo", err.message);
equal("no such frame", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -264,7 +280,7 @@ add_test(function test_NoSuchWindowError() {
equal("NoSuchWindowError", err.name);
equal("foo", err.message);
equal("no such window", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -274,7 +290,7 @@ add_test(function test_ScriptTimeoutError() {
equal("ScriptTimeoutError", err.name);
equal("foo", err.message);
equal("script timeout", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -284,7 +300,7 @@ add_test(function test_SessionNotCreatedError() {
equal("SessionNotCreatedError", err.name);
equal("foo", err.message);
equal("session not created", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -294,7 +310,7 @@ add_test(function test_StaleElementReferenceError() {
equal("StaleElementReferenceError", err.name);
equal("foo", err.message);
equal("stale element reference", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -304,7 +320,7 @@ add_test(function test_TimeoutError() {
equal("TimeoutError", err.name);
equal("foo", err.message);
equal("timeout", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -314,7 +330,7 @@ add_test(function test_UnableToSetCookieError() {
equal("UnableToSetCookieError", err.name);
equal("foo", err.message);
equal("unable to set cookie", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -324,7 +340,7 @@ add_test(function test_UnknownCommandError() {
equal("UnknownCommandError", err.name);
equal("foo", err.message);
equal("unknown command", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -334,7 +350,7 @@ add_test(function test_UnknownError() {
equal("UnknownError", err.name);
equal("foo", err.message);
equal("unknown error", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});
@ -344,7 +360,7 @@ add_test(function test_UnsupportedOperationError() {
equal("UnsupportedOperationError", err.name);
equal("foo", err.message);
equal("unsupported operation", err.status);
equal(WebDriverError.prototype.toString(), Object.getPrototypeOf(err).toString());
ok(err instanceof WebDriverError);
run_next_test();
});

Просмотреть файл

@ -143,7 +143,7 @@ add_test(function test_Response_send() {
add_test(function test_Response_sendError() {
let err = new WebDriverError();
let resp = new Response(42, r => {
equal(error.toJson(err).error, r.error.error);
equal(err.toJSON().error, r.error.error);
equal(null, r.body);
equal(false, r.sent);
});