Merge branch 'master' into 3.0-features

This commit is contained in:
Steve Gravrock
2017-12-18 09:48:17 -08:00
9 changed files with 167 additions and 31 deletions

View File

@@ -1,17 +0,0 @@
languages:
JavaScript: true
ratings:
paths:
- "src/**/*.js"
exclude_paths:
- "spec/**/*.js"
- "lib/**"
- "dist/*"
- "grunt/**"
- "images/*"
- "**/*.md"
- "**/*.yml"
- "**/*.json"
- "**/*.scss"
- "**/*.erb"
- "*.sh"

View File

@@ -1,7 +1,6 @@
<a name="README">[<img src="https://rawgithub.com/jasmine/jasmine/master/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a> <a name="README">[<img src="https://rawgithub.com/jasmine/jasmine/master/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a>
[![Build Status](https://travis-ci.org/jasmine/jasmine.svg?branch=master)](https://travis-ci.org/jasmine/jasmine) [![Build Status](https://travis-ci.org/jasmine/jasmine.svg?branch=master)](https://travis-ci.org/jasmine/jasmine)
[![Code Climate](https://codeclimate.com/github/jasmine/jasmine.svg)](https://codeclimate.com/github/jasmine/jasmine)
# A JavaScript Testing Framework # A JavaScript Testing Framework

View File

@@ -140,14 +140,20 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
* Set this to a lower value to speed up pretty printing if you have large objects. * Set this to a lower value to speed up pretty printing if you have large objects.
* @name jasmine.MAX_PRETTY_PRINT_DEPTH * @name jasmine.MAX_PRETTY_PRINT_DEPTH
*/ */
j$.MAX_PRETTY_PRINT_DEPTH = 40; j$.MAX_PRETTY_PRINT_DEPTH = 8;
/** /**
* Maximum number of array elements to display when pretty printing objects. * Maximum number of array elements to display when pretty printing objects.
* This will also limit the number of keys and values displayed for an object. * This will also limit the number of keys and values displayed for an object.
* Elements past this number will be ellipised. * Elements past this number will be ellipised.
* @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH * @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH
*/ */
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 50;
/**
* Maximum number of charasters to display when pretty printing objects.
* Characters past this number will be ellipised.
* @name jasmine.MAX_PRETTY_PRINT_CHARS
*/
j$.MAX_PRETTY_PRINT_CHARS = 1000;
/** /**
* Default number of milliseconds Jasmine will wait for an asynchronous spec to complete. * Default number of milliseconds Jasmine will wait for an asynchronous spec to complete.
* @name jasmine.DEFAULT_TIMEOUT_INTERVAL * @name jasmine.DEFAULT_TIMEOUT_INTERVAL
@@ -4177,6 +4183,10 @@ getJasmineRequireObj().pp = function(j$) {
} else { } else {
this.emitScalar(value.toString()); this.emitScalar(value.toString());
} }
} catch (e) {
if (this.ppNestLevel_ > 1 || !(e instanceof MaxCharsReachedError)) {
throw e;
}
} finally { } finally {
this.ppNestLevel_--; this.ppNestLevel_--;
} }
@@ -4213,6 +4223,7 @@ getJasmineRequireObj().pp = function(j$) {
function StringPrettyPrinter() { function StringPrettyPrinter() {
PrettyPrinter.call(this); PrettyPrinter.call(this);
this.length = 0;
this.stringParts = []; this.stringParts = [];
} }
@@ -4368,9 +4379,31 @@ getJasmineRequireObj().pp = function(j$) {
}; };
StringPrettyPrinter.prototype.append = function(value) { StringPrettyPrinter.prototype.append = function(value) {
this.stringParts.push(value); var result = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length);
this.length += result.value.length;
this.stringParts.push(result.value);
if (result.truncated) {
throw new MaxCharsReachedError();
}
}; };
function truncate(s, maxlen) {
if (s.length <= maxlen) {
return { value: s, truncated: false };
}
s = s.substring(0, maxlen - 4) + ' ...';
return { value: s, truncated: true };
}
function MaxCharsReachedError() {
this.message = 'Exceeded ' + j$.MAX_PRETTY_PRINT_CHARS +
' characters while pretty-printing a value';
}
MaxCharsReachedError.prototype = new Error();
function keys(obj, isArray) { function keys(obj, isArray) {
var allKeys = Object.keys ? Object.keys(obj) : var allKeys = Object.keys ? Object.keys(obj) :
(function(o) { (function(o) {
@@ -4534,7 +4567,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
var maybeThenable = queueableFn.fn.call(self.userContext); var maybeThenable = queueableFn.fn.call(self.userContext);
if (maybeThenable && j$.isFunction_(maybeThenable.then)) { if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
maybeThenable.then(next, next.fail); maybeThenable.then(next, onPromiseRejection);
completedSynchronously = false; completedSynchronously = false;
return { completedSynchronously: false }; return { completedSynchronously: false };
} }
@@ -4556,6 +4589,11 @@ getJasmineRequireObj().QueueRunner = function(j$) {
errored = true; errored = true;
} }
function onPromiseRejection(e) {
onException(e);
next();
}
function handleException(e, queueableFn) { function handleException(e, queueableFn) {
onException(e); onException(e);
if (!self.catchException(e)) { if (!self.catchException(e)) {

View File

@@ -131,6 +131,41 @@ describe("jasmineUnderTest.pp", function () {
} }
}); });
function withMaxChars(maxChars, fn) {
var originalMaxChars = jasmineUnderTest.MAX_PRETTY_PRINT_CHARS;
try {
jasmineUnderTest.MAX_PRETTY_PRINT_CHARS = maxChars;
fn();
} finally {
jasmineUnderTest.MAX_PRETTY_PRINT_CHARS = originalMaxChars;
}
}
it("should truncate outputs that are too long", function() {
var big = [
{ a: 1, b: "a long string" },
{}
];
withMaxChars(34, function() {
expect(jasmineUnderTest.pp(big)).toEqual("[ Object({ a: 1, b: 'a long st ...");
});
});
it("should not serialize more objects after hitting MAX_PRETTY_PRINT_CHARS", function() {
var a = { jasmineToString: function() { return 'object a'; } },
b = { jasmineToString: function() { return 'object b'; } },
c = { jasmineToString: jasmine.createSpy('c jasmineToString').and.returnValue('') },
d = { jasmineToString: jasmine.createSpy('d jasmineToString').and.returnValue('') };
withMaxChars(30, function() {
jasmineUnderTest.pp([{a: a, b: b, c: c}, d]);
expect(c.jasmineToString).not.toHaveBeenCalled();
expect(d.jasmineToString).not.toHaveBeenCalled();
});
});
it("should print 'null' as the constructor of an object with its own constructor property", function() { it("should print 'null' as the constructor of an object with its own constructor property", function() {
expect(jasmineUnderTest.pp({constructor: function() {}})).toContain("null({"); expect(jasmineUnderTest.pp({constructor: function() {}})).toContain("null({");
expect(jasmineUnderTest.pp({constructor: 'foo'})).toContain("null({"); expect(jasmineUnderTest.pp({constructor: 'foo'})).toContain("null({");

View File

@@ -375,27 +375,30 @@ describe("QueueRunner", function() {
expect(onComplete).toHaveBeenCalled(); expect(onComplete).toHaveBeenCalled();
}); });
it("fails the function when the promise is rejected", function() { it("handles a rejected promise like an unhandled exception", function() {
var promise = new StubPromise(), var promise = new StubPromise(),
queueableFn1 = { fn: function() { queueableFn1 = { fn: function() {
setTimeout(function() { promise.rejectHandler('foo'); }, 100); setTimeout(function() {
promise.rejectHandler('foo')
}, 100);
return promise; return promise;
} }, } },
queueableFn2 = { fn: jasmine.createSpy('fn2') }, queueableFn2 = { fn: jasmine.createSpy('fn2') },
failFn = jasmine.createSpy('fail'), failFn = jasmine.createSpy('fail'),
onExceptionCallback = jasmine.createSpy('on exception callback'),
queueRunner = new jasmineUnderTest.QueueRunner({ queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2], queueableFns: [queueableFn1, queueableFn2],
fail: failFn onException: onExceptionCallback
}); });
queueRunner.execute(); queueRunner.execute();
expect(failFn).not.toHaveBeenCalled(); expect(onExceptionCallback).not.toHaveBeenCalled();
expect(queueableFn2.fn).not.toHaveBeenCalled(); expect(queueableFn2.fn).not.toHaveBeenCalled();
jasmine.clock().tick(100); jasmine.clock().tick(100);
expect(failFn).toHaveBeenCalledWith('foo'); expect(onExceptionCallback).toHaveBeenCalledWith('foo');
expect(queueableFn2.fn).toHaveBeenCalled(); expect(queueableFn2.fn).toHaveBeenCalled();
}); });
}); });

View File

@@ -1530,6 +1530,7 @@ describe("Env integration", function() {
reporter.jasmineDone.and.callFake(function() { reporter.jasmineDone.and.callFake(function() {
var specStatus = reporter.specDone.calls.argsFor(0)[0]; var specStatus = reporter.specDone.calls.argsFor(0)[0];
expect(specStatus.status).toBe('pending');
expect(specStatus.pendingReason).toBe('with a message'); expect(specStatus.pendingReason).toBe('with a message');
done(); done();
@@ -1544,6 +1545,45 @@ describe("Env integration", function() {
env.execute(); env.execute();
}); });
it('should report pending spec messages from promise-returning functions', function(done) {
function StubPromise(fn) {
try {
fn();
} catch (e) {
this.exception = e;
}
}
StubPromise.prototype.then = function(resolve, reject) {
reject(this.exception);
};
var env = new jasmineUnderTest.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
'specDone',
'jasmineDone'
]);
reporter.jasmineDone.and.callFake(function() {
var specStatus = reporter.specDone.calls.argsFor(0)[0];
expect(specStatus.status).toBe('pending');
expect(specStatus.pendingReason).toBe('with a message');
done();
});
env.addReporter(reporter);
env.it('will be pending', function() {
return new StubPromise(function() {
env.pending('with a message');
});
});
env.execute();
});
it('should report using fallback reporter', function(done) { it('should report using fallback reporter', function(done) {
var env = new jasmineUnderTest.Env(), var env = new jasmineUnderTest.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [ reporter = jasmine.createSpyObj('fakeReporter', [

View File

@@ -59,6 +59,10 @@ getJasmineRequireObj().pp = function(j$) {
} else { } else {
this.emitScalar(value.toString()); this.emitScalar(value.toString());
} }
} catch (e) {
if (this.ppNestLevel_ > 1 || !(e instanceof MaxCharsReachedError)) {
throw e;
}
} finally { } finally {
this.ppNestLevel_--; this.ppNestLevel_--;
} }
@@ -95,6 +99,7 @@ getJasmineRequireObj().pp = function(j$) {
function StringPrettyPrinter() { function StringPrettyPrinter() {
PrettyPrinter.call(this); PrettyPrinter.call(this);
this.length = 0;
this.stringParts = []; this.stringParts = [];
} }
@@ -250,9 +255,31 @@ getJasmineRequireObj().pp = function(j$) {
}; };
StringPrettyPrinter.prototype.append = function(value) { StringPrettyPrinter.prototype.append = function(value) {
this.stringParts.push(value); var result = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length);
this.length += result.value.length;
this.stringParts.push(result.value);
if (result.truncated) {
throw new MaxCharsReachedError();
}
}; };
function truncate(s, maxlen) {
if (s.length <= maxlen) {
return { value: s, truncated: false };
}
s = s.substring(0, maxlen - 4) + ' ...';
return { value: s, truncated: true };
}
function MaxCharsReachedError() {
this.message = 'Exceeded ' + j$.MAX_PRETTY_PRINT_CHARS +
' characters while pretty-printing a value';
}
MaxCharsReachedError.prototype = new Error();
function keys(obj, isArray) { function keys(obj, isArray) {
var allKeys = Object.keys ? Object.keys(obj) : var allKeys = Object.keys ? Object.keys(obj) :
(function(o) { (function(o) {

View File

@@ -125,7 +125,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
var maybeThenable = queueableFn.fn.call(self.userContext); var maybeThenable = queueableFn.fn.call(self.userContext);
if (maybeThenable && j$.isFunction_(maybeThenable.then)) { if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
maybeThenable.then(next, next.fail); maybeThenable.then(next, onPromiseRejection);
completedSynchronously = false; completedSynchronously = false;
return { completedSynchronously: false }; return { completedSynchronously: false };
} }
@@ -147,6 +147,11 @@ getJasmineRequireObj().QueueRunner = function(j$) {
errored = true; errored = true;
} }
function onPromiseRejection(e) {
onException(e);
next();
}
function handleException(e, queueableFn) { function handleException(e, queueableFn) {
onException(e); onException(e);
if (!self.catchException(e)) { if (!self.catchException(e)) {

View File

@@ -8,14 +8,20 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
* Set this to a lower value to speed up pretty printing if you have large objects. * Set this to a lower value to speed up pretty printing if you have large objects.
* @name jasmine.MAX_PRETTY_PRINT_DEPTH * @name jasmine.MAX_PRETTY_PRINT_DEPTH
*/ */
j$.MAX_PRETTY_PRINT_DEPTH = 40; j$.MAX_PRETTY_PRINT_DEPTH = 8;
/** /**
* Maximum number of array elements to display when pretty printing objects. * Maximum number of array elements to display when pretty printing objects.
* This will also limit the number of keys and values displayed for an object. * This will also limit the number of keys and values displayed for an object.
* Elements past this number will be ellipised. * Elements past this number will be ellipised.
* @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH * @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH
*/ */
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 50;
/**
* Maximum number of charasters to display when pretty printing objects.
* Characters past this number will be ellipised.
* @name jasmine.MAX_PRETTY_PRINT_CHARS
*/
j$.MAX_PRETTY_PRINT_CHARS = 1000;
/** /**
* Default number of milliseconds Jasmine will wait for an asynchronous spec to complete. * Default number of milliseconds Jasmine will wait for an asynchronous spec to complete.
* @name jasmine.DEFAULT_TIMEOUT_INTERVAL * @name jasmine.DEFAULT_TIMEOUT_INTERVAL