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