Permalink
Browse files

add ability to log by URL and add browser testing

  • Loading branch information...
Paul Baumgart
Paul Baumgart committed Aug 21, 2012
1 parent 87f0001 commit 62bf594319cc504d2401c23e38829e3cbdbd19de
View
@@ -1,2 +1,3 @@
node_modules/
npm-debug.log
+browser-test.js
View
@@ -69,9 +69,12 @@ function init(options) {
if (logLevel === 'off') {
return src;
} else {
+ var loggerType = JSON.stringify(options.loggerUrl ? 'url' : 'console');
+ var loggerArg = JSON.stringify(options.loggerUrl || '');
return 'var __shortfilename = String(__filename).split("/");\n' +
'__shortfilename = __shortfilename.slice(__shortfilename.length - 3).join("/");\n' +
- 'var logger = new (require(' + JSON.stringify(loggerFile) + '));\n' + src;
+ 'var logger = new (require(' + JSON.stringify(loggerFile) + ')(' + loggerType + '))(' + loggerArg + ');\n' +
+ src;
}
},
View
@@ -1,69 +1,133 @@
-function Logger() {
+var isInternetExplorer = (navigator.appName === 'Microsoft Internet Explorer');
+
+function UrlLogger(url) {
+ this._url = url || '';
+ this.error = this.log;
+ this.warn = this.log;
+ this.info = this.log;
+ this.debug = this.log;
+ this.trace = this.log;
+ this.log = void 0;
+}
+
+UrlLogger.prototype = {
+ log: function() {
+ var args = Array.prototype.slice.call(arguments);
+ for (var i = 0, len = args.length; i < len; i++) {
+ var arg = args[i];
+ if (arg instanceof Error) {
+ if (arg.stack) {
+ if (isInternetExplorer) { // avoid hitting URL length limits in IE
+ args[i] = arg.stack.split(/\s*\n\s*/)[1];
+ } else {
+ args[i] = arg.stack;
+ }
+ } else {
+ args[i] = arg.message;
+ }
+ }
+ }
+
+ this._sendData(args);
+ },
+
+ _sendData: function(data) {
+ if (typeof document !== 'undefined' &&
+ document.createElement &&
+ document.documentElement) { // don't try to send data if we don't have a DOM
+ var body = document.body || document.documentElement;
+
+ var img = document.createElement('img');
+ img.onload = img.onerror = function() {
+ body.removeChild(img);
+ img = null;
+ };
+ img.src = this._url + encodeURIComponent(JSON.stringify(data));
+
+ body.appendChild(img);
+ }
+ }
+}
+
+function ConsoleLogger() {
if (this.log) {
this.trace = this.log;
this.log = void 0;
}
}
-try {
- Logger.prototype = console;
- (new Logger).groupEnd();
-} catch (e) {
- function getLogFunction(name) {
- return function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) {
- if (typeof console !== 'undefined') {
- switch (arguments.length) {
- case 0:
- console[name]();
- break;
- case 1:
- console[name](arg0);
- break;
- case 2:
- console[name](arg0, arg1);
- break;
- case 3:
- console[name](arg0, arg1, arg2);
- break
- case 4:
- console[name](arg0, arg1, arg2, arg3);
- break;
- case 5:
- console[name](arg0, arg1, arg2, arg3, arg4);
- break;
- case 6:
- console[name](arg0, arg1, arg2, arg3, arg4, arg5);
- break;
- case 7:
- console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6);
- break;
- case 7:
- console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
- break;
- case 8:
- console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
- break;
- case 9:
- console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
- break;
- case 10:
- console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
- break;
- default:
- break;
- }
+// ugly hack because IE doesn't support console.log.apply
+function getConsoleLogFunction(name) {
+ return function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) {
+ if (typeof console !== 'undefined') {
+ switch (arguments.length) {
+ case 0:
+ console[name]();
+ break;
+ case 1:
+ console[name](arg0);
+ break;
+ case 2:
+ console[name](arg0, arg1);
+ break;
+ case 3:
+ console[name](arg0, arg1, arg2);
+ break
+ case 4:
+ console[name](arg0, arg1, arg2, arg3);
+ break;
+ case 5:
+ console[name](arg0, arg1, arg2, arg3, arg4);
+ break;
+ case 6:
+ console[name](arg0, arg1, arg2, arg3, arg4, arg5);
+ break;
+ case 7:
+ console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
+ case 7:
+ console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ break;
+ case 8:
+ console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ break;
+ case 9:
+ console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+ break;
+ case 10:
+ console[name](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
+ break;
+ default:
+ break;
}
- };
- }
+ }
+ };
+}
- Logger.prototype = {
- error: getLogFunction('error'),
- warn: getLogFunction('warn'),
- info: getLogFunction('info'),
- debug: getLogFunction('log'),
- trace: getLogFunction('log')
+
+try {
+ ConsoleLogger.prototype = console;
+ (new ConsoleLogger).groupEnd(); // feature detection for ability to use the console object as a prototype
+} catch (e) {
+ ConsoleLogger.prototype = {
+ error: getConsoleLogFunction('error'),
+ warn: getConsoleLogFunction('warn'),
+ info: getConsoleLogFunction('info'),
+ debug: getConsoleLogFunction('log'),
+ trace: getConsoleLogFunction('log')
};
}
-module.exports = Logger;
+function getLogger(type) {
+ switch (type && type.toLowerCase()) {
+ case 'console':
+ return ConsoleLogger;
+ case 'url':
+ return UrlLogger;
+ default:
+ throw new Error('unknown logger type: ' + type);
+ }
+}
+
+module.exports = getLogger;
View
@@ -1,13 +1,13 @@
var parseConfig = require('./lib/parse-config');
var Bundle = require('./lib/bundle');
-function compilePackage(configOrPackageDir, env, bundleUrl) {
+function compileBundle(configOrBundleDir, env, bundleUrl) {
var config;
- if (typeof configOrPackageDir === 'string') {
- var packageDir = configOrPackageDir;
- config = parseConfig(packageDir, env, bundleUrl);
+ if (typeof configOrBundleDir === 'string') {
+ var bundleDir = configOrBundleDir;
+ config = parseConfig(bundleDir, env, bundleUrl);
} else {
- config = configOrPackageDir;
+ config = configOrBundleDir;
}
var bundle = new Bundle(config);
@@ -22,5 +22,5 @@ function compilePackage(configOrPackageDir, env, bundleUrl) {
exports.createDevCdn = require('./lib/dev-cdn');
exports.parseConfig = parseConfig;
exports.Bundle = Bundle;
-exports.compilePackage = compilePackage;
+exports.compileBundle = exports.compilePackage = compileBundle;
View
@@ -35,8 +35,11 @@
"loggerLevel": "warn", # Filter out all but "error" and "warn" logs in production mode (used by the logger filter).
+ "loggerUrl": # Report logs to an external URL (used by the logger filter).
+ "logging.png?m=",
+
"bundleUrl": # Exposed in your code as module.bundleUrl.
- "http://s3.amazonaws.com/example/bundle.js"
+ "//s3.amazonaws.com/example/bundle.js"
}
View
@@ -10,7 +10,7 @@
},
"main": "jsbundle.js",
"scripts": {
- "test": "find test -name \"test*.js\" | xargs node_modules/vows/bin/vows"
+ "test": "find test -name \"test*.js\" | xargs node_modules/vows/bin/vows && JSBUNDLE_ENV=production bin/jsbundle . > test/fixtures/browser-test.js && open test/fixtures/browser-test.html"
},
"bin": {
"devcdn": "./bin/devcdn",
View
@@ -1,5 +1,49 @@
#!/usr/bin/env node
+output = [];
+
+var numAssertions = 4;
+var numSuccesses = 0;
+
+function testResults() {
+ if (numSuccesses === numAssertions) {
+ log('all ' + numAssertions + ' tests passed!');
+ } else {
+ error(numSuccesses + ' / ' + numAssertions + ' tests passed');
+ }
+}
+
+function log(message, color) {
+ color = color || '#ada';
+ if (typeof document !== 'undefined') {
+ document.writeln('<pre style="background-color:' + color + '">' + message + '</pre>');
+ } else {
+ console.log(message);
+ output.push(message);
+ }
+}
+
+function error(message) {
+ log(message, '#daa');
+}
+
+function assert(isTrue, description) {
+ if (!isTrue) {
+ allAssertionsPassed = false;
+ error('assertion failed: ' + description);
+ } else {
+ numSuccesses++;
+ log('assertion succeeded: ' + description);
+ }
+}
+
+if (typeof window !== 'undefined') {
+ window.onerror = function(message, script, line) {
+ assert(false, 'window.onerror should not fire (got: ' + message + ' at ' + script + ':' + line + ')');
+ testResults();
+ }
+}
+
logger.
warn(
'this code executed!'
@@ -10,29 +54,22 @@ var def = require(
.js'
)();
-module.mock('xyz.js', { mock: true });
-module.mock('3', { mock: true });
-if (!require('./xyz.js').mock) {
- throw new Error('mocking failed');
-}
-module.unmock('xyz.js');
-module.unmock('3');
-if (require('./xyz.js').mock) {
- throw new Error('unmocking failed');
-}
+assert(def === 'output from module "def"', 'got output from module def');
-if (typeof alert !== 'undefined') {
- alert(def);
-} else {
- output = def;
- console.log(def);
-}
+module.mock('', { mock: true });
+assert(require('./xyz.js').mock, 'mocking works');
+module.unmock('');
+assert(!require('./xyz.js').mock, 'unmocking works');
if (typeof document !== 'undefined') {
var $ = require('./jquery');
- $('<h1>externalDependency works!</h1>').appendTo($('body'));
+ assert($, 'module.externalDependency works');
+} else {
+ numAssertions--;
}
require('./ghi.js');
+testResults();
+
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <script src="./browser-test.js"></script>
+ </head>
+ <body>
+ Running tests....
+ </body>
+</html>
View
Binary file not shown.
@@ -3,7 +3,8 @@ var assert = require('assert');
var path = require('path');
var vm = require('vm');
var jsbundle = require('../jsbundle');
-var PACKAGE_DIR = __dirname + '/fixtures/';
+var _ = require('underscore');
+var BUNDLE_DIR = __dirname + '/fixtures/';
function execute(code, env) {
env.global = env;
@@ -15,9 +16,9 @@ function execute(code, env) {
}
}
-vows.describe('package').addBatch({
+vows.describe('bundle').addBatch({
"no mangled names": {
- topic: jsbundle.compilePackage(PACKAGE_DIR),
+ topic: jsbundle.compileBundle(BUNDLE_DIR),
"find all modules": function(bundled) {
assert.equal(typeof bundled, 'string');
@@ -35,7 +36,9 @@ vows.describe('package').addBatch({
};
assert.equal(typeof bundled, 'string');
execute(bundled, env);
- assert.equal(env.output, 'output from module "def"');
+ _.each(env.output, function(outputLine) {
+ assert.match(outputLine, /^assertion succeeded:|^all \d+ tests passed/);
+ });
}
},
@@ -54,7 +57,9 @@ vows.describe('package').addBatch({
};
assert.equal(typeof bundled, 'string');
execute(bundled, env);
- assert.equal(env.output, 'output from module "def"');
+ _.each(env.output, function(outputLine) {
+ assert.match(outputLine, /^assertion succeeded:|^all \d+ tests passed/);
+ });
}
}
}).export(module);

0 comments on commit 62bf594

Please sign in to comment.