Merge branch 'master' into 3.0-features
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2008-2017 Pivotal Labs
|
||||
Copyright (c) 2008-2018 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2008-2017 Pivotal Labs
|
||||
Copyright (c) 2008-2018 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -35,6 +35,46 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
elapsed: function() { return 0; }
|
||||
};
|
||||
|
||||
function ResultsStateBuilder() {
|
||||
this.topResults = new j$.ResultsNode({}, '', null);
|
||||
this.currentParent = this.topResults;
|
||||
this.specsExecuted = 0;
|
||||
this.failureCount = 0;
|
||||
this.pendingSpecCount = 0;
|
||||
}
|
||||
|
||||
ResultsStateBuilder.prototype.suiteStarted = function(result) {
|
||||
this.currentParent.addChild(result, 'suite');
|
||||
this.currentParent = this.currentParent.last();
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.suiteDone = function(result) {
|
||||
if (this.currentParent !== this.topResults) {
|
||||
this.currentParent = this.currentParent.parent;
|
||||
}
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.specStarted = function(result) {
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.specDone = function(result) {
|
||||
this.currentParent.addChild(result, 'spec');
|
||||
|
||||
if (result.status !== 'disabled') {
|
||||
this.specsExecuted++;
|
||||
}
|
||||
|
||||
if (result.status === 'failed') {
|
||||
this.failureCount++;
|
||||
}
|
||||
|
||||
if (result.status == 'pending') {
|
||||
this.pendingSpecCount++;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
function HtmlReporter(options) {
|
||||
var env = options.env || {},
|
||||
getContainer = options.getContainer,
|
||||
@@ -47,9 +87,6 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
filterSpecs = options.filterSpecs,
|
||||
timer = options.timer || noopTimer,
|
||||
results = [],
|
||||
specsExecuted = 0,
|
||||
failureCount = 0,
|
||||
pendingSpecCount = 0,
|
||||
htmlReporterMain,
|
||||
symbols,
|
||||
failedSuites = [];
|
||||
@@ -78,12 +115,10 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
var summary = createDom('div', {className: 'jasmine-summary'});
|
||||
|
||||
var topResults = new j$.ResultsNode({}, '', null),
|
||||
currentParent = topResults;
|
||||
var stateBuilder = new ResultsStateBuilder();
|
||||
|
||||
this.suiteStarted = function(result) {
|
||||
currentParent.addChild(result, 'suite');
|
||||
currentParent = currentParent.last();
|
||||
stateBuilder.suiteStarted(result);
|
||||
};
|
||||
|
||||
this.suiteDone = function(result) {
|
||||
@@ -91,27 +126,21 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
failedSuites.push(result);
|
||||
}
|
||||
|
||||
if (currentParent == topResults) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentParent = currentParent.parent;
|
||||
stateBuilder.suiteDone(result);
|
||||
};
|
||||
|
||||
this.specStarted = function(result) {
|
||||
currentParent.addChild(result, 'spec');
|
||||
stateBuilder.specStarted(result);
|
||||
};
|
||||
|
||||
var failures = [];
|
||||
this.specDone = function(result) {
|
||||
stateBuilder.specDone(result);
|
||||
|
||||
if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') {
|
||||
console.error('Spec \'' + result.fullName + '\' has no expectations.');
|
||||
}
|
||||
|
||||
if (result.status != 'disabled') {
|
||||
specsExecuted++;
|
||||
}
|
||||
|
||||
if (!symbols){
|
||||
symbols = find('.jasmine-symbol-summary');
|
||||
}
|
||||
@@ -124,11 +153,9 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
));
|
||||
|
||||
if (result.status == 'failed') {
|
||||
failureCount++;
|
||||
|
||||
var failure =
|
||||
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
|
||||
failureDescription(result, currentParent),
|
||||
failureDescription(result, stateBuilder.currentParent),
|
||||
createDom('div', {className: 'jasmine-messages'})
|
||||
);
|
||||
var messages = failure.childNodes[1];
|
||||
@@ -141,10 +168,6 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
failures.push(failure);
|
||||
}
|
||||
|
||||
if (result.status == 'pending') {
|
||||
pendingSpecCount++;
|
||||
}
|
||||
};
|
||||
|
||||
this.jasmineDone = function(doneResult) {
|
||||
@@ -207,8 +230,8 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
if (specsExecuted < totalSpecsDefined) {
|
||||
var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
|
||||
if (stateBuilder.specsExecuted < totalSpecsDefined) {
|
||||
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
|
||||
var skippedLink = addToExistingQueryString('spec', '');
|
||||
alert.appendChild(
|
||||
createDom('span', {className: 'jasmine-bar jasmine-skipped'},
|
||||
@@ -219,11 +242,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
var statusBarMessage = '';
|
||||
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
|
||||
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
|
||||
var failed = failureCount + globalFailures.length + failedSuites.length > 0;
|
||||
var failed = stateBuilder.failureCount + globalFailures.length + failedSuites.length > 0;
|
||||
|
||||
if (totalSpecsDefined > 0 || failed) {
|
||||
statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount);
|
||||
if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); }
|
||||
statusBarMessage += pluralize('spec', stateBuilder.specsExecuted) + ', ' + pluralize('failure', stateBuilder.failureCount);
|
||||
if (stateBuilder.pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', stateBuilder.pendingSpecCount); }
|
||||
}
|
||||
|
||||
if (doneResult.overallStatus === 'passed') {
|
||||
@@ -276,7 +299,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
var results = find('.jasmine-results');
|
||||
results.appendChild(summary);
|
||||
|
||||
summaryList(topResults, summary);
|
||||
summaryList(stateBuilder.topResults, summary);
|
||||
|
||||
function summaryList(resultsTree, domParent) {
|
||||
var specListNode;
|
||||
|
||||
@@ -34,7 +34,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') {
|
||||
jasmineGlobal = window;
|
||||
}
|
||||
jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {};
|
||||
jasmineRequire = jasmineGlobal.jasmineRequire = {};
|
||||
}
|
||||
|
||||
function getJasmineRequire() {
|
||||
@@ -54,7 +54,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
j$.MockDate = jRequire.MockDate();
|
||||
j$.getClearStack = jRequire.clearStack(j$);
|
||||
j$.Clock = jRequire.Clock();
|
||||
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
|
||||
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(j$);
|
||||
j$.Env = jRequire.Env(j$);
|
||||
j$.StackTrace = jRequire.StackTrace(j$);
|
||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
|
||||
@@ -1951,6 +1951,9 @@ getJasmineRequireObj().clearStack = function(j$) {
|
||||
};
|
||||
|
||||
getJasmineRequireObj().Clock = function() {
|
||||
|
||||
var NODE_JS = typeof process !== 'undefined' && process.versions && typeof process.versions.node === 'string';
|
||||
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, Jasmine will make one during booting. You can get the current clock with {@link jasmine.clock}.
|
||||
* @class Clock
|
||||
@@ -1974,6 +1977,7 @@ getJasmineRequireObj().Clock = function() {
|
||||
delayedFunctionScheduler,
|
||||
timer;
|
||||
|
||||
self.FakeTimeout = FakeTimeout;
|
||||
|
||||
/**
|
||||
* Install the mock clock over the built-in methods.
|
||||
@@ -2080,7 +2084,15 @@ getJasmineRequireObj().Clock = function() {
|
||||
}
|
||||
|
||||
function setTimeout(fn, delay) {
|
||||
return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2));
|
||||
if (!NODE_JS) {
|
||||
return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2));
|
||||
}
|
||||
|
||||
var timeout = new FakeTimeout();
|
||||
|
||||
delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2), false, timeout);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
function clearTimeout(id) {
|
||||
@@ -2088,7 +2100,15 @@ getJasmineRequireObj().Clock = function() {
|
||||
}
|
||||
|
||||
function setInterval(fn, interval) {
|
||||
return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
|
||||
if (!NODE_JS) {
|
||||
return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
|
||||
}
|
||||
|
||||
var timeout = new FakeTimeout();
|
||||
|
||||
delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true, timeout);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
function clearInterval(id) {
|
||||
@@ -2100,16 +2120,30 @@ getJasmineRequireObj().Clock = function() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks Node.js Timeout class
|
||||
*/
|
||||
function FakeTimeout() {}
|
||||
|
||||
FakeTimeout.prototype.ref = function () {
|
||||
return this;
|
||||
};
|
||||
|
||||
FakeTimeout.prototype.unref = function () {
|
||||
return this;
|
||||
};
|
||||
|
||||
return Clock;
|
||||
};
|
||||
|
||||
getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
|
||||
function DelayedFunctionScheduler() {
|
||||
var self = this;
|
||||
var scheduledLookup = [];
|
||||
var scheduledFunctions = {};
|
||||
var currentTime = 0;
|
||||
var delayedFnCount = 0;
|
||||
var deletedKeys = [];
|
||||
|
||||
self.tick = function(millis, tickDate) {
|
||||
millis = millis || 0;
|
||||
@@ -2156,6 +2190,8 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
};
|
||||
|
||||
self.removeFunctionWithId = function(timeoutKey) {
|
||||
deletedKeys.push(timeoutKey);
|
||||
|
||||
for (var runAtMillis in scheduledFunctions) {
|
||||
var funcs = scheduledFunctions[runAtMillis];
|
||||
var i = indexOfFirstToPass(funcs, function (func) {
|
||||
@@ -2232,6 +2268,7 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
currentTime = newCurrentTime;
|
||||
|
||||
var funcsToRun = scheduledFunctions[currentTime];
|
||||
|
||||
delete scheduledFunctions[currentTime];
|
||||
|
||||
forEachFunction(funcsToRun, function(funcToRun) {
|
||||
@@ -2241,8 +2278,13 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
});
|
||||
|
||||
forEachFunction(funcsToRun, function(funcToRun) {
|
||||
if (j$.util.arrayContains(deletedKeys, funcToRun.timeoutKey)) {
|
||||
// skip a timeoutKey deleted whilst we were running
|
||||
return;
|
||||
}
|
||||
funcToRun.funcToCall.apply(null, funcToRun.params || []);
|
||||
});
|
||||
deletedKeys = [];
|
||||
} while (scheduledLookup.length > 0 &&
|
||||
// checking first if we're out of time prevents setTimeout(0)
|
||||
// scheduled in a funcToRun from forcing an extra iteration
|
||||
@@ -4127,6 +4169,8 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
function PrettyPrinter() {
|
||||
this.ppNestLevel_ = 0;
|
||||
this.seen = [];
|
||||
this.length = 0;
|
||||
this.stringParts = [];
|
||||
}
|
||||
|
||||
function hasCustomToString(value) {
|
||||
@@ -4212,32 +4256,15 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
return objKeys.length > length;
|
||||
};
|
||||
|
||||
PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitSet = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitMap = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitString = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitDomElement = j$.unimplementedMethod_;
|
||||
|
||||
function StringPrettyPrinter() {
|
||||
PrettyPrinter.call(this);
|
||||
|
||||
this.length = 0;
|
||||
this.stringParts = [];
|
||||
}
|
||||
|
||||
j$.util.inherit(StringPrettyPrinter, PrettyPrinter);
|
||||
|
||||
StringPrettyPrinter.prototype.emitScalar = function(value) {
|
||||
PrettyPrinter.prototype.emitScalar = function(value) {
|
||||
this.append(value);
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitString = function(value) {
|
||||
PrettyPrinter.prototype.emitString = function(value) {
|
||||
this.append('\'' + value + '\'');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitArray = function(array) {
|
||||
PrettyPrinter.prototype.emitArray = function(array) {
|
||||
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
|
||||
this.append('Array');
|
||||
return;
|
||||
@@ -4271,7 +4298,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' ]');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitSet = function(set) {
|
||||
PrettyPrinter.prototype.emitSet = function(set) {
|
||||
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
|
||||
this.append('Set');
|
||||
return;
|
||||
@@ -4291,7 +4318,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' )');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitMap = function(map) {
|
||||
PrettyPrinter.prototype.emitMap = function(map) {
|
||||
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
|
||||
this.append('Map');
|
||||
return;
|
||||
@@ -4311,7 +4338,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' )');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitObject = function(obj) {
|
||||
PrettyPrinter.prototype.emitObject = function(obj) {
|
||||
var ctor = obj.constructor,
|
||||
constructorName;
|
||||
|
||||
@@ -4344,7 +4371,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' })');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitTypedArray = function(arr) {
|
||||
PrettyPrinter.prototype.emitTypedArray = function(arr) {
|
||||
var constructorName = j$.fnNameFor(arr.constructor),
|
||||
limitedArray = Array.prototype.slice.call(arr, 0, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH),
|
||||
itemsString = Array.prototype.join.call(limitedArray, ', ');
|
||||
@@ -4356,7 +4383,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(constructorName + ' [ ' + itemsString + ' ]');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitDomElement = function(el) {
|
||||
PrettyPrinter.prototype.emitDomElement = function(el) {
|
||||
var closingTag = '</' + el.tagName.toLowerCase() + '>';
|
||||
|
||||
if (el.innerHTML === '') {
|
||||
@@ -4368,7 +4395,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {
|
||||
PrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {
|
||||
this.append(property);
|
||||
this.append(': ');
|
||||
if (isGetter) {
|
||||
@@ -4378,7 +4405,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.append = function(value) {
|
||||
PrettyPrinter.prototype.append = function(value) {
|
||||
var result = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length);
|
||||
this.length += result.value.length;
|
||||
this.stringParts.push(result.value);
|
||||
@@ -4388,6 +4415,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function truncate(s, maxlen) {
|
||||
if (s.length <= maxlen) {
|
||||
return { value: s, truncated: false };
|
||||
@@ -4434,9 +4462,9 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
return extraKeys;
|
||||
}
|
||||
return function(value) {
|
||||
var stringPrettyPrinter = new StringPrettyPrinter();
|
||||
stringPrettyPrinter.format(value);
|
||||
return stringPrettyPrinter.stringParts.join('');
|
||||
var prettyPrinter = new PrettyPrinter();
|
||||
prettyPrinter.format(value);
|
||||
return prettyPrinter.stringParts.join('');
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5086,6 +5114,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
|
||||
function SpyRegistry(options) {
|
||||
options = options || {};
|
||||
var global = options.global || j$.getGlobal();
|
||||
var currentSpies = options.currentSpies || function() { return []; };
|
||||
|
||||
this.allowRespy = function(allow){
|
||||
@@ -5124,7 +5153,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
spiedMethod = j$.createSpy(methodName, originalMethod),
|
||||
restoreStrategy;
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(obj, methodName)) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, methodName) || (obj === global && methodName === 'onerror')) {
|
||||
restoreStrategy = function() {
|
||||
obj[methodName] = originalMethod;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2008-2017 Pivotal Labs
|
||||
Copyright (c) 2008-2018 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
describe("Clock", function() {
|
||||
|
||||
var NODE_JS = typeof process !== 'undefined' && process.versions && typeof process.versions.node === 'string';
|
||||
|
||||
it("does not replace setTimeout until it is installed", function() {
|
||||
var fakeSetTimeout = jasmine.createSpy("global setTimeout"),
|
||||
fakeGlobal = { setTimeout: fakeSetTimeout },
|
||||
@@ -294,13 +296,19 @@ describe("Clock", function() {
|
||||
fakeGlobal = { setTimeout: fakeSetTimeout },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
|
||||
clock = new jasmineUnderTest.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
|
||||
clock = new jasmineUnderTest.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
|
||||
timeout = new clock.FakeTimeout();
|
||||
|
||||
clock.install();
|
||||
clock.setTimeout(delayedFn, 0, 'a', 'b');
|
||||
|
||||
expect(fakeSetTimeout).not.toHaveBeenCalled();
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b']);
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b']);
|
||||
} else {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b'], false, timeout);
|
||||
}
|
||||
});
|
||||
|
||||
it("returns an id for the delayed function", function() {
|
||||
@@ -312,12 +320,16 @@ describe("Clock", function() {
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
|
||||
clock = new jasmineUnderTest.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
|
||||
timeoutId;
|
||||
timeout;
|
||||
|
||||
clock.install();
|
||||
timeoutId = clock.setTimeout(delayedFn, 0);
|
||||
timeout = clock.setTimeout(delayedFn, 0);
|
||||
|
||||
expect(timeoutId).toEqual(123);
|
||||
if (!NODE_JS) {
|
||||
expect(timeout).toEqual(123);
|
||||
} else {
|
||||
expect(timeout.constructor.name).toEqual('FakeTimeout');
|
||||
}
|
||||
});
|
||||
|
||||
it("clears the scheduled function with the scheduler", function() {
|
||||
@@ -342,13 +354,19 @@ describe("Clock", function() {
|
||||
fakeGlobal = { setInterval: fakeSetInterval },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
|
||||
clock = new jasmineUnderTest.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
|
||||
clock = new jasmineUnderTest.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
|
||||
timeout = new clock.FakeTimeout;
|
||||
|
||||
clock.install();
|
||||
clock.setInterval(delayedFn, 0, 'a', 'b');
|
||||
|
||||
expect(fakeSetInterval).not.toHaveBeenCalled();
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b'], true);
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b'], true);
|
||||
} else {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b'], true, timeout);
|
||||
}
|
||||
});
|
||||
|
||||
it("returns an id for the delayed function", function() {
|
||||
@@ -360,12 +378,16 @@ describe("Clock", function() {
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
|
||||
clock = new jasmineUnderTest.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
|
||||
intervalId;
|
||||
interval;
|
||||
|
||||
clock.install();
|
||||
intervalId = clock.setInterval(delayedFn, 0);
|
||||
interval = clock.setInterval(delayedFn, 0);
|
||||
|
||||
expect(intervalId).toEqual(123);
|
||||
if (!NODE_JS) {
|
||||
expect(interval).toEqual(123);
|
||||
} else {
|
||||
expect(interval.constructor.name).toEqual('FakeTimeout');
|
||||
}
|
||||
});
|
||||
|
||||
it("clears the scheduled function with the scheduler", function() {
|
||||
@@ -648,4 +670,41 @@ describe("Clock (acceptance)", function() {
|
||||
|
||||
expect(actualTimes).toEqual([baseTime.getTime(), baseTime.getTime() + 1, baseTime.getTime() + 3]);
|
||||
})
|
||||
|
||||
it('correctly clears a scheduled timeout while the Clock is advancing', function () {
|
||||
var delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
global = {Date: Date, setTimeout: undefined},
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(global, function () { return delayedFunctionScheduler; }, mockDate);
|
||||
|
||||
clock.install();
|
||||
|
||||
var timerId2;
|
||||
|
||||
global.setTimeout(function () {
|
||||
global.clearTimeout(timerId2);
|
||||
}, 100);
|
||||
|
||||
timerId2 = global.setTimeout(fail, 100);
|
||||
|
||||
clock.tick(100);
|
||||
});
|
||||
|
||||
it('correctly clears a scheduled interval while the Clock is advancing', function () {
|
||||
var delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
global = {Date: Date, setTimeout: undefined},
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(global, function () { return delayedFunctionScheduler; }, mockDate);
|
||||
|
||||
clock.install();
|
||||
|
||||
var timerId2;
|
||||
var timerId1 = global.setInterval(function () {
|
||||
global.clearInterval(timerId2);
|
||||
}, 100);
|
||||
|
||||
timerId2 = global.setInterval(fail, 100);
|
||||
|
||||
clock.tick(400);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -216,21 +216,23 @@ describe("DelayedFunctionScheduler", function() {
|
||||
|
||||
it("removes functions during a tick that runs the function", function() {
|
||||
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
spy = jasmine.createSpy('fn'),
|
||||
spyAndRemove = jasmine.createSpy('fn'),
|
||||
fnDelay = 10,
|
||||
timeoutKey;
|
||||
|
||||
timeoutKey = scheduler.scheduleFunction(fn, fnDelay, [], true);
|
||||
scheduler.scheduleFunction(function () {
|
||||
spyAndRemove.and.callFake(function() {
|
||||
scheduler.removeFunctionWithId(timeoutKey);
|
||||
}, 2 * fnDelay);
|
||||
});
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
scheduler.scheduleFunction(spyAndRemove, fnDelay);
|
||||
|
||||
scheduler.tick(3 * fnDelay);
|
||||
timeoutKey = scheduler.scheduleFunction(spy, fnDelay, [], true);
|
||||
|
||||
expect(fn).toHaveBeenCalled();
|
||||
expect(fn.calls.count()).toBe(2);
|
||||
scheduler.tick(2 * fnDelay);
|
||||
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(spyAndRemove).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("removes functions during the first tick that runs the function", function() {
|
||||
|
||||
@@ -275,6 +275,24 @@ describe("SpyRegistry", function() {
|
||||
|
||||
expect(jasmineUnderTest.isSpy(subject.spiedFunc)).toBe(false);
|
||||
});
|
||||
|
||||
it("restores window.onerror by overwriting, not deleting", function() {
|
||||
function FakeWindow() {
|
||||
}
|
||||
FakeWindow.prototype.onerror = function() {};
|
||||
|
||||
var spies = [],
|
||||
global = new FakeWindow(),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
global: global
|
||||
});
|
||||
|
||||
spyRegistry.spyOn(global, 'onerror');
|
||||
spyRegistry.clearSpies();
|
||||
expect(global.onerror).toBe(FakeWindow.prototype.onerror);
|
||||
expect(global.hasOwnProperty('onerror')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('spying on properties', function() {
|
||||
|
||||
@@ -241,7 +241,7 @@ describe("HtmlReporter", function() {
|
||||
});
|
||||
|
||||
describe("when Jasmine is done", function() {
|
||||
it("adds EMPTY to the link title of specs that have no expectations", function() {
|
||||
it("adds a warning to the link title of specs that have no expectations", function() {
|
||||
if (!window.console) {
|
||||
window.console = { error: function(){} };
|
||||
}
|
||||
@@ -260,7 +260,7 @@ describe("HtmlReporter", function() {
|
||||
reporter.initialize();
|
||||
reporter.jasmineStarted({});
|
||||
reporter.suiteStarted({id: 1});
|
||||
reporter.specStarted({id: 1, status: 'passed', passedExpectations: [], failedExpectations: []});
|
||||
reporter.specStarted({id: 1, passedExpectations: [], failedExpectations: []});
|
||||
reporter.specDone({
|
||||
id: 1,
|
||||
status: 'passed',
|
||||
|
||||
34
spec/html/SpyRegistryHtmlSpec.js
Normal file
34
spec/html/SpyRegistryHtmlSpec.js
Normal file
@@ -0,0 +1,34 @@
|
||||
describe('Spy Registry browser-specific behavior', function() {
|
||||
it('can spy on and unspy window.onerror', function() {
|
||||
requireWriteableOnerror();
|
||||
|
||||
var spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
global: window
|
||||
}),
|
||||
originalHandler = window.onerror;
|
||||
|
||||
try {
|
||||
spyRegistry.spyOn(window, 'onerror');
|
||||
spyRegistry.clearSpies();
|
||||
expect(window.onerror).toBe(originalHandler);
|
||||
} finally {
|
||||
window.onerror = originalHandler;
|
||||
}
|
||||
});
|
||||
|
||||
function requireWriteableOnerror() {
|
||||
var descriptor;
|
||||
|
||||
try {
|
||||
descriptor = Object.getOwnPropertyDescriptor(window, 'onerror');
|
||||
} catch(e) {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
}
|
||||
|
||||
if (descriptor && !(descriptor.writable || descriptor.set)) {
|
||||
pending('Browser declares window.onerror to be readonly');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -3,6 +3,7 @@
|
||||
src_dir:
|
||||
- 'src'
|
||||
src_files:
|
||||
- 'core/requireCore.js'
|
||||
- 'core/base.js'
|
||||
- 'core/util.js'
|
||||
#end of known dependencies
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
getJasmineRequireObj().Clock = function() {
|
||||
|
||||
var NODE_JS = typeof process !== 'undefined' && process.versions && typeof process.versions.node === 'string';
|
||||
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, Jasmine will make one during booting. You can get the current clock with {@link jasmine.clock}.
|
||||
* @class Clock
|
||||
@@ -22,6 +25,7 @@ getJasmineRequireObj().Clock = function() {
|
||||
delayedFunctionScheduler,
|
||||
timer;
|
||||
|
||||
self.FakeTimeout = FakeTimeout;
|
||||
|
||||
/**
|
||||
* Install the mock clock over the built-in methods.
|
||||
@@ -128,7 +132,15 @@ getJasmineRequireObj().Clock = function() {
|
||||
}
|
||||
|
||||
function setTimeout(fn, delay) {
|
||||
return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2));
|
||||
if (!NODE_JS) {
|
||||
return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2));
|
||||
}
|
||||
|
||||
var timeout = new FakeTimeout();
|
||||
|
||||
delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2), false, timeout);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
function clearTimeout(id) {
|
||||
@@ -136,7 +148,15 @@ getJasmineRequireObj().Clock = function() {
|
||||
}
|
||||
|
||||
function setInterval(fn, interval) {
|
||||
return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
|
||||
if (!NODE_JS) {
|
||||
return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
|
||||
}
|
||||
|
||||
var timeout = new FakeTimeout();
|
||||
|
||||
delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true, timeout);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
function clearInterval(id) {
|
||||
@@ -148,5 +168,18 @@ getJasmineRequireObj().Clock = function() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks Node.js Timeout class
|
||||
*/
|
||||
function FakeTimeout() {}
|
||||
|
||||
FakeTimeout.prototype.ref = function () {
|
||||
return this;
|
||||
};
|
||||
|
||||
FakeTimeout.prototype.unref = function () {
|
||||
return this;
|
||||
};
|
||||
|
||||
return Clock;
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
|
||||
function DelayedFunctionScheduler() {
|
||||
var self = this;
|
||||
var scheduledLookup = [];
|
||||
var scheduledFunctions = {};
|
||||
var currentTime = 0;
|
||||
var delayedFnCount = 0;
|
||||
var deletedKeys = [];
|
||||
|
||||
self.tick = function(millis, tickDate) {
|
||||
millis = millis || 0;
|
||||
@@ -51,6 +52,8 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
};
|
||||
|
||||
self.removeFunctionWithId = function(timeoutKey) {
|
||||
deletedKeys.push(timeoutKey);
|
||||
|
||||
for (var runAtMillis in scheduledFunctions) {
|
||||
var funcs = scheduledFunctions[runAtMillis];
|
||||
var i = indexOfFirstToPass(funcs, function (func) {
|
||||
@@ -127,6 +130,7 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
currentTime = newCurrentTime;
|
||||
|
||||
var funcsToRun = scheduledFunctions[currentTime];
|
||||
|
||||
delete scheduledFunctions[currentTime];
|
||||
|
||||
forEachFunction(funcsToRun, function(funcToRun) {
|
||||
@@ -136,8 +140,13 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
});
|
||||
|
||||
forEachFunction(funcsToRun, function(funcToRun) {
|
||||
if (j$.util.arrayContains(deletedKeys, funcToRun.timeoutKey)) {
|
||||
// skip a timeoutKey deleted whilst we were running
|
||||
return;
|
||||
}
|
||||
funcToRun.funcToCall.apply(null, funcToRun.params || []);
|
||||
});
|
||||
deletedKeys = [];
|
||||
} while (scheduledLookup.length > 0 &&
|
||||
// checking first if we're out of time prevents setTimeout(0)
|
||||
// scheduled in a funcToRun from forcing an extra iteration
|
||||
|
||||
@@ -3,6 +3,8 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
function PrettyPrinter() {
|
||||
this.ppNestLevel_ = 0;
|
||||
this.seen = [];
|
||||
this.length = 0;
|
||||
this.stringParts = [];
|
||||
}
|
||||
|
||||
function hasCustomToString(value) {
|
||||
@@ -88,32 +90,15 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
return objKeys.length > length;
|
||||
};
|
||||
|
||||
PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitSet = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitMap = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitString = j$.unimplementedMethod_;
|
||||
PrettyPrinter.prototype.emitDomElement = j$.unimplementedMethod_;
|
||||
|
||||
function StringPrettyPrinter() {
|
||||
PrettyPrinter.call(this);
|
||||
|
||||
this.length = 0;
|
||||
this.stringParts = [];
|
||||
}
|
||||
|
||||
j$.util.inherit(StringPrettyPrinter, PrettyPrinter);
|
||||
|
||||
StringPrettyPrinter.prototype.emitScalar = function(value) {
|
||||
PrettyPrinter.prototype.emitScalar = function(value) {
|
||||
this.append(value);
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitString = function(value) {
|
||||
PrettyPrinter.prototype.emitString = function(value) {
|
||||
this.append('\'' + value + '\'');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitArray = function(array) {
|
||||
PrettyPrinter.prototype.emitArray = function(array) {
|
||||
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
|
||||
this.append('Array');
|
||||
return;
|
||||
@@ -147,7 +132,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' ]');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitSet = function(set) {
|
||||
PrettyPrinter.prototype.emitSet = function(set) {
|
||||
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
|
||||
this.append('Set');
|
||||
return;
|
||||
@@ -167,7 +152,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' )');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitMap = function(map) {
|
||||
PrettyPrinter.prototype.emitMap = function(map) {
|
||||
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
|
||||
this.append('Map');
|
||||
return;
|
||||
@@ -187,7 +172,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' )');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitObject = function(obj) {
|
||||
PrettyPrinter.prototype.emitObject = function(obj) {
|
||||
var ctor = obj.constructor,
|
||||
constructorName;
|
||||
|
||||
@@ -220,7 +205,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' })');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitTypedArray = function(arr) {
|
||||
PrettyPrinter.prototype.emitTypedArray = function(arr) {
|
||||
var constructorName = j$.fnNameFor(arr.constructor),
|
||||
limitedArray = Array.prototype.slice.call(arr, 0, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH),
|
||||
itemsString = Array.prototype.join.call(limitedArray, ', ');
|
||||
@@ -232,7 +217,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(constructorName + ' [ ' + itemsString + ' ]');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitDomElement = function(el) {
|
||||
PrettyPrinter.prototype.emitDomElement = function(el) {
|
||||
var closingTag = '</' + el.tagName.toLowerCase() + '>';
|
||||
|
||||
if (el.innerHTML === '') {
|
||||
@@ -244,7 +229,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {
|
||||
PrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {
|
||||
this.append(property);
|
||||
this.append(': ');
|
||||
if (isGetter) {
|
||||
@@ -254,7 +239,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.append = function(value) {
|
||||
PrettyPrinter.prototype.append = function(value) {
|
||||
var result = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length);
|
||||
this.length += result.value.length;
|
||||
this.stringParts.push(result.value);
|
||||
@@ -264,6 +249,7 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function truncate(s, maxlen) {
|
||||
if (s.length <= maxlen) {
|
||||
return { value: s, truncated: false };
|
||||
@@ -310,8 +296,8 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
return extraKeys;
|
||||
}
|
||||
return function(value) {
|
||||
var stringPrettyPrinter = new StringPrettyPrinter();
|
||||
stringPrettyPrinter.format(value);
|
||||
return stringPrettyPrinter.stringParts.join('');
|
||||
var prettyPrinter = new PrettyPrinter();
|
||||
prettyPrinter.format(value);
|
||||
return prettyPrinter.stringParts.join('');
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
|
||||
function SpyRegistry(options) {
|
||||
options = options || {};
|
||||
var global = options.global || j$.getGlobal();
|
||||
var currentSpies = options.currentSpies || function() { return []; };
|
||||
|
||||
this.allowRespy = function(allow){
|
||||
@@ -42,7 +43,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
spiedMethod = j$.createSpy(methodName, originalMethod),
|
||||
restoreStrategy;
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(obj, methodName)) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, methodName) || (obj === global && methodName === 'onerror')) {
|
||||
restoreStrategy = function() {
|
||||
obj[methodName] = originalMethod;
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') {
|
||||
jasmineGlobal = window;
|
||||
}
|
||||
jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {};
|
||||
jasmineRequire = jasmineGlobal.jasmineRequire = {};
|
||||
}
|
||||
|
||||
function getJasmineRequire() {
|
||||
@@ -32,7 +32,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
j$.MockDate = jRequire.MockDate();
|
||||
j$.getClearStack = jRequire.clearStack(j$);
|
||||
j$.Clock = jRequire.Clock();
|
||||
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
|
||||
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(j$);
|
||||
j$.Env = jRequire.Env(j$);
|
||||
j$.StackTrace = jRequire.StackTrace(j$);
|
||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
|
||||
|
||||
@@ -5,6 +5,46 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
elapsed: function() { return 0; }
|
||||
};
|
||||
|
||||
function ResultsStateBuilder() {
|
||||
this.topResults = new j$.ResultsNode({}, '', null);
|
||||
this.currentParent = this.topResults;
|
||||
this.specsExecuted = 0;
|
||||
this.failureCount = 0;
|
||||
this.pendingSpecCount = 0;
|
||||
}
|
||||
|
||||
ResultsStateBuilder.prototype.suiteStarted = function(result) {
|
||||
this.currentParent.addChild(result, 'suite');
|
||||
this.currentParent = this.currentParent.last();
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.suiteDone = function(result) {
|
||||
if (this.currentParent !== this.topResults) {
|
||||
this.currentParent = this.currentParent.parent;
|
||||
}
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.specStarted = function(result) {
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.specDone = function(result) {
|
||||
this.currentParent.addChild(result, 'spec');
|
||||
|
||||
if (result.status !== 'disabled') {
|
||||
this.specsExecuted++;
|
||||
}
|
||||
|
||||
if (result.status === 'failed') {
|
||||
this.failureCount++;
|
||||
}
|
||||
|
||||
if (result.status == 'pending') {
|
||||
this.pendingSpecCount++;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
function HtmlReporter(options) {
|
||||
var env = options.env || {},
|
||||
getContainer = options.getContainer,
|
||||
@@ -17,9 +57,6 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
filterSpecs = options.filterSpecs,
|
||||
timer = options.timer || noopTimer,
|
||||
results = [],
|
||||
specsExecuted = 0,
|
||||
failureCount = 0,
|
||||
pendingSpecCount = 0,
|
||||
htmlReporterMain,
|
||||
symbols,
|
||||
failedSuites = [];
|
||||
@@ -48,12 +85,10 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
var summary = createDom('div', {className: 'jasmine-summary'});
|
||||
|
||||
var topResults = new j$.ResultsNode({}, '', null),
|
||||
currentParent = topResults;
|
||||
var stateBuilder = new ResultsStateBuilder();
|
||||
|
||||
this.suiteStarted = function(result) {
|
||||
currentParent.addChild(result, 'suite');
|
||||
currentParent = currentParent.last();
|
||||
stateBuilder.suiteStarted(result);
|
||||
};
|
||||
|
||||
this.suiteDone = function(result) {
|
||||
@@ -61,27 +96,21 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
failedSuites.push(result);
|
||||
}
|
||||
|
||||
if (currentParent == topResults) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentParent = currentParent.parent;
|
||||
stateBuilder.suiteDone(result);
|
||||
};
|
||||
|
||||
this.specStarted = function(result) {
|
||||
currentParent.addChild(result, 'spec');
|
||||
stateBuilder.specStarted(result);
|
||||
};
|
||||
|
||||
var failures = [];
|
||||
this.specDone = function(result) {
|
||||
stateBuilder.specDone(result);
|
||||
|
||||
if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') {
|
||||
console.error('Spec \'' + result.fullName + '\' has no expectations.');
|
||||
}
|
||||
|
||||
if (result.status != 'disabled') {
|
||||
specsExecuted++;
|
||||
}
|
||||
|
||||
if (!symbols){
|
||||
symbols = find('.jasmine-symbol-summary');
|
||||
}
|
||||
@@ -94,11 +123,9 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
));
|
||||
|
||||
if (result.status == 'failed') {
|
||||
failureCount++;
|
||||
|
||||
var failure =
|
||||
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
|
||||
failureDescription(result, currentParent),
|
||||
failureDescription(result, stateBuilder.currentParent),
|
||||
createDom('div', {className: 'jasmine-messages'})
|
||||
);
|
||||
var messages = failure.childNodes[1];
|
||||
@@ -111,10 +138,6 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
failures.push(failure);
|
||||
}
|
||||
|
||||
if (result.status == 'pending') {
|
||||
pendingSpecCount++;
|
||||
}
|
||||
};
|
||||
|
||||
this.jasmineDone = function(doneResult) {
|
||||
@@ -177,8 +200,8 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
if (specsExecuted < totalSpecsDefined) {
|
||||
var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
|
||||
if (stateBuilder.specsExecuted < totalSpecsDefined) {
|
||||
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
|
||||
var skippedLink = addToExistingQueryString('spec', '');
|
||||
alert.appendChild(
|
||||
createDom('span', {className: 'jasmine-bar jasmine-skipped'},
|
||||
@@ -189,11 +212,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
var statusBarMessage = '';
|
||||
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
|
||||
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
|
||||
var failed = failureCount + globalFailures.length + failedSuites.length > 0;
|
||||
var failed = stateBuilder.failureCount + globalFailures.length + failedSuites.length > 0;
|
||||
|
||||
if (totalSpecsDefined > 0 || failed) {
|
||||
statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount);
|
||||
if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); }
|
||||
statusBarMessage += pluralize('spec', stateBuilder.specsExecuted) + ', ' + pluralize('failure', stateBuilder.failureCount);
|
||||
if (stateBuilder.pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', stateBuilder.pendingSpecCount); }
|
||||
}
|
||||
|
||||
if (doneResult.overallStatus === 'passed') {
|
||||
@@ -246,7 +269,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
var results = find('.jasmine-results');
|
||||
results.appendChild(summary);
|
||||
|
||||
summaryList(topResults, summary);
|
||||
summaryList(stateBuilder.topResults, summary);
|
||||
|
||||
function summaryList(resultsTree, domParent) {
|
||||
var specListNode;
|
||||
|
||||
Reference in New Issue
Block a user