/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ const prefs = require("sdk/preferences/service"); const { id, name } = require("sdk/self"); const { Cc, Cu, Ci } = require("chrome"); const { loadSubScript } = Cc['@mozilla.org/moz/jssubscript-loader;1']. getService(Ci.mozIJSSubScriptLoader); const ADDON_LOG_LEVEL_PREF = "extensions." + id + ".sdk.console.logLevel"; const SDK_LOG_LEVEL_PREF = "extensions.sdk.console.logLevel"; const HAS_ORIGINAL_ADDON_LOG_LEVEL = prefs.has(ADDON_LOG_LEVEL_PREF); const ORIGINAL_ADDON_LOG_LEVEL = prefs.get(ADDON_LOG_LEVEL_PREF); const HAS_ORIGINAL_SDK_LOG_LEVEL = prefs.has(SDK_LOG_LEVEL_PREF); const ORIGINAL_SDK_LOG_LEVEL = prefs.get(SDK_LOG_LEVEL_PREF); exports.testPlainTextConsole = function(assert) { let prints = []; let tbLines; function print(message) { prints.push(message); } function lastPrint() { let last = prints.slice(-1)[0]; prints = []; return last; } prefs.set(SDK_LOG_LEVEL_PREF, "all"); prefs.reset(ADDON_LOG_LEVEL_PREF); let Console = require("sdk/console/plain-text").PlainTextConsole; let con = new Console(print); assert.ok("PlainTextConsole instantiates"); con.log('testing', 1, [2, 3, 4]); assert.equal(lastPrint(), "console.log: " + name + ": testing 1 Array [2,3,4]\n", "PlainTextConsole.log() must work."); con.info('testing', 1, [2, 3, 4]); assert.equal(lastPrint(), "console.info: " + name + ": testing 1 Array [2,3,4]\n", "PlainTextConsole.info() must work."); con.warn('testing', 1, [2, 3, 4]); assert.equal(lastPrint(), "console.warn: " + name + ": testing 1 Array [2,3,4]\n", "PlainTextConsole.warn() must work."); con.error('testing', 1, [2, 3, 4]); assert.equal(prints[0], "console.error: " + name + ": \n", "PlainTextConsole.error() must work."); assert.equal(prints[1], " testing\n") assert.equal(prints[2], " 1\n") assert.equal(prints[3], "Array\n - 0 = 2\n - 1 = 3\n - 2 = 4\n - length = 3\n"); prints = []; con.debug('testing', 1, [2, 3, 4]); assert.equal(prints[0], "console.debug: " + name + ": \n", "PlainTextConsole.debug() must work."); assert.equal(prints[1], " testing\n") assert.equal(prints[2], " 1\n") assert.equal(prints[3], "Array\n - 0 = 2\n - 1 = 3\n - 2 = 4\n - length = 3\n"); prints = []; con.log('testing', undefined); assert.equal(lastPrint(), "console.log: " + name + ": testing undefined\n", "PlainTextConsole.log() must stringify undefined."); con.log('testing', null); assert.equal(lastPrint(), "console.log: " + name + ": testing null\n", "PlainTextConsole.log() must stringify null."); // TODO: Fix console.jsm to detect custom toString. con.log("testing", { toString: () => "obj.toString()" }); assert.equal(lastPrint(), "console.log: " + name + ": testing {}\n", "PlainTextConsole.log() doesn't printify custom toString."); con.log("testing", { toString: function() { throw "fail!"; } }); assert.equal(lastPrint(), "console.log: " + name + ": testing {}\n", "PlainTextConsole.log() must stringify custom bad toString."); con.exception(new Error("blah")); assert.equal(prints[0], "console.error: " + name + ": \n", "prints[0] is correct"); tbLines = prints[1].split("\n"); assert.equal(tbLines[0], " Message: Error: blah", "tbLines[0] is correct"); assert.equal(tbLines[1], " Stack:", "tbLines[1] is correct"); let lineNumber = prints[1].match(module.uri + ":(\\d+)")[1]; assert.equal(lineNumber, "84", "line number is correct") assert.ok(prints[1].indexOf(module.uri + ":84") !== -1, "line number is correct"); prints = [] try { loadSubScript("invalid-url", {}); assert.fail("successed in calling loadSubScript with invalid-url"); } catch(e) { con.exception(e); } assert.equal(prints[0], "console.error: " + name + ": \n", "prints[0] is correct"); assert.equal(prints[1], " Error creating URI (invalid URL scheme?)\n", "prints[1] is correct"); prints = []; con.trace(); tbLines = prints[0].split("\n"); assert.equal(tbLines[0], "console.trace: " + name + ": ", "contains correct console.trace"); assert.ok(tbLines[1].indexOf("_ain-text-console.js 106") == 0); prints = []; // Whether or not console methods should print at the various log levels, // structured as a hash of levels, each of which contains a hash of methods, // each of whose value is whether or not it should print, i.e.: // { [level]: { [method]: [prints?], ... }, ... }. let levels = { all: { debug: true, log: true, info: true, warn: true, error: true }, debug: { debug: true, log: true, info: true, warn: true, error: true }, info: { debug: false, log: true, info: true, warn: true, error: true }, warn: { debug: false, log: false, info: false, warn: true, error: true }, error: { debug: false, log: false, info: false, warn: false, error: true }, off: { debug: false, log: false, info: false, warn: false, error: false }, }; // The messages we use to test the various methods, as a hash of methods. let messages = { debug: "console.debug: " + name + ": \n \n", log: "console.log: " + name + ": \n", info: "console.info: " + name + ": \n", warn: "console.warn: " + name + ": \n", error: "console.error: " + name + ": \n \n", }; for (let level in levels) { let methods = levels[level]; for (let method in methods) { // We have to reset the log level pref each time we run the test // because the test runner relies on the console to print test output, // and test results would not get printed to the console for some // values of the pref. prefs.set(SDK_LOG_LEVEL_PREF, level); con[method](""); prefs.set(SDK_LOG_LEVEL_PREF, "all"); assert.equal(prints.join(""), (methods[method] ? messages[method] : ""), "at log level '" + level + "', " + method + "() " + (methods[method] ? "prints" : "doesn't print")); prints = []; } } prefs.set(SDK_LOG_LEVEL_PREF, "off"); prefs.set(ADDON_LOG_LEVEL_PREF, "all"); con.debug(""); assert.equal(prints.join(""), messages["debug"], "addon log level 'all' overrides SDK log level 'off'"); prints = []; prefs.set(SDK_LOG_LEVEL_PREF, "all"); prefs.set(ADDON_LOG_LEVEL_PREF, "off"); con.error(""); prefs.reset(ADDON_LOG_LEVEL_PREF); assert.equal(lastPrint(), null, "addon log level 'off' overrides SDK log level 'all'"); restorePrefs(); }; exports.testPlainTextConsoleBoundMethods = function(assert) { let prints = []; let tbLines; function print(message) { prints.push(message); } function lastPrint() { let last = prints.slice(-1)[0]; prints = []; return last; } prefs.set(SDK_LOG_LEVEL_PREF, "all"); prefs.reset(ADDON_LOG_LEVEL_PREF); let Console = require("sdk/console/plain-text").PlainTextConsole; let { log, info, warn, error, debug, exception, trace } = new Console(print); assert.ok("PlainTextConsole instantiates"); log('testing', 1, [2, 3, 4]); assert.equal(lastPrint(), "console.log: " + name + ": testing 1 Array [2,3,4]\n", "PlainTextConsole.log() must work."); info('testing', 1, [2, 3, 4]); assert.equal(lastPrint(), "console.info: " + name + ": testing 1 Array [2,3,4]\n", "PlainTextConsole.info() must work."); warn('testing', 1, [2, 3, 4]); assert.equal(lastPrint(), "console.warn: " + name + ": testing 1 Array [2,3,4]\n", "PlainTextConsole.warn() must work."); error('testing', 1, [2, 3, 4]); assert.equal(prints[0], "console.error: " + name + ": \n", "PlainTextConsole.error() must work."); assert.equal(prints[1], " testing\n") assert.equal(prints[2], " 1\n") assert.equal(prints[3], "Array\n - 0 = 2\n - 1 = 3\n - 2 = 4\n - length = 3\n"); prints = []; debug('testing', 1, [2, 3, 4]); assert.equal(prints[0], "console.debug: " + name + ": \n", "PlainTextConsole.debug() must work."); assert.equal(prints[1], " testing\n", "prints[1] is correct"); assert.equal(prints[2], " 1\n", "prints[2] is correct"); assert.equal(prints[3], "Array\n - 0 = 2\n - 1 = 3\n - 2 = 4\n - length = 3\n", "prints[3] is correct"); prints = []; exception(new Error("blah")); assert.equal(prints[0], "console.error: " + name + ": \n", "prints[0] is correct"); tbLines = prints[1].split("\n"); assert.equal(tbLines[0], " Message: Error: blah", "tbLines[0] is correct"); assert.equal(tbLines[1], " Stack:", "tbLines[1] is correct"); assert.ok(prints[1].indexOf(module.uri + ":219") !== -1, "correct line number"); prints = [] trace(); tbLines = prints[0].split("\n"); assert.equal(tbLines[0], "console.trace: " + name + ": ", "console.trace is correct"); assert.ok(tbLines[1].indexOf("_ain-text-console.js 228") === 0, "correct line number"); prints = []; restorePrefs(); }; exports.testConsoleInnerID = function(assert) { let Console = require("sdk/console/plain-text").PlainTextConsole; let { log, info, warn, error, debug, exception, trace } = new Console(function() {}, "test ID"); prefs.set(SDK_LOG_LEVEL_PREF, "all"); let messages = []; function onMessage({ subject }) { let message = subject.wrappedJSObject; messages.push({ msg: message.arguments[0], type: message.level, innerID: message.innerID }); } const system = require("sdk/system/events"); system.on("console-api-log-event", onMessage); log("Test log"); warn("Test warning"); error("Test error"); assert.equal(messages.length, 3, "Should see 3 log events"); assert.deepEqual(messages[0], { msg: "Test log", type: "log", innerID: "test ID" }, "Should see the right event"); assert.deepEqual(messages[1], { msg: "Test warning", type: "warn", innerID: "test ID" }, "Should see the right event"); assert.deepEqual(messages[2], { msg: "Test error", type: "error", innerID: "test ID" }, "Should see the right event"); system.off("console-api-log-event", onMessage); restorePrefs(); }; function restorePrefs() { if (HAS_ORIGINAL_ADDON_LOG_LEVEL) prefs.set(ADDON_LOG_LEVEL_PREF, ORIGINAL_ADDON_LOG_LEVEL); else prefs.reset(ADDON_LOG_LEVEL_PREF); if (HAS_ORIGINAL_SDK_LOG_LEVEL) prefs.set(SDK_LOG_LEVEL_PREF, ORIGINAL_SDK_LOG_LEVEL); else prefs.reset(SDK_LOG_LEVEL_PREF); } require("sdk/test").run(exports);