You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pm...@apache.org on 2012/05/17 18:42:54 UTC

js commit: [CB-623] added logger module / tests to common-js

Updated Branches:
  refs/heads/master 41dc4857f -> 2ba772d49


[CB-623] added logger module / tests to common-js

- added a new plugin module "logger" (common/plugin/logger.js)
- install the logger into cordova.logger (via common/common.js)
- added configuration of logger in ios/platform.js (don't use console)
- test cases for logger
- refactored utils.format() into utils.format() and utils.vformat()
- added tests cases for utils.vformat()


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/commit/2ba772d4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/tree/2ba772d4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/diff/2ba772d4

Branch: refs/heads/master
Commit: 2ba772d49db4bf000dd33f4db8d5713bc87906a2
Parents: 41dc485
Author: Patrick Mueller <pm...@apache.org>
Authored: Thu May 17 12:38:43 2012 -0400
Committer: Patrick Mueller <pm...@apache.org>
Committed: Thu May 17 12:38:43 2012 -0400

----------------------------------------------------------------------
 lib/common/common.js        |    3 +
 lib/common/plugin/logger.js |  221 ++++++++++++++++++++++++++++++++++++++
 lib/common/utils.js         |   13 ++-
 lib/ios/platform.js         |    6 +-
 test/test.logger.js         |  143 ++++++++++++++++++++++++
 test/test.utils.js          |   22 ++++
 6 files changed, 405 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/2ba772d4/lib/common/common.js
----------------------------------------------------------------------
diff --git a/lib/common/common.js b/lib/common/common.js
index ec89202..3e85e42 100644
--- a/lib/common/common.js
+++ b/lib/common/common.js
@@ -5,6 +5,9 @@ module.exports = {
             children: {
                 exec: {
                     path: 'cordova/exec'
+                },
+                logger: {
+                    path: 'cordova/plugin/logger'
                 }
             }
         },

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/2ba772d4/lib/common/plugin/logger.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/logger.js b/lib/common/plugin/logger.js
new file mode 100644
index 0000000..bcbc0cf
--- /dev/null
+++ b/lib/common/plugin/logger.js
@@ -0,0 +1,221 @@
+//------------------------------------------------------------------------------
+// The logger module exports the following properties/functions:
+//
+// LOG                          - constant for the level LOG
+// ERROR                        - constant for the level ERROR
+// WARN                         - constant for the level WARN
+// INFO                         - constant for the level INFO
+// DEBUG                        - constant for the level DEBUG
+// logLevel()                   - returns current log level
+// logLevel(value)              - sets and returns a new log level
+// useConsole()                 - returns whether logger is using console
+// useConsole(value)            - sets and returns whether logger is using console
+// log(message,...)             - logs a message at level LOG
+// error(message,...)           - logs a message at level ERROR
+// warn(message,...)            - logs a message at level WARN
+// info(message,...)            - logs a message at level INFO
+// debug(message,...)           - logs a message at level DEBUG
+// logLevel(level,message,...)  - logs a message specified level
+//
+//------------------------------------------------------------------------------
+
+var logger = exports
+
+var exec    = require('cordova/exec')
+var utils   = require('cordova/utils')
+
+var UseConsole   = true
+var Queued       = []
+var DeviceReady  = false
+var CurrentLevel
+
+/**
+ * Logging levels
+ */
+
+var Levels = [
+    "LOG",
+    "ERROR",
+    "WARN",
+    "INFO",
+    "DEBUG"
+]
+
+/*
+ * add the logging levels to the logger object and
+ * to a separate levelsMap object for testing
+ */
+
+var LevelsMap = {}
+for (var i=0; i<Levels.length; i++) {
+    var level = Levels[i]
+    LevelsMap[level] = i
+    logger[level]    = level
+}
+
+CurrentLevel = LevelsMap["WARN"]
+
+/**
+ * Getter/Setter for the logging level
+ *
+ * Returns the current logging level.
+ *
+ * When a value is passed, sets the logging level to that value.
+ * The values should be one of the following constants:
+ *    logger.LOG
+ *    logger.ERROR
+ *    logger.WARN
+ *    logger.INFO
+ *    logger.DEBUG
+ *
+ * The value used determines which messages get printed.  The logging
+ * values above are in order, and only messages logged at the logging
+ * level or above will actually be displayed to the user.  Eg, the
+ * default level is WARN, so only messages logged with LOG, ERROR, or
+ * WARN will be displayed; INFO and DEBUG messages will be ignored.
+ */
+logger.level = function (value) {
+    if (arguments.length) {
+        if (LevelsMap[value] == null) {
+            throw new Error("invalid logging level: " + value)
+        }
+        CurrentLevel = LevelsMap[value]
+    }
+
+    return Levels[CurrentLevel]
+}
+
+
+/**
+ * Getter/Setter for the useConsole functionality
+ *
+ * When useConsole is true, the logger will log via the
+ * browser 'console' object.  Otherwise, it will use the
+ * native Logger plugin.
+ */
+logger.useConsole = function (value) {
+    if (arguments.length) UseConsole = !!value
+
+    if (UseConsole) {
+        if (typeof console == "undefined") {
+            throw new Error("global console object is not defined")
+        }
+
+        if (typeof console.log != "function") {
+            throw new Error("global console object does not have a log function")
+        }
+
+        if (console.__usingCordovaLogger) {
+            throw new Error("console and logger are too intertwingly")
+        }
+    }
+
+    return UseConsole
+}
+
+/**
+ * Logs a message at the LOG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.log   = function(message) { logWithArgs("LOG",   arguments) }
+
+/**
+ * Logs a message at the ERROR level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.error = function(message) { logWithArgs("ERROR", arguments) }
+
+/**
+ * Logs a message at the WARN level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.warn  = function(message) { logWithArgs("WARN",  arguments) }
+
+/**
+ * Logs a message at the INFO level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.info  = function(message) { logWithArgs("INFO",  arguments) }
+
+/**
+ * Logs a message at the DEBUG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.debug = function(message) { logWithArgs("DEBUG", arguments) }
+
+// log at the specified level with args
+function logWithArgs(level, args) {
+    var args = [level].concat([].slice.call(args))
+    logger.logLevel.apply(logger, args)
+}
+
+/**
+ * Logs a message at the specified level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.logLevel = function(level, message /* , ... */) {
+    // format the message with the parameters
+    var formatArgs = [].slice.call(arguments, 2)
+    var message    = utils.vformat(message, formatArgs)
+
+    if (LevelsMap[level] == null) {
+        throw new Error("invalid logging level: " + level)
+    }
+
+    if (LevelsMap[level] > CurrentLevel) return
+
+    // queue the message if not yet at deviceready
+    if (!DeviceReady && !UseConsole) {
+        Queued.push([level, message])
+        return
+    }
+
+    // if not using the console, use the native logger
+    if (!UseConsole) {
+        exec(null, null, "Logger", "logLevel", [level, message])
+        return
+    }
+
+    // make sure console is not using logger
+    if (console.__usingCordovaLogger) {
+        throw new Error("console and logger are too intertwingly")
+    }
+
+    // log to the console
+    switch (level) {
+        case logger.LOG:   console.log(message); break
+        case logger.ERROR: console.log("ERROR: " + message); break
+        case logger.WARN:  console.log("WARN: "  + message); break
+        case logger.INFO:  console.log("INFO: "  + message); break
+        case logger.DEBUG: console.log("DEBUG: " + message); break
+    }
+}
+
+// when deviceready fires, log queued messages
+logger.__onDeviceReady = function() {
+    if (DeviceReady) return
+
+    DeviceReady = true
+
+    for (var i=0; i<Queued.length; i++) {
+        var messageArgs = Queued[i]
+        logger.logLevel(messageArgs[0], messageArgs[1])
+    }
+
+    Queued = null
+}
+
+// add a deviceready event to log queued messages
+document.addEventListener("deviceready", logger.__onDeviceReady, false)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/2ba772d4/lib/common/utils.js
----------------------------------------------------------------------
diff --git a/lib/common/utils.js b/lib/common/utils.js
index 30393f2..eecbae4 100644
--- a/lib/common/utils.js
+++ b/lib/common/utils.js
@@ -97,6 +97,16 @@ utils.alert = function(msg) {
 /**
  * Formats a string and arguments following it ala sprintf()
  *
+ * see utils.vformat() for more information
+ */
+utils.format = function(formatString /* ,... */) {
+    var args = [].slice.call(arguments, 1);
+    return utils.vformat(formatString, args);
+};
+
+/**
+ * Formats a string and arguments following it ala vsprintf()
+ *
  * format chars:
  *   %j - format arg as JSON
  *   %o - format arg as JSON
@@ -108,14 +118,13 @@ utils.alert = function(msg) {
  * for rationale, see FireBug's Console API:
  *    http://getfirebug.com/wiki/index.php/Console_API
  */
-utils.format = function(formatString /* ,... */) {
+utils.vformat = function(formatString, args) {
     if (formatString === null || formatString === undefined) return "";
     if (arguments.length == 1) return formatString.toString();
 
     var pattern = /(.*?)%(.)(.*)/;
     var rest    = formatString.toString();
     var result  = [];
-    var args    = [].slice.call(arguments,1);
 
     while (args.length) {
         var arg   = args.shift();

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/2ba772d4/lib/ios/platform.js
----------------------------------------------------------------------
diff --git a/lib/ios/platform.js b/lib/ios/platform.js
index 8333ffd..d31c49c 100644
--- a/lib/ios/platform.js
+++ b/lib/ios/platform.js
@@ -44,4 +44,8 @@ module.exports = {
             }
         }
     }
-};
\ No newline at end of file
+};
+
+// use the native logger
+var logger = require("cordova/plugin/logger")
+logger.useConsole(false)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/2ba772d4/test/test.logger.js
----------------------------------------------------------------------
diff --git a/test/test.logger.js b/test/test.logger.js
new file mode 100644
index 0000000..31c0d55
--- /dev/null
+++ b/test/test.logger.js
@@ -0,0 +1,143 @@
+var cordova = require('cordova')
+var logger  = require('cordova/plugin/logger')
+var exec    = require("cordova/exec")
+
+// fake device ready, but can't test the queued messages this way
+logger.__onDeviceReady()
+
+//(function() { 
+
+describe("logger using exec", function () {
+
+    var savedLevel 
+    
+    beforeEach(function() {
+        savedLevel = logger.level()
+        logger.useConsole(false)
+        exec.reset();
+    })
+    
+    afterEach(function() {
+        logger.level(savedLevel)
+    })
+
+    it("is not logging to console", function () {
+        expect(logger.useConsole()).toBe(false)
+    })
+
+    it("is using level WARN by default", function () {
+        expect(logger.level()).toBe(logger.WARN)
+    })
+
+    it("has it's level constants set right", function () {
+        expect(logger.LOG  ).toBe("LOG")
+        expect(logger.ERROR).toBe("ERROR")
+        expect(logger.WARN ).toBe("WARN")
+        expect(logger.INFO ).toBe("INFO")
+        expect(logger.DEBUG).toBe("DEBUG")
+    })
+
+    it("supports setting the level", function () {
+        logger.level(logger.INFO)
+        expect(logger.level()).toBe(logger.INFO)
+    })
+
+    it("implements log() correctly", function () {
+        logger.log("1")
+        expect(exec).toHaveBeenCalledWith(null, null, "Logger", "logLevel", [logger.LOG, "1"]);
+    })
+
+    it("implements error() correctly", function () {
+        logger.error("2")
+        expect(exec).toHaveBeenCalledWith(null, null, "Logger", "logLevel", [logger.ERROR, "2"]);
+    })
+
+    it("implements warn() correctly", function () {
+        logger.warn("3")
+        expect(exec).toHaveBeenCalledWith(null, null, "Logger", "logLevel", [logger.WARN, "3"]);
+    })
+
+    it("implements info() correctly", function () {
+        logger.level(logger.INFO)
+        logger.info("4")
+        expect(exec).toHaveBeenCalledWith(null, null, "Logger", "logLevel", [logger.INFO, "4"]);
+    })
+
+    it("implements debug() correctly", function () {
+        logger.level(logger.DEBUG)
+        logger.debug("5")
+        expect(exec).toHaveBeenCalledWith(null, null, "Logger", "logLevel", [logger.DEBUG, "5"]);
+    })
+
+    it("implements logLevel() correctly", function () {
+        logger.logLevel("LOG", "6")
+        expect(exec).toHaveBeenCalledWith(null, null, "Logger", "logLevel", [logger.LOG, "6"]);
+    })
+
+    it("implements format strings correctly", function () {
+        logger.log("a-%s-b-%o-c")
+        expect(exec).toHaveBeenCalledWith(null, null, "Logger", "logLevel", [logger.LOG, "a-%s-b-%o-c"]);
+
+        logger.log("a-%s-b-%o-c", "xyz", {f:1, g:2})
+        expect(exec).toHaveBeenCalledWith(null, null, "Logger", "logLevel", [logger.LOG, "a-xyz-b-{\"f\":1,\"g\":2}-c"]);
+    })
+    
+})
+
+describe("logger using console", function () {
+    var loggedMessage 
+    var originalConsoleLog = console.log
+
+    function fakeConsoleLog(message) {
+        loggedMessage = message
+    }
+    
+    beforeEach(function() {
+        logger.useConsole(true)
+        loggedMessage = null
+        console.log = fakeConsoleLog
+    })
+    
+    afterEach(function() {
+        console.log = originalConsoleLog
+    })
+    
+    it("is logging to console", function () {
+        expect(logger.useConsole()).toBe(true)
+    })
+
+    it("implements log() correctly", function () {
+        logger.log("1")
+        expect(loggedMessage).toBe("1")
+    })
+
+    it("implements error() correctly", function () {
+        logger.error("2")
+        expect(loggedMessage).toBe("ERROR: 2")
+    })
+
+    it("implements warn() correctly", function () {
+        logger.warn("3")
+        expect(loggedMessage).toBe("WARN: 3")
+    })
+
+    it("implements info() correctly", function () {
+        logger.info("4")
+        expect(loggedMessage).toBe(null)
+        
+        logger.level(logger.INFO)
+        logger.info("4")
+        expect(loggedMessage).toBe("INFO: 4")
+    })
+
+    it("implements debug() correctly", function () {
+        logger.debug("5")
+        expect(loggedMessage).toBe(null)
+
+        logger.level(logger.DEBUG)
+        logger.debug("5")
+        expect(loggedMessage).toBe("DEBUG: 5")
+    })
+
+})
+

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/2ba772d4/test/test.utils.js
----------------------------------------------------------------------
diff --git a/test/test.utils.js b/test/test.utils.js
index 7ea7d53..0b9fb69 100644
--- a/test/test.utils.js
+++ b/test/test.utils.js
@@ -93,6 +93,28 @@ describe("utils", function () {
         expect(uuid).not.toEqual(utils.createUUID());
     });
     
+    describe("vformat() method", function () {
+        it("handles passing nothing", function() {
+            expect(utils.format()).toBe("")
+        })
+
+        it("handles empty args", function() {
+            expect(utils.vformat("abc",[])).toBe("abc")
+        })
+
+        it("handles empty args and format char", function() {
+            expect(utils.vformat("ab%oc",[])).toBe("ab%oc")
+        })
+
+        it("handles one arg", function() {
+            expect(utils.vformat("a%sb", ["-"])).toBe("a-b")
+        })
+
+        it("handles two args", function() {
+            expect(utils.vformat("a%sb%sc", ["-","_"])).toBe("a-b_c")
+        })
+    })
+        
     describe("format() method", function () {
         it("handles passing nothing", function() {
             expect(utils.format()).toBe("")