Skip to content

Commit

Permalink
fix: better serialization in dump/console.log
Browse files Browse the repository at this point in the history
Serialize functions, null, undefined, etc…

Closes #640
  • Loading branch information
vojtajina committed Jul 16, 2013
1 parent 9ea7626 commit fd46365
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 13 deletions.
8 changes: 6 additions & 2 deletions lib/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@ var Browser = function(id, collection, emitter) {
return;
}

// TODO(vojta): rename to log
// TODO(vojta): remove
if (helper.isDefined(info.dump)) {
emitter.emit('browser_dump', this, info.dump);
emitter.emit('browser_log', this, info.dump, 'dump');
}

if (helper.isDefined(info.log)) {
emitter.emit('browser_log', this, info.log, info.type);
}

if (helper.isDefined(info.total)) {
Expand Down
22 changes: 16 additions & 6 deletions lib/reporters/Base.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ var helper = require('../helper');
var BaseReporter = function(formatError, reportSlow, adapter) {
this.adapters = [adapter || process.stdout.write.bind(process.stdout)];

this.onRunStart = function(browsers) {
this._browsers = browsers;
};


this.renderBrowser = function(browser) {
var results = browser.lastResult;
Expand Down Expand Up @@ -55,14 +59,17 @@ var BaseReporter = function(formatError, reportSlow, adapter) {
};


this.onBrowserDump = function(browser, dump) {
if (dump.length === 1) {
dump = dump[0];
this.onBrowserLog = function(browser, log, type) {
if (!helper.isString(log)) {
// TODO(vojta): change util to new syntax (config object)
log = util.inspect(log, false, undefined, this.USE_COLORS);
}

// TODO(vojta): change util to new syntax (config object)
dump = util.inspect(dump, false, undefined, this.USE_COLORS);
this.writeCommonMsg(browser + ' LOG: ' + dump + '\n');
if (this._browsers && this._browsers.length === 1) {
this.writeCommonMsg(util.format(this.LOG_SINGLE_BROWSER, type.toUpperCase(), log));
} else {
this.writeCommonMsg(util.format(this.LOG_MULTI_BROWSER, browser, type.toUpperCase(), log));
}
};


Expand Down Expand Up @@ -111,6 +118,9 @@ var BaseReporter = function(formatError, reportSlow, adapter) {

this.USE_COLORS = false;

this.LOG_SINGLE_BROWSER = 'LOG: %s\n';
this.LOG_MULTI_BROWSER = '%s LOG: %s\n';

this.SPEC_FAILURE = '%s %s FAILED' + '\n';
this.SPEC_SLOW = '%s SLOW %s: %s\n';
this.ERROR = '%s ERROR\n';
Expand Down
3 changes: 3 additions & 0 deletions lib/reporters/BaseColor.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ require('colors');
var BaseColorReporter = function() {
this.USE_COLORS = true;

this.LOG_SINGLE_BROWSER = '%s: ' + '%s'.cyan + '\n';
this.LOG_MULTI_BROWSER = '%s %s: ' + '%s'.cyan + '\n';

this.SPEC_FAILURE = '%s %s FAILED'.red + '\n';
this.SPEC_SLOW = '%s SLOW %s: %s'.yellow + '\n';
this.ERROR = '%s ERROR'.red + '\n';
Expand Down
72 changes: 71 additions & 1 deletion static/karma.src.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,16 @@ socket.on('reconnecting', updateStatus('reconnecting in $ ms...'));
socket.on('reconnect', updateStatus('re-connected'));
socket.on('reconnect_failed', updateStatus('failed to reconnect'));

var instanceOf = function(value, constructorName) {
return Object.prototype.toString.apply(value) === '[object ' + constructorName + ']';
};

/* jshint unused: false */
var Karma = function(socket, context, navigator, location) {
var config;
var hasError = false;
var store = {};
var self = this;

this.VERSION = VERSION;

Expand Down Expand Up @@ -77,15 +82,80 @@ var Karma = function(socket, context, navigator, location) {
return;
}
localConsole[method] = function() {
contextWindow.__karma__.info({dump: Array.prototype.slice.call(arguments, 0)});
self.log(method, arguments);
return Function.prototype.apply.call(orig, localConsole, arguments);
};
};
for (var i = 0; i < logMethods.length; i++) {
patchConsoleMethod(logMethods[i]);
}

contextWindow.dump = function() {
self.log('dump', arguments);
};
};

this.log = function(type, args) {
var values = [];

for (var i = 0; i < args.length; i++) {
values.push(this.stringify(args[i], 3));
}

this.info({log: values.join(', '), type: type});
};

this.stringify = function(obj, depth) {

if (depth == 0) return '...';

if (obj === null) return 'null';

switch (typeof obj) {
case 'string':
return "'" + obj + "'";
case 'undefined':
return 'undefined';
case 'function':
return obj.toString().replace(/\{[\s\S]*\}/, '{ ... }');
case 'boolean':
return obj ? 'true' : 'false';
case 'object':
var strs = [];
if (instanceOf(obj, 'Array')) {
strs.push('[');
for (var i = 0, ii = obj.length; i < ii; i++) {
if (i) strs.push(', ');
strs.push(this.stringify(obj[i], depth - 1));
}
strs.push(']');
} else if (instanceOf(obj, 'Date')) {
return obj.toString();
} else if (instanceOf(obj, 'Text')) {
return obj.nodeValue;
} else if (instanceOf(obj, 'Comment')) {
return '<!--' + obj.nodeValue + '-->';
} else if (obj.outerHTML) {
return obj.outerHTML;
} else {
strs.push(obj.constructor.name);
strs.push('{');
var first = true;
for(var key in obj) {
if (obj.hasOwnProperty(key)) {
if (first) { first = false; } else { strs.push(', '); }
strs.push(key + ': ' + this.stringify(obj[key], depth - 1));
}
}
strs.push('}');
}
return strs.join('');
default:
return obj;
};
};


var clearContext = function() {
context.src = 'about:blank';
};
Expand Down
51 changes: 51 additions & 0 deletions test/client/testacular.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,55 @@ describe('karma', function() {
expect(tc.store('one.array')).not.toBe(array);
});
});


describe('stringify', function() {
it('should serialize string', function() {
expect(tc.stringify('aaa')).toBe("'aaa'");
});


it('should serialize booleans', function() {
expect(tc.stringify(true)).toBe('true');
expect(tc.stringify(false)).toBe('false');
});


it('should serialize null and undefined', function() {
expect(tc.stringify(null)).toBe('null');
expect(tc.stringify()).toBe('undefined');
});


it('should serialize functions', function() {
function abc(a, b, c) { return 'whatever'; }
var def = function(d, e, f) { return 'whatever'; };

expect(tc.stringify(abc)).toBe('function abc(a, b, c) { ... }');
expect(tc.stringify(def)).toBe('function (d, e, f) { ... }');
});


it('should serialize arrays', function() {
expect(tc.stringify(['a', 'b', null, true, false])).toBe("['a', 'b', null, true, false]");
});


it('should serialize html', function() {
var div = document.createElement('div');

expect(tc.stringify(div)).toBe('<div></div>');

div.innerHTML = 'some <span>text</span>';
expect(tc.stringify(div)).toBe('<div>some <span>text</span></div>');
});


it('should serialize across iframes', function() {
var div = document.createElement('div');
expect(__karma__.stringify(div)).toBe('<div></div>');

expect(__karma__.stringify([1, 2])).toBe('[1, 2]');
});
});
});
8 changes: 4 additions & 4 deletions test/unit/browser.spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ describe 'browser', ->
expect(browser.lastResult.total).to.equal 20


it 'should emit "browser_dump"', ->
it 'should emit "browser_log"', ->
spy = sinon.spy()
emitter.on 'browser_dump', spy
emitter.on 'browser_log', spy

browser.isReady = false
browser.onInfo {dump: 'something'}
expect(spy).to.have.been.calledWith browser, 'something'
browser.onInfo {log: 'something', type: 'info'}
expect(spy).to.have.been.calledWith browser, 'something', 'info'


it 'should ignore if browser not executing', ->
Expand Down

0 comments on commit fd46365

Please sign in to comment.