Merge branch '3.0-features'
This commit is contained in:
19
.travis.yml
19
.travis.yml
@@ -22,9 +22,6 @@ addons:
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env:
|
||||
- USE_SAUCE=false
|
||||
- TEST_COMMAND="bash travis-node-script.sh v0.12.18"
|
||||
- env:
|
||||
- USE_SAUCE=false
|
||||
- TEST_COMMAND="bash travis-node-script.sh v4"
|
||||
@@ -34,6 +31,10 @@ matrix:
|
||||
- env:
|
||||
- USE_SAUCE=false
|
||||
- TEST_COMMAND="bash travis-node-script.sh v9"
|
||||
- env:
|
||||
- JASMINE_BROWSER="safari"
|
||||
- SAUCE_OS="OS X 10.12"
|
||||
- SAUCE_BROWSER_VERSION=10
|
||||
- env:
|
||||
- JASMINE_BROWSER="safari"
|
||||
- SAUCE_OS="OS X 10.11"
|
||||
@@ -46,6 +47,10 @@ matrix:
|
||||
- JASMINE_BROWSER="safari"
|
||||
- SAUCE_OS="OS X 10.9"
|
||||
- SAUCE_BROWSER_VERSION=7
|
||||
- env:
|
||||
- JASMINE_BROWSER="MicrosoftEdge"
|
||||
- SAUCE_OS="Windows 10"
|
||||
- SAUCE_BROWSER_VERSION="15"
|
||||
- env:
|
||||
- JASMINE_BROWSER="internet explorer"
|
||||
- SAUCE_OS="Windows 8.1"
|
||||
@@ -54,14 +59,6 @@ matrix:
|
||||
- JASMINE_BROWSER="internet explorer"
|
||||
- SAUCE_OS="Windows 8"
|
||||
- SAUCE_BROWSER_VERSION=10
|
||||
- env:
|
||||
- JASMINE_BROWSER="internet explorer"
|
||||
- SAUCE_OS="Windows 7"
|
||||
- SAUCE_BROWSER_VERSION=9
|
||||
- env:
|
||||
- JASMINE_BROWSER="internet explorer"
|
||||
- SAUCE_OS="Windows 7"
|
||||
- SAUCE_BROWSER_VERSION=8
|
||||
- env:
|
||||
- JASMINE_BROWSER="chrome"
|
||||
- SAUCE_OS="Linux"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
recursive-include . *.py
|
||||
prune node_modules
|
||||
include lib/jasmine-core/*.js
|
||||
include lib/jasmine-core/*.css
|
||||
include images/*.png
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
[](https://travis-ci.org/jasmine/jasmine)
|
||||
|
||||
=======
|
||||
|
||||
**A JavaScript Testing Framework**
|
||||
# A JavaScript Testing Framework
|
||||
|
||||
Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, [Node.js](http://nodejs.org) projects, or anywhere that JavaScript can run.
|
||||
|
||||
@@ -52,7 +50,7 @@ Add the following to your HTML file:
|
||||
|
||||
## Supported environments
|
||||
|
||||
Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, and new Internet Explorer) as well as node. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/master/.travis.yml)
|
||||
Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, Microsoft Edge, and new Internet Explorer) as well as nodejs. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/master/.travis.yml)
|
||||
|
||||
|
||||
## Support
|
||||
|
||||
@@ -2,7 +2,6 @@ var standaloneLibDir = "lib/jasmine-" + jasmineVersion;
|
||||
|
||||
function root(path) { return "./" + path; }
|
||||
function libJasmineCore(path) { return root("lib/jasmine-core/" + path); }
|
||||
function libConsole() { return "lib/console/" }
|
||||
function dist(path) { return root("dist/" + path); }
|
||||
|
||||
module.exports = {
|
||||
@@ -29,14 +28,6 @@ module.exports = {
|
||||
expand: true,
|
||||
cwd: libJasmineCore("")
|
||||
},
|
||||
{
|
||||
src: [
|
||||
"console.js"
|
||||
],
|
||||
dest: standaloneLibDir,
|
||||
expand: true,
|
||||
cwd: libConsole()
|
||||
},
|
||||
{
|
||||
src: [ "boot.js" ],
|
||||
dest: standaloneLibDir,
|
||||
|
||||
@@ -15,7 +15,8 @@ module.exports = {
|
||||
'src/html/HtmlReporter.js',
|
||||
'src/html/HtmlSpecFilter.js',
|
||||
'src/html/ResultsNode.js',
|
||||
'src/html/QueryString.js'
|
||||
'src/html/QueryString.js',
|
||||
'src/html/**/*.js'
|
||||
],
|
||||
dest: 'lib/jasmine-core/jasmine-html.js'
|
||||
},
|
||||
@@ -44,13 +45,6 @@ module.exports = {
|
||||
src: ['lib/jasmine-core/boot/node_boot.js'],
|
||||
dest: 'lib/jasmine-core/node_boot.js'
|
||||
},
|
||||
console: {
|
||||
src: [
|
||||
'src/console/requireConsole.js',
|
||||
'src/console/ConsoleReporter.js'
|
||||
],
|
||||
dest: 'lib/console/console.js'
|
||||
},
|
||||
options: {
|
||||
banner: license(),
|
||||
process: {
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
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
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
function getJasmineRequireObj() {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
return exports;
|
||||
} else {
|
||||
window.jasmineRequire = window.jasmineRequire || {};
|
||||
return window.jasmineRequire;
|
||||
}
|
||||
}
|
||||
|
||||
getJasmineRequireObj().console = function(jRequire, j$) {
|
||||
j$.ConsoleReporter = jRequire.ConsoleReporter();
|
||||
};
|
||||
|
||||
getJasmineRequireObj().ConsoleReporter = function() {
|
||||
|
||||
var noopTimer = {
|
||||
start: function(){},
|
||||
elapsed: function(){ return 0; }
|
||||
};
|
||||
|
||||
function ConsoleReporter(options) {
|
||||
var print = options.print,
|
||||
showColors = options.showColors || false,
|
||||
onComplete = options.onComplete || function() {},
|
||||
timer = options.timer || noopTimer,
|
||||
specCount,
|
||||
failureCount,
|
||||
failedSpecs = [],
|
||||
pendingCount,
|
||||
ansi = {
|
||||
green: '\x1B[32m',
|
||||
red: '\x1B[31m',
|
||||
yellow: '\x1B[33m',
|
||||
none: '\x1B[0m'
|
||||
},
|
||||
failedSuites = [];
|
||||
|
||||
print('ConsoleReporter is deprecated and will be removed in a future version.');
|
||||
|
||||
this.jasmineStarted = function() {
|
||||
specCount = 0;
|
||||
failureCount = 0;
|
||||
pendingCount = 0;
|
||||
print('Started');
|
||||
printNewline();
|
||||
timer.start();
|
||||
};
|
||||
|
||||
this.jasmineDone = function() {
|
||||
printNewline();
|
||||
for (var i = 0; i < failedSpecs.length; i++) {
|
||||
specFailureDetails(failedSpecs[i]);
|
||||
}
|
||||
|
||||
if(specCount > 0) {
|
||||
printNewline();
|
||||
|
||||
var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' +
|
||||
failureCount + ' ' + plural('failure', failureCount);
|
||||
|
||||
if (pendingCount) {
|
||||
specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount);
|
||||
}
|
||||
|
||||
print(specCounts);
|
||||
} else {
|
||||
print('No specs found');
|
||||
}
|
||||
|
||||
printNewline();
|
||||
var seconds = timer.elapsed() / 1000;
|
||||
print('Finished in ' + seconds + ' ' + plural('second', seconds));
|
||||
printNewline();
|
||||
|
||||
for(i = 0; i < failedSuites.length; i++) {
|
||||
suiteFailureDetails(failedSuites[i]);
|
||||
}
|
||||
|
||||
onComplete(failureCount === 0);
|
||||
};
|
||||
|
||||
this.specDone = function(result) {
|
||||
specCount++;
|
||||
|
||||
if (result.status == 'pending') {
|
||||
pendingCount++;
|
||||
print(colored('yellow', '*'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.status == 'passed') {
|
||||
print(colored('green', '.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.status == 'failed') {
|
||||
failureCount++;
|
||||
failedSpecs.push(result);
|
||||
print(colored('red', 'F'));
|
||||
}
|
||||
};
|
||||
|
||||
this.suiteDone = function(result) {
|
||||
if (result.failedExpectations && result.failedExpectations.length > 0) {
|
||||
failureCount++;
|
||||
failedSuites.push(result);
|
||||
}
|
||||
};
|
||||
|
||||
return this;
|
||||
|
||||
function printNewline() {
|
||||
print('\n');
|
||||
}
|
||||
|
||||
function colored(color, str) {
|
||||
return showColors ? (ansi[color] + str + ansi.none) : str;
|
||||
}
|
||||
|
||||
function plural(str, count) {
|
||||
return count == 1 ? str : str + 's';
|
||||
}
|
||||
|
||||
function repeat(thing, times) {
|
||||
var arr = [];
|
||||
for (var i = 0; i < times; i++) {
|
||||
arr.push(thing);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
function indent(str, spaces) {
|
||||
var lines = (str || '').split('\n');
|
||||
var newArr = [];
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
newArr.push(repeat(' ', spaces).join('') + lines[i]);
|
||||
}
|
||||
return newArr.join('\n');
|
||||
}
|
||||
|
||||
function specFailureDetails(result) {
|
||||
printNewline();
|
||||
print(result.fullName);
|
||||
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
var failedExpectation = result.failedExpectations[i];
|
||||
printNewline();
|
||||
print(indent(failedExpectation.message, 2));
|
||||
print(indent(failedExpectation.stack, 2));
|
||||
}
|
||||
|
||||
printNewline();
|
||||
}
|
||||
|
||||
function suiteFailureDetails(result) {
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
printNewline();
|
||||
print(colored('red', 'An error was thrown in an afterAll'));
|
||||
printNewline();
|
||||
print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
|
||||
|
||||
}
|
||||
printNewline();
|
||||
}
|
||||
}
|
||||
|
||||
return ConsoleReporter;
|
||||
};
|
||||
@@ -73,14 +73,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var filterSpecs = !!queryString.getParam("spec");
|
||||
|
||||
var catchingExceptions = queryString.getParam("catch");
|
||||
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
|
||||
var stoppingOnSpecFailure = queryString.getParam("failFast");
|
||||
env.stopOnSpecFailure(stoppingOnSpecFailure);
|
||||
|
||||
var throwingExpectationFailures = queryString.getParam("throwFailures");
|
||||
env.throwOnExpectationFailure(throwingExpectationFailures);
|
||||
|
||||
var random = queryString.getParam("random");
|
||||
env.randomizeTests(random);
|
||||
|
||||
if (random !== undefined && random !== "") {
|
||||
env.randomizeTests(random);
|
||||
}
|
||||
|
||||
var seed = queryString.getParam("seed");
|
||||
if (seed) {
|
||||
@@ -93,9 +96,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
var htmlReporter = new jasmine.HtmlReporter({
|
||||
env: env,
|
||||
onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
|
||||
onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); },
|
||||
onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); },
|
||||
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
|
||||
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
|
||||
getContainer: function() { return document.body; },
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
|
||||
@@ -51,14 +51,17 @@
|
||||
|
||||
var filterSpecs = !!queryString.getParam("spec");
|
||||
|
||||
var catchingExceptions = queryString.getParam("catch");
|
||||
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
|
||||
var stoppingOnSpecFailure = queryString.getParam("failFast");
|
||||
env.stopOnSpecFailure(stoppingOnSpecFailure);
|
||||
|
||||
var throwingExpectationFailures = queryString.getParam("throwFailures");
|
||||
env.throwOnExpectationFailure(throwingExpectationFailures);
|
||||
|
||||
var random = queryString.getParam("random");
|
||||
env.randomizeTests(random);
|
||||
|
||||
if (random !== undefined && random !== "") {
|
||||
env.randomizeTests(random);
|
||||
}
|
||||
|
||||
var seed = queryString.getParam("seed");
|
||||
if (seed) {
|
||||
@@ -71,9 +74,7 @@
|
||||
*/
|
||||
var htmlReporter = new jasmine.HtmlReporter({
|
||||
env: env,
|
||||
onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
|
||||
onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); },
|
||||
onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); },
|
||||
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
|
||||
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
|
||||
getContainer: function() { return document.body; },
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
module.exports = function(jasmineRequire) {
|
||||
var jasmine = jasmineRequire.core(jasmineRequire);
|
||||
|
||||
var consoleFns = require('../console/console.js');
|
||||
consoleFns.console(consoleFns, jasmine);
|
||||
|
||||
var env = jasmine.getEnv();
|
||||
|
||||
var jasmineInterface = jasmineRequire.interface(jasmine, env);
|
||||
|
||||
@@ -25,6 +25,7 @@ jasmineRequire.html = function(j$) {
|
||||
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
|
||||
j$.QueryString = jasmineRequire.QueryString();
|
||||
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
|
||||
j$.matchers.toHaveClass = jasmineRequire.toHaveClass(j$);
|
||||
};
|
||||
|
||||
jasmineRequire.HtmlReporter = function(j$) {
|
||||
@@ -48,9 +49,14 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.suiteDone = function(result) {
|
||||
this.currentParent.updateResult(result);
|
||||
if (this.currentParent !== this.topResults) {
|
||||
this.currentParent = this.currentParent.parent;
|
||||
}
|
||||
|
||||
if (result.status === 'failed') {
|
||||
this.failureCount++;
|
||||
}
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.specStarted = function(result) {
|
||||
@@ -59,7 +65,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
ResultsStateBuilder.prototype.specDone = function(result) {
|
||||
this.currentParent.addChild(result, 'spec');
|
||||
|
||||
if (result.status !== 'disabled') {
|
||||
if (result.status !== 'excluded') {
|
||||
this.specsExecuted++;
|
||||
}
|
||||
|
||||
@@ -79,16 +85,12 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
getContainer = options.getContainer,
|
||||
createElement = options.createElement,
|
||||
createTextNode = options.createTextNode,
|
||||
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
|
||||
onThrowExpectationsClick = options.onThrowExpectationsClick || function() {},
|
||||
onRandomClick = options.onRandomClick || function() {},
|
||||
navigateWithNewParam = options.navigateWithNewParam || function() {},
|
||||
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
|
||||
filterSpecs = options.filterSpecs,
|
||||
timer = options.timer || noopTimer,
|
||||
results = [],
|
||||
htmlReporterMain,
|
||||
symbols,
|
||||
failedSuites = [],
|
||||
deprecationWarnings = [];
|
||||
|
||||
this.initialize = function() {
|
||||
@@ -122,11 +124,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
};
|
||||
|
||||
this.suiteDone = function(result) {
|
||||
if (result.status == 'failed') {
|
||||
failedSuites.push(result);
|
||||
}
|
||||
|
||||
stateBuilder.suiteDone(result);
|
||||
|
||||
if (result.status === 'failed') {
|
||||
failures.push(failureDom(result));
|
||||
}
|
||||
addDeprecationWarnings(result);
|
||||
};
|
||||
|
||||
@@ -153,23 +155,8 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
));
|
||||
|
||||
if (result.status == 'failed') {
|
||||
var failure =
|
||||
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
|
||||
createDom('div', {className: 'jasmine-description'},
|
||||
createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName)
|
||||
),
|
||||
createDom('div', {className: 'jasmine-messages'})
|
||||
);
|
||||
var messages = failure.childNodes[1];
|
||||
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
var expectation = result.failedExpectations[i];
|
||||
messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
|
||||
messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
|
||||
}
|
||||
|
||||
failures.push(failure);
|
||||
if (result.status === 'failed') {
|
||||
failures.push(failureDom(result));
|
||||
}
|
||||
|
||||
addDeprecationWarnings(result);
|
||||
@@ -181,59 +168,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
var order = doneResult && doneResult.order;
|
||||
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
|
||||
|
||||
banner.appendChild(
|
||||
createDom('div', { className: 'jasmine-run-options' },
|
||||
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
|
||||
createDom('div', { className: 'jasmine-payload' },
|
||||
createDom('div', { className: 'jasmine-exceptions' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-raise',
|
||||
id: 'jasmine-raise-exceptions',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
|
||||
createDom('div', { className: 'jasmine-throw-failures' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-throw',
|
||||
id: 'jasmine-throw-failures',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
|
||||
createDom('div', { className: 'jasmine-random-order' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-random',
|
||||
id: 'jasmine-random-order',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
|
||||
)
|
||||
));
|
||||
|
||||
var raiseCheckbox = find('#jasmine-raise-exceptions');
|
||||
|
||||
raiseCheckbox.checked = !env.catchingExceptions();
|
||||
raiseCheckbox.onclick = onRaiseExceptionsClick;
|
||||
|
||||
var throwCheckbox = find('#jasmine-throw-failures');
|
||||
throwCheckbox.checked = env.throwingExpectationFailures();
|
||||
throwCheckbox.onclick = onThrowExpectationsClick;
|
||||
|
||||
var randomCheckbox = find('#jasmine-random-order');
|
||||
randomCheckbox.checked = env.randomTests();
|
||||
randomCheckbox.onclick = onRandomClick;
|
||||
|
||||
var optionsMenu = find('.jasmine-run-options'),
|
||||
optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'),
|
||||
optionsPayload = optionsMenu.querySelector('.jasmine-payload'),
|
||||
isOpen = /\bjasmine-open\b/;
|
||||
|
||||
optionsTrigger.onclick = function() {
|
||||
if (isOpen.test(optionsPayload.className)) {
|
||||
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
|
||||
} else {
|
||||
optionsPayload.className += ' jasmine-open';
|
||||
}
|
||||
};
|
||||
banner.appendChild(optionsMenu(env));
|
||||
|
||||
if (stateBuilder.specsExecuted < totalSpecsDefined) {
|
||||
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
|
||||
@@ -245,15 +180,22 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
);
|
||||
}
|
||||
var statusBarMessage = '';
|
||||
var statusBarClassName = 'jasmine-bar ';
|
||||
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
|
||||
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
|
||||
var failed = stateBuilder.failureCount + globalFailures.length > 0;
|
||||
|
||||
if (totalSpecsDefined > 0) {
|
||||
if (totalSpecsDefined > 0 || failed) {
|
||||
statusBarMessage += pluralize('spec', stateBuilder.specsExecuted) + ', ' + pluralize('failure', stateBuilder.failureCount);
|
||||
if (stateBuilder.pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', stateBuilder.pendingSpecCount); }
|
||||
statusBarClassName += (stateBuilder.failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed';
|
||||
}
|
||||
|
||||
if (doneResult.overallStatus === 'passed') {
|
||||
statusBarClassName += ' jasmine-passed ';
|
||||
} else if (doneResult.overallStatus === 'incomplete') {
|
||||
statusBarClassName += ' jasmine-incomplete ';
|
||||
statusBarMessage = 'Incomplete: ' + doneResult.incompleteReason + ', ' + statusBarMessage;
|
||||
} else {
|
||||
statusBarClassName += 'jasmine-skipped';
|
||||
statusBarMessage += 'No specs found';
|
||||
statusBarClassName += ' jasmine-failed ';
|
||||
}
|
||||
|
||||
var seedBar;
|
||||
@@ -267,19 +209,24 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar));
|
||||
|
||||
var errorBarClassName = 'jasmine-bar jasmine-errored';
|
||||
var errorBarMessagePrefix = 'AfterAll ';
|
||||
var afterAllMessagePrefix = 'AfterAll ';
|
||||
|
||||
for(var i = 0; i < failedSuites.length; i++) {
|
||||
var failedSuite = failedSuites[i];
|
||||
for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
|
||||
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failedSuite.failedExpectations[j].message));
|
||||
}
|
||||
for(i = 0; i < globalFailures.length; i++) {
|
||||
alert.appendChild(createDom('span', {className: errorBarClassName}, globalFailureMessage(globalFailures[i])));
|
||||
}
|
||||
|
||||
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
|
||||
for(i = 0; i < globalFailures.length; i++) {
|
||||
var failure = globalFailures[i];
|
||||
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failure.message));
|
||||
function globalFailureMessage(failure) {
|
||||
if (failure.globalErrorType === 'load') {
|
||||
var prefix = 'Error during loading: ' + failure.message;
|
||||
|
||||
if (failure.filename) {
|
||||
return prefix + ' in ' + failure.filename + ' line ' + failure.lineno;
|
||||
} else {
|
||||
return prefix;
|
||||
}
|
||||
} else {
|
||||
return afterAllMessagePrefix + failure.message;
|
||||
}
|
||||
}
|
||||
|
||||
addDeprecationWarnings(doneResult);
|
||||
@@ -295,47 +242,6 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
summaryList(stateBuilder.topResults, summary);
|
||||
|
||||
function summaryList(resultsTree, domParent) {
|
||||
var specListNode;
|
||||
for (var i = 0; i < resultsTree.children.length; i++) {
|
||||
var resultNode = resultsTree.children[i];
|
||||
if (filterSpecs && !hasActiveSpec(resultNode)) {
|
||||
continue;
|
||||
}
|
||||
if (resultNode.type == 'suite') {
|
||||
var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
|
||||
createDom('li', {className: 'jasmine-suite-detail'},
|
||||
createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
|
||||
)
|
||||
);
|
||||
|
||||
summaryList(resultNode, suiteListNode);
|
||||
domParent.appendChild(suiteListNode);
|
||||
}
|
||||
if (resultNode.type == 'spec') {
|
||||
if (domParent.getAttribute('class') != 'jasmine-specs') {
|
||||
specListNode = createDom('ul', {className: 'jasmine-specs'});
|
||||
domParent.appendChild(specListNode);
|
||||
}
|
||||
var specDescription = resultNode.result.description;
|
||||
if(noExpectations(resultNode.result)) {
|
||||
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
|
||||
}
|
||||
if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
|
||||
specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
|
||||
}
|
||||
specListNode.appendChild(
|
||||
createDom('li', {
|
||||
className: 'jasmine-' + resultNode.result.status,
|
||||
id: 'spec-' + resultNode.result.id
|
||||
},
|
||||
createDom('a', {href: specHref(resultNode.result)}, specDescription)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failures.length) {
|
||||
alert.appendChild(
|
||||
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'},
|
||||
@@ -364,6 +270,153 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
return this;
|
||||
|
||||
function failureDom(result) {
|
||||
var failure =
|
||||
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
|
||||
failureDescription(result, stateBuilder.currentParent),
|
||||
createDom('div', {className: 'jasmine-messages'})
|
||||
);
|
||||
var messages = failure.childNodes[1];
|
||||
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
var expectation = result.failedExpectations[i];
|
||||
messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
|
||||
messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
|
||||
}
|
||||
|
||||
return failure;
|
||||
}
|
||||
|
||||
function summaryList(resultsTree, domParent) {
|
||||
var specListNode;
|
||||
for (var i = 0; i < resultsTree.children.length; i++) {
|
||||
var resultNode = resultsTree.children[i];
|
||||
if (filterSpecs && !hasActiveSpec(resultNode)) {
|
||||
continue;
|
||||
}
|
||||
if (resultNode.type === 'suite') {
|
||||
var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
|
||||
createDom('li', {className: 'jasmine-suite-detail jasmine-' + resultNode.result.status},
|
||||
createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
|
||||
)
|
||||
);
|
||||
|
||||
summaryList(resultNode, suiteListNode);
|
||||
domParent.appendChild(suiteListNode);
|
||||
}
|
||||
if (resultNode.type === 'spec') {
|
||||
if (domParent.getAttribute('class') !== 'jasmine-specs') {
|
||||
specListNode = createDom('ul', {className: 'jasmine-specs'});
|
||||
domParent.appendChild(specListNode);
|
||||
}
|
||||
var specDescription = resultNode.result.description;
|
||||
if(noExpectations(resultNode.result)) {
|
||||
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
|
||||
}
|
||||
if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
|
||||
specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
|
||||
}
|
||||
specListNode.appendChild(
|
||||
createDom('li', {
|
||||
className: 'jasmine-' + resultNode.result.status,
|
||||
id: 'spec-' + resultNode.result.id
|
||||
},
|
||||
createDom('a', {href: specHref(resultNode.result)}, specDescription)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function optionsMenu(env) {
|
||||
var optionsMenuDom = createDom('div', { className: 'jasmine-run-options' },
|
||||
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
|
||||
createDom('div', { className: 'jasmine-payload' },
|
||||
createDom('div', { className: 'jasmine-stop-on-failure' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-fail-fast',
|
||||
id: 'jasmine-fail-fast',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-fail-fast' }, 'stop execution on spec failure')),
|
||||
createDom('div', { className: 'jasmine-throw-failures' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-throw',
|
||||
id: 'jasmine-throw-failures',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
|
||||
createDom('div', { className: 'jasmine-random-order' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-random',
|
||||
id: 'jasmine-random-order',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
|
||||
)
|
||||
);
|
||||
|
||||
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
|
||||
failFastCheckbox.checked = env.stoppingOnSpecFailure();
|
||||
failFastCheckbox.onclick = function() {
|
||||
navigateWithNewParam('failFast', !env.stoppingOnSpecFailure());
|
||||
};
|
||||
|
||||
var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
|
||||
throwCheckbox.checked = env.throwingExpectationFailures();
|
||||
throwCheckbox.onclick = function() {
|
||||
navigateWithNewParam('throwFailures', !env.throwingExpectationFailures());
|
||||
};
|
||||
|
||||
var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
|
||||
randomCheckbox.checked = env.randomTests();
|
||||
randomCheckbox.onclick = function() {
|
||||
navigateWithNewParam('random', !env.randomTests());
|
||||
};
|
||||
|
||||
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),
|
||||
optionsPayload = optionsMenuDom.querySelector('.jasmine-payload'),
|
||||
isOpen = /\bjasmine-open\b/;
|
||||
|
||||
optionsTrigger.onclick = function() {
|
||||
if (isOpen.test(optionsPayload.className)) {
|
||||
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
|
||||
} else {
|
||||
optionsPayload.className += ' jasmine-open';
|
||||
}
|
||||
};
|
||||
|
||||
return optionsMenuDom;
|
||||
}
|
||||
|
||||
function failureDescription(result, suite) {
|
||||
var wrapper = createDom('div', {className: 'jasmine-description'},
|
||||
createDom('a', {title: result.description, href: specHref(result)}, result.description)
|
||||
);
|
||||
var suiteLink;
|
||||
|
||||
while (suite && suite.parent) {
|
||||
wrapper.insertBefore(createTextNode(' > '), wrapper.firstChild);
|
||||
suiteLink = createDom('a', {href: suiteHref(suite)}, suite.result.description);
|
||||
wrapper.insertBefore(suiteLink, wrapper.firstChild);
|
||||
|
||||
suite = suite.parent;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function suiteHref(suite) {
|
||||
var els = [];
|
||||
|
||||
while (suite && suite.parent) {
|
||||
els.unshift(suite.result.description);
|
||||
suite = suite.parent;
|
||||
}
|
||||
|
||||
return addToExistingQueryString('spec', els.join(' '));
|
||||
}
|
||||
|
||||
function addDeprecationWarnings(result) {
|
||||
if (result && result.deprecationWarnings) {
|
||||
for(var i = 0; i < result.deprecationWarnings.length; i++) {
|
||||
@@ -442,7 +495,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function hasActiveSpec(resultNode) {
|
||||
if (resultNode.type == 'spec' && resultNode.result.status != 'disabled') {
|
||||
if (resultNode.type == 'spec' && resultNode.result.status != 'excluded') {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -487,6 +540,10 @@ jasmineRequire.ResultsNode = function() {
|
||||
this.last = function() {
|
||||
return this.children[this.children.length - 1];
|
||||
};
|
||||
|
||||
this.updateResult = function(result) {
|
||||
this.result = result;
|
||||
};
|
||||
}
|
||||
|
||||
return ResultsNode;
|
||||
@@ -543,3 +600,37 @@ jasmineRequire.QueryString = function() {
|
||||
|
||||
return QueryString;
|
||||
};
|
||||
|
||||
jasmineRequire.toHaveClass = function(j$) {
|
||||
/**
|
||||
* {@link expect} the actual value to be a DOM element that has the expected class
|
||||
* @function
|
||||
* @name matchers#toHaveClass
|
||||
* @param {Object} expected - The class name to test for
|
||||
* @example
|
||||
* var el = document.createElement('div');
|
||||
* el.className = 'foo bar baz';
|
||||
* expect(el).toHaveClass('bar');
|
||||
*/
|
||||
function toHaveClass(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
if (!isElement(actual)) {
|
||||
throw new Error(j$.pp(actual) + ' is not a DOM element');
|
||||
}
|
||||
|
||||
return {
|
||||
pass: actual.classList.contains(expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function isElement(maybeEl) {
|
||||
return maybeEl &&
|
||||
maybeEl.classList &&
|
||||
j$.isFunction_(maybeEl.classList.contains);
|
||||
}
|
||||
|
||||
return toHaveClass;
|
||||
};
|
||||
|
||||
@@ -18,8 +18,8 @@ body { overflow-y: scroll; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed:before { color: #007069; content: "\02022"; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed { line-height: 9px; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled { font-size: 14px; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled:before { color: #bababa; content: "\02022"; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-excluded { font-size: 14px; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-excluded:before { color: #bababa; content: "\02022"; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending { line-height: 17px; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending:before { color: #ba9d37; content: "*"; }
|
||||
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty { font-size: 14px; }
|
||||
@@ -29,11 +29,17 @@ body { overflow-y: scroll; }
|
||||
.jasmine_html-reporter .jasmine-run-options .jasmine-payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; }
|
||||
.jasmine_html-reporter .jasmine-run-options .jasmine-payload.jasmine-open { display: block; }
|
||||
.jasmine_html-reporter .jasmine-bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-failed { background-color: #ca3a11; }
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-failed, .jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; border-bottom: 1px solid #eee; }
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-passed { background-color: #007069; }
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-incomplete { background-color: #bababa; }
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-skipped { background-color: #bababa; }
|
||||
<<<<<<< HEAD
|
||||
||||||| merged common ancestors
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; }
|
||||
=======
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; }
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-warning { background-color: #ba9d37; color: #333; }
|
||||
>>>>>>> master
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-menu { background-color: #fff; color: #aaa; }
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-menu a { color: #333; }
|
||||
.jasmine_html-reporter .jasmine-bar a { color: white; }
|
||||
@@ -47,12 +53,12 @@ body { overflow-y: scroll; }
|
||||
.jasmine_html-reporter .jasmine-summary li.jasmine-failed a { color: #ca3a11; }
|
||||
.jasmine_html-reporter .jasmine-summary li.jasmine-empty a { color: #ba9d37; }
|
||||
.jasmine_html-reporter .jasmine-summary li.jasmine-pending a { color: #ba9d37; }
|
||||
.jasmine_html-reporter .jasmine-summary li.jasmine-disabled a { color: #bababa; }
|
||||
.jasmine_html-reporter .jasmine-summary li.jasmine-excluded a { color: #bababa; }
|
||||
.jasmine_html-reporter .jasmine-description + .jasmine-suite { margin-top: 0; }
|
||||
.jasmine_html-reporter .jasmine-suite { margin-top: 14px; }
|
||||
.jasmine_html-reporter .jasmine-suite a { color: #333; }
|
||||
.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail { margin-bottom: 28px; }
|
||||
.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; }
|
||||
.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; color: white; }
|
||||
.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description a { color: white; }
|
||||
.jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre; }
|
||||
.jasmine_html-reporter .jasmine-result-message span.jasmine-result { display: block; }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,9 +23,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
module.exports = function(jasmineRequire) {
|
||||
var jasmine = jasmineRequire.core(jasmineRequire);
|
||||
|
||||
var consoleFns = require('../console/console.js');
|
||||
consoleFns.console(consoleFns, jasmine);
|
||||
|
||||
var env = jasmine.getEnv();
|
||||
|
||||
var jasmineInterface = jasmineRequire.interface(jasmine, env);
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
#
|
||||
module Jasmine
|
||||
module Core
|
||||
VERSION = "2.99.0"
|
||||
VERSION = "3.0.0"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jasmine-core",
|
||||
"license": "MIT",
|
||||
"version": "2.99.0",
|
||||
"version": "3.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jasmine/jasmine.git"
|
||||
|
||||
82
release_notes/3.0.md
Normal file
82
release_notes/3.0.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Jasmine-Core 3.0 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
Jasmine 3.0 is a major release of Jasmine, and as such includes some breaking changes in addition to various new features.
|
||||
|
||||
There is also a 2.99 release of Jasmine that will present deprecation warnings for suites that will encounter different behavior in 3.0.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
* Replace old "catch exceptions" logic with proper fail fast with error reporting
|
||||
- Fixes [#414](https://github.com/jasmine/jasmine/issues/414)
|
||||
- Fixes [jasmine/jasmine-npm#16](https://github.com/jasmine/jasmine/jasmine-npm/issues/16)
|
||||
|
||||
* Detect an Error passed to `done` and add an expectation failure
|
||||
- Fixes [#567](https://github.com/jasmine/jasmine/issues/567)
|
||||
|
||||
* Unify status for xdescribe and xit
|
||||
- Ensure *All's only execute if at least one child will run
|
||||
- Specs will report a status of `excluded` instead of disabled
|
||||
- Fixes [#1418](https://github.com/jasmine/jasmine/issues/1418)
|
||||
|
||||
* Suite level errors all report the same way (on suiteDone)
|
||||
|
||||
* Refactor QueueRunner and remove references to functions that Jasmine is done with
|
||||
|
||||
* expect(null).toEqual(jasmine.any(Object)) no longer passes
|
||||
- Fixes [#1255](https://github.com/jasmine/jasmine/issues/1255)
|
||||
|
||||
* Default to running tests in random order
|
||||
|
||||
## Changes
|
||||
|
||||
* Remove node modules from python wheel, and update languages
|
||||
|
||||
* Allow reporter callbacks to be asynchronous
|
||||
- Fixes [#842](https://github.com/jasmine/jasmine/issues/842)
|
||||
|
||||
* Allow adding custom spy strategies
|
||||
|
||||
* Add the ability to specify the strategy to use for a spy based on which parameters are passed
|
||||
|
||||
* Added links to re-run the suites containing a failing spec
|
||||
|
||||
* Added a toHaveClass matcher
|
||||
|
||||
* More informative pretty-printing of DOM elements
|
||||
|
||||
* Allow jasmine-npm to handle its own load errors
|
||||
|
||||
* Treat random= as a no-op rather than disabling randomization
|
||||
|
||||
* Use prototype for spy strategy for better memory management
|
||||
|
||||
* Remove console.js altogether
|
||||
|
||||
* Add safari 10 and update readme to include edge
|
||||
|
||||
* Determine overall status in core, not reporters
|
||||
|
||||
* Filter Jasmine frames from stack traces
|
||||
|
||||
* Treat afterAll errors at any level as failures
|
||||
|
||||
* Improved reporting of load errors and afterAll errors
|
||||
- Pass file and line number to reporters when present
|
||||
- Show file and line number in the HTML reporter when present
|
||||
- Visually separate adjacent errors in the HTML reporter
|
||||
|
||||
* Report loading errors as loading errors, not afterAll errors
|
||||
|
||||
* HTML reporter reports overall failure if there are any global errors
|
||||
|
||||
* Fail if error events (e.g. syntax errors) occur during loading
|
||||
|
||||
* Allow use of a predicate function to validate thrown exceptions
|
||||
|
||||
* Check truthiness of toThrowError args, not arg count
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
3
setup.py
3
setup.py
@@ -23,9 +23,6 @@ setup(
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
|
||||
@@ -1,270 +0,0 @@
|
||||
describe("ConsoleReporter", function() {
|
||||
var out;
|
||||
|
||||
beforeEach(function() {
|
||||
out = (function() {
|
||||
var output = "";
|
||||
return {
|
||||
print: function(str) {
|
||||
output += str;
|
||||
},
|
||||
getOutput: function() {
|
||||
return output.replace('ConsoleReporter is deprecated and will be removed in a future version.', '');
|
||||
},
|
||||
clear: function() {
|
||||
output = "";
|
||||
}
|
||||
};
|
||||
}());
|
||||
});
|
||||
|
||||
it("reports that the suite has started to the console", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
|
||||
expect(out.getOutput()).toEqual("Started\n");
|
||||
});
|
||||
|
||||
it("starts the provided timer when jasmine starts", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start']),
|
||||
reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print,
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
|
||||
expect(timerSpy.start).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reports a passing spec as a dot", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.specDone({status: "passed"});
|
||||
|
||||
expect(out.getOutput()).toEqual(".");
|
||||
});
|
||||
|
||||
it("does not report a disabled spec", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.specDone({status: "disabled"});
|
||||
|
||||
expect(out.getOutput()).toEqual("");
|
||||
});
|
||||
|
||||
it("reports a failing spec as an 'F'", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.specDone({status: "failed"});
|
||||
|
||||
expect(out.getOutput()).toEqual("F");
|
||||
});
|
||||
|
||||
it("reports a pending spec as a '*'", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.specDone({status: "pending"});
|
||||
|
||||
expect(out.getOutput()).toEqual("*");
|
||||
});
|
||||
|
||||
it("alerts user if there are no specs", function(){
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
out.clear();
|
||||
reporter.jasmineDone();
|
||||
|
||||
expect(out.getOutput()).toMatch(/No specs found/);
|
||||
});
|
||||
|
||||
it("reports a summary when done (singular spec and time)", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print,
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
reporter.specDone({status: "passed"});
|
||||
|
||||
timerSpy.elapsed.and.returnValue(1000);
|
||||
|
||||
out.clear();
|
||||
reporter.jasmineDone();
|
||||
|
||||
expect(out.getOutput()).toMatch(/1 spec, 0 failures/);
|
||||
expect(out.getOutput()).not.toMatch(/0 pending specs/);
|
||||
expect(out.getOutput()).toMatch("Finished in 1 second\n");
|
||||
});
|
||||
|
||||
it("reports a summary when done (pluralized specs and seconds)", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print,
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
reporter.specDone({status: "passed"});
|
||||
reporter.specDone({status: "pending"});
|
||||
reporter.specDone({
|
||||
status: "failed",
|
||||
description: "with a failing spec",
|
||||
fullName: "A suite with a failing spec",
|
||||
failedExpectations: [
|
||||
{
|
||||
passed: false,
|
||||
message: "Expected true to be false.",
|
||||
expected: false,
|
||||
actual: true,
|
||||
stack: "foo\nbar\nbaz"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
out.clear();
|
||||
|
||||
timerSpy.elapsed.and.returnValue(100);
|
||||
|
||||
reporter.jasmineDone();
|
||||
|
||||
expect(out.getOutput()).toMatch(/3 specs, 1 failure, 1 pending spec/);
|
||||
expect(out.getOutput()).toMatch("Finished in 0.1 seconds\n");
|
||||
});
|
||||
|
||||
it("reports a summary when done that includes stack traces for a failing suite", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
reporter.specDone({status: "passed"});
|
||||
reporter.specDone({
|
||||
status: "failed",
|
||||
description: "with a failing spec",
|
||||
fullName: "A suite with a failing spec",
|
||||
failedExpectations: [
|
||||
{
|
||||
passed: false,
|
||||
message: "Expected true to be false.",
|
||||
expected: false,
|
||||
actual: true,
|
||||
stack: "foo bar baz"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
out.clear();
|
||||
|
||||
reporter.jasmineDone();
|
||||
|
||||
expect(out.getOutput()).toMatch(/true to be false/);
|
||||
expect(out.getOutput()).toMatch(/foo bar baz/);
|
||||
});
|
||||
|
||||
describe('onComplete callback', function(){
|
||||
var onComplete, reporter;
|
||||
|
||||
beforeEach(function() {
|
||||
onComplete = jasmine.createSpy('onComplete');
|
||||
reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print,
|
||||
onComplete: onComplete
|
||||
});
|
||||
reporter.jasmineStarted();
|
||||
});
|
||||
|
||||
it("is called when the suite is done", function() {
|
||||
reporter.jasmineDone();
|
||||
expect(onComplete).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('calls it with false if there are spec failures', function() {
|
||||
reporter.specDone({status: "failed", failedExpectations: []});
|
||||
reporter.jasmineDone();
|
||||
expect(onComplete).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('calls it with false if there are suite failures', function() {
|
||||
reporter.specDone({status: "passed"});
|
||||
reporter.suiteDone({failedExpectations: [{ message: 'bananas' }] });
|
||||
reporter.jasmineDone();
|
||||
expect(onComplete).toHaveBeenCalledWith(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with color", function() {
|
||||
it("reports that the suite has started to the console", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print,
|
||||
showColors: true
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
|
||||
expect(out.getOutput()).toEqual("Started\n");
|
||||
});
|
||||
|
||||
it("reports a passing spec as a dot", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print,
|
||||
showColors: true
|
||||
});
|
||||
|
||||
reporter.specDone({status: "passed"});
|
||||
|
||||
expect(out.getOutput()).toEqual("\x1B[32m.\x1B[0m");
|
||||
});
|
||||
|
||||
it("does not report a disabled spec", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print,
|
||||
showColors: true
|
||||
});
|
||||
|
||||
reporter.specDone({status: 'disabled'});
|
||||
|
||||
expect(out.getOutput()).toEqual("");
|
||||
});
|
||||
|
||||
it("reports a failing spec as an 'F'", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print,
|
||||
showColors: true
|
||||
});
|
||||
|
||||
reporter.specDone({status: 'failed'});
|
||||
|
||||
expect(out.getOutput()).toEqual("\x1B[31mF\x1B[0m");
|
||||
});
|
||||
|
||||
it("displays all afterAll exceptions", function() {
|
||||
var reporter = new jasmineUnderTest.ConsoleReporter({
|
||||
print: out.print,
|
||||
showColors: true
|
||||
});
|
||||
|
||||
reporter.suiteDone({ failedExpectations: [{ message: 'After All Exception' }] });
|
||||
reporter.suiteDone({ failedExpectations: [{ message: 'Some Other Exception' }] });
|
||||
reporter.jasmineDone();
|
||||
|
||||
expect(out.getOutput()).toMatch(/After All Exception/);
|
||||
expect(out.getOutput()).toMatch(/Some Other Exception/);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -411,50 +411,6 @@ describe("Clock", function() {
|
||||
clock.tick(50);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
it("on IE < 9, fails if extra args are passed to fake clock", function() {
|
||||
//fail, because this would break in IE9.
|
||||
var fakeSetTimeout = jasmine.createSpy('setTimeout'),
|
||||
fakeSetInterval = jasmine.createSpy('setInterval'),
|
||||
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
fakeGlobal = {
|
||||
setTimeout: fakeSetTimeout,
|
||||
setInterval: fakeSetInterval
|
||||
},
|
||||
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
|
||||
clock = new jasmineUnderTest.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
|
||||
timeout = new clock.FakeTimeout();
|
||||
|
||||
fakeSetTimeout.apply = null;
|
||||
fakeSetInterval.apply = null;
|
||||
|
||||
clock.install();
|
||||
|
||||
clock.setTimeout(fn, 0);
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, []);
|
||||
} else {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, [], false, timeout);
|
||||
}
|
||||
|
||||
expect(function() {
|
||||
clock.setTimeout(fn, 0, 'extra');
|
||||
}).toThrow();
|
||||
|
||||
clock.setInterval(fn, 0);
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, [], true);
|
||||
} else {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, [], true, timeout);
|
||||
}
|
||||
|
||||
expect(function() {
|
||||
clock.setInterval(fn, 0, 'extra');
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Clock (acceptance)", function() {
|
||||
|
||||
@@ -47,15 +47,72 @@ describe("ExceptionFormatter", function() {
|
||||
});
|
||||
|
||||
describe("#stack", function() {
|
||||
it("formats stack traces from Webkit, Firefox, node.js or IE10+", function() {
|
||||
if (jasmine.getEnv().ieVersion < 10 || jasmine.getEnv().safariVersion < 6) { return; }
|
||||
|
||||
it("formats stack traces", function() {
|
||||
var error;
|
||||
try { throw new Error("an error") } catch(e) { error = e; }
|
||||
|
||||
expect(new jasmineUnderTest.ExceptionFormatter().stack(error)).toMatch(/ExceptionFormatterSpec\.js.*\d+/)
|
||||
});
|
||||
|
||||
it("filters Jasmine stack frames from V8 style traces", function() {
|
||||
var error = {
|
||||
stack: 'Error: nope\n' +
|
||||
' at fn1 (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||
' at fn2 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
|
||||
' at fn3 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
|
||||
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)\n'
|
||||
};
|
||||
var subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||
});
|
||||
var result = subject.stack(error);
|
||||
expect(result).toEqual('Error: nope\n' +
|
||||
' at fn1 (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||
' at <Jasmine>\n' +
|
||||
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)'
|
||||
);
|
||||
});
|
||||
|
||||
it("filters Jamine stack frames from Webkit style traces", function() {
|
||||
var error = {
|
||||
stack: 'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||
'fn1@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||
'fn2@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
|
||||
};
|
||||
var subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||
});
|
||||
var result = subject.stack(error);
|
||||
expect(result).toEqual(
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||
'<Jasmine>\n' +
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
|
||||
);
|
||||
});
|
||||
|
||||
it("filters Jasmine stack frames in this environment", function() {
|
||||
var error, i;
|
||||
try { throw new Error("an error"); } catch(e) { error = e; }
|
||||
var subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
jasmineFile: jasmine.util.jasmineFile()
|
||||
});
|
||||
var result = subject.stack(error);
|
||||
var lines = result.split('\n');
|
||||
|
||||
if (lines[0].match(/an error/)) {
|
||||
lines.shift();
|
||||
}
|
||||
|
||||
expect(lines[0]).toMatch(/ExceptionFormatterSpec.js/);
|
||||
expect(lines[1]).toMatch(/<Jasmine>/);
|
||||
|
||||
// Node has some number of additional frames below Jasmine.
|
||||
for (i = 2; i < lines.length; i++) {
|
||||
expect(lines[i]).not.toMatch(/jasmine.js/);
|
||||
}
|
||||
});
|
||||
|
||||
it("returns null if no Error provided", function() {
|
||||
expect(new jasmineUnderTest.ExceptionFormatter().stack()).toBeNull();
|
||||
});
|
||||
|
||||
@@ -5,64 +5,42 @@ describe('Exceptions:', function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
});
|
||||
|
||||
describe('with break on exception', function() {
|
||||
it('should not catch the exception', function() {
|
||||
env.catchExceptions(false);
|
||||
env.describe('suite for break on exceptions', function() {
|
||||
env.it('should break when an exception is thrown', function() {
|
||||
throw new Error('I should hit a breakpoint!');
|
||||
});
|
||||
it('should handle exceptions thrown, but continue', function(done) {
|
||||
var secondTest = jasmine.createSpy('second test');
|
||||
env.describe('Suite for handles exceptions', function () {
|
||||
env.it('should be a test that fails because it throws an exception', function() {
|
||||
throw new Error();
|
||||
});
|
||||
var spy = jasmine.createSpy('spy');
|
||||
|
||||
try {
|
||||
env.execute();
|
||||
spy();
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
env.it('should be a passing test that runs after exceptions are thrown from a async test', secondTest);
|
||||
});
|
||||
|
||||
var expectations = function() {
|
||||
expect(secondTest).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: expectations });
|
||||
env.execute();
|
||||
});
|
||||
|
||||
describe("with catch on exception", function() {
|
||||
it('should handle exceptions thrown, but continue', function(done) {
|
||||
var secondTest = jasmine.createSpy('second test');
|
||||
env.describe('Suite for handles exceptions', function () {
|
||||
env.it('should be a test that fails because it throws an exception', function() {
|
||||
throw new Error();
|
||||
});
|
||||
env.it('should be a passing test that runs after exceptions are thrown from a async test', secondTest);
|
||||
it("should handle exceptions thrown directly in top-level describe blocks and continue", function(done) {
|
||||
var secondDescribe = jasmine.createSpy("second describe");
|
||||
env.describe("a suite that throws an exception", function () {
|
||||
env.it("is a test that should pass", function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
|
||||
var expectations = function() {
|
||||
expect(secondTest).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: expectations });
|
||||
env.execute();
|
||||
throw new Error("top level error");
|
||||
});
|
||||
env.describe("a suite that doesn't throw an exception", secondDescribe);
|
||||
|
||||
it("should handle exceptions thrown directly in top-level describe blocks and continue", function(done) {
|
||||
var secondDescribe = jasmine.createSpy("second describe");
|
||||
env.describe("a suite that throws an exception", function () {
|
||||
env.it("is a test that should pass", function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
var expectations = function() {
|
||||
expect(secondDescribe).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
throw new Error("top level error");
|
||||
});
|
||||
env.describe("a suite that doesn't throw an exception", secondDescribe);
|
||||
|
||||
var expectations = function() {
|
||||
expect(secondDescribe).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: expectations });
|
||||
env.execute();
|
||||
});
|
||||
env.addReporter({ jasmineDone: expectations });
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ describe("JsApiReporter", function() {
|
||||
};
|
||||
suiteResult2 = {
|
||||
id: 2,
|
||||
status: 'finished'
|
||||
status: 'passed'
|
||||
};
|
||||
|
||||
reporter.suiteStarted(suiteStarted1);
|
||||
|
||||
@@ -268,12 +268,17 @@ describe("jasmineUnderTest.pp", function () {
|
||||
},
|
||||
env = new jasmineUnderTest.Env();
|
||||
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() {return [];}});
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() {return [];},
|
||||
createSpy: function(name, originalFn) {
|
||||
return jasmineUnderTest.Spy(name, originalFn);
|
||||
}
|
||||
});
|
||||
|
||||
spyRegistry.spyOn(TestObject, 'someFunction');
|
||||
expect(jasmineUnderTest.pp(TestObject.someFunction)).toEqual("spy on someFunction");
|
||||
|
||||
expect(jasmineUnderTest.pp(jasmineUnderTest.createSpy("something"))).toEqual("spy on something");
|
||||
expect(jasmineUnderTest.pp(env.createSpy("something"))).toEqual("spy on something");
|
||||
});
|
||||
|
||||
it("should stringify objects that implement jasmineToString", function () {
|
||||
@@ -298,11 +303,7 @@ describe("jasmineUnderTest.pp", function () {
|
||||
toString: function () { return Object.prototype.toString.call(this); }
|
||||
};
|
||||
|
||||
if (jasmine.getEnv().ieVersion < 9) {
|
||||
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar' })");
|
||||
} else {
|
||||
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar', toString: Function })");
|
||||
}
|
||||
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar', toString: Function })");
|
||||
});
|
||||
|
||||
it("should stringify objects have have a toString that isn't a function", function() {
|
||||
@@ -310,11 +311,7 @@ describe("jasmineUnderTest.pp", function () {
|
||||
toString: "foo"
|
||||
};
|
||||
|
||||
if (jasmine.getEnv().ieVersion < 9) {
|
||||
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ })");
|
||||
} else {
|
||||
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ toString: 'foo' })");
|
||||
}
|
||||
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ toString: 'foo' })");
|
||||
});
|
||||
|
||||
it("should stringify objects from anonymous constructors with custom toString", function () {
|
||||
@@ -327,8 +324,6 @@ describe("jasmineUnderTest.pp", function () {
|
||||
});
|
||||
|
||||
it("should handle objects with null prototype", function() {
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var obj = Object.create(null);
|
||||
obj.foo = 'bar';
|
||||
|
||||
|
||||
@@ -135,6 +135,52 @@ describe("QueueRunner", function() {
|
||||
expect(queueableFn2.fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("explicitly fails an async function when next is called with an Error and moves to the next function", function() {
|
||||
var err = new Error('foo'),
|
||||
queueableFn1 = { fn: function(done) {
|
||||
setTimeout(function() { done(err); }, 100);
|
||||
} },
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
fail: failFn
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
expect(failFn).not.toHaveBeenCalled();
|
||||
expect(queueableFn2.fn).not.toHaveBeenCalled();
|
||||
|
||||
jasmine.clock().tick(100);
|
||||
|
||||
expect(failFn).toHaveBeenCalledWith(err);
|
||||
expect(queueableFn2.fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not cause an explicit fail if execution is being stopped", function() {
|
||||
var err = new jasmineUnderTest.StopExecutionError('foo'),
|
||||
queueableFn1 = { fn: function(done) {
|
||||
setTimeout(function() { done(err); }, 100);
|
||||
} },
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
fail: failFn
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
expect(failFn).not.toHaveBeenCalled();
|
||||
expect(queueableFn2.fn).not.toHaveBeenCalled();
|
||||
|
||||
jasmine.clock().tick(100);
|
||||
|
||||
expect(failFn).not.toHaveBeenCalled();
|
||||
expect(queueableFn2.fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("sets a timeout if requested for asynchronous functions so they don't go on forever", function() {
|
||||
var timeout = 3,
|
||||
beforeFn = { fn: function(done) { }, type: 'before', timeout: function() { return timeout; } },
|
||||
@@ -419,20 +465,6 @@ describe("QueueRunner", function() {
|
||||
expect(onExceptionCallback).toHaveBeenCalledWith(jasmine.any(Error));
|
||||
});
|
||||
|
||||
it("rethrows an exception if told to", function() {
|
||||
var queueableFn = { fn: function() {
|
||||
throw new Error('fake error');
|
||||
} },
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
catchException: function(e) { return false; }
|
||||
});
|
||||
|
||||
expect(function() {
|
||||
queueRunner.execute();
|
||||
}).toThrowError('fake error');
|
||||
});
|
||||
|
||||
it("continues running the functions even after an exception is thrown in an async spec", function() {
|
||||
var queueableFn = { fn: function(done) { throw new Error("error"); } },
|
||||
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
|
||||
@@ -522,6 +554,24 @@ describe("QueueRunner", function() {
|
||||
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
|
||||
expect(cleanupFn.fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("skips to cleanup functions when next is called with an Error", function() {
|
||||
var queueableFn = { fn: function(done) {
|
||||
done(new Error('nope'));
|
||||
} },
|
||||
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
|
||||
cleanupFn = { fn: jasmine.createSpy('cleanup') },
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, nextQueueableFn],
|
||||
cleanupFns: [cleanupFn],
|
||||
completeOnFirstError: true,
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
jasmine.clock().tick();
|
||||
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
|
||||
expect(cleanupFn.fn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -9,70 +9,131 @@ describe("ReportDispatcher", function() {
|
||||
});
|
||||
|
||||
it("dispatches requested methods to added reporters", function() {
|
||||
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
|
||||
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar'], queueRunnerFactory),
|
||||
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
|
||||
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
|
||||
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
|
||||
completeCallback = jasmine.createSpy('complete');
|
||||
|
||||
dispatcher.addReporter(reporter);
|
||||
dispatcher.addReporter(anotherReporter);
|
||||
|
||||
dispatcher.foo(123, 456);
|
||||
dispatcher.foo(123, 456, completeCallback);
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
queueableFns: [{fn: jasmine.any(Function)}, {fn: jasmine.any(Function)}],
|
||||
isReporter: true
|
||||
}));
|
||||
|
||||
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
expect(reporter.foo.calls.mostRecent().object).toBe(reporter);
|
||||
|
||||
fns[1].fn();
|
||||
expect(anotherReporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
expect(anotherReporter.foo.calls.mostRecent().object).toBe(anotherReporter);
|
||||
|
||||
dispatcher.bar('a', 'b');
|
||||
queueRunnerFactory.calls.reset();
|
||||
|
||||
dispatcher.bar('a', 'b', completeCallback);
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
queueableFns: [{fn: jasmine.any(Function)}, {fn: jasmine.any(Function)}],
|
||||
isReporter: true
|
||||
}));
|
||||
|
||||
fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter.bar).toHaveBeenCalledWith('a', 'b');
|
||||
|
||||
fns[1].fn();
|
||||
expect(anotherReporter.bar).toHaveBeenCalledWith('a', 'b');
|
||||
});
|
||||
|
||||
it("does not dispatch to a reporter if the reporter doesn't accept the method", function() {
|
||||
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo']),
|
||||
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo'], queueRunnerFactory),
|
||||
reporter = jasmine.createSpyObj('reporter', ['baz']);
|
||||
|
||||
dispatcher.addReporter(reporter);
|
||||
|
||||
expect(function() {
|
||||
dispatcher.foo(123, 456);
|
||||
}).not.toThrow();
|
||||
dispatcher.foo(123, 456);
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
queueableFns: []
|
||||
}));
|
||||
});
|
||||
|
||||
it("allows providing a fallback reporter in case there's no other report", function() {
|
||||
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
|
||||
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
|
||||
it("allows providing a fallback reporter in case there's no other reporter", function() {
|
||||
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar'], queueRunnerFactory),
|
||||
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
|
||||
completeCallback = jasmine.createSpy('complete');
|
||||
|
||||
dispatcher.provideFallbackReporter(reporter);
|
||||
dispatcher.foo(123, 456);
|
||||
dispatcher.foo(123, 456, completeCallback);
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
queueableFns: [{fn: jasmine.any(Function)}],
|
||||
isReporter: true
|
||||
}));
|
||||
|
||||
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
});
|
||||
|
||||
it("does not call fallback reporting methods when another report is provided", function() {
|
||||
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
|
||||
it("does not call fallback reporting methods when another reporter is provided", function() {
|
||||
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar'], queueRunnerFactory),
|
||||
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
|
||||
fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']);
|
||||
fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']),
|
||||
completeCallback = jasmine.createSpy('complete');
|
||||
|
||||
dispatcher.provideFallbackReporter(fallbackReporter);
|
||||
dispatcher.addReporter(reporter);
|
||||
dispatcher.foo(123, 456);
|
||||
dispatcher.foo(123, 456, completeCallback);
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
queueableFns: [{fn: jasmine.any(Function)}],
|
||||
isReporter: true
|
||||
}));
|
||||
|
||||
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
expect(fallbackReporter.foo).not.toHaveBeenCalledWith(123, 456);
|
||||
});
|
||||
|
||||
it("allows registered reporters to be cleared", function() {
|
||||
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
|
||||
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar'], queueRunnerFactory),
|
||||
reporter1 = jasmine.createSpyObj('reporter1', ['foo', 'bar']),
|
||||
reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']);
|
||||
reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']),
|
||||
completeCallback = jasmine.createSpy('complete');
|
||||
|
||||
dispatcher.addReporter(reporter1);
|
||||
dispatcher.foo(123);
|
||||
dispatcher.foo(123, completeCallback);
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
queueableFns: [{fn: jasmine.any(Function)}],
|
||||
isReporter: true
|
||||
}));
|
||||
|
||||
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter1.foo).toHaveBeenCalledWith(123);
|
||||
|
||||
dispatcher.clearReporters();
|
||||
dispatcher.addReporter(reporter2);
|
||||
dispatcher.bar(456);
|
||||
dispatcher.bar(456, completeCallback);
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
queueableFns: [{fn: jasmine.any(Function)}],
|
||||
isReporter: true
|
||||
}));
|
||||
|
||||
fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter1.bar).not.toHaveBeenCalled();
|
||||
expect(reporter2.bar).toHaveBeenCalledWith(456);
|
||||
});
|
||||
|
||||
@@ -55,6 +55,7 @@ describe("Spec", function() {
|
||||
|
||||
spec.execute();
|
||||
|
||||
fakeQueueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
// TODO: due to some issue with the Pretty Printer, this line fails, but the other two pass.
|
||||
// This means toHaveBeenCalledWith on IE8 will always be broken.
|
||||
|
||||
@@ -82,6 +83,7 @@ describe("Spec", function() {
|
||||
|
||||
spec.execute();
|
||||
|
||||
fakeQueueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
expect(startCallback).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -104,8 +106,8 @@ describe("Spec", function() {
|
||||
spec.execute();
|
||||
|
||||
var options = fakeQueueRunner.calls.mostRecent().args[0];
|
||||
expect(options.queueableFns).toEqual([before, queueableFn]);
|
||||
expect(options.cleanupFns).toEqual([after]);
|
||||
expect(options.queueableFns).toEqual([{fn: jasmine.any(Function)}, before, queueableFn]);
|
||||
expect(options.cleanupFns).toEqual([after, {fn: jasmine.any(Function)}]);
|
||||
});
|
||||
|
||||
it("tells the queue runner that it's a leaf node", function() {
|
||||
@@ -140,9 +142,8 @@ describe("Spec", function() {
|
||||
expect(spec.status()).toBe('pending');
|
||||
});
|
||||
|
||||
it("can be disabled, but still calls callbacks", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner')
|
||||
.and.callFake(function(attrs) { attrs.onComplete(); }),
|
||||
it("can be excluded at execution time by a parent", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
|
||||
startCallback = jasmine.createSpy('startCallback'),
|
||||
specBody = jasmine.createSpy('specBody'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
@@ -153,46 +154,26 @@ describe("Spec", function() {
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.disable();
|
||||
spec.execute('cally-back', true);
|
||||
|
||||
expect(spec.status()).toBe('disabled');
|
||||
|
||||
spec.execute();
|
||||
|
||||
expect(fakeQueueRunner).toHaveBeenCalled();
|
||||
expect(fakeQueueRunner).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||
onComplete: jasmine.any(Function),
|
||||
queueableFns: [{fn: jasmine.any(Function)}],
|
||||
cleanupFns: [{fn: jasmine.any(Function)}]
|
||||
}));
|
||||
expect(specBody).not.toHaveBeenCalled();
|
||||
|
||||
var args = fakeQueueRunner.calls.mostRecent().args[0];
|
||||
args.queueableFns[0].fn();
|
||||
expect(startCallback).toHaveBeenCalled();
|
||||
args.cleanupFns[0].fn();
|
||||
expect(resultCallback).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("can be disabled at execution time by a parent", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner')
|
||||
.and.callFake(function(attrs) { attrs.onComplete(); }),
|
||||
startCallback = jasmine.createSpy('startCallback'),
|
||||
specBody = jasmine.createSpy('specBody'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
spec = new jasmineUnderTest.Spec({
|
||||
onStart:startCallback,
|
||||
queueableFn: { fn: specBody },
|
||||
resultCallback: resultCallback,
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute(undefined, false);
|
||||
|
||||
expect(spec.result.status).toBe('disabled');
|
||||
|
||||
expect(fakeQueueRunner).toHaveBeenCalled();
|
||||
expect(specBody).not.toHaveBeenCalled();
|
||||
|
||||
expect(startCallback).toHaveBeenCalled();
|
||||
expect(resultCallback).toHaveBeenCalled();
|
||||
expect(spec.result.status).toBe('excluded');
|
||||
});
|
||||
|
||||
it("can be marked pending, but still calls callbacks when executed", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner')
|
||||
.and.callFake(function(attrs) { attrs.onComplete(); }),
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
|
||||
startCallback = jasmine.createSpy('startCallback'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
spec = new jasmineUnderTest.Spec({
|
||||
@@ -214,7 +195,10 @@ describe("Spec", function() {
|
||||
|
||||
expect(fakeQueueRunner).toHaveBeenCalled();
|
||||
|
||||
var args = fakeQueueRunner.calls.mostRecent().args[0];
|
||||
args.queueableFns[0].fn();
|
||||
expect(startCallback).toHaveBeenCalled();
|
||||
args.cleanupFns[0].fn('things');
|
||||
expect(resultCallback).toHaveBeenCalledWith({
|
||||
id: spec.id,
|
||||
status: 'pending',
|
||||
@@ -224,7 +208,7 @@ describe("Spec", function() {
|
||||
passedExpectations: [],
|
||||
deprecationWarnings: [],
|
||||
pendingReason: ''
|
||||
});
|
||||
}, 'things');
|
||||
});
|
||||
|
||||
it("should call the done callback on execution complete", function() {
|
||||
@@ -241,6 +225,23 @@ describe("Spec", function() {
|
||||
expect(done).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call the done callback with an error if the spec is failed", function() {
|
||||
var done = jasmine.createSpy('done callback'),
|
||||
spec = new jasmineUnderTest.Spec({
|
||||
queueableFn: { fn: function() {} },
|
||||
catchExceptions: function() { return false; },
|
||||
resultCallback: function() {},
|
||||
queueRunnerFactory: function(attrs) {
|
||||
spec.result.status = 'failed';
|
||||
attrs.onComplete();
|
||||
}
|
||||
});
|
||||
|
||||
spec.execute(done);
|
||||
|
||||
expect(done).toHaveBeenCalledWith(jasmine.any(jasmineUnderTest.StopExecutionError));
|
||||
});
|
||||
|
||||
it("#status returns passing by default", function() {
|
||||
var spec = new jasmineUnderTest.Spec({queueableFn: { fn: jasmine.createSpy("spec body")} });
|
||||
expect(spec.status()).toBe('passed');
|
||||
@@ -260,11 +261,12 @@ describe("Spec", function() {
|
||||
});
|
||||
|
||||
it("keeps track of passed and failed expectations", function() {
|
||||
var resultCallback = jasmine.createSpy('resultCallback'),
|
||||
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
spec = new jasmineUnderTest.Spec({
|
||||
queueableFn: { fn: jasmine.createSpy("spec body") },
|
||||
expectationResultFactory: function (data) { return data; },
|
||||
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
|
||||
queueRunnerFactory: fakeQueueRunner,
|
||||
resultCallback: resultCallback
|
||||
});
|
||||
spec.addExpectationResult(true, 'expectation1');
|
||||
@@ -272,19 +274,21 @@ describe("Spec", function() {
|
||||
|
||||
spec.execute();
|
||||
|
||||
fakeQueueRunner.calls.mostRecent().args[0].cleanupFns[0].fn();
|
||||
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual(['expectation1']);
|
||||
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual(['expectation2']);
|
||||
});
|
||||
|
||||
it("throws an ExpectationFailed error upon receiving a failed expectation when 'throwOnExpectationFailure' is set", function() {
|
||||
var resultCallback = jasmine.createSpy('resultCallback'),
|
||||
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
spec = new jasmineUnderTest.Spec({
|
||||
queueableFn: { fn: function() {} },
|
||||
expectationResultFactory: function(data) { return data; },
|
||||
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
|
||||
resultCallback: resultCallback,
|
||||
throwOnExpectationFailure: true
|
||||
});
|
||||
queueableFn: { fn: function() {} },
|
||||
expectationResultFactory: function(data) { return data; },
|
||||
queueRunnerFactory: fakeQueueRunner,
|
||||
resultCallback: resultCallback,
|
||||
throwOnExpectationFailure: true
|
||||
});
|
||||
|
||||
spec.addExpectationResult(true, 'passed');
|
||||
expect(function() {
|
||||
@@ -293,6 +297,7 @@ describe("Spec", function() {
|
||||
|
||||
spec.execute();
|
||||
|
||||
fakeQueueRunner.calls.mostRecent().args[0].cleanupFns[0].fn();
|
||||
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual(['passed']);
|
||||
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual(['failed']);
|
||||
});
|
||||
@@ -359,17 +364,20 @@ describe("Spec", function() {
|
||||
});
|
||||
|
||||
it("should log a failure when handling an exception", function() {
|
||||
var resultCallback = jasmine.createSpy('resultCallback'),
|
||||
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
spec = new jasmineUnderTest.Spec({
|
||||
queueableFn: { fn: function() {} },
|
||||
expectationResultFactory: function(data) { return data; },
|
||||
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
|
||||
queueRunnerFactory: fakeQueueRunner,
|
||||
resultCallback: resultCallback
|
||||
});
|
||||
|
||||
spec.onException('foo');
|
||||
spec.execute();
|
||||
|
||||
var args = fakeQueueRunner.calls.mostRecent().args[0];
|
||||
args.cleanupFns[0].fn();
|
||||
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([{
|
||||
error: 'foo',
|
||||
matcherName: '',
|
||||
@@ -380,63 +388,20 @@ describe("Spec", function() {
|
||||
});
|
||||
|
||||
it("should not log an additional failure when handling an ExpectationFailed error", function() {
|
||||
var resultCallback = jasmine.createSpy('resultCallback'),
|
||||
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
spec = new jasmineUnderTest.Spec({
|
||||
queueableFn: { fn: function() {} },
|
||||
expectationResultFactory: function(data) { return data; },
|
||||
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
|
||||
queueRunnerFactory: fakeQueueRunner,
|
||||
resultCallback: resultCallback
|
||||
});
|
||||
|
||||
spec.onException(new jasmineUnderTest.errors.ExpectationFailed());
|
||||
spec.execute();
|
||||
|
||||
var args = fakeQueueRunner.calls.mostRecent().args[0];
|
||||
args.cleanupFns[0].fn();
|
||||
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([]);
|
||||
});
|
||||
|
||||
it("retrieves a result with updated status", function() {
|
||||
var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: function() {} } });
|
||||
|
||||
expect(spec.getResult().status).toBe('passed');
|
||||
});
|
||||
|
||||
it("retrives a result with disabled status", function() {
|
||||
var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: function() {} } });
|
||||
spec.disable();
|
||||
|
||||
expect(spec.getResult().status).toBe('disabled');
|
||||
});
|
||||
|
||||
it("retrives a result with pending status", function() {
|
||||
var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: function() {} } });
|
||||
spec.pend();
|
||||
|
||||
expect(spec.getResult().status).toBe('pending');
|
||||
});
|
||||
|
||||
it("should not be executable when disabled", function() {
|
||||
var spec = new jasmineUnderTest.Spec({
|
||||
queueableFn: { fn: function() {} }
|
||||
});
|
||||
spec.disable();
|
||||
|
||||
expect(spec.isExecutable()).toBe(false);
|
||||
});
|
||||
|
||||
it("should be executable when pending", function() {
|
||||
var spec = new jasmineUnderTest.Spec({
|
||||
queueableFn: { fn: function() {} }
|
||||
});
|
||||
spec.pend();
|
||||
|
||||
expect(spec.isExecutable()).toBe(true);
|
||||
});
|
||||
|
||||
it("should be executable when not disabled or pending", function() {
|
||||
var spec = new jasmineUnderTest.Spec({
|
||||
queueableFn: { fn: function() {} }
|
||||
});
|
||||
|
||||
expect(spec.isExecutable()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
describe("SpyRegistry", function() {
|
||||
function createSpy(name, originalFn) {
|
||||
return jasmineUnderTest.Spy(name, originalFn);
|
||||
}
|
||||
|
||||
describe("#spyOn", function() {
|
||||
it("checks for the existence of the object", function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry();
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy});
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(void 0, 'pants');
|
||||
}).toThrowError(/could not find an object/);
|
||||
@@ -43,7 +47,10 @@ describe("SpyRegistry", function() {
|
||||
|
||||
it("checks if it has already been spied upon", function() {
|
||||
var spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
createSpy: createSpy
|
||||
}),
|
||||
subject = { spiedFunc: function() {} };
|
||||
|
||||
spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
@@ -54,9 +61,6 @@ describe("SpyRegistry", function() {
|
||||
});
|
||||
|
||||
it("checks if it can be spied upon", function() {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var scope = {};
|
||||
|
||||
function myFunc() {
|
||||
@@ -84,7 +88,7 @@ describe("SpyRegistry", function() {
|
||||
|
||||
it("overrides the method on the object and returns the spy", function() {
|
||||
var originalFunctionWasCalled = false,
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy}),
|
||||
subject = { spiedFunc: function() { originalFunctionWasCalled = true; } };
|
||||
|
||||
var spy = spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
@@ -94,9 +98,6 @@ describe("SpyRegistry", function() {
|
||||
});
|
||||
|
||||
describe("#spyOnProperty", function() {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
it("checks for the existence of the object", function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry();
|
||||
expect(function() {
|
||||
@@ -137,7 +138,7 @@ describe("SpyRegistry", function() {
|
||||
});
|
||||
|
||||
it("checks if it has already been spied upon", function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy}),
|
||||
subject = {};
|
||||
|
||||
Object.defineProperty(subject, 'spiedProp', {
|
||||
@@ -176,7 +177,7 @@ describe("SpyRegistry", function() {
|
||||
});
|
||||
|
||||
it("overrides the property getter on the object and returns the spy", function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy}),
|
||||
subject = {},
|
||||
returnValue = 1;
|
||||
|
||||
@@ -195,7 +196,7 @@ describe("SpyRegistry", function() {
|
||||
});
|
||||
|
||||
it("overrides the property setter on the object and returns the spy", function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy}),
|
||||
subject = {},
|
||||
returnValue = 1;
|
||||
|
||||
@@ -216,7 +217,10 @@ describe("SpyRegistry", function() {
|
||||
describe("#clearSpies", function() {
|
||||
it("restores the original functions on the spied-upon objects", function() {
|
||||
var spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalFunction = function() {},
|
||||
subject = { spiedFunc: originalFunction };
|
||||
|
||||
@@ -228,7 +232,10 @@ describe("SpyRegistry", function() {
|
||||
|
||||
it("restores the original functions, even when that spy has been replace and re-spied upon", function() {
|
||||
var spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalFunction = function() {},
|
||||
subject = { spiedFunc: originalFunction };
|
||||
|
||||
@@ -246,11 +253,11 @@ describe("SpyRegistry", function() {
|
||||
});
|
||||
|
||||
it("does not add a property that the spied-upon object didn't originally have", function() {
|
||||
// IE 8 doesn't support `Object.create`
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalFunction = function() {},
|
||||
subjectParent = {spiedFunc: originalFunction};
|
||||
|
||||
@@ -266,11 +273,11 @@ describe("SpyRegistry", function() {
|
||||
});
|
||||
|
||||
it("restores the original function when it\'s inherited and cannot be deleted", function() {
|
||||
// IE 8 doesn't support `Object.create` or `Object.defineProperty`
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalFunction = function() {},
|
||||
subjectParent = {spiedFunc: originalFunction};
|
||||
|
||||
@@ -297,6 +304,7 @@ describe("SpyRegistry", function() {
|
||||
global = new FakeWindow(),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
createSpy: createSpy,
|
||||
global: global
|
||||
});
|
||||
|
||||
@@ -309,11 +317,11 @@ describe("SpyRegistry", function() {
|
||||
|
||||
describe('spying on properties', function() {
|
||||
it("restores the original properties on the spied-upon objects", function() {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalReturn = 1,
|
||||
subject = {};
|
||||
|
||||
@@ -329,11 +337,11 @@ describe("SpyRegistry", function() {
|
||||
});
|
||||
|
||||
it("does not add a property that the spied-upon object didn't originally have", function() {
|
||||
// IE 8 doesn't support `Object.create`
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalReturn = 1,
|
||||
subjectParent = {};
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
describe('Spies', function () {
|
||||
var env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
});
|
||||
|
||||
describe("createSpy", function() {
|
||||
var TestClass;
|
||||
|
||||
@@ -9,7 +15,7 @@ describe('Spies', function () {
|
||||
});
|
||||
|
||||
it("preserves the properties of the spied function", function() {
|
||||
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
|
||||
expect(spy.bob).toEqual("test");
|
||||
});
|
||||
@@ -18,19 +24,19 @@ describe('Spies', function () {
|
||||
TestClass.prototype.someFunction.and = "turkey";
|
||||
|
||||
expect(function() {
|
||||
jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
}).toThrowError("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
|
||||
});
|
||||
|
||||
it("adds a spyStrategy and callTracker to the spy", function() {
|
||||
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
|
||||
expect(spy.and).toEqual(jasmine.any(jasmineUnderTest.SpyStrategy));
|
||||
expect(spy.calls).toEqual(jasmine.any(jasmineUnderTest.CallTracker));
|
||||
});
|
||||
|
||||
it("tracks the argument of calls", function () {
|
||||
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var trackSpy = spyOn(spy.calls, "track");
|
||||
|
||||
spy("arg");
|
||||
@@ -39,7 +45,7 @@ describe('Spies', function () {
|
||||
});
|
||||
|
||||
it("tracks the context of calls", function () {
|
||||
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var trackSpy = spyOn(spy.calls, "track");
|
||||
|
||||
var contextObject = { spyMethod: spy };
|
||||
@@ -49,7 +55,7 @@ describe('Spies', function () {
|
||||
});
|
||||
|
||||
it("tracks the return value of calls", function () {
|
||||
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var trackSpy = spyOn(spy.calls, "track");
|
||||
|
||||
spy.and.returnValue("return value");
|
||||
@@ -71,7 +77,7 @@ describe('Spies', function () {
|
||||
|
||||
for (var arity = 0; arity < functions.length; arity++) {
|
||||
var someFunction = functions[arity],
|
||||
spy = jasmineUnderTest.createSpy(someFunction.name, someFunction);
|
||||
spy = env.createSpy(someFunction.name, someFunction);
|
||||
|
||||
expect(spy.length).toEqual(arity);
|
||||
}
|
||||
@@ -80,48 +86,92 @@ describe('Spies', function () {
|
||||
|
||||
describe("createSpyObj", function() {
|
||||
it("should create an object with spy methods and corresponding return values when you call jasmine.createSpyObj() with an object", function () {
|
||||
var spyObj = jasmineUnderTest.createSpyObj('BaseName', {'method1': 42, 'method2': 'special sauce' });
|
||||
var spyObj = env.createSpyObj('BaseName', {'method1': 42, 'method2': 'special sauce' });
|
||||
|
||||
expect(spyObj.method1()).toEqual(42);
|
||||
expect(spyObj.method1.and.identity()).toEqual('BaseName.method1');
|
||||
expect(spyObj.method1.and.identity).toEqual('BaseName.method1');
|
||||
|
||||
expect(spyObj.method2()).toEqual('special sauce');
|
||||
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
|
||||
expect(spyObj.method2.and.identity).toEqual('BaseName.method2');
|
||||
});
|
||||
|
||||
|
||||
it("should create an object with a bunch of spy methods when you call jasmine.createSpyObj()", function() {
|
||||
var spyObj = jasmineUnderTest.createSpyObj('BaseName', ['method1', 'method2']);
|
||||
var spyObj = env.createSpyObj('BaseName', ['method1', 'method2']);
|
||||
|
||||
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
|
||||
expect(spyObj.method1.and.identity()).toEqual('BaseName.method1');
|
||||
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
|
||||
expect(spyObj.method1.and.identity).toEqual('BaseName.method1');
|
||||
expect(spyObj.method2.and.identity).toEqual('BaseName.method2');
|
||||
});
|
||||
|
||||
it("should allow you to omit the baseName", function() {
|
||||
var spyObj = jasmineUnderTest.createSpyObj(['method1', 'method2']);
|
||||
var spyObj = env.createSpyObj(['method1', 'method2']);
|
||||
|
||||
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
|
||||
expect(spyObj.method1.and.identity()).toEqual('unknown.method1');
|
||||
expect(spyObj.method2.and.identity()).toEqual('unknown.method2');
|
||||
expect(spyObj.method1.and.identity).toEqual('unknown.method1');
|
||||
expect(spyObj.method2.and.identity).toEqual('unknown.method2');
|
||||
});
|
||||
|
||||
it("should throw if you do not pass an array or object argument", function() {
|
||||
expect(function() {
|
||||
jasmineUnderTest.createSpyObj('BaseName');
|
||||
env.createSpyObj('BaseName');
|
||||
}).toThrow("createSpyObj requires a non-empty array or object of method names to create spies for");
|
||||
});
|
||||
|
||||
it("should throw if you pass an empty array argument", function() {
|
||||
expect(function() {
|
||||
jasmineUnderTest.createSpyObj('BaseName', []);
|
||||
env.createSpyObj('BaseName', []);
|
||||
}).toThrow("createSpyObj requires a non-empty array or object of method names to create spies for");
|
||||
});
|
||||
|
||||
it("should throw if you pass an empty object argument", function() {
|
||||
expect(function() {
|
||||
jasmineUnderTest.createSpyObj('BaseName', {});
|
||||
env.createSpyObj('BaseName', {});
|
||||
}).toThrow("createSpyObj requires a non-empty array or object of method names to create spies for");
|
||||
});
|
||||
});
|
||||
|
||||
it("can use different strategies for different arguments", function() {
|
||||
var spy = env.createSpy('foo');
|
||||
spy.and.returnValue(42);
|
||||
spy.withArgs('baz', 'grault').and.returnValue(-1);
|
||||
spy.withArgs('thud').and.returnValue('bob');
|
||||
|
||||
expect(spy('foo')).toEqual(42);
|
||||
expect(spy('baz', 'grault')).toEqual(-1);
|
||||
expect(spy('thud')).toEqual('bob');
|
||||
expect(spy('baz', 'grault', 'waldo')).toEqual(42);
|
||||
});
|
||||
|
||||
it("uses custom equality testers when selecting a strategy", function() {
|
||||
var spy = env.createSpy('foo');
|
||||
spy.and.returnValue(42);
|
||||
spy.withArgs(jasmineUnderTest.any(String)).and.returnValue(-1);
|
||||
|
||||
expect(spy('foo')).toEqual(-1);
|
||||
expect(spy({})).toEqual(42);
|
||||
});
|
||||
|
||||
it("can reconfigure an argument-specific strategy", function() {
|
||||
var spy = env.createSpy('foo');
|
||||
spy.withArgs('foo').and.returnValue(42);
|
||||
spy.withArgs('foo').and.returnValue(17);
|
||||
expect(spy('foo')).toEqual(17);
|
||||
});
|
||||
|
||||
describe("When withArgs is used without a base strategy", function() {
|
||||
it("uses the matching strategy", function() {
|
||||
var spy = env.createSpy('foo');
|
||||
spy.withArgs('baz').and.returnValue(-1);
|
||||
|
||||
expect(spy('baz')).toEqual(-1);
|
||||
});
|
||||
|
||||
it("throws if the args don't match", function() {
|
||||
var spy = env.createSpy('foo');
|
||||
spy.withArgs('bar').and.returnValue(-1);
|
||||
|
||||
expect(function() { spy('baz', {qux: 42}); }).toThrowError('Spy \'foo\' receieved a call with arguments [ \'baz\', Object({ qux: 42 }) ] but all configured strategies specify other arguments.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,13 +3,13 @@ describe("SpyStrategy", function() {
|
||||
it("defaults its name to unknown", function() {
|
||||
var spyStrategy = new jasmineUnderTest.SpyStrategy();
|
||||
|
||||
expect(spyStrategy.identity()).toEqual("unknown");
|
||||
expect(spyStrategy.identity).toEqual("unknown");
|
||||
});
|
||||
|
||||
it("takes a name", function() {
|
||||
var spyStrategy = new jasmineUnderTest.SpyStrategy({name: "foo"});
|
||||
|
||||
expect(spyStrategy.identity()).toEqual("foo");
|
||||
expect(spyStrategy.identity).toEqual("foo");
|
||||
});
|
||||
|
||||
it("stubs an original function, if provided", function() {
|
||||
@@ -27,7 +27,7 @@ describe("SpyStrategy", function() {
|
||||
returnValue;
|
||||
|
||||
spyStrategy.callThrough();
|
||||
returnValue = spyStrategy.exec("foo");
|
||||
returnValue = spyStrategy.exec(null, ["foo"]);
|
||||
|
||||
expect(originalFn).toHaveBeenCalled();
|
||||
expect(originalFn.calls.mostRecent().args).toEqual(["foo"]);
|
||||
@@ -110,6 +110,49 @@ describe("SpyStrategy", function() {
|
||||
})
|
||||
});
|
||||
|
||||
it("allows a custom strategy to be used", function() {
|
||||
var plan = jasmine.createSpy('custom strategy')
|
||||
.and.returnValue('custom strategy result'),
|
||||
customStrategy = jasmine.createSpy('custom strategy')
|
||||
.and.returnValue(plan),
|
||||
originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
fn: originalFn,
|
||||
customStrategies: {
|
||||
doSomething: customStrategy
|
||||
}
|
||||
});
|
||||
|
||||
spyStrategy.doSomething(1, 2, 3);
|
||||
expect(customStrategy).toHaveBeenCalledWith(1, 2, 3);
|
||||
expect(spyStrategy.exec(null, ['some', 'args']))
|
||||
.toEqual('custom strategy result');
|
||||
expect(plan).toHaveBeenCalledWith('some', 'args');
|
||||
});
|
||||
|
||||
it("throws an error if a custom strategy doesn't return a function", function() {
|
||||
var originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
fn: originalFn,
|
||||
customStrategies: {
|
||||
doSomething: function() { return 'not a function' }
|
||||
}
|
||||
});
|
||||
|
||||
expect(function() { spyStrategy.doSomething(1, 2, 3) }).toThrowError('Spy strategy must return a function');
|
||||
});
|
||||
|
||||
it("does not allow custom strategies to overwrite existing methods", function() {
|
||||
var spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
fn: function() {},
|
||||
customStrategies: {
|
||||
exec: function() {}
|
||||
}
|
||||
});
|
||||
|
||||
expect(spyStrategy.exec).toBe(jasmineUnderTest.SpyStrategy.prototype.exec);
|
||||
});
|
||||
|
||||
it('throws an error when a non-function is passed to callFake strategy', function() {
|
||||
var originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}),
|
||||
|
||||
166
spec/core/StackTraceSpec.js
Normal file
166
spec/core/StackTraceSpec.js
Normal file
@@ -0,0 +1,166 @@
|
||||
describe("StackTrace", function() {
|
||||
it("understands Chrome/IE/Edge style traces", function() {
|
||||
var raw =
|
||||
'Error: nope\n' +
|
||||
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)';
|
||||
|
||||
var result = new jasmineUnderTest.StackTrace(raw);
|
||||
|
||||
expect(result.message).toEqual('Error: nope');
|
||||
expect(result.style).toEqual('v8');
|
||||
expect(result.frames).toEqual([
|
||||
{
|
||||
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
||||
func: 'UserContext.<anonymous>',
|
||||
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||
line: 115
|
||||
},
|
||||
{
|
||||
raw: ' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
|
||||
func: 'QueueRunner.run',
|
||||
file: 'http://localhost:8888/__jasmine__/jasmine.js',
|
||||
line: 4320
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it("understands Node style traces", function() {
|
||||
var raw = 'Error\n' +
|
||||
' at /somewhere/jasmine/lib/jasmine-core/jasmine.js:4255:9\n' +
|
||||
' at QueueRunner.complete [as onComplete] (/somewhere/jasmine/lib/jasmine-core/jasmine.js:579:9)\n' +
|
||||
' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)\n' +
|
||||
' at runCallback (timers.js:672:20)';
|
||||
var result = new jasmineUnderTest.StackTrace(raw);
|
||||
|
||||
expect(result.message).toEqual('Error');
|
||||
expect(result.style).toEqual('v8');
|
||||
expect(result.frames).toEqual([
|
||||
{
|
||||
raw: ' at /somewhere/jasmine/lib/jasmine-core/jasmine.js:4255:9',
|
||||
func: undefined,
|
||||
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
|
||||
line: 4255
|
||||
},
|
||||
{
|
||||
raw: ' at QueueRunner.complete [as onComplete] (/somewhere/jasmine/lib/jasmine-core/jasmine.js:579:9)',
|
||||
func: 'QueueRunner.complete [as onComplete]',
|
||||
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
|
||||
line: 579
|
||||
},
|
||||
{
|
||||
raw: ' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)',
|
||||
func: 'Immediate.<anonymous>',
|
||||
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
|
||||
line: 4314
|
||||
},
|
||||
{
|
||||
raw: ' at runCallback (timers.js:672:20)',
|
||||
func: 'runCallback',
|
||||
file: 'timers.js',
|
||||
line: 672
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it("understands Safari/Firefox/Phantom-OS X style traces", function() {
|
||||
var raw =
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||
'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27';
|
||||
var result = new jasmineUnderTest.StackTrace(raw);
|
||||
|
||||
expect(result.message).toBeFalsy();
|
||||
expect(result.style).toEqual('webkit');
|
||||
expect(result.frames).toEqual([
|
||||
{
|
||||
raw: 'http://localhost:8888/__spec__/core/UtilSpec.js:115:28',
|
||||
func: undefined,
|
||||
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||
line: 115
|
||||
},
|
||||
{
|
||||
raw: 'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27',
|
||||
func: 'run',
|
||||
file: 'http://localhost:8888/__jasmine__/jasmine.js',
|
||||
line: 4320
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it("does not mistake gibberish for Safari/Firefox/Phantom-OS X style traces", function() {
|
||||
var raw = 'randomcharsnotincludingwhitespace';
|
||||
var result = new jasmineUnderTest.StackTrace(raw);
|
||||
expect(result.style).toBeNull();
|
||||
expect(result.frames).toEqual([
|
||||
{ raw: raw }
|
||||
]);
|
||||
});
|
||||
|
||||
it("understands Phantom-Linux style traces", function() {
|
||||
var raw =
|
||||
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)';
|
||||
|
||||
var result = new jasmineUnderTest.StackTrace(raw);
|
||||
|
||||
expect(result.message).toBeFalsy();
|
||||
expect(result.style).toEqual('v8');
|
||||
expect(result.frames).toEqual([
|
||||
{
|
||||
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
||||
func: 'UserContext.<anonymous>',
|
||||
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||
line: 115
|
||||
},
|
||||
{
|
||||
raw: ' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
|
||||
func: 'QueueRunner.run',
|
||||
file: 'http://localhost:8888/__jasmine__/jasmine.js',
|
||||
line: 4320
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it("ignores blank lines", function() {
|
||||
var raw =
|
||||
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n';
|
||||
|
||||
var result = new jasmineUnderTest.StackTrace(raw);
|
||||
|
||||
expect(result.frames).toEqual([
|
||||
{
|
||||
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
||||
func: 'UserContext.<anonymous>',
|
||||
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||
line: 115
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it("omits properties except 'raw' for frames that are not understood", function() {
|
||||
var raw =
|
||||
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||
' but this is quite unexpected\n' +
|
||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)';
|
||||
|
||||
var result = new jasmineUnderTest.StackTrace(raw);
|
||||
expect(result.style).toEqual('v8');
|
||||
expect(result.frames).toEqual([
|
||||
{
|
||||
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
||||
func: 'UserContext.<anonymous>',
|
||||
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||
line: 115
|
||||
},
|
||||
{
|
||||
raw: ' but this is quite unexpected'
|
||||
},
|
||||
{
|
||||
raw: ' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
|
||||
func: 'QueueRunner.run',
|
||||
file: 'http://localhost:8888/__jasmine__/jasmine.js',
|
||||
line: 4320
|
||||
}
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -67,11 +67,10 @@ describe("Suite", function() {
|
||||
expect(suite.afterFns).toEqual([innerAfter, outerAfter]);
|
||||
});
|
||||
|
||||
it('has a status of failed if any afterAll expectations have failed', function() {
|
||||
it('has a status of failed if any expectations have failed', function() {
|
||||
var suite = new jasmineUnderTest.Suite({
|
||||
expectationResultFactory: function() { return 'hi'; }
|
||||
});
|
||||
suite.addChild({ result: { status: 'done' } });
|
||||
|
||||
suite.addExpectationResult(false);
|
||||
expect(suite.status()).toBe('failed');
|
||||
@@ -80,7 +79,7 @@ describe("Suite", function() {
|
||||
it("retrieves a result with updated status", function() {
|
||||
var suite = new jasmineUnderTest.Suite({});
|
||||
|
||||
expect(suite.getResult().status).toBe('finished');
|
||||
expect(suite.getResult().status).toBe('passed');
|
||||
});
|
||||
|
||||
it("retrieves a result with pending status", function() {
|
||||
@@ -90,41 +89,11 @@ describe("Suite", function() {
|
||||
expect(suite.getResult().status).toBe('pending');
|
||||
});
|
||||
|
||||
it("is executable if not pending", function() {
|
||||
var suite = new jasmineUnderTest.Suite({});
|
||||
|
||||
expect(suite.isExecutable()).toBe(true);
|
||||
});
|
||||
|
||||
it("is not executable if pending", function() {
|
||||
var suite = new jasmineUnderTest.Suite({});
|
||||
suite.pend();
|
||||
|
||||
expect(suite.isExecutable()).toBe(false);
|
||||
});
|
||||
|
||||
it("tells all children about expectation failures, even if one throws", function() {
|
||||
var suite = new jasmineUnderTest.Suite({}),
|
||||
child1 = { addExpectationResult: jasmine.createSpy('child1#expectationResult'), result: {} },
|
||||
child2 = { addExpectationResult: jasmine.createSpy('child2#expectationResult'), result: {} };
|
||||
|
||||
suite.addChild(child1);
|
||||
suite.addChild(child2);
|
||||
|
||||
child1.addExpectationResult.and.throwError('foo');
|
||||
|
||||
suite.addExpectationResult('stuff');
|
||||
|
||||
expect(child1.addExpectationResult).toHaveBeenCalledWith('stuff');
|
||||
expect(child2.addExpectationResult).toHaveBeenCalledWith('stuff');
|
||||
});
|
||||
|
||||
it("throws an ExpectationFailed when receiving a failed expectation in an afterAll when throwOnExpectationFailure is set", function() {
|
||||
it("throws an ExpectationFailed when receiving a failed expectation when throwOnExpectationFailure is set", function() {
|
||||
var suite = new jasmineUnderTest.Suite({
|
||||
expectationResultFactory: function(data) { return data; },
|
||||
throwOnExpectationFailure: true
|
||||
});
|
||||
suite.addChild({ result: { status: 'done' } });
|
||||
|
||||
expect(function() {
|
||||
suite.addExpectationResult(false, 'failed');
|
||||
@@ -134,9 +103,8 @@ describe("Suite", function() {
|
||||
expect(suite.result.failedExpectations).toEqual(['failed']);
|
||||
});
|
||||
|
||||
it("does not add an additional failure when an expectation fails in an afterAll", function(){
|
||||
it("does not add an additional failure when an expectation fails", function(){
|
||||
var suite = new jasmineUnderTest.Suite({});
|
||||
suite.addChild({ result: { status: 'done' } });
|
||||
|
||||
suite.onException(new jasmineUnderTest.errors.ExpectationFailed());
|
||||
|
||||
|
||||
@@ -8,27 +8,24 @@ describe("TreeProcessor", function() {
|
||||
this.canBeReentered = function() {
|
||||
return !attrs.noReenter;
|
||||
};
|
||||
this.isExecutable = function() {
|
||||
return attrs.executable !== false;
|
||||
};
|
||||
this.markedPending = attrs.markedPending || false;
|
||||
this.sharedUserContext = function() {
|
||||
return attrs.userContext || {};
|
||||
};
|
||||
this.getResult = jasmine.createSpy(this.id + '#execute');
|
||||
this.beforeAllFns = attrs.beforeAllFns || [];
|
||||
this.afterAllFns = attrs.afterAllFns || [];
|
||||
this.cleanupBeforeAfter = function() { };
|
||||
}
|
||||
|
||||
function Leaf(attrs) {
|
||||
attrs = attrs || {};
|
||||
this.id = 'leaf' + leafNumber++;
|
||||
this.isExecutable = function() {
|
||||
return attrs.executable !== false;
|
||||
};
|
||||
this.markedPending = attrs.markedPending || false;
|
||||
this.execute = jasmine.createSpy(this.id + '#execute');
|
||||
}
|
||||
|
||||
it("processes a single executable leaf", function() {
|
||||
it("processes a single leaf", function() {
|
||||
var leaf = new Leaf(),
|
||||
processor = new jasmineUnderTest.TreeProcessor({ tree: leaf, runnableIds: [leaf.id] }),
|
||||
result = processor.processTree();
|
||||
@@ -36,20 +33,22 @@ describe("TreeProcessor", function() {
|
||||
expect(result.valid).toBe(true);
|
||||
|
||||
expect(result[leaf.id]).toEqual({
|
||||
executable: true,
|
||||
excluded: false,
|
||||
willExecute: true,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
});
|
||||
|
||||
it("processes a single non-executable leaf", function() {
|
||||
var leaf = new Leaf({ executable: false }),
|
||||
it("processes a single pending leaf", function() {
|
||||
var leaf = new Leaf({ markedPending: true }),
|
||||
processor = new jasmineUnderTest.TreeProcessor({ tree: leaf, runnableIds: [leaf.id] }),
|
||||
result = processor.processTree();
|
||||
|
||||
expect(result.valid).toBe(true);
|
||||
|
||||
expect(result[leaf.id]).toEqual({
|
||||
executable: false,
|
||||
excluded: false,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
});
|
||||
@@ -62,7 +61,26 @@ describe("TreeProcessor", function() {
|
||||
expect(result.valid).toBe(true);
|
||||
|
||||
expect(result[leaf.id]).toEqual({
|
||||
executable: false,
|
||||
excluded: true,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
});
|
||||
|
||||
it("processes a single excluded leaf", function() {
|
||||
var leaf = new Leaf(),
|
||||
processor = new jasmineUnderTest.TreeProcessor({
|
||||
tree: leaf,
|
||||
runnableIds: [leaf.id],
|
||||
excludeNode: function(node) { return true; }
|
||||
}),
|
||||
result = processor.processTree();
|
||||
|
||||
expect(result.valid).toBe(true);
|
||||
|
||||
expect(result[leaf.id]).toEqual({
|
||||
excluded: true,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
});
|
||||
@@ -76,18 +94,20 @@ describe("TreeProcessor", function() {
|
||||
expect(result.valid).toBe(true);
|
||||
|
||||
expect(result[parent.id]).toEqual({
|
||||
executable: true,
|
||||
excluded: false,
|
||||
willExecute: true,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
|
||||
expect(result[leaf.id]).toEqual({
|
||||
executable: true,
|
||||
excluded: false,
|
||||
willExecute: true,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
});
|
||||
|
||||
it("processes a tree with a single non-executable leaf, with the root specified", function() {
|
||||
var leaf = new Leaf({ executable: false }),
|
||||
it("processes a tree with a single pending leaf, with the root specified", function() {
|
||||
var leaf = new Leaf({ markedPending: true }),
|
||||
parent = new Node({ children: [leaf] }),
|
||||
processor = new jasmineUnderTest.TreeProcessor({ tree: parent, runnableIds: [parent.id] }),
|
||||
result = processor.processTree();
|
||||
@@ -95,61 +115,77 @@ describe("TreeProcessor", function() {
|
||||
expect(result.valid).toBe(true);
|
||||
|
||||
expect(result[parent.id]).toEqual({
|
||||
executable: false,
|
||||
excluded: false,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
|
||||
expect(result[leaf.id]).toEqual({
|
||||
executable: false,
|
||||
excluded: false,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
});
|
||||
|
||||
it("processes a complicated tree with the root specified", function() {
|
||||
var nonExecutable = new Leaf({ executable: false }),
|
||||
executable = new Leaf({ executable: true }),
|
||||
parent = new Node({ children: [nonExecutable, executable] }),
|
||||
var pendingLeaf = new Leaf({ markedPending: true }),
|
||||
executableLeaf = new Leaf({ markedPending: false }),
|
||||
parent = new Node({ children: [pendingLeaf, executableLeaf] }),
|
||||
childless = new Node(),
|
||||
childOfDisabled = new Leaf({ executable: true }),
|
||||
disabledNode = new Node({ executable: false, children: [childOfDisabled] }),
|
||||
root = new Node({ children: [parent, childless, disabledNode] }),
|
||||
childOfPending = new Leaf({ markedPending: true }),
|
||||
pendingNode = new Node({ markedPending: true, children: [childOfPending] }),
|
||||
parentOfPendings = new Node({ markedPending: false, children: [childless, pendingNode] }),
|
||||
root = new Node({ children: [parent, parentOfPendings] }),
|
||||
processor = new jasmineUnderTest.TreeProcessor({ tree: root, runnableIds: [root.id] }),
|
||||
result = processor.processTree();
|
||||
|
||||
expect(result.valid).toBe(true);
|
||||
|
||||
expect(result[root.id]).toEqual({
|
||||
executable: true,
|
||||
excluded: false,
|
||||
willExecute: true,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
|
||||
expect(result[parentOfPendings.id]).toEqual({
|
||||
excluded: false,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
|
||||
expect(result[childless.id]).toEqual({
|
||||
executable: false,
|
||||
excluded: false,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
|
||||
expect(result[nonExecutable.id]).toEqual({
|
||||
executable: false,
|
||||
expect(result[pendingLeaf.id]).toEqual({
|
||||
excluded: false,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
|
||||
expect(result[executable.id]).toEqual({
|
||||
executable: true,
|
||||
expect(result[executableLeaf.id]).toEqual({
|
||||
excluded: false,
|
||||
willExecute: true,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
|
||||
expect(result[parent.id]).toEqual({
|
||||
executable: true,
|
||||
excluded: false,
|
||||
willExecute: true,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
|
||||
expect(result[disabledNode.id]).toEqual({
|
||||
executable: false,
|
||||
expect(result[pendingNode.id]).toEqual({
|
||||
excluded: false,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
|
||||
expect(result[childOfDisabled.id]).toEqual({
|
||||
executable: false,
|
||||
expect(result[childOfPending.id]).toEqual({
|
||||
excluded: false,
|
||||
willExecute: false,
|
||||
segments: jasmine.any(Array)
|
||||
});
|
||||
});
|
||||
@@ -218,7 +254,7 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn('foo');
|
||||
|
||||
expect(leaf.execute).toHaveBeenCalledWith('foo', true);
|
||||
expect(leaf.execute).toHaveBeenCalledWith('foo', false);
|
||||
});
|
||||
|
||||
it("runs a node with no children", function() {
|
||||
@@ -248,19 +284,20 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn(nodeDone);
|
||||
|
||||
expect(nodeStart).toHaveBeenCalledWith(node);
|
||||
expect(queueRunner).toHaveBeenCalledWith({
|
||||
onComplete: jasmine.any(Function),
|
||||
queueableFns: [],
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
userContext: { node: 'context' },
|
||||
onException: jasmine.any(Function)
|
||||
});
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn('foo');
|
||||
expect(nodeStart).toHaveBeenCalledWith(node, 'foo');
|
||||
|
||||
node.getResult.and.returnValue({ my: 'result' });
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].onComplete();
|
||||
expect(nodeComplete).toHaveBeenCalledWith(node, { my: 'result' });
|
||||
expect(nodeDone).toHaveBeenCalled();
|
||||
expect(nodeComplete).toHaveBeenCalledWith(node, { my: 'result' }, nodeDone);
|
||||
});
|
||||
|
||||
it("runs a node with children", function() {
|
||||
@@ -282,25 +319,25 @@ describe("TreeProcessor", function() {
|
||||
queueableFns[0].fn(nodeDone);
|
||||
|
||||
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
|
||||
expect(queueableFns.length).toBe(2);
|
||||
expect(queueableFns.length).toBe(3);
|
||||
|
||||
queueableFns[0].fn('foo');
|
||||
expect(leaf1.execute).toHaveBeenCalledWith('foo', true);
|
||||
queueableFns[1].fn('foo');
|
||||
expect(leaf1.execute).toHaveBeenCalledWith('foo', false);
|
||||
|
||||
queueableFns[1].fn('bar');
|
||||
expect(leaf2.execute).toHaveBeenCalledWith('bar', true);
|
||||
queueableFns[2].fn('bar');
|
||||
expect(leaf2.execute).toHaveBeenCalledWith('bar', false);
|
||||
});
|
||||
|
||||
it("runs a disabled node", function() {
|
||||
it("runs an excluded node with leaf", function() {
|
||||
var leaf1 = new Leaf(),
|
||||
node = new Node({ children: [leaf1], executable: false }),
|
||||
node = new Node({ children: [leaf1] }),
|
||||
root = new Node({ children: [node] }),
|
||||
queueRunner = jasmine.createSpy('queueRunner'),
|
||||
nodeStart = jasmine.createSpy('nodeStart'),
|
||||
nodeComplete = jasmine.createSpy('nodeComplete'),
|
||||
processor = new jasmineUnderTest.TreeProcessor({
|
||||
tree: root,
|
||||
runnableIds: [node.id],
|
||||
runnableIds: [],
|
||||
queueRunnerFactory: queueRunner,
|
||||
nodeStart: nodeStart,
|
||||
nodeComplete: nodeComplete
|
||||
@@ -312,18 +349,19 @@ describe("TreeProcessor", function() {
|
||||
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn(nodeDone);
|
||||
|
||||
expect(nodeStart).toHaveBeenCalledWith(node);
|
||||
|
||||
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
|
||||
expect(queueableFns.length).toBe(1);
|
||||
expect(queueableFns.length).toBe(2);
|
||||
|
||||
queueableFns[0].fn('foo');
|
||||
expect(leaf1.execute).toHaveBeenCalledWith('foo', false);
|
||||
queueableFns[0].fn('bar');
|
||||
expect(nodeStart).toHaveBeenCalledWith(node, 'bar');
|
||||
|
||||
queueableFns[1].fn('foo');
|
||||
expect(leaf1.execute).toHaveBeenCalledWith('foo', true);
|
||||
|
||||
node.getResult.and.returnValue({ im: 'disabled' });
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].onComplete();
|
||||
expect(nodeComplete).toHaveBeenCalledWith(node, { im: 'disabled' });
|
||||
expect(nodeComplete).toHaveBeenCalledWith(node, { im: 'disabled' }, nodeDone);
|
||||
});
|
||||
|
||||
it("runs beforeAlls for a node with children", function() {
|
||||
@@ -348,7 +386,7 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
|
||||
|
||||
expect(queueableFns).toEqual(['beforeAll1', 'beforeAll2', { fn: jasmine.any(Function) }]);
|
||||
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }, 'beforeAll1', 'beforeAll2', { fn: jasmine.any(Function) }]);
|
||||
});
|
||||
|
||||
it("runs afterAlls for a node with children", function() {
|
||||
@@ -373,7 +411,7 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
|
||||
|
||||
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }, 'afterAll1', 'afterAll2']);
|
||||
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }, { fn: jasmine.any(Function) }, 'afterAll1', 'afterAll2']);
|
||||
});
|
||||
|
||||
it("does not run beforeAlls or afterAlls for a node with no children", function() {
|
||||
@@ -397,16 +435,16 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
|
||||
|
||||
expect(queueableFns).toEqual([]);
|
||||
expect(queueableFns).toEqual([{fn: jasmine.any(Function)}]);
|
||||
});
|
||||
|
||||
it("does not run beforeAlls or afterAlls for a disabled node", function() {
|
||||
var leaf = new Leaf(),
|
||||
it("does not run beforeAlls or afterAlls for a node with only pending children", function() {
|
||||
var leaf = new Leaf({ markedPending: true }),
|
||||
node = new Node({
|
||||
children: [leaf],
|
||||
beforeAllFns: ['before'],
|
||||
afterAllFns: ['after'],
|
||||
executable: false
|
||||
markedPending: false
|
||||
}),
|
||||
root = new Node({ children: [node] }),
|
||||
queueRunner = jasmine.createSpy('queueRunner'),
|
||||
@@ -424,7 +462,7 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
|
||||
|
||||
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }]);
|
||||
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }, { fn: jasmine.any(Function) }]);
|
||||
});
|
||||
|
||||
it("runs leaves in the order specified", function() {
|
||||
@@ -451,7 +489,7 @@ describe("TreeProcessor", function() {
|
||||
expect(leaf1.execute).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("runs specified leaves before non-specified leaves", function() {
|
||||
it("runs specified leaves before non-specified leaves within a parent node", function() {
|
||||
var specified = new Leaf(),
|
||||
nonSpecified = new Leaf(),
|
||||
root = new Node({ children: [nonSpecified, specified] }),
|
||||
@@ -468,11 +506,11 @@ describe("TreeProcessor", function() {
|
||||
queueableFns[0].fn();
|
||||
|
||||
expect(nonSpecified.execute).not.toHaveBeenCalled();
|
||||
expect(specified.execute).toHaveBeenCalledWith(undefined, true);
|
||||
expect(specified.execute).toHaveBeenCalledWith(undefined, false);
|
||||
|
||||
queueableFns[1].fn();
|
||||
|
||||
expect(nonSpecified.execute).toHaveBeenCalledWith(undefined, false);
|
||||
expect(nonSpecified.execute).toHaveBeenCalledWith(undefined, true);
|
||||
});
|
||||
|
||||
it("runs nodes and leaves with a specified order", function() {
|
||||
@@ -493,7 +531,7 @@ describe("TreeProcessor", function() {
|
||||
|
||||
expect(specifiedLeaf.execute).not.toHaveBeenCalled();
|
||||
var nodeQueueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
|
||||
nodeQueueableFns[0].fn();
|
||||
nodeQueueableFns[1].fn();
|
||||
|
||||
expect(childLeaf.execute).toHaveBeenCalled();
|
||||
|
||||
@@ -522,8 +560,8 @@ describe("TreeProcessor", function() {
|
||||
expect(queueableFns.length).toBe(5);
|
||||
|
||||
queueableFns[0].fn();
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
|
||||
expect(leaf1.execute).toHaveBeenCalled();
|
||||
|
||||
queueableFns[1].fn();
|
||||
@@ -531,8 +569,8 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueableFns[2].fn();
|
||||
expect(queueRunner.calls.count()).toBe(3);
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
|
||||
expect(leaf2.execute).toHaveBeenCalled();
|
||||
|
||||
queueableFns[3].fn();
|
||||
@@ -540,8 +578,8 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueableFns[4].fn();
|
||||
expect(queueRunner.calls.count()).toBe(4);
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
|
||||
expect(leaf3.execute).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -567,12 +605,12 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueableFns[0].fn();
|
||||
expect(queueRunner.calls.count()).toBe(2);
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
|
||||
expect(queueRunner.calls.count()).toBe(3);
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
|
||||
expect(leaf1.execute).toHaveBeenCalled();
|
||||
|
||||
queueableFns[1].fn();
|
||||
@@ -580,12 +618,12 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueableFns[2].fn();
|
||||
expect(queueRunner.calls.count()).toBe(4);
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
|
||||
expect(queueRunner.calls.count()).toBe(5);
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
|
||||
expect(leaf2.execute).toHaveBeenCalled();
|
||||
|
||||
queueableFns[3].fn();
|
||||
@@ -593,12 +631,12 @@ describe("TreeProcessor", function() {
|
||||
|
||||
queueableFns[4].fn();
|
||||
expect(queueRunner.calls.count()).toBe(6);
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
|
||||
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
|
||||
expect(queueRunner.calls.count()).toBe(7);
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
|
||||
expect(leaf3.execute).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -625,11 +663,11 @@ describe("TreeProcessor", function() {
|
||||
queueableFns[1].fn();
|
||||
|
||||
var childFns = queueRunner.calls.mostRecent().args[0].queueableFns;
|
||||
expect(childFns.length).toBe(2);
|
||||
childFns[0].fn();
|
||||
expect(childFns.length).toBe(3);
|
||||
childFns[1].fn();
|
||||
expect(leaf2.execute).toHaveBeenCalled();
|
||||
|
||||
childFns[1].fn();
|
||||
childFns[2].fn();
|
||||
expect(leaf3.execute).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -691,7 +729,7 @@ describe("TreeProcessor", function() {
|
||||
expect(leaf11.execute).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("runs nodes in a custom order when orderChildren is overrided", function() {
|
||||
it("runs nodes in a custom order when orderChildren is overridden", function() {
|
||||
var leaf1 = new Leaf(),
|
||||
leaf2 = new Leaf(),
|
||||
leaf3 = new Leaf(),
|
||||
|
||||
@@ -43,9 +43,6 @@ describe("jasmineUnderTest.util", function() {
|
||||
});
|
||||
|
||||
describe("getPropertyDescriptor", function() {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
it("get property descriptor from object", function() {
|
||||
var obj = {prop: 1},
|
||||
actual = jasmineUnderTest.util.getPropertyDescriptor(obj, 'prop'),
|
||||
@@ -94,6 +91,15 @@ describe("jasmineUnderTest.util", function() {
|
||||
|
||||
expect(jasmineUnderTest.util.objectDifference(a, b)).toEqual({x: 1});
|
||||
expect(jasmineUnderTest.util.objectDifference(b, a)).toEqual({y: 2});
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe("jasmineFile", function() {
|
||||
it("returns the file containing jasmine.util", function() {
|
||||
// Chrome sometimes reports foo.js as foo.js/, so tolerate
|
||||
// a trailing slash if present.
|
||||
expect(jasmineUnderTest.util.jasmineFile()).toMatch(/util.js\/?$/);
|
||||
expect(jasmine.util.jasmineFile()).toMatch(/jasmine.js\/?$/);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -68,10 +68,17 @@ describe("Any", function() {
|
||||
expect(any.asymmetricMatch(new Thing())).toBe(true);
|
||||
});
|
||||
|
||||
it("does not treat null as an Object", function() {
|
||||
var any = new jasmineUnderTest.Any(Object);
|
||||
|
||||
expect(any.asymmetricMatch(null)).toBe(false);
|
||||
});
|
||||
|
||||
it("jasmineToString's itself", function() {
|
||||
var any = new jasmineUnderTest.Any(Number);
|
||||
|
||||
expect(any.jasmineToString()).toEqual('<jasmine.any(Number)>');
|
||||
expect(any.jasmineToString()).toEqual('<jasmine.any(Number)>');
|
||||
});
|
||||
|
||||
describe("when called without an argument", function() {
|
||||
|
||||
@@ -57,9 +57,6 @@ describe("ObjectContaining", function() {
|
||||
});
|
||||
|
||||
it("matches defined properties", function(){
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var containing = new jasmineUnderTest.ObjectContaining({ foo: "fooVal" });
|
||||
|
||||
var definedPropertyObject = {};
|
||||
|
||||
@@ -4,6 +4,7 @@ describe("Custom Matchers (Integration)", function() {
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
env.randomizeTests(false);
|
||||
});
|
||||
|
||||
it("allows adding more matchers local to a spec", function(done) {
|
||||
|
||||
138
spec/core/integration/CustomSpyStrategiesSpec.js
Normal file
138
spec/core/integration/CustomSpyStrategiesSpec.js
Normal file
@@ -0,0 +1,138 @@
|
||||
describe('Custom Spy Strategies (Integration)', function() {
|
||||
var env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
env.randomizeTests(false);
|
||||
});
|
||||
|
||||
it('allows adding more strategies local to a suite', function(done) {
|
||||
var plan = jasmine.createSpy('custom strategy plan')
|
||||
.and.returnValue(42);
|
||||
var strategy = jasmine.createSpy('custom strategy')
|
||||
.and.returnValue(plan);
|
||||
|
||||
env.describe('suite defining a custom spy strategy', function() {
|
||||
env.beforeEach(function() {
|
||||
env.addSpyStrategy('frobnicate', strategy);
|
||||
});
|
||||
|
||||
env.it('spec in the suite', function() {
|
||||
var spy = env.createSpy('something').and.frobnicate(17);
|
||||
expect(spy(1, 2, 3)).toEqual(42);
|
||||
expect(strategy).toHaveBeenCalledWith(17);
|
||||
expect(plan).toHaveBeenCalledWith(1, 2, 3);
|
||||
});
|
||||
});
|
||||
|
||||
env.it('spec without custom strategy defined', function() {
|
||||
expect(env.createSpy('something').and.frobnicate).toBeUndefined();
|
||||
});
|
||||
|
||||
function jasmineDone(result) {
|
||||
expect(result.overallStatus).toEqual('passed');
|
||||
done();
|
||||
}
|
||||
|
||||
env.addReporter({ jasmineDone: jasmineDone });
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it('allows adding more strategies local to a spec', function(done) {
|
||||
var plan = jasmine.createSpy('custom strategy plan')
|
||||
.and.returnValue(42);
|
||||
var strategy = jasmine.createSpy('custom strategy')
|
||||
.and.returnValue(plan);
|
||||
|
||||
env.it('spec defining a custom spy strategy', function() {
|
||||
env.addSpyStrategy('frobnicate', strategy);
|
||||
var spy = env.createSpy('something').and.frobnicate(17);
|
||||
expect(spy(1, 2, 3)).toEqual(42);
|
||||
expect(strategy).toHaveBeenCalledWith(17);
|
||||
expect(plan).toHaveBeenCalledWith(1, 2, 3);
|
||||
});
|
||||
|
||||
env.it('spec without custom strategy defined', function() {
|
||||
expect(env.createSpy('something').and.frobnicate).toBeUndefined();
|
||||
});
|
||||
|
||||
function jasmineDone(result) {
|
||||
expect(result.overallStatus).toEqual('passed');
|
||||
done();
|
||||
}
|
||||
|
||||
env.addReporter({ jasmineDone: jasmineDone });
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it('allows using custom strategies on a per-argument basis', function(done) {
|
||||
var plan = jasmine.createSpy('custom strategy plan')
|
||||
.and.returnValue(42);
|
||||
var strategy = jasmine.createSpy('custom strategy')
|
||||
.and.returnValue(plan);
|
||||
|
||||
env.it('spec defining a custom spy strategy', function() {
|
||||
env.addSpyStrategy('frobnicate', strategy);
|
||||
var spy = env.createSpy('something')
|
||||
.and.returnValue('no args return')
|
||||
.withArgs(1, 2, 3).and.frobnicate(17);
|
||||
|
||||
expect(spy()).toEqual('no args return');
|
||||
expect(plan).not.toHaveBeenCalled();
|
||||
expect(spy(1, 2, 3)).toEqual(42);
|
||||
expect(plan).toHaveBeenCalledWith(1, 2, 3);
|
||||
});
|
||||
|
||||
env.it('spec without custom strategy defined', function() {
|
||||
expect(env.createSpy('something').and.frobnicate).toBeUndefined();
|
||||
});
|
||||
|
||||
function jasmineDone(result) {
|
||||
expect(result.overallStatus).toEqual('passed');
|
||||
done();
|
||||
}
|
||||
|
||||
env.addReporter({ jasmineDone: jasmineDone });
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it('allows multiple custom strategies to be used', function(done) {
|
||||
var plan1 = jasmine.createSpy('plan 1').and.returnValue(42),
|
||||
strategy1 = jasmine.createSpy('strat 1').and.returnValue(plan1),
|
||||
plan2 = jasmine.createSpy('plan 2').and.returnValue(24),
|
||||
strategy2 = jasmine.createSpy('strat 2').and.returnValue(plan2),
|
||||
specDone = jasmine.createSpy('specDone');
|
||||
|
||||
env.beforeEach(function() {
|
||||
env.addSpyStrategy('frobnicate', strategy1);
|
||||
env.addSpyStrategy('jiggle', strategy2);
|
||||
});
|
||||
|
||||
env.it('frobnicates', function() {
|
||||
plan1.calls.reset();
|
||||
plan2.calls.reset();
|
||||
var spy = env.createSpy('spy').and.frobnicate();
|
||||
expect(spy()).toEqual(42);
|
||||
expect(plan1).toHaveBeenCalled();
|
||||
expect(plan2).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
env.it('jiggles', function() {
|
||||
plan1.calls.reset();
|
||||
plan2.calls.reset();
|
||||
var spy = env.createSpy('spy').and.jiggle();
|
||||
expect(spy()).toEqual(24);
|
||||
expect(plan1).not.toHaveBeenCalled();
|
||||
expect(plan2).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
function jasmineDone(result) {
|
||||
expect(result.overallStatus).toEqual('passed');
|
||||
expect(specDone.calls.count()).toBe(2);
|
||||
done();
|
||||
}
|
||||
|
||||
env.addReporter({ jasmineDone: jasmineDone, specDone: specDone });
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,10 @@
|
||||
describe("jasmine spec running", function () {
|
||||
describe("spec running", function () {
|
||||
var env;
|
||||
|
||||
beforeEach(function() {
|
||||
jasmine.getEnv().registerIntegrationMatchers();
|
||||
env = new jasmineUnderTest.Env();
|
||||
env.randomizeTests(false);
|
||||
});
|
||||
|
||||
it('should assign spec ids sequentially', function() {
|
||||
@@ -600,18 +602,16 @@ describe("jasmine spec running", function () {
|
||||
|
||||
it("should recover gracefully when there are errors in describe functions", function(done) {
|
||||
var specs = [],
|
||||
reporter = jasmine.createSpyObj(['specDone', 'jasmineDone']);
|
||||
reporter = jasmine.createSpyObj(['specDone', 'suiteDone', 'jasmineDone']);
|
||||
|
||||
reporter.specDone.and.callFake(function(result) {
|
||||
specs.push(result.fullName);
|
||||
});
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
expect(specs).toContain('outer1 inner1 should thingy');
|
||||
expect(specs).toContain('outer1 inner1 encountered a declaration exception');
|
||||
expect(specs).toContain('outer1 inner2 should other thingy');
|
||||
expect(specs).toContain('outer1 encountered a declaration exception');
|
||||
expect(specs).toContain('outer2 should xxx');
|
||||
expect(specs).toEqual(['outer1 inner1 should thingy', 'outer1 inner2 should other thingy', 'outer2 should xxx']);
|
||||
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('outer1 inner1', [/inner error/]);
|
||||
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('outer1', [/outer error/]);
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -622,7 +622,7 @@ describe("jasmine spec running", function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
|
||||
throw new Error("fake error");
|
||||
throw new Error("inner error");
|
||||
});
|
||||
|
||||
env.describe("inner2", function() {
|
||||
@@ -631,7 +631,7 @@ describe("jasmine spec running", function () {
|
||||
});
|
||||
});
|
||||
|
||||
throw new Error("fake error");
|
||||
throw new Error("outer error");
|
||||
|
||||
});
|
||||
}).not.toThrow();
|
||||
@@ -740,8 +740,8 @@ describe("jasmine spec running", function () {
|
||||
|
||||
it("should run the tests in a consistent order when a seed is supplied", function(done) {
|
||||
var actions = [];
|
||||
env.randomizeTests(true);
|
||||
env.seed('123456');
|
||||
env.randomizeTests(true);
|
||||
|
||||
env.beforeEach(function () {
|
||||
actions.push('topSuite beforeEach');
|
||||
@@ -947,4 +947,30 @@ describe("jasmine spec running", function () {
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when stopOnSpecFailure is on", function() {
|
||||
it("does not run further specs when one fails", function(done) {
|
||||
var actions = [];
|
||||
|
||||
env.it('fails', function() {
|
||||
actions.push('fails');
|
||||
env.expect(1).toBe(2);
|
||||
});
|
||||
|
||||
env.it('does not run', function() {
|
||||
actions.push('does not run');
|
||||
});
|
||||
|
||||
env.randomizeTests(false);
|
||||
env.stopOnSpecFailure(true);
|
||||
|
||||
var assertions = function() {
|
||||
expect(actions).toEqual(['fails']);
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -156,8 +156,6 @@ describe("matchersUtil", function() {
|
||||
});
|
||||
|
||||
it("passes for equivalent frozen objects (GitHub issue #266)", function() {
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var a = { foo: 1 },
|
||||
b = {foo: 1 };
|
||||
|
||||
@@ -201,10 +199,6 @@ describe("matchersUtil", function() {
|
||||
if (isNotRunningInBrowser()) {
|
||||
return;
|
||||
}
|
||||
// iframe.contentWindow.eval isn't supported in ie8
|
||||
if (jasmine.getEnv().ieVersion < 9) {
|
||||
return;
|
||||
}
|
||||
var iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe);
|
||||
iframe.contentWindow.eval('window.testObject = {}');
|
||||
@@ -366,8 +360,6 @@ describe("matchersUtil", function() {
|
||||
});
|
||||
|
||||
it("passes for null prototype objects with same properties", function () {
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var objA = Object.create(null),
|
||||
objB = Object.create(null);
|
||||
|
||||
@@ -378,8 +370,6 @@ describe("matchersUtil", function() {
|
||||
});
|
||||
|
||||
it("fails for null prototype objects with different properties", function () {
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var objA = Object.create(null),
|
||||
objB = Object.create(null);
|
||||
|
||||
@@ -535,9 +525,6 @@ describe("matchersUtil", function() {
|
||||
});
|
||||
|
||||
describe("when running in an environment with array polyfills", function() {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var findIndexDescriptor = Object.getOwnPropertyDescriptor(Array.prototype, 'findIndex');
|
||||
if (!findIndexDescriptor) {
|
||||
return;
|
||||
|
||||
@@ -299,22 +299,7 @@ describe("toEqual", function() {
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
function constructorIsNotEnumerable() {
|
||||
// in IE8, the constructor property is not enumerable, even if it is an
|
||||
// own property of the object.
|
||||
// Objects that differ only by an own `constructor` property are thus
|
||||
// considered equal in IE8.
|
||||
for (var key in {constructor: 1}) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
it("reports mismatches between objects with their own constructor property", function () {
|
||||
if (constructorIsNotEnumerable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
function Foo() {}
|
||||
function Bar() {}
|
||||
|
||||
@@ -326,10 +311,6 @@ describe("toEqual", function() {
|
||||
});
|
||||
|
||||
it("reports mismatches between an object with a real constructor and one with its own constructor property", function () {
|
||||
if (constructorIsNotEnumerable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
function Foo() {}
|
||||
function Bar() {}
|
||||
|
||||
@@ -600,7 +581,7 @@ describe("toEqual", function() {
|
||||
|
||||
var actual = {a: document.createElement('div')},
|
||||
expected = {a: document.createElement('p')},
|
||||
message = 'Expected $.a = HTMLNode to equal HTMLNode.';
|
||||
message = 'Expected $.a = <div> to equal <p>.';
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
@@ -618,7 +599,7 @@ describe("toEqual", function() {
|
||||
|
||||
var actual = {a: nodeA},
|
||||
expected = {a: nodeB},
|
||||
message = 'Expected $.a = HTMLNode to equal HTMLNode.';
|
||||
message = 'Expected $.a = <div>...</div> to equal <div>...</div>.';
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
})
|
||||
@@ -630,7 +611,7 @@ describe("toEqual", function() {
|
||||
|
||||
var actual = {a: document.createElement('div')},
|
||||
expected = {a: {}},
|
||||
message = 'Expected $.a = HTMLNode to equal Object({ }).';
|
||||
message = 'Expected $.a = <div> to equal Object({ }).';
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
@@ -2,14 +2,14 @@ describe("toHaveBeenCalledBefore", function() {
|
||||
it("throws an exception when the actual is not a spy", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
|
||||
fn = function() {},
|
||||
secondSpy = jasmineUnderTest.createSpy('second spy');
|
||||
secondSpy = new jasmineUnderTest.Env().createSpy('second spy');
|
||||
|
||||
expect(function() { matcher.compare(fn, secondSpy) }).toThrowError(Error, /Expected a spy, but got Function./);
|
||||
});
|
||||
|
||||
it("throws an exception when the expected is not a spy", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
|
||||
firstSpy = jasmineUnderTest.createSpy('first spy'),
|
||||
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
|
||||
fn = function() {};
|
||||
|
||||
expect(function() { matcher.compare(firstSpy, fn) }).toThrowError(Error, /Expected a spy, but got Function./);
|
||||
@@ -17,8 +17,8 @@ describe("toHaveBeenCalledBefore", function() {
|
||||
|
||||
it("fails when the actual was not called", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
|
||||
firstSpy = jasmineUnderTest.createSpy('first spy'),
|
||||
secondSpy = jasmineUnderTest.createSpy('second spy');
|
||||
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
|
||||
secondSpy = new jasmineUnderTest.Env().createSpy('second spy');
|
||||
|
||||
secondSpy();
|
||||
|
||||
@@ -29,8 +29,8 @@ describe("toHaveBeenCalledBefore", function() {
|
||||
|
||||
it("fails when the expected was not called", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
|
||||
firstSpy = jasmineUnderTest.createSpy('first spy'),
|
||||
secondSpy = jasmineUnderTest.createSpy('second spy');
|
||||
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
|
||||
secondSpy = new jasmineUnderTest.Env().createSpy('second spy');
|
||||
|
||||
firstSpy();
|
||||
|
||||
@@ -41,8 +41,8 @@ describe("toHaveBeenCalledBefore", function() {
|
||||
|
||||
it("fails when the actual is called after the expected", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
|
||||
firstSpy = jasmineUnderTest.createSpy('first spy'),
|
||||
secondSpy = jasmineUnderTest.createSpy('second spy'),
|
||||
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
|
||||
secondSpy = new jasmineUnderTest.Env().createSpy('second spy'),
|
||||
result;
|
||||
|
||||
secondSpy();
|
||||
@@ -55,8 +55,8 @@ describe("toHaveBeenCalledBefore", function() {
|
||||
|
||||
it("fails when the actual is called before and after the expected", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
|
||||
firstSpy = jasmineUnderTest.createSpy('first spy'),
|
||||
secondSpy = jasmineUnderTest.createSpy('second spy'),
|
||||
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
|
||||
secondSpy = new jasmineUnderTest.Env().createSpy('second spy'),
|
||||
result;
|
||||
|
||||
firstSpy();
|
||||
@@ -70,8 +70,8 @@ describe("toHaveBeenCalledBefore", function() {
|
||||
|
||||
it("fails when the expected is called before and after the actual", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
|
||||
firstSpy = jasmineUnderTest.createSpy('first spy'),
|
||||
secondSpy = jasmineUnderTest.createSpy('second spy'),
|
||||
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
|
||||
secondSpy = new jasmineUnderTest.Env().createSpy('second spy'),
|
||||
result;
|
||||
|
||||
secondSpy();
|
||||
@@ -85,8 +85,8 @@ describe("toHaveBeenCalledBefore", function() {
|
||||
|
||||
it("passes when the actual is called before the expected", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
|
||||
firstSpy = jasmineUnderTest.createSpy('first spy'),
|
||||
secondSpy = jasmineUnderTest.createSpy('second spy'),
|
||||
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
|
||||
secondSpy = new jasmineUnderTest.Env().createSpy('second spy'),
|
||||
result;
|
||||
|
||||
firstSpy();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
describe("toHaveBeenCalled", function() {
|
||||
it("passes when the actual was called, with a custom .not fail message", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalled(),
|
||||
calledSpy = jasmineUnderTest.createSpy('called-spy'),
|
||||
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy'),
|
||||
result;
|
||||
|
||||
calledSpy();
|
||||
@@ -13,7 +13,7 @@ describe("toHaveBeenCalled", function() {
|
||||
|
||||
it("fails when the actual was not called", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalled(),
|
||||
uncalledSpy = jasmineUnderTest.createSpy('uncalled spy'),
|
||||
uncalledSpy = new jasmineUnderTest.Env().createSpy('uncalled spy'),
|
||||
result;
|
||||
|
||||
result = matcher.compare(uncalledSpy);
|
||||
@@ -29,14 +29,14 @@ describe("toHaveBeenCalled", function() {
|
||||
|
||||
it("throws an exception when invoked with any arguments", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalled(),
|
||||
spy = jasmineUnderTest.createSpy('sample spy');
|
||||
spy = new jasmineUnderTest.Env().createSpy('sample spy');
|
||||
|
||||
expect(function() { matcher.compare(spy, 'foo') }).toThrowError(Error, /Does not take arguments, use toHaveBeenCalledWith/);
|
||||
});
|
||||
|
||||
it("has a custom message on failure", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalled(),
|
||||
spy = jasmineUnderTest.createSpy('sample-spy'),
|
||||
spy = new jasmineUnderTest.Env().createSpy('sample-spy'),
|
||||
result;
|
||||
|
||||
result = matcher.compare(spy);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
describe("toHaveBeenCalledTimes", function() {
|
||||
it("passes when the actual 0 matches the expected 0 ", function () {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
|
||||
calledSpy = jasmineUnderTest.createSpy('called-spy'),
|
||||
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy'),
|
||||
result;
|
||||
result = matcher.compare(calledSpy, 0);
|
||||
expect(result.pass).toBeTruthy();
|
||||
});
|
||||
it("passes when the actual matches the expected", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
|
||||
calledSpy = jasmineUnderTest.createSpy('called-spy'),
|
||||
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy'),
|
||||
result;
|
||||
calledSpy();
|
||||
|
||||
@@ -18,7 +18,7 @@ describe("toHaveBeenCalledTimes", function() {
|
||||
|
||||
it("fails when expected numbers is not supplied", function(){
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
|
||||
spy = jasmineUnderTest.createSpy('spy'),
|
||||
spy = new jasmineUnderTest.Env().createSpy('spy'),
|
||||
result;
|
||||
|
||||
spy();
|
||||
@@ -29,7 +29,7 @@ describe("toHaveBeenCalledTimes", function() {
|
||||
|
||||
it("fails when the actual was called less than the expected", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
|
||||
uncalledSpy = jasmineUnderTest.createSpy('uncalled spy'),
|
||||
uncalledSpy = new jasmineUnderTest.Env().createSpy('uncalled spy'),
|
||||
result;
|
||||
|
||||
result = matcher.compare(uncalledSpy, 2);
|
||||
@@ -38,7 +38,7 @@ describe("toHaveBeenCalledTimes", function() {
|
||||
|
||||
it("fails when the actual was called more than expected", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
|
||||
uncalledSpy = jasmineUnderTest.createSpy('uncalled spy'),
|
||||
uncalledSpy = new jasmineUnderTest.Env().createSpy('uncalled spy'),
|
||||
result;
|
||||
|
||||
uncalledSpy();
|
||||
@@ -59,7 +59,7 @@ describe("toHaveBeenCalledTimes", function() {
|
||||
|
||||
it("has a custom message on failure that tells it was called only once", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
|
||||
spy = jasmineUnderTest.createSpy('sample-spy'),
|
||||
spy = new jasmineUnderTest.Env().createSpy('sample-spy'),
|
||||
result;
|
||||
spy();
|
||||
spy();
|
||||
@@ -72,7 +72,7 @@ describe("toHaveBeenCalledTimes", function() {
|
||||
|
||||
it("has a custom message on failure that tells how many times it was called", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
|
||||
spy = jasmineUnderTest.createSpy('sample-spy'),
|
||||
spy = new jasmineUnderTest.Env().createSpy('sample-spy'),
|
||||
result;
|
||||
spy();
|
||||
spy();
|
||||
|
||||
@@ -5,7 +5,7 @@ describe("toHaveBeenCalledWith", function() {
|
||||
contains: jasmine.createSpy('delegated-contains').and.returnValue(true)
|
||||
},
|
||||
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(util),
|
||||
calledSpy = jasmineUnderTest.createSpy('called-spy'),
|
||||
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy'),
|
||||
result;
|
||||
|
||||
calledSpy('a', 'b');
|
||||
@@ -21,7 +21,7 @@ describe("toHaveBeenCalledWith", function() {
|
||||
},
|
||||
customEqualityTesters = [function() { return true; }],
|
||||
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(util, customEqualityTesters),
|
||||
calledSpy = jasmineUnderTest.createSpy('called-spy');
|
||||
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy');
|
||||
|
||||
calledSpy('a', 'b');
|
||||
matcher.compare(calledSpy, 'a', 'b');
|
||||
@@ -34,7 +34,7 @@ describe("toHaveBeenCalledWith", function() {
|
||||
contains: jasmine.createSpy('delegated-contains').and.returnValue(false)
|
||||
},
|
||||
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(util),
|
||||
uncalledSpy = jasmineUnderTest.createSpy('uncalled spy'),
|
||||
uncalledSpy = new jasmineUnderTest.Env().createSpy('uncalled spy'),
|
||||
result;
|
||||
|
||||
result = matcher.compare(uncalledSpy);
|
||||
@@ -47,7 +47,7 @@ describe("toHaveBeenCalledWith", function() {
|
||||
contains: jasmine.createSpy('delegated-contains').and.returnValue(false)
|
||||
},
|
||||
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(util),
|
||||
calledSpy = jasmineUnderTest.createSpy('called spy'),
|
||||
calledSpy = new jasmineUnderTest.Env().createSpy('called spy'),
|
||||
result;
|
||||
|
||||
calledSpy('a');
|
||||
|
||||
@@ -79,7 +79,7 @@ describe("toThrowError", function() {
|
||||
});
|
||||
|
||||
it("passes if thrown is an instanceof Error regardless of global that contains its constructor", function() {
|
||||
if (isNotRunningInBrowser() || jasmine.getEnv().phantomVersion < 2 || jasmine.getEnv().ieVersion < 10) {
|
||||
if (isNotRunningInBrowser()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ describe("toThrowError", function() {
|
||||
iframeDocument.body.appendChild(iframeDocument.createElement("script"))
|
||||
.textContent = "function method() { throw new Error('foo'); }";
|
||||
} else {
|
||||
// older IE
|
||||
// IE 10 and older
|
||||
iframeDocument.write("<html><head><script>function method() { throw new Error('foo'); }</script></head></html>");
|
||||
}
|
||||
|
||||
|
||||
73
spec/core/matchers/toThrowMatchingSpec.js
Normal file
73
spec/core/matchers/toThrowMatchingSpec.js
Normal file
@@ -0,0 +1,73 @@
|
||||
describe("toThrowMatching", function() {
|
||||
it("throws an error when the actual is not a function", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching();
|
||||
|
||||
expect(function() {
|
||||
matcher.compare({}, function() { return true; });
|
||||
}).toThrowError(/Actual is not a Function/);
|
||||
});
|
||||
|
||||
it("throws an error when the expected is not a function", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
fn = function() {
|
||||
throw new Error("foo");
|
||||
};
|
||||
|
||||
expect(function() {
|
||||
matcher.compare(fn, 1);
|
||||
}).toThrowError(/Predicate is not a Function/);
|
||||
});
|
||||
|
||||
it("fails if actual does not throw at all", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
fn = function() {
|
||||
return true;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, function() { return true; });
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw an exception.");
|
||||
});
|
||||
|
||||
it("fails with the correct message if thrown is a falsy value", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
fn = function() {
|
||||
throw undefined;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, function() { return false; });
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message()).toEqual("Expected function to throw an exception matching a predicate, but it threw undefined.");
|
||||
});
|
||||
|
||||
it("passes if the argument is a function that returns true when called with the error", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
predicate = function(e) { return e.message === "nope" },
|
||||
fn = function() {
|
||||
throw new TypeError("nope");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, predicate);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw an exception matching a predicate.");
|
||||
});
|
||||
|
||||
it("fails if the argument is a function that returns false when called with the error", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
predicate = function(e) { return e.message === "oh no" },
|
||||
fn = function() {
|
||||
throw new TypeError("nope");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, predicate);
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message()).toEqual("Expected function to throw an exception matching a predicate, but it threw TypeError with message 'nope'.");
|
||||
});
|
||||
});
|
||||
@@ -8,20 +8,8 @@
|
||||
return match ? parseFloat(match[1]) : void 0;
|
||||
}
|
||||
|
||||
env.ieVersion = browserVersion(function(userAgent) {
|
||||
return /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(userAgent);
|
||||
});
|
||||
|
||||
env.safariVersion = browserVersion(function(userAgent) {
|
||||
return /Safari/.exec(userAgent) && /Version\/([0-9]{0,})/.exec(userAgent);
|
||||
});
|
||||
|
||||
env.firefoxVersion = browserVersion(function(userAgent) {
|
||||
return /Firefox\/([0-9]{0,})/.exec(userAgent);
|
||||
});
|
||||
|
||||
env.phantomVersion = browserVersion(function(userAgent) {
|
||||
return /PhantomJS\/([0-9]{0,})/.exec(userAgent);
|
||||
});
|
||||
|
||||
})(jasmine.getEnv());
|
||||
|
||||
@@ -3,5 +3,4 @@
|
||||
// to the Jasmine source files (and not jasmine.js). So re-require
|
||||
window.jasmineUnderTest = jasmineRequire.core(jasmineRequire);
|
||||
jasmineRequire.html(jasmineUnderTest);
|
||||
jasmineRequire.console(jasmineRequire, jasmineUnderTest);
|
||||
})();
|
||||
|
||||
43
spec/helpers/integrationMatchers.js
Normal file
43
spec/helpers/integrationMatchers.js
Normal file
@@ -0,0 +1,43 @@
|
||||
(function(env) {
|
||||
env.registerIntegrationMatchers = function() {
|
||||
jasmine.addMatchers({
|
||||
toHaveFailedExpectationsForRunnable: function (util, customeEqualityTesters) {
|
||||
return {
|
||||
compare: function (actual, fullName, expectedFailures) {
|
||||
var foundRunnable = false, expectations = true, foundFailures = [];
|
||||
for (var i = 0; i < actual.calls.count(); i++) {
|
||||
var args = actual.calls.argsFor(i)[0];
|
||||
|
||||
if (args.fullName === fullName) {
|
||||
foundRunnable = true;
|
||||
|
||||
for (var j = 0; j < args.failedExpectations.length; j++) {
|
||||
foundFailures.push(args.failedExpectations[j].message);
|
||||
}
|
||||
|
||||
for (var j = 0; j < expectedFailures.length; j++) {
|
||||
var failure = foundFailures[j];
|
||||
var expectedFailure = expectedFailures[j];
|
||||
|
||||
if (Object.prototype.toString.call(expectedFailure) === '[object RegExp]') {
|
||||
expectations = expectations && expectedFailure.test(failure);
|
||||
} else {
|
||||
expectations = expectations && failure === expectedFailure;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
pass: foundRunnable && expectations,
|
||||
message: !foundRunnable ? 'The runnable "' + fullName + '" never finished' :
|
||||
'Expected runnable "' + fullName + '" to have failures ' + jasmine.pp(expectedFailures) + ' but it had ' + jasmine.pp(foundFailures)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
})(jasmine.getEnv());
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
}
|
||||
|
||||
function getSourceFiles() {
|
||||
var src_files = ['core/**/*.js', 'console/**/*.js', 'version.js'];
|
||||
var src_files = ['core/**/*.js', 'version.js'];
|
||||
src_files.forEach(function(file) {
|
||||
var filePath = path.join(__dirname, "../../", 'src/', file);
|
||||
glob.sync(filePath).forEach(function(resolvedFile) {
|
||||
@@ -25,9 +25,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
extend(jasmineUnderTestRequire, require(path.join(__dirname,"../../src/console/requireConsole.js")));
|
||||
getSourceFiles();
|
||||
global.jasmineUnderTest = jasmineUnderTestRequire.core(jasmineUnderTestRequire);
|
||||
|
||||
jasmineUnderTestRequire.console(jasmineUnderTestRequire, jasmineUnderTest);
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
describe("New HtmlReporter", function() {
|
||||
describe("HtmlReporter", function() {
|
||||
it("builds the initial DOM elements, including the title banner", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
@@ -26,9 +26,8 @@ describe("New HtmlReporter", function() {
|
||||
expect(title.getAttribute('href')).toEqual('http://jasmine.github.io/');
|
||||
expect(title.getAttribute('target')).toEqual('_blank');
|
||||
|
||||
var version = banner.querySelector(".jasmine-version"),
|
||||
versionText = 'textContent' in version ? version.textContent : version.innerText;
|
||||
expect(versionText).toEqual(jasmineUnderTest.version);
|
||||
var version = banner.querySelector(".jasmine-version");
|
||||
expect(version.textContent).toEqual(jasmineUnderTest.version);
|
||||
});
|
||||
|
||||
it("builds a single reporter even if initialized multiple times", function() {
|
||||
@@ -93,7 +92,7 @@ describe("New HtmlReporter", function() {
|
||||
expect(specEl.getAttribute("class")).toEqual("jasmine-empty");
|
||||
});
|
||||
|
||||
it("reports the status symbol of a disabled spec", function() {
|
||||
it("reports the status symbol of a excluded spec", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
@@ -105,10 +104,10 @@ describe("New HtmlReporter", function() {
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
reporter.specDone({id: 789, status: "disabled", fullName: "symbols should have titles", passedExpectations: [], failedExpectations: []});
|
||||
reporter.specDone({id: 789, status: "excluded", fullName: "symbols should have titles", passedExpectations: [], failedExpectations: []});
|
||||
|
||||
var specEl = container.querySelector('.jasmine-symbol-summary li');
|
||||
expect(specEl.getAttribute("class")).toEqual("jasmine-disabled");
|
||||
expect(specEl.getAttribute("class")).toEqual("jasmine-excluded");
|
||||
expect(specEl.getAttribute("id")).toEqual("spec_789");
|
||||
expect(specEl.getAttribute("title")).toEqual("symbols should have titles");
|
||||
});
|
||||
@@ -178,36 +177,6 @@ describe("New HtmlReporter", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("when there are suite failures", function () {
|
||||
it("displays the exceptions in their own alert bars", function(){
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.suiteDone({ status: 'failed', failedExpectations: [{ message: 'My After All Exception' }] });
|
||||
reporter.suiteDone({ status: 'failed', failedExpectations: [{ message: 'My Other Exception' }] });
|
||||
reporter.jasmineDone({ failedExpectations: [{ message: 'Global After All Failure' }, { message: 'Other Global' }] });
|
||||
|
||||
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
|
||||
|
||||
expect(alertBars.length).toEqual(5);
|
||||
expect(alertBars[1].innerHTML).toMatch(/My After All Exception/);
|
||||
expect(alertBars[1].getAttribute("class")).toEqual('jasmine-bar jasmine-errored');
|
||||
expect(alertBars[2].innerHTML).toMatch(/My Other Exception/);
|
||||
expect(alertBars[3].innerHTML).toMatch(/Global After All Failure/);
|
||||
expect(alertBars[4].innerHTML).toMatch(/Other Global/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there are deprecation warnings', function() {
|
||||
it('displays the messages in their own alert bars', function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
@@ -306,7 +275,7 @@ describe("New HtmlReporter", function() {
|
||||
reporter.jasmineStarted({});
|
||||
|
||||
timer.elapsed.and.returnValue(100);
|
||||
reporter.jasmineDone();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var duration = container.querySelector(".jasmine-alert .jasmine-duration");
|
||||
expect(duration.innerHTML).toMatch(/finished in 0.1s/);
|
||||
@@ -360,7 +329,12 @@ describe("New HtmlReporter", function() {
|
||||
reporter.specStarted(specResult);
|
||||
reporter.specDone(specResult);
|
||||
|
||||
reporter.suiteDone({id: 2});
|
||||
reporter.suiteDone({
|
||||
id: 2,
|
||||
status: 'things',
|
||||
description: "inner suite",
|
||||
fullName: "A Suite inner suite"
|
||||
});
|
||||
|
||||
specResult = {
|
||||
id: 209,
|
||||
@@ -373,7 +347,12 @@ describe("New HtmlReporter", function() {
|
||||
reporter.specStarted(specResult);
|
||||
reporter.specDone(specResult);
|
||||
|
||||
reporter.suiteDone({id: 1});
|
||||
reporter.suiteDone({
|
||||
id: 1,
|
||||
status: 'things',
|
||||
description: "A Suite",
|
||||
fullName: "A Suite"
|
||||
});
|
||||
|
||||
reporter.jasmineDone({});
|
||||
var summary = container.querySelector(".jasmine-summary");
|
||||
@@ -388,7 +367,7 @@ describe("New HtmlReporter", function() {
|
||||
var node = outerSuite.childNodes[i];
|
||||
classes.push(node.getAttribute("class"));
|
||||
}
|
||||
expect(classes).toEqual(["jasmine-suite-detail", "jasmine-specs", "jasmine-suite", "jasmine-specs"]);
|
||||
expect(classes).toEqual(["jasmine-suite-detail jasmine-things", "jasmine-specs", "jasmine-suite", "jasmine-specs"]);
|
||||
|
||||
var suiteDetail = outerSuite.childNodes[0];
|
||||
var suiteLink = suiteDetail.childNodes[0];
|
||||
@@ -403,7 +382,6 @@ describe("New HtmlReporter", function() {
|
||||
var specLink = spec.childNodes[0];
|
||||
expect(specLink.innerHTML).toEqual("with a spec");
|
||||
expect(specLink.getAttribute("href")).toEqual("?foo=bar&spec=A Suite with a spec");
|
||||
// expect(specLink.getAttribute("title")).toEqual("A Suite with a spec");
|
||||
});
|
||||
|
||||
it("has an options menu", function() {
|
||||
@@ -429,43 +407,78 @@ describe("New HtmlReporter", function() {
|
||||
var trigger = container.querySelector('.jasmine-run-options .jasmine-trigger'),
|
||||
payload = container.querySelector('.jasmine-run-options .jasmine-payload');
|
||||
|
||||
expect(payload.className).not.toContain('jasmine-open');
|
||||
expect(payload).not.toHaveClass('jasmine-open');
|
||||
|
||||
trigger.onclick();
|
||||
|
||||
expect(payload.className).toContain('jasmine-open');
|
||||
expect(payload).toHaveClass('jasmine-open');
|
||||
|
||||
trigger.onclick();
|
||||
|
||||
expect(payload.className).not.toContain('jasmine-open');
|
||||
expect(payload).not.toHaveClass('jasmine-open');
|
||||
});
|
||||
|
||||
describe("UI for raising/catching exceptions", function() {
|
||||
it("should be unchecked if the env is catching", function() {
|
||||
describe("when there are global errors", function() {
|
||||
it("displays the exceptions in their own alert bars", function(){
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
getContainer = function() { return container; },
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var raisingExceptionsUI = container.querySelector(".jasmine-raise");
|
||||
expect(raisingExceptionsUI.checked).toBe(false);
|
||||
reporter.jasmineStarted({});
|
||||
reporter.jasmineDone({ failedExpectations: [
|
||||
{ message: 'Global After All Failure', globalErrorType: 'afterAll' },
|
||||
{ message: 'Your JS is borken', globalErrorType: 'load' }
|
||||
] });
|
||||
|
||||
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
|
||||
|
||||
expect(alertBars.length).toEqual(3);
|
||||
expect(alertBars[1].getAttribute("class")).toEqual('jasmine-bar jasmine-errored');
|
||||
expect(alertBars[1].innerHTML).toMatch(/AfterAll Global After All Failure/);
|
||||
expect(alertBars[2].innerHTML).toMatch(/Error during loading: Your JS is borken/);
|
||||
expect(alertBars[2].innerHTML).not.toMatch(/line/);
|
||||
});
|
||||
|
||||
it("should be checked if the env is not catching", function() {
|
||||
it("displays file and line information if available", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.jasmineDone({ failedExpectations: [
|
||||
{
|
||||
message: 'Your JS is borken',
|
||||
globalErrorType: 'load',
|
||||
filename: 'some/file.js',
|
||||
lineno: 42
|
||||
}
|
||||
] });
|
||||
|
||||
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
|
||||
|
||||
expect(alertBars.length).toEqual(2);
|
||||
expect(alertBars[1].innerHTML).toMatch(/Error during loading: Your JS is borken in some\/file.js line 42/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("UI for stop on spec failure", function() {
|
||||
it("should be unchecked for full execution", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() {
|
||||
@@ -483,24 +496,49 @@ describe("New HtmlReporter", function() {
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
env.catchExceptions(false);
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var raisingExceptionsUI = container.querySelector(".jasmine-raise");
|
||||
expect(raisingExceptionsUI.checked).toBe(true);
|
||||
var stopOnFailureUI = container.querySelector(".jasmine-fail-fast");
|
||||
expect(stopOnFailureUI.checked).toBe(false);
|
||||
});
|
||||
|
||||
it("should affect the query param for catching exceptions", function() {
|
||||
it("should be checked if stopping short", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
exceptionsClickHandler = jasmine.createSpy("raise exceptions checked"),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
onRaiseExceptionsClick: exceptionsClickHandler,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
env.stopOnSpecFailure(true);
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var stopOnFailureUI = container.querySelector(".jasmine-fail-fast");
|
||||
expect(stopOnFailureUI.checked).toBe(true);
|
||||
});
|
||||
|
||||
it("should navigate and turn the setting on", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
navigationHandler = jasmine.createSpy('navigate'),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
navigateWithNewParam: navigationHandler,
|
||||
getContainer: getContainer,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
@@ -512,9 +550,40 @@ describe("New HtmlReporter", function() {
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var input = container.querySelector(".jasmine-raise");
|
||||
input.click();
|
||||
expect(exceptionsClickHandler).toHaveBeenCalled();
|
||||
var stopOnFailureUI = container.querySelector(".jasmine-fail-fast");
|
||||
stopOnFailureUI.click();
|
||||
|
||||
expect(navigationHandler).toHaveBeenCalledWith('failFast', true);
|
||||
});
|
||||
|
||||
it("should navigate and turn the setting off", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
navigationHandler = jasmine.createSpy('navigate'),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
navigateWithNewParam: navigationHandler,
|
||||
getContainer: getContainer,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
env.stopOnSpecFailure(true);
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var stopOnFailureUI = container.querySelector(".jasmine-fail-fast");
|
||||
stopOnFailureUI.click();
|
||||
|
||||
expect(navigationHandler).toHaveBeenCalledWith('failFast', false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -569,17 +638,17 @@ describe("New HtmlReporter", function() {
|
||||
expect(throwingExpectationsUI.checked).toBe(true);
|
||||
});
|
||||
|
||||
it("should affect the query param for throw expectation failures", function() {
|
||||
it("should navigate and change the setting to on", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
throwingExceptionHandler = jasmine.createSpy('throwingExceptions'),
|
||||
navigateHandler = jasmine.createSpy('navigate'),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
onThrowExpectationsClick: throwingExceptionHandler,
|
||||
navigateWithNewParam: navigateHandler,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
@@ -594,7 +663,37 @@ describe("New HtmlReporter", function() {
|
||||
var throwingExpectationsUI = container.querySelector(".jasmine-throw");
|
||||
throwingExpectationsUI.click();
|
||||
|
||||
expect(throwingExceptionHandler).toHaveBeenCalled();
|
||||
expect(navigateHandler).toHaveBeenCalledWith('throwFailures', true);
|
||||
});
|
||||
|
||||
it("should navigate and change the setting to off", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
navigateHandler = jasmine.createSpy('navigate'),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
navigateWithNewParam: navigateHandler,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
env.throwOnExpectationFailure(true);
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var throwingExpectationsUI = container.querySelector(".jasmine-throw");
|
||||
throwingExpectationsUI.click();
|
||||
|
||||
expect(navigateHandler).toHaveBeenCalledWith('throwFailures', false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -616,6 +715,7 @@ describe("New HtmlReporter", function() {
|
||||
}
|
||||
});
|
||||
|
||||
env.randomizeTests(false);
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
@@ -648,17 +748,17 @@ describe("New HtmlReporter", function() {
|
||||
expect(randomUI.checked).toBe(true);
|
||||
});
|
||||
|
||||
it("should affect the query param for random tests", function() {
|
||||
it("should navigate and change the setting to on", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
randomHandler = jasmine.createSpy('randomHandler'),
|
||||
navigateHandler = jasmine.createSpy('navigate'),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
onRandomClick: randomHandler,
|
||||
navigateWithNewParam: navigateHandler,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
@@ -667,13 +767,43 @@ describe("New HtmlReporter", function() {
|
||||
}
|
||||
});
|
||||
|
||||
env.randomizeTests(false);
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var randomUI = container.querySelector(".jasmine-random");
|
||||
randomUI.click();
|
||||
|
||||
expect(randomHandler).toHaveBeenCalled();
|
||||
expect(navigateHandler).toHaveBeenCalledWith('random', true);
|
||||
});
|
||||
|
||||
it("should navigate and change the setting to off", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
navigateHandler = jasmine.createSpy('navigate'),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
navigateWithNewParam: navigateHandler,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
env.randomizeTests(true);
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var randomUI = container.querySelector(".jasmine-random");
|
||||
randomUI.click();
|
||||
|
||||
expect(navigateHandler).toHaveBeenCalledWith('random', false);
|
||||
});
|
||||
|
||||
it("should show the seed bar if randomizing", function() {
|
||||
@@ -702,8 +832,7 @@ describe("New HtmlReporter", function() {
|
||||
});
|
||||
|
||||
var seedBar = container.querySelector(".jasmine-seed-bar");
|
||||
var seedBarText = 'textContent' in seedBar ? seedBar.textContent : seedBar.innerText;
|
||||
expect(seedBarText).toBe(', randomized with seed 424242');
|
||||
expect(seedBar.textContent).toBe(', randomized with seed 424242');
|
||||
var seedLink = container.querySelector(".jasmine-seed-bar a");
|
||||
expect(seedLink.getAttribute('href')).toBe('?seed=424242');
|
||||
});
|
||||
@@ -726,7 +855,7 @@ describe("New HtmlReporter", function() {
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var seedBar = container.querySelector(".jasmine-seed-bar");
|
||||
expect(seedBar).toBeNull();
|
||||
@@ -752,27 +881,6 @@ describe("New HtmlReporter", function() {
|
||||
});
|
||||
});
|
||||
|
||||
it("shows a message if no specs are run", function(){
|
||||
var env, container, reporter;
|
||||
env = new jasmineUnderTest.Env();
|
||||
container = document.createElement("div");
|
||||
var getContainer = function() { return container; },
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
|
||||
expect(alertBars[0].getAttribute('class')).toMatch(/jasmine-skipped/);
|
||||
expect(alertBars[0].innerHTML).toMatch(/No specs found/);
|
||||
});
|
||||
|
||||
describe("and all specs pass", function() {
|
||||
var env, container, reporter;
|
||||
beforeEach(function() {
|
||||
@@ -811,7 +919,6 @@ describe("New HtmlReporter", function() {
|
||||
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
|
||||
|
||||
expect(alertBars.length).toEqual(1);
|
||||
expect(alertBars[0].getAttribute('class')).toMatch(/jasmine-passed/);
|
||||
expect(alertBars[0].innerHTML).toMatch(/2 specs, 0 failures/);
|
||||
});
|
||||
|
||||
@@ -828,7 +935,7 @@ describe("New HtmlReporter", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("and there are disabled specs", function() {
|
||||
describe("and there are excluded specs", function() {
|
||||
var env, container, reporter, reporterConfig, specStatus;
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
@@ -841,9 +948,9 @@ describe("New HtmlReporter", function() {
|
||||
};
|
||||
specStatus = {
|
||||
id: 123,
|
||||
description: "with a disabled spec",
|
||||
fullName: "A Suite with a disabled spec",
|
||||
status: "disabled",
|
||||
description: "with a excluded spec",
|
||||
fullName: "A Suite with a excluded spec",
|
||||
status: "excluded",
|
||||
passedExpectations: [],
|
||||
failedExpectations: []
|
||||
};
|
||||
@@ -860,10 +967,10 @@ describe("New HtmlReporter", function() {
|
||||
reporter.jasmineDone({});
|
||||
});
|
||||
|
||||
it("shows the disabled spec in the spec list", function() {
|
||||
it("shows the excluded spec in the spec list", function() {
|
||||
var specList = container.querySelector(".jasmine-summary");
|
||||
|
||||
expect(specList.innerHTML).toContain('with a disabled spec');
|
||||
expect(specList.innerHTML).toContain('with a excluded spec');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -878,7 +985,7 @@ describe("New HtmlReporter", function() {
|
||||
reporter.jasmineDone({});
|
||||
});
|
||||
|
||||
it("doesn't show the disabled spec in the spec list", function() {
|
||||
it("doesn't show the excluded spec in the spec list", function() {
|
||||
var specList = container.querySelector(".jasmine-summary");
|
||||
|
||||
expect(specList.innerHTML).toEqual('');
|
||||
@@ -951,16 +1058,24 @@ describe("New HtmlReporter", function() {
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({ totalSpecsDefined: 1 });
|
||||
reporter.suiteStarted({
|
||||
id: 1,
|
||||
description: "A suite"
|
||||
});
|
||||
reporter.suiteStarted({
|
||||
id: 2,
|
||||
description: "inner suite"
|
||||
});
|
||||
|
||||
var passingResult = {id: 123, status: "passed", passedExpectations: [{passed: true}], failedExpectations: []};
|
||||
reporter.specStarted(passingResult);
|
||||
reporter.specDone(passingResult);
|
||||
var passingSpecResult = {id: 123, status: "passed", passedExpectations: [{passed: true}], failedExpectations: []};
|
||||
reporter.specStarted(passingSpecResult);
|
||||
reporter.specDone(passingSpecResult);
|
||||
|
||||
var failingResult = {
|
||||
var failingSpecResult = {
|
||||
id: 124,
|
||||
status: "failed",
|
||||
description: "a failing spec",
|
||||
fullName: "a suite with a failing spec",
|
||||
fullName: "a suite inner suite a failing spec",
|
||||
passedExpectations: [],
|
||||
failedExpectations: [
|
||||
{
|
||||
@@ -969,39 +1084,83 @@ describe("New HtmlReporter", function() {
|
||||
}
|
||||
]
|
||||
};
|
||||
reporter.specStarted(failingResult);
|
||||
reporter.specDone(failingResult);
|
||||
|
||||
var passingSuiteResult = {
|
||||
id: 1,
|
||||
description: "A suite"
|
||||
};
|
||||
var failingSuiteResult = {
|
||||
id: 2,
|
||||
description: 'a suite',
|
||||
fullName: 'a suite',
|
||||
status: 'failed',
|
||||
failedExpectations: [{ message: 'My After All Exception' }]
|
||||
};
|
||||
reporter.specStarted(failingSpecResult);
|
||||
reporter.specDone(failingSpecResult);
|
||||
reporter.suiteDone(passingSuiteResult);
|
||||
reporter.suiteDone(failingSuiteResult);
|
||||
reporter.suiteDone(passingSuiteResult);
|
||||
reporter.jasmineDone({});
|
||||
});
|
||||
|
||||
it("reports the specs counts", function() {
|
||||
var alertBar = container.querySelector(".jasmine-alert .jasmine-bar");
|
||||
|
||||
expect(alertBar.getAttribute('class')).toMatch(/jasmine-failed/);
|
||||
expect(alertBar.innerHTML).toMatch(/2 specs, 1 failure/);
|
||||
expect(alertBar.innerHTML).toMatch(/2 specs, 2 failure/);
|
||||
});
|
||||
|
||||
it("reports failure messages and stack traces", function() {
|
||||
var specFailures = container.querySelector(".jasmine-failures");
|
||||
|
||||
var failure = specFailures.childNodes[0];
|
||||
expect(failure.getAttribute("class")).toMatch(/jasmine-failed/);
|
||||
expect(failure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
|
||||
expect(specFailures.childNodes.length).toEqual(2);
|
||||
|
||||
var specDiv = failure.childNodes[0];
|
||||
var specFailure = specFailures.childNodes[0];
|
||||
expect(specFailure.getAttribute("class")).toMatch(/jasmine-failed/);
|
||||
expect(specFailure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
|
||||
|
||||
var specDiv = specFailure.childNodes[0];
|
||||
expect(specDiv.getAttribute("class")).toEqual("jasmine-description");
|
||||
|
||||
var specLink = specDiv.childNodes[0];
|
||||
expect(specLink.getAttribute("title")).toEqual("a suite with a failing spec");
|
||||
expect(specLink.getAttribute("href")).toEqual("?foo=bar&spec=a suite with a failing spec");
|
||||
|
||||
var message = failure.childNodes[1].childNodes[0];
|
||||
var message = specFailure.childNodes[1].childNodes[0];
|
||||
expect(message.getAttribute("class")).toEqual("jasmine-result-message");
|
||||
expect(message.innerHTML).toEqual("a failure message");
|
||||
|
||||
var stackTrace = failure.childNodes[1].childNodes[1];
|
||||
var stackTrace = specFailure.childNodes[1].childNodes[1];
|
||||
expect(stackTrace.getAttribute("class")).toEqual("jasmine-stack-trace");
|
||||
expect(stackTrace.innerHTML).toEqual("a stack trace");
|
||||
|
||||
var suiteFailure = specFailures.childNodes[0];
|
||||
expect(suiteFailure.getAttribute("class")).toMatch(/jasmine-failed/);
|
||||
expect(suiteFailure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
|
||||
|
||||
var suiteDiv = suiteFailure.childNodes[0];
|
||||
expect(suiteDiv.getAttribute("class")).toEqual("jasmine-description");
|
||||
|
||||
var suiteMessage = suiteFailure.childNodes[1].childNodes[0];
|
||||
expect(suiteMessage.getAttribute("class")).toEqual("jasmine-result-message");
|
||||
expect(suiteMessage.innerHTML).toEqual("a failure message");
|
||||
|
||||
var suiteStackTrace = suiteFailure.childNodes[1].childNodes[1];
|
||||
expect(suiteStackTrace.getAttribute("class")).toEqual("jasmine-stack-trace");
|
||||
expect(suiteStackTrace.innerHTML).toEqual("a stack trace");
|
||||
});
|
||||
|
||||
it('provides links to focus on a failure and each containing suite', function() {
|
||||
var description = container.querySelector('.jasmine-failures .jasmine-description');
|
||||
var links = description.querySelectorAll('a');
|
||||
|
||||
expect(description.textContent).toEqual('A suite > inner suite > a failing spec');
|
||||
|
||||
expect(links.length).toEqual(3);
|
||||
expect(links[0].textContent).toEqual('A suite');
|
||||
|
||||
expect(links[0].getAttribute('href')).toMatch(/\?foo=bar&spec=A suite/);
|
||||
|
||||
expect(links[1].textContent).toEqual('inner suite');
|
||||
expect(links[1].getAttribute('href')).toMatch(/\?foo=bar&spec=A suite inner suite/);
|
||||
|
||||
expect(links[2].textContent).toEqual('a failing spec');
|
||||
expect(links[2].getAttribute('href')).toMatch(/\?foo=bar&spec=a suite inner suite a failing spec/);
|
||||
});
|
||||
|
||||
it("allows switching between failure details and the spec summary", function() {
|
||||
@@ -1020,4 +1179,83 @@ describe("New HtmlReporter", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("The overall result bar", function() {
|
||||
describe("When the jasmineDone event's overallStatus is 'passed'", function() {
|
||||
it("has class jasmine-passed", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.jasmineDone({
|
||||
overallStatus: 'passed',
|
||||
failedExpectations: []
|
||||
});
|
||||
|
||||
var alertBar = container.querySelector(".jasmine-overall-result");
|
||||
expect(alertBar).toHaveClass("jasmine-passed");
|
||||
});
|
||||
});
|
||||
|
||||
describe("When the jasmineDone event's overallStatus is 'failed'", function() {
|
||||
it("has class jasmine-failed", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.jasmineDone({
|
||||
overallStatus: 'failed',
|
||||
failedExpectations: []
|
||||
});
|
||||
|
||||
var alertBar = container.querySelector(".jasmine-overall-result");
|
||||
expect(alertBar).toHaveClass("jasmine-failed");
|
||||
});
|
||||
});
|
||||
|
||||
describe("When the jasmineDone event's overallStatus is 'incomplete'", function() {
|
||||
it("has class jasmine-incomplete", function() {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.jasmineDone({
|
||||
overallStatus: 'incomplete',
|
||||
incompleteReason: 'because nope',
|
||||
failedExpectations: []
|
||||
});
|
||||
|
||||
var alertBar = container.querySelector(".jasmine-overall-result");
|
||||
expect(alertBar).toHaveClass("jasmine-incomplete");
|
||||
expect(alertBar.textContent).toContain("Incomplete: because nope");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
describe("jasmineUnderTest.pp (HTML Dependent)", function () {
|
||||
it("should stringify HTML nodes properly", function() {
|
||||
var sampleNode = document.createElement('div');
|
||||
sampleNode.innerHTML = 'foo<b>bar</b>';
|
||||
it("should stringify non-element HTML nodes properly", function() {
|
||||
var sampleNode = document.createTextNode("");
|
||||
expect(jasmineUnderTest.pp(sampleNode)).toEqual("HTMLNode");
|
||||
expect(jasmineUnderTest.pp({foo: sampleNode})).toEqual("Object({ foo: HTMLNode })");
|
||||
});
|
||||
|
||||
it("should stringify empty HTML elements as their opening tags", function () {
|
||||
var simple = document.createElement('div');
|
||||
simple.className = 'foo';
|
||||
expect(jasmineUnderTest.pp(simple)).toEqual('<div class="foo">');
|
||||
});
|
||||
|
||||
it("should stringify non-empty HTML elements as tags with placeholders", function() {
|
||||
var nonEmpty = document.createElement('div');
|
||||
nonEmpty.className = 'foo';
|
||||
nonEmpty.innerHTML = '<p>Irrelevant</p>';
|
||||
expect(jasmineUnderTest.pp(nonEmpty)).toEqual('<div class="foo">...</div>');
|
||||
});
|
||||
|
||||
it("should print Firefox's wrapped native objects correctly", function() {
|
||||
if(jasmine.getEnv().firefoxVersion) {
|
||||
try { new CustomEvent(); } catch(e) { var err = e; };
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
describe('Spy Registry browser-specific behavior', function() {
|
||||
function createSpy(name, originalFn) {
|
||||
return jasmineUnderTest.Spy(name, originalFn);
|
||||
}
|
||||
|
||||
it('can spy on and unspy window.onerror', function() {
|
||||
requireWriteableOnerror();
|
||||
|
||||
var spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
currentSpies: function() { return spies; },
|
||||
global: window
|
||||
}),
|
||||
currentSpies: function() { return spies; },
|
||||
createSpy: createSpy,
|
||||
global: window
|
||||
}),
|
||||
originalHandler = window.onerror;
|
||||
|
||||
try {
|
||||
|
||||
48
spec/html/matchers/toHaveClassSpec.js
Normal file
48
spec/html/matchers/toHaveClassSpec.js
Normal file
@@ -0,0 +1,48 @@
|
||||
describe('toHaveClass', function() {
|
||||
it('fails for a DOM element that lacks the expected class', function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveClass(),
|
||||
result = matcher.compare(document.createElement('div'), 'foo');
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
|
||||
it('passes for a DOM element that has the expected class', function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveClass(),
|
||||
el = document.createElement('div');
|
||||
|
||||
el.className = 'foo bar baz';
|
||||
|
||||
expect(matcher.compare(el, 'foo').pass).toBe(true);
|
||||
expect(matcher.compare(el, 'bar').pass).toBe(true);
|
||||
expect(matcher.compare(el, 'bar').pass).toBe(true);
|
||||
});
|
||||
|
||||
it('fails for a DOM element that only has other classes', function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveClass(),
|
||||
el = document.createElement('div');
|
||||
|
||||
el.className = 'foo bar';
|
||||
|
||||
expect(matcher.compare(el, 'fo').pass).toBe(false);
|
||||
});
|
||||
|
||||
it('throws an exception when actual is not a DOM element', function() {
|
||||
var matcher = jasmineUnderTest.matchers.toHaveClass();
|
||||
|
||||
expect(function() {
|
||||
matcher.compare('x', 'foo');
|
||||
}).toThrowError("'x' is not a DOM element");
|
||||
|
||||
expect(function() {
|
||||
matcher.compare(undefined, 'foo');
|
||||
}).toThrowError('undefined is not a DOM element');
|
||||
|
||||
expect(function() {
|
||||
matcher.compare(document.createTextNode(''), 'foo')
|
||||
}).toThrowError('HTMLNode is not a DOM element');
|
||||
|
||||
expect(function() {
|
||||
matcher.compare({classList: ''}, 'foo');
|
||||
}).toThrowError("Object({ classList: '' }) is not a DOM element");
|
||||
});
|
||||
});
|
||||
@@ -2,7 +2,6 @@
|
||||
"spec_dir": "spec",
|
||||
"spec_files": [
|
||||
"core/**/*.js",
|
||||
"console/**/*.js",
|
||||
"npmPackage/**/*.js"
|
||||
],
|
||||
"helpers": [
|
||||
@@ -11,6 +10,7 @@
|
||||
"helpers/checkForSet.js",
|
||||
"helpers/checkForSymbol.js",
|
||||
"helpers/checkForTypedArrays.js",
|
||||
"helpers/integrationMatchers.js",
|
||||
"helpers/nodeDefineJasmineUnderTest.js"
|
||||
],
|
||||
"random": true
|
||||
|
||||
@@ -13,7 +13,7 @@ src_files:
|
||||
- 'core/PrettyPrinter.js'
|
||||
- 'core/Suite.js'
|
||||
- 'core/**/*.js'
|
||||
- 'html/**.js'
|
||||
- 'html/**/*.js'
|
||||
- '**/*.js'
|
||||
stylesheets:
|
||||
helpers:
|
||||
@@ -23,6 +23,7 @@ helpers:
|
||||
- 'helpers/checkForSet.js'
|
||||
- 'helpers/checkForSymbol.js'
|
||||
- 'helpers/checkForTypedArrays.js'
|
||||
- 'helpers/integrationMatchers.js'
|
||||
- 'helpers/defineJasmineUnderTest.js'
|
||||
spec_files:
|
||||
- '**/*[Ss]pec.js'
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
getJasmineRequireObj().ConsoleReporter = function() {
|
||||
|
||||
var noopTimer = {
|
||||
start: function(){},
|
||||
elapsed: function(){ return 0; }
|
||||
};
|
||||
|
||||
function ConsoleReporter(options) {
|
||||
var print = options.print,
|
||||
showColors = options.showColors || false,
|
||||
onComplete = options.onComplete || function() {},
|
||||
timer = options.timer || noopTimer,
|
||||
specCount,
|
||||
failureCount,
|
||||
failedSpecs = [],
|
||||
pendingCount,
|
||||
ansi = {
|
||||
green: '\x1B[32m',
|
||||
red: '\x1B[31m',
|
||||
yellow: '\x1B[33m',
|
||||
none: '\x1B[0m'
|
||||
},
|
||||
failedSuites = [];
|
||||
|
||||
print('ConsoleReporter is deprecated and will be removed in a future version.');
|
||||
|
||||
this.jasmineStarted = function() {
|
||||
specCount = 0;
|
||||
failureCount = 0;
|
||||
pendingCount = 0;
|
||||
print('Started');
|
||||
printNewline();
|
||||
timer.start();
|
||||
};
|
||||
|
||||
this.jasmineDone = function() {
|
||||
printNewline();
|
||||
for (var i = 0; i < failedSpecs.length; i++) {
|
||||
specFailureDetails(failedSpecs[i]);
|
||||
}
|
||||
|
||||
if(specCount > 0) {
|
||||
printNewline();
|
||||
|
||||
var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' +
|
||||
failureCount + ' ' + plural('failure', failureCount);
|
||||
|
||||
if (pendingCount) {
|
||||
specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount);
|
||||
}
|
||||
|
||||
print(specCounts);
|
||||
} else {
|
||||
print('No specs found');
|
||||
}
|
||||
|
||||
printNewline();
|
||||
var seconds = timer.elapsed() / 1000;
|
||||
print('Finished in ' + seconds + ' ' + plural('second', seconds));
|
||||
printNewline();
|
||||
|
||||
for(i = 0; i < failedSuites.length; i++) {
|
||||
suiteFailureDetails(failedSuites[i]);
|
||||
}
|
||||
|
||||
onComplete(failureCount === 0);
|
||||
};
|
||||
|
||||
this.specDone = function(result) {
|
||||
specCount++;
|
||||
|
||||
if (result.status == 'pending') {
|
||||
pendingCount++;
|
||||
print(colored('yellow', '*'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.status == 'passed') {
|
||||
print(colored('green', '.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.status == 'failed') {
|
||||
failureCount++;
|
||||
failedSpecs.push(result);
|
||||
print(colored('red', 'F'));
|
||||
}
|
||||
};
|
||||
|
||||
this.suiteDone = function(result) {
|
||||
if (result.failedExpectations && result.failedExpectations.length > 0) {
|
||||
failureCount++;
|
||||
failedSuites.push(result);
|
||||
}
|
||||
};
|
||||
|
||||
return this;
|
||||
|
||||
function printNewline() {
|
||||
print('\n');
|
||||
}
|
||||
|
||||
function colored(color, str) {
|
||||
return showColors ? (ansi[color] + str + ansi.none) : str;
|
||||
}
|
||||
|
||||
function plural(str, count) {
|
||||
return count == 1 ? str : str + 's';
|
||||
}
|
||||
|
||||
function repeat(thing, times) {
|
||||
var arr = [];
|
||||
for (var i = 0; i < times; i++) {
|
||||
arr.push(thing);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
function indent(str, spaces) {
|
||||
var lines = (str || '').split('\n');
|
||||
var newArr = [];
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
newArr.push(repeat(' ', spaces).join('') + lines[i]);
|
||||
}
|
||||
return newArr.join('\n');
|
||||
}
|
||||
|
||||
function specFailureDetails(result) {
|
||||
printNewline();
|
||||
print(result.fullName);
|
||||
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
var failedExpectation = result.failedExpectations[i];
|
||||
printNewline();
|
||||
print(indent(failedExpectation.message, 2));
|
||||
print(indent(failedExpectation.stack, 2));
|
||||
}
|
||||
|
||||
printNewline();
|
||||
}
|
||||
|
||||
function suiteFailureDetails(result) {
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
printNewline();
|
||||
print(colored('red', 'An error was thrown in an afterAll'));
|
||||
printNewline();
|
||||
print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
|
||||
|
||||
}
|
||||
printNewline();
|
||||
}
|
||||
}
|
||||
|
||||
return ConsoleReporter;
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
function getJasmineRequireObj() {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
return exports;
|
||||
} else {
|
||||
window.jasmineRequire = window.jasmineRequire || {};
|
||||
return window.jasmineRequire;
|
||||
}
|
||||
}
|
||||
|
||||
getJasmineRequireObj().console = function(jRequire, j$) {
|
||||
j$.ConsoleReporter = jRequire.ConsoleReporter();
|
||||
};
|
||||
@@ -87,22 +87,10 @@ getJasmineRequireObj().Clock = function() {
|
||||
};
|
||||
|
||||
self.setTimeout = function(fn, delay, params) {
|
||||
if (legacyIE()) {
|
||||
if (arguments.length > 2) {
|
||||
throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill');
|
||||
}
|
||||
return timer.setTimeout(fn, delay);
|
||||
}
|
||||
return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]);
|
||||
};
|
||||
|
||||
self.setInterval = function(fn, delay, params) {
|
||||
if (legacyIE()) {
|
||||
if (arguments.length > 2) {
|
||||
throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill');
|
||||
}
|
||||
return timer.setInterval(fn, delay);
|
||||
}
|
||||
return Function.prototype.apply.apply(timer.setInterval, [global, arguments]);
|
||||
};
|
||||
|
||||
@@ -137,11 +125,6 @@ getJasmineRequireObj().Clock = function() {
|
||||
global.clearInterval === realTimingFunctions.clearInterval;
|
||||
}
|
||||
|
||||
function legacyIE() {
|
||||
//if these methods are polyfilled, apply will be present
|
||||
return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
|
||||
}
|
||||
|
||||
function replace(dest, source) {
|
||||
for (var prop in source) {
|
||||
dest[prop] = source[prop];
|
||||
|
||||
@@ -147,6 +147,7 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
|
||||
}
|
||||
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
|
||||
|
||||
314
src/core/Env.js
314
src/core/Env.js
@@ -11,12 +11,8 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
var self = this;
|
||||
var global = options.global || j$.getGlobal();
|
||||
|
||||
var hasExecuted = false;
|
||||
|
||||
var totalSpecsDefined = 0;
|
||||
|
||||
var catchExceptions = true;
|
||||
|
||||
var realSetTimeout = j$.getGlobal().setTimeout;
|
||||
var realClearTimeout = j$.getGlobal().clearTimeout;
|
||||
var clearStack = j$.getClearStack(j$.getGlobal());
|
||||
@@ -28,8 +24,11 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
var currentlyExecutingSuites = [];
|
||||
var currentDeclarationSuite = null;
|
||||
var throwOnExpectationFailure = false;
|
||||
var random = false;
|
||||
var stopOnSpecFailure = false;
|
||||
var random = true;
|
||||
var seed = null;
|
||||
var handlingLoadErrors = true;
|
||||
var hasFailures = false;
|
||||
|
||||
var currentSuite = function() {
|
||||
return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
|
||||
@@ -39,65 +38,29 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
return currentSpec || currentSuite();
|
||||
};
|
||||
|
||||
/**
|
||||
* This represents the available reporter callback for an object passed to {@link Env#addReporter}.
|
||||
* @interface Reporter
|
||||
*/
|
||||
var reporter = new j$.ReportDispatcher([
|
||||
/**
|
||||
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
||||
* @function
|
||||
* @name Reporter#jasmineStarted
|
||||
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
|
||||
*/
|
||||
'jasmineStarted',
|
||||
/**
|
||||
* When the entire suite has finished execution `jasmineDone` is called
|
||||
* @function
|
||||
* @name Reporter#jasmineDone
|
||||
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
|
||||
*/
|
||||
'jasmineDone',
|
||||
/**
|
||||
* `suiteStarted` is invoked when a `describe` starts to run
|
||||
* @function
|
||||
* @name Reporter#suiteStarted
|
||||
* @param {SuiteResult} result Information about the individual {@link describe} being run
|
||||
*/
|
||||
'suiteStarted',
|
||||
/**
|
||||
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
|
||||
*
|
||||
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
|
||||
* @function
|
||||
* @name Reporter#suiteDone
|
||||
* @param {SuiteResult} result
|
||||
*/
|
||||
'suiteDone',
|
||||
/**
|
||||
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
|
||||
* @function
|
||||
* @name Reporter#specStarted
|
||||
* @param {SpecResult} result Information about the individual {@link it} being run
|
||||
*/
|
||||
'specStarted',
|
||||
/**
|
||||
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
|
||||
*
|
||||
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
|
||||
* @function
|
||||
* @name Reporter#specDone
|
||||
* @param {SpecResult} result
|
||||
*/
|
||||
'specDone'
|
||||
]);
|
||||
|
||||
var globalErrors = new j$.GlobalErrors();
|
||||
globalErrors.install();
|
||||
globalErrors.pushListener(function(message, filename, lineno) {
|
||||
topSuite.result.failedExpectations.push({
|
||||
passed: false,
|
||||
globalErrorType: 'load',
|
||||
message: message,
|
||||
filename: filename,
|
||||
lineno: lineno
|
||||
});
|
||||
});
|
||||
|
||||
this.specFilter = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
this.addSpyStrategy = function(name, fn) {
|
||||
if(!currentRunnable()) {
|
||||
throw new Error('Custom spy strategies must be added in a before function or a spec');
|
||||
}
|
||||
runnableResources[currentRunnable().id].customSpyStrategies[name] = fn;
|
||||
};
|
||||
|
||||
this.addCustomEqualityTester = function(tester) {
|
||||
if(!currentRunnable()) {
|
||||
throw new Error('Custom Equalities must be added in a before function or a spec');
|
||||
@@ -142,7 +105,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
};
|
||||
|
||||
var defaultResourcesForRunnable = function(id, parentRunnableId) {
|
||||
var resources = {spies: [], customEqualityTesters: [], customMatchers: {}};
|
||||
var resources = {spies: [], customEqualityTesters: [], customMatchers: {}, customSpyStrategies: {}};
|
||||
|
||||
if(runnableResources[parentRunnableId]){
|
||||
resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters);
|
||||
@@ -196,24 +159,9 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
return buildExpectationResult(attrs);
|
||||
};
|
||||
|
||||
// TODO: fix this naming, and here's where the value comes in
|
||||
this.catchExceptions = function(value) {
|
||||
this.deprecated('The catchExceptions option is deprecated and will be replaced with stopOnSpecFailure in Jasmine 3.0');
|
||||
catchExceptions = !!value;
|
||||
return catchExceptions;
|
||||
};
|
||||
|
||||
this.catchingExceptions = function() {
|
||||
return catchExceptions;
|
||||
};
|
||||
|
||||
var maximumSpecCallbackDepth = 20;
|
||||
var currentSpecCallbackDepth = 0;
|
||||
|
||||
var catchException = function(e) {
|
||||
return j$.Spec.isPendingSpecException(e) || catchExceptions;
|
||||
};
|
||||
|
||||
this.throwOnExpectationFailure = function(value) {
|
||||
throwOnExpectationFailure = !!value;
|
||||
};
|
||||
@@ -222,6 +170,14 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
return throwOnExpectationFailure;
|
||||
};
|
||||
|
||||
this.stopOnSpecFailure = function(value) {
|
||||
stopOnSpecFailure = !!value;
|
||||
};
|
||||
|
||||
this.stoppingOnSpecFailure = function() {
|
||||
return stopOnSpecFailure;
|
||||
};
|
||||
|
||||
this.randomizeTests = function(value) {
|
||||
random = !!value;
|
||||
};
|
||||
@@ -237,6 +193,13 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
return seed;
|
||||
};
|
||||
|
||||
this.suppressLoadErrors = function() {
|
||||
if (handlingLoadErrors) {
|
||||
globalErrors.popListener();
|
||||
}
|
||||
handlingLoadErrors = false;
|
||||
};
|
||||
|
||||
this.deprecated = function(msg) {
|
||||
var runnable = currentRunnable() || topSuite;
|
||||
runnable.addDeprecationWarning(msg);
|
||||
@@ -245,16 +208,24 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
var queueRunnerFactory = function(options) {
|
||||
options.catchException = catchException;
|
||||
var queueRunnerFactory = function(options, args) {
|
||||
var failFast = false;
|
||||
if (options.isLeaf) {
|
||||
failFast = throwOnExpectationFailure;
|
||||
} else if (!options.isReporter) {
|
||||
failFast = stopOnSpecFailure;
|
||||
}
|
||||
options.clearStack = options.clearStack || clearStack;
|
||||
options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
|
||||
options.fail = self.fail;
|
||||
options.globalErrors = globalErrors;
|
||||
options.completeOnFirstError = throwOnExpectationFailure && options.isLeaf;
|
||||
options.completeOnFirstError = failFast;
|
||||
options.onException = options.onException || function(e) {
|
||||
(currentRunnable() || topSuite).onException(e);
|
||||
};
|
||||
options.deprecated = self.deprecated;
|
||||
|
||||
new j$.QueueRunner(options).execute();
|
||||
new j$.QueueRunner(options).execute(args);
|
||||
};
|
||||
|
||||
var topSuite = new j$.Suite({
|
||||
@@ -271,12 +242,62 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
return topSuite;
|
||||
};
|
||||
|
||||
this.execute = function(runnablesToRun) {
|
||||
if (hasExecuted) {
|
||||
this.deprecated('Executing the same Jasmine multiple times will no longer work in Jasmine 3.0');
|
||||
}
|
||||
/**
|
||||
* This represents the available reporter callback for an object passed to {@link Env#addReporter}.
|
||||
* @interface Reporter
|
||||
*/
|
||||
var reporter = new j$.ReportDispatcher([
|
||||
/**
|
||||
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
||||
* @function
|
||||
* @name Reporter#jasmineStarted
|
||||
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
|
||||
*/
|
||||
'jasmineStarted',
|
||||
/**
|
||||
* When the entire suite has finished execution `jasmineDone` is called
|
||||
* @function
|
||||
* @name Reporter#jasmineDone
|
||||
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
|
||||
*/
|
||||
'jasmineDone',
|
||||
/**
|
||||
* `suiteStarted` is invoked when a `describe` starts to run
|
||||
* @function
|
||||
* @name Reporter#suiteStarted
|
||||
* @param {SuiteResult} result Information about the individual {@link describe} being run
|
||||
*/
|
||||
'suiteStarted',
|
||||
/**
|
||||
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
|
||||
*
|
||||
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
|
||||
* @function
|
||||
* @name Reporter#suiteDone
|
||||
* @param {SuiteResult} result
|
||||
*/
|
||||
'suiteDone',
|
||||
/**
|
||||
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
|
||||
* @function
|
||||
* @name Reporter#specStarted
|
||||
* @param {SpecResult} result Information about the individual {@link it} being run
|
||||
*/
|
||||
'specStarted',
|
||||
/**
|
||||
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
|
||||
*
|
||||
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
|
||||
* @function
|
||||
* @name Reporter#specDone
|
||||
* @param {SpecResult} result
|
||||
*/
|
||||
'specDone'
|
||||
], queueRunnerFactory);
|
||||
|
||||
hasExecuted = true;
|
||||
this.execute = function(runnablesToRun) {
|
||||
var self = this;
|
||||
this.suppressLoadErrors();
|
||||
|
||||
if(!runnablesToRun) {
|
||||
if (focusedRunnables.length) {
|
||||
@@ -295,24 +316,30 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
tree: topSuite,
|
||||
runnableIds: runnablesToRun,
|
||||
queueRunnerFactory: queueRunnerFactory,
|
||||
nodeStart: function(suite) {
|
||||
nodeStart: function(suite, next) {
|
||||
currentlyExecutingSuites.push(suite);
|
||||
defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
|
||||
reporter.suiteStarted(suite.result);
|
||||
reporter.suiteStarted(suite.result, next);
|
||||
},
|
||||
nodeComplete: function(suite, result) {
|
||||
nodeComplete: function(suite, result, next) {
|
||||
if (suite !== currentSuite()) {
|
||||
throw new Error('Tried to complete the wrong suite');
|
||||
}
|
||||
|
||||
if (!suite.markedPending) {
|
||||
clearResourcesForRunnable(suite.id);
|
||||
}
|
||||
clearResourcesForRunnable(suite.id);
|
||||
currentlyExecutingSuites.pop();
|
||||
reporter.suiteDone(result);
|
||||
|
||||
if (result.status === 'failed') {
|
||||
hasFailures = true;
|
||||
}
|
||||
|
||||
reporter.suiteDone(result, next);
|
||||
},
|
||||
orderChildren: function(node) {
|
||||
return order.sort(node.children);
|
||||
},
|
||||
excludeNode: function(spec) {
|
||||
return !self.specFilter(spec);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -329,27 +356,42 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
reporter.jasmineStarted({
|
||||
totalSpecsDefined: totalSpecsDefined,
|
||||
order: order
|
||||
});
|
||||
}, function() {
|
||||
currentlyExecutingSuites.push(topSuite);
|
||||
|
||||
currentlyExecutingSuites.push(topSuite);
|
||||
processor.execute(function () {
|
||||
clearResourcesForRunnable(topSuite.id);
|
||||
currentlyExecutingSuites.pop();
|
||||
var overallStatus, incompleteReason;
|
||||
|
||||
globalErrors.install();
|
||||
processor.execute(function() {
|
||||
clearResourcesForRunnable(topSuite.id);
|
||||
currentlyExecutingSuites.pop();
|
||||
globalErrors.uninstall();
|
||||
if (hasFailures || topSuite.result.failedExpectations.length > 0) {
|
||||
overallStatus = 'failed';
|
||||
} else if (focusedRunnables.length > 0) {
|
||||
overallStatus = 'incomplete';
|
||||
incompleteReason = 'fit() or fdescribe() was found';
|
||||
} else if (totalSpecsDefined === 0) {
|
||||
overallStatus = 'incomplete';
|
||||
incompleteReason = 'No specs found';
|
||||
} else {
|
||||
overallStatus = 'passed';
|
||||
}
|
||||
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineDone} event.
|
||||
* @typedef JasmineDoneInfo
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
* @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
||||
* @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
|
||||
*/
|
||||
reporter.jasmineDone({
|
||||
order: order,
|
||||
failedExpectations: topSuite.result.failedExpectations,
|
||||
deprecationWarnings: topSuite.result.deprecationWarnings
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineDone} event.
|
||||
* @typedef JasmineDoneInfo
|
||||
* @property {OverallStatus} - The overall result of the sute: 'passed', 'failed', or 'incomplete'.
|
||||
* @property {IncompleteReason} - Explanation of why the suite was incimplete.
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
* @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
||||
* @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
|
||||
*/
|
||||
reporter.jasmineDone({
|
||||
overallStatus: overallStatus,
|
||||
incompleteReason: incompleteReason,
|
||||
order: order,
|
||||
failedExpectations: topSuite.result.failedExpectations,
|
||||
deprecationWarnings: topSuite.result.deprecationWarnings
|
||||
}, function() {});
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -373,12 +415,27 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
reporter.clearReporters();
|
||||
};
|
||||
|
||||
var spyRegistry = new j$.SpyRegistry({currentSpies: function() {
|
||||
if(!currentRunnable()) {
|
||||
throw new Error('Spies must be created in a before function or a spec');
|
||||
var spyFactory = new j$.SpyFactory(function() {
|
||||
var runnable = currentRunnable();
|
||||
|
||||
if (runnable) {
|
||||
return runnableResources[runnable.id].customSpyStrategies;
|
||||
}
|
||||
return runnableResources[currentRunnable().id].spies;
|
||||
}});
|
||||
|
||||
return {};
|
||||
});
|
||||
|
||||
var spyRegistry = new j$.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
if(!currentRunnable()) {
|
||||
throw new Error('Spies must be created in a before function or a spec');
|
||||
}
|
||||
return runnableResources[currentRunnable().id].spies;
|
||||
},
|
||||
createSpy: function(name, originalFn) {
|
||||
return self.createSpy(name, originalFn);
|
||||
}
|
||||
});
|
||||
|
||||
this.allowRespy = function(allow){
|
||||
spyRegistry.allowRespy(allow);
|
||||
@@ -392,6 +449,14 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
return spyRegistry.spyOnProperty.apply(spyRegistry, arguments);
|
||||
};
|
||||
|
||||
this.createSpy = function(name, originalFn) {
|
||||
return spyFactory.createSpy(name, originalFn);
|
||||
};
|
||||
|
||||
this.createSpyObj = function(baseName, methodNames) {
|
||||
return spyFactory.createSpyObj(baseName, methodNames);
|
||||
};
|
||||
|
||||
var ensureIsFunction = function(fn, caller) {
|
||||
if (!j$.isFunction_(fn)) {
|
||||
throw new Error(caller + ' expects a function argument; received ' + j$.getType_(fn));
|
||||
@@ -451,7 +516,6 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
var focusedRunnables = [];
|
||||
|
||||
this.fdescribe = function(description, specDefinitions) {
|
||||
this.deprecated('fit and fdescribe will cause your suite to report an \'incomplete\' status in Jasmine 3.0');
|
||||
ensureIsNotNested('fdescribe');
|
||||
ensureIsFunction(specDefinitions, 'fdescribe');
|
||||
var suite = suiteFactory(description);
|
||||
@@ -477,9 +541,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
}
|
||||
|
||||
if (declarationError) {
|
||||
self.it('encountered a declaration exception', function() {
|
||||
throw declarationError;
|
||||
});
|
||||
suite.onException(declarationError);
|
||||
}
|
||||
|
||||
currentDeclarationSuite = parentSuite;
|
||||
@@ -530,22 +592,23 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
throwOnExpectationFailure: throwOnExpectationFailure
|
||||
});
|
||||
|
||||
if (!self.specFilter(spec)) {
|
||||
spec.disable();
|
||||
}
|
||||
|
||||
return spec;
|
||||
|
||||
function specResultCallback(result) {
|
||||
function specResultCallback(result, next) {
|
||||
clearResourcesForRunnable(spec.id);
|
||||
currentSpec = null;
|
||||
reporter.specDone(result);
|
||||
|
||||
if (result.status === 'failed') {
|
||||
hasFailures = true;
|
||||
}
|
||||
|
||||
reporter.specDone(result, next);
|
||||
}
|
||||
|
||||
function specStarted(spec) {
|
||||
function specStarted(spec, next) {
|
||||
currentSpec = spec;
|
||||
defaultResourcesForRunnable(spec.id, suite.id);
|
||||
reporter.specStarted(spec.result);
|
||||
reporter.specStarted(spec.result, next);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -577,7 +640,6 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
};
|
||||
|
||||
this.fit = function(description, fn, timeout){
|
||||
this.deprecated('fit and fdescribe will cause your suite to report an \'incomplete\' status in Jasmine 3.0');
|
||||
ensureIsNotNested('fit');
|
||||
ensureIsFunctionOrAsync(fn, 'fit');
|
||||
var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
getJasmineRequireObj().ExceptionFormatter = function() {
|
||||
function ExceptionFormatter() {
|
||||
getJasmineRequireObj().ExceptionFormatter = function(j$) {
|
||||
|
||||
function ExceptionFormatter(options) {
|
||||
var jasmineFile = (options && options.jasmineFile) || j$.util.jasmineFile();
|
||||
this.message = function(error) {
|
||||
var message = '';
|
||||
|
||||
@@ -21,8 +23,34 @@ getJasmineRequireObj().ExceptionFormatter = function() {
|
||||
};
|
||||
|
||||
this.stack = function(error) {
|
||||
return error ? error.stack : null;
|
||||
if (!error || !error.stack) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var stackTrace = new j$.StackTrace(error.stack);
|
||||
var lines = filterJasmine(stackTrace);
|
||||
|
||||
if (stackTrace.message) {
|
||||
lines.unshift(stackTrace.message);
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
};
|
||||
|
||||
function filterJasmine(stackTrace) {
|
||||
var result = [],
|
||||
jasmineMarker = stackTrace.style === 'webkit' ? '<Jasmine>' : ' at <Jasmine>';
|
||||
|
||||
stackTrace.frames.forEach(function(frame) {
|
||||
if (frame.file && frame.file !== jasmineFile) {
|
||||
result.push(frame.raw);
|
||||
} else if (result[result.length - 1] !== jasmineMarker) {
|
||||
result.push(jasmineMarker);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return ExceptionFormatter;
|
||||
|
||||
@@ -13,8 +13,6 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
this.uninstall = function noop() {};
|
||||
|
||||
this.install = function install() {
|
||||
if (global.process && global.process.listeners && j$.isFunction_(global.process.on)) {
|
||||
var originalHandlers = global.process.listeners('uncaughtException');
|
||||
|
||||
@@ -29,11 +29,13 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
} else if (typeof value === 'string') {
|
||||
this.emitString(value);
|
||||
} else if (j$.isSpy(value)) {
|
||||
this.emitScalar('spy on ' + value.and.identity());
|
||||
this.emitScalar('spy on ' + value.and.identity);
|
||||
} else if (value instanceof RegExp) {
|
||||
this.emitScalar(value.toString());
|
||||
} else if (typeof value === 'function') {
|
||||
this.emitScalar('Function');
|
||||
} else if (value.nodeType === 1) {
|
||||
this.emitDomElement(value);
|
||||
} else if (typeof value.nodeType === 'number') {
|
||||
this.emitScalar('HTMLNode');
|
||||
} else if (value instanceof Date) {
|
||||
@@ -225,6 +227,18 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(constructorName + ' [ ' + itemsString + ' ]');
|
||||
};
|
||||
|
||||
PrettyPrinter.prototype.emitDomElement = function(el) {
|
||||
var closingTag = '</' + el.tagName.toLowerCase() + '>';
|
||||
|
||||
if (el.innerHTML === '') {
|
||||
this.append(el.outerHTML.replace(closingTag, ''));
|
||||
} else {
|
||||
var tagEnd = el.outerHTML.indexOf(el.innerHTML);
|
||||
this.append(el.outerHTML.substring(0, tagEnd));
|
||||
this.append('...' + closingTag);
|
||||
}
|
||||
};
|
||||
|
||||
PrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {
|
||||
this.append(property);
|
||||
this.append(': ');
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
function StopExecutionError() {}
|
||||
StopExecutionError.prototype = new Error();
|
||||
j$.StopExecutionError = StopExecutionError;
|
||||
|
||||
function once(fn) {
|
||||
var called = false;
|
||||
@@ -18,12 +21,16 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
this.onComplete = attrs.onComplete || function() {};
|
||||
this.clearStack = attrs.clearStack || function(fn) {fn();};
|
||||
this.onException = attrs.onException || function() {};
|
||||
this.catchException = attrs.catchException || function() { return true; };
|
||||
this.userContext = attrs.userContext || new j$.UserContext();
|
||||
this.timeout = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
|
||||
this.fail = attrs.fail || function() {};
|
||||
this.globalErrors = attrs.globalErrors || { pushListener: function() {}, popListener: function() {} };
|
||||
this.completeOnFirstError = !!attrs.completeOnFirstError;
|
||||
this.errored = false;
|
||||
|
||||
if (typeof(this.onComplete) !== 'function') {
|
||||
throw new Error('invalid onComplete ' + JSON.stringify(this.onComplete));
|
||||
}
|
||||
this.deprecated = attrs.deprecated;
|
||||
}
|
||||
|
||||
@@ -44,6 +51,101 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
QueueRunner.prototype.clearTimeout = function(timeoutId) {
|
||||
Function.prototype.apply.apply(this.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]);
|
||||
};
|
||||
|
||||
QueueRunner.prototype.setTimeout = function(fn, timeout) {
|
||||
return Function.prototype.apply.apply(this.timeout.setTimeout, [j$.getGlobal(), [fn, timeout]]);
|
||||
};
|
||||
|
||||
QueueRunner.prototype.attempt = function attempt(iterativeIndex) {
|
||||
var self = this, completedSynchronously = true,
|
||||
handleError = function handleError(error) {
|
||||
onException(error);
|
||||
next(error);
|
||||
},
|
||||
cleanup = once(function cleanup() {
|
||||
self.clearTimeout(timeoutId);
|
||||
self.globalErrors.popListener(handleError);
|
||||
}),
|
||||
next = once(function next(err) {
|
||||
cleanup();
|
||||
|
||||
if (j$.isError_(err)) {
|
||||
if (!(err instanceof StopExecutionError)) {
|
||||
self.fail(err);
|
||||
}
|
||||
self.errored = errored = true;
|
||||
}
|
||||
|
||||
function runNext() {
|
||||
if (self.completeOnFirstError && errored) {
|
||||
self.skipToCleanup(iterativeIndex);
|
||||
} else {
|
||||
self.run(iterativeIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (completedSynchronously) {
|
||||
self.setTimeout(runNext);
|
||||
} else {
|
||||
runNext();
|
||||
}
|
||||
}),
|
||||
errored = false,
|
||||
queueableFn = self.queueableFns[iterativeIndex],
|
||||
timeoutId;
|
||||
|
||||
next.fail = function nextFail() {
|
||||
self.fail.apply(null, arguments);
|
||||
self.errored = errored = true;
|
||||
next();
|
||||
};
|
||||
|
||||
self.globalErrors.pushListener(handleError);
|
||||
|
||||
if (queueableFn.timeout) {
|
||||
timeoutId = self.setTimeout(function() {
|
||||
var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.');
|
||||
onException(error);
|
||||
next();
|
||||
}, queueableFn.timeout());
|
||||
}
|
||||
|
||||
try {
|
||||
if (queueableFn.fn.length === 0) {
|
||||
var maybeThenable = queueableFn.fn.call(self.userContext);
|
||||
|
||||
if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
|
||||
maybeThenable.then(next, onPromiseRejection);
|
||||
completedSynchronously = false;
|
||||
return { completedSynchronously: false };
|
||||
}
|
||||
} else {
|
||||
queueableFn.fn.call(self.userContext, next);
|
||||
completedSynchronously = false;
|
||||
return { completedSynchronously: false };
|
||||
}
|
||||
} catch (e) {
|
||||
onException(e);
|
||||
self.errored = errored = true;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
return { completedSynchronously: true, errored: errored };
|
||||
|
||||
function onException(e) {
|
||||
self.onException(e);
|
||||
self.errored = errored = true;
|
||||
}
|
||||
|
||||
function onPromiseRejection(e) {
|
||||
onException(e);
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
QueueRunner.prototype.run = function(recursiveIndex) {
|
||||
var length = this.queueableFns.length,
|
||||
self = this,
|
||||
@@ -51,12 +153,14 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
|
||||
|
||||
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
|
||||
var result = attempt(iterativeIndex);
|
||||
var result = this.attempt(iterativeIndex);
|
||||
|
||||
if (!result.completedSynchronously) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.errored = result.errored;
|
||||
|
||||
if (this.completeOnFirstError && result.errored) {
|
||||
this.skipToCleanup(iterativeIndex);
|
||||
return;
|
||||
@@ -65,107 +169,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
|
||||
this.clearStack(function() {
|
||||
self.globalErrors.popListener(self.handleFinalError);
|
||||
self.onComplete();
|
||||
self.onComplete(self.errored && new StopExecutionError());
|
||||
});
|
||||
|
||||
function attempt() {
|
||||
var clearTimeout = function () {
|
||||
Function.prototype.apply.apply(self.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]);
|
||||
},
|
||||
setTimeout = function(delayedFn, delay) {
|
||||
return Function.prototype.apply.apply(self.timeout.setTimeout, [j$.getGlobal(), [delayedFn, delay]]);
|
||||
},
|
||||
completedSynchronously = true,
|
||||
handleError = function(error) {
|
||||
onException(error);
|
||||
next();
|
||||
},
|
||||
cleanup = once(function() {
|
||||
clearTimeout(timeoutId);
|
||||
self.globalErrors.popListener(handleError);
|
||||
}),
|
||||
next = once(function (err) {
|
||||
cleanup();
|
||||
|
||||
if (err instanceof Error) {
|
||||
self.deprecated('done callback received an Error object. Jasmine 3.0 will treat this as a failure');
|
||||
}
|
||||
|
||||
function runNext() {
|
||||
if (self.completeOnFirstError && errored) {
|
||||
self.skipToCleanup(iterativeIndex);
|
||||
} else {
|
||||
self.run(iterativeIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (completedSynchronously) {
|
||||
setTimeout(runNext);
|
||||
} else {
|
||||
runNext();
|
||||
}
|
||||
}),
|
||||
errored = false,
|
||||
queueableFn = self.queueableFns[iterativeIndex],
|
||||
timeoutId;
|
||||
|
||||
next.fail = function() {
|
||||
self.fail.apply(null, arguments);
|
||||
errored = true;
|
||||
next();
|
||||
};
|
||||
|
||||
self.globalErrors.pushListener(handleError);
|
||||
|
||||
if (queueableFn.timeout) {
|
||||
timeoutId = setTimeout(function() {
|
||||
var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.');
|
||||
onException(error);
|
||||
next();
|
||||
}, queueableFn.timeout());
|
||||
}
|
||||
|
||||
try {
|
||||
if (queueableFn.fn.length === 0) {
|
||||
var maybeThenable = queueableFn.fn.call(self.userContext);
|
||||
|
||||
if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
|
||||
maybeThenable.then(next, onPromiseRejection);
|
||||
completedSynchronously = false;
|
||||
return { completedSynchronously: false };
|
||||
}
|
||||
} else {
|
||||
queueableFn.fn.call(self.userContext, next);
|
||||
completedSynchronously = false;
|
||||
return { completedSynchronously: false };
|
||||
}
|
||||
} catch (e) {
|
||||
handleException(e, queueableFn);
|
||||
errored = true;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
return { completedSynchronously: true, errored: errored };
|
||||
|
||||
function onException(e) {
|
||||
self.onException(e);
|
||||
errored = true;
|
||||
}
|
||||
|
||||
function onPromiseRejection(e) {
|
||||
onException(e);
|
||||
next();
|
||||
}
|
||||
|
||||
function handleException(e, queueableFn) {
|
||||
onException(e);
|
||||
if (!self.catchException(e)) {
|
||||
//TODO: set a var when we catch an exception and
|
||||
//use a finally block to close the loop in a nice way..
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return QueueRunner;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
getJasmineRequireObj().ReportDispatcher = function(j$) {
|
||||
function ReportDispatcher(methods) {
|
||||
function ReportDispatcher(methods, queueRunnerFactory) {
|
||||
|
||||
var dispatchedMethods = methods || [];
|
||||
|
||||
@@ -33,11 +33,40 @@ getJasmineRequireObj().ReportDispatcher = function(j$) {
|
||||
if (reporters.length === 0 && fallbackReporter !== null) {
|
||||
reporters.push(fallbackReporter);
|
||||
}
|
||||
var onComplete = args[args.length - 1];
|
||||
args = j$.util.argsToArray(args).splice(0, args.length - 1);
|
||||
var fns = [];
|
||||
for (var i = 0; i < reporters.length; i++) {
|
||||
var reporter = reporters[i];
|
||||
if (reporter[method]) {
|
||||
reporter[method].apply(reporter, j$.util.cloneArgs(args));
|
||||
}
|
||||
addFn(fns, reporter, method, args);
|
||||
}
|
||||
|
||||
queueRunnerFactory({
|
||||
queueableFns: fns,
|
||||
onComplete: onComplete,
|
||||
isReporter: true
|
||||
});
|
||||
}
|
||||
|
||||
function addFn(fns, reporter, method, args) {
|
||||
var fn = reporter[method];
|
||||
if (!fn) {
|
||||
return;
|
||||
}
|
||||
|
||||
var thisArgs = j$.util.cloneArgs(args);
|
||||
if (fn.length <= 1) {
|
||||
fns.push({
|
||||
fn: function () {
|
||||
return fn.apply(reporter, thisArgs);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fns.push({
|
||||
fn: function (done) {
|
||||
return fn.apply(reporter, thisArgs.concat([done]));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,10 +57,22 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
return this.expectationFactory(actual, this);
|
||||
};
|
||||
|
||||
Spec.prototype.execute = function(onComplete, enabled) {
|
||||
Spec.prototype.execute = function(onComplete, excluded) {
|
||||
var self = this;
|
||||
|
||||
this.onStart(this);
|
||||
var onStart = {
|
||||
fn: function(done) {
|
||||
self.onStart(self, done);
|
||||
}
|
||||
};
|
||||
|
||||
var complete = {
|
||||
fn: function(done) {
|
||||
self.queueableFn.fn = null;
|
||||
self.result.status = self.status(excluded);
|
||||
self.resultCallback(self.result, done);
|
||||
}
|
||||
};
|
||||
|
||||
var fns = this.beforeAndAfterFns();
|
||||
var regularFns = fns.befores.concat(this.queueableFn);
|
||||
@@ -69,27 +81,24 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
isLeaf: true,
|
||||
queueableFns: regularFns,
|
||||
cleanupFns: fns.afters,
|
||||
onException: function() { self.onException.apply(self, arguments); },
|
||||
onComplete: complete,
|
||||
onException: function () {
|
||||
self.onException.apply(self, arguments);
|
||||
},
|
||||
onComplete: function() {
|
||||
onComplete(self.result.status === 'failed' && new j$.StopExecutionError('spec failed'));
|
||||
},
|
||||
userContext: this.userContext()
|
||||
};
|
||||
|
||||
if (!this.isExecutable() || this.markedPending || enabled === false) {
|
||||
if (this.markedPending || excluded === true) {
|
||||
runnerConfig.queueableFns = [];
|
||||
runnerConfig.cleanupFns = [];
|
||||
runnerConfig.onComplete = function() { complete(enabled); };
|
||||
}
|
||||
|
||||
runnerConfig.queueableFns.unshift(onStart);
|
||||
runnerConfig.cleanupFns.push(complete);
|
||||
|
||||
this.queueRunnerFactory(runnerConfig);
|
||||
|
||||
function complete(enabledAgain) {
|
||||
self.result.status = self.status(enabledAgain);
|
||||
self.resultCallback(self.result);
|
||||
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Spec.prototype.onException = function onException(e) {
|
||||
@@ -111,10 +120,6 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
}, true);
|
||||
};
|
||||
|
||||
Spec.prototype.disable = function() {
|
||||
this.disabled = true;
|
||||
};
|
||||
|
||||
Spec.prototype.pend = function(message) {
|
||||
this.markedPending = true;
|
||||
if (message) {
|
||||
@@ -127,9 +132,9 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
return this.result;
|
||||
};
|
||||
|
||||
Spec.prototype.status = function(enabled) {
|
||||
if (this.disabled || enabled === false) {
|
||||
return 'disabled';
|
||||
Spec.prototype.status = function(excluded) {
|
||||
if (excluded === true) {
|
||||
return 'excluded';
|
||||
}
|
||||
|
||||
if (this.markedPending) {
|
||||
@@ -143,10 +148,6 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
Spec.prototype.isExecutable = function() {
|
||||
return !this.disabled;
|
||||
};
|
||||
|
||||
Spec.prototype.getFullName = function() {
|
||||
return this.getSpecName(this);
|
||||
};
|
||||
|
||||
@@ -13,17 +13,18 @@ getJasmineRequireObj().Spy = function (j$) {
|
||||
* @constructor
|
||||
* @name Spy
|
||||
*/
|
||||
function Spy(name, originalFn) {
|
||||
function Spy(name, originalFn, customStrategies) {
|
||||
var numArgs = (typeof originalFn === 'function' ? originalFn.length : 0),
|
||||
wrapper = makeFunc(numArgs, function () {
|
||||
return spy.apply(this, Array.prototype.slice.call(arguments));
|
||||
}),
|
||||
spyStrategy = new j$.SpyStrategy({
|
||||
strategyDispatcher = new SpyStrategyDispatcher({
|
||||
name: name,
|
||||
fn: originalFn,
|
||||
getSpy: function () {
|
||||
return wrapper;
|
||||
}
|
||||
},
|
||||
customStrategies: customStrategies
|
||||
}),
|
||||
callTracker = new j$.CallTracker(),
|
||||
spy = function () {
|
||||
@@ -40,7 +41,7 @@ getJasmineRequireObj().Spy = function (j$) {
|
||||
};
|
||||
|
||||
callTracker.track(callData);
|
||||
var returnValue = spyStrategy.exec.apply(this, arguments);
|
||||
var returnValue = strategyDispatcher.exec(this, arguments);
|
||||
callData.returnValue = returnValue;
|
||||
|
||||
return returnValue;
|
||||
@@ -69,11 +70,94 @@ getJasmineRequireObj().Spy = function (j$) {
|
||||
wrapper[prop] = originalFn[prop];
|
||||
}
|
||||
|
||||
wrapper.and = spyStrategy;
|
||||
/**
|
||||
* @member {SpyStrategy} - Accesses the default strategy for the spy. This strategy will be used
|
||||
* whenever the spy is called with arguments that don't match any strategy
|
||||
* created with {@link Spy#withArgs}.
|
||||
* @name Spy#and
|
||||
* @example
|
||||
* spyOn(someObj, 'func').and.returnValue(42);
|
||||
*/
|
||||
wrapper.and = strategyDispatcher.and;
|
||||
/**
|
||||
* Specifies a strategy to be used for calls to the spy that have the
|
||||
* specified arguments.
|
||||
* @name Spy#withArgs
|
||||
* @function
|
||||
* @param {...*} args - The arguments to match
|
||||
* @type {SpyStrategy}
|
||||
* @example
|
||||
* spyOn(someObj, 'func').withArgs(1, 2, 3).and.returnValue(42);
|
||||
* someObj.func(1, 2, 3); // returns 42
|
||||
*/
|
||||
wrapper.withArgs = function() {
|
||||
return strategyDispatcher.withArgs.apply(strategyDispatcher, arguments);
|
||||
};
|
||||
wrapper.calls = callTracker;
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
||||
function SpyStrategyDispatcher(strategyArgs) {
|
||||
var baseStrategy = new j$.SpyStrategy(strategyArgs);
|
||||
var argsStrategies = new StrategyDict(function() {
|
||||
return new j$.SpyStrategy(strategyArgs);
|
||||
});
|
||||
|
||||
this.and = baseStrategy;
|
||||
|
||||
this.exec = function(spy, args) {
|
||||
var strategy = argsStrategies.get(args);
|
||||
|
||||
if (!strategy) {
|
||||
if (argsStrategies.any() && !baseStrategy.isConfigured()) {
|
||||
throw new Error('Spy \'' + strategyArgs.name + '\' receieved a call with arguments ' + j$.pp(Array.prototype.slice.call(args)) + ' but all configured strategies specify other arguments.');
|
||||
} else {
|
||||
strategy = baseStrategy;
|
||||
}
|
||||
}
|
||||
|
||||
return strategy.exec(spy, args);
|
||||
};
|
||||
|
||||
this.withArgs = function() {
|
||||
return { and: argsStrategies.getOrCreate(arguments) };
|
||||
};
|
||||
}
|
||||
|
||||
function StrategyDict(strategyFactory) {
|
||||
this.strategies = [];
|
||||
this.strategyFactory = strategyFactory;
|
||||
}
|
||||
|
||||
StrategyDict.prototype.any = function() {
|
||||
return this.strategies.length > 0;
|
||||
};
|
||||
|
||||
StrategyDict.prototype.getOrCreate = function(args) {
|
||||
var strategy = this.get(args);
|
||||
|
||||
if (!strategy) {
|
||||
strategy = this.strategyFactory();
|
||||
this.strategies.push({
|
||||
args: args,
|
||||
strategy: strategy
|
||||
});
|
||||
}
|
||||
|
||||
return strategy;
|
||||
};
|
||||
|
||||
StrategyDict.prototype.get = function(args) {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < this.strategies.length; i++) {
|
||||
if (j$.matchersUtil.equals(args, this.strategies[i].args)) {
|
||||
return this.strategies[i].strategy;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Spy;
|
||||
};
|
||||
|
||||
45
src/core/SpyFactory.js
Normal file
45
src/core/SpyFactory.js
Normal file
@@ -0,0 +1,45 @@
|
||||
getJasmineRequireObj().SpyFactory = function(j$) {
|
||||
|
||||
function SpyFactory(getCustomStrategies) {
|
||||
var self = this;
|
||||
|
||||
this.createSpy = function(name, originalFn) {
|
||||
return j$.Spy(name, originalFn, getCustomStrategies());
|
||||
};
|
||||
|
||||
this.createSpyObj = function(baseName, methodNames) {
|
||||
var baseNameIsCollection = j$.isObject_(baseName) || j$.isArray_(baseName);
|
||||
|
||||
if (baseNameIsCollection && j$.util.isUndefined(methodNames)) {
|
||||
methodNames = baseName;
|
||||
baseName = 'unknown';
|
||||
}
|
||||
|
||||
var obj = {};
|
||||
var spiesWereSet = false;
|
||||
|
||||
if (j$.isArray_(methodNames)) {
|
||||
for (var i = 0; i < methodNames.length; i++) {
|
||||
obj[methodNames[i]] = self.createSpy(baseName + '.' + methodNames[i]);
|
||||
spiesWereSet = true;
|
||||
}
|
||||
} else if (j$.isObject_(methodNames)) {
|
||||
for (var key in methodNames) {
|
||||
if (methodNames.hasOwnProperty(key)) {
|
||||
obj[key] = self.createSpy(baseName + '.' + key);
|
||||
obj[key].and.returnValue(methodNames[key]);
|
||||
spiesWereSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!spiesWereSet) {
|
||||
throw 'createSpyObj requires a non-empty array or object of method names to create spies for';
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
}
|
||||
|
||||
return SpyFactory;
|
||||
};
|
||||
@@ -5,6 +5,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
function SpyRegistry(options) {
|
||||
options = options || {};
|
||||
var global = options.global || j$.getGlobal();
|
||||
var createSpy = options.createSpy;
|
||||
var currentSpies = options.currentSpies || function() { return []; };
|
||||
|
||||
this.allowRespy = function(allow){
|
||||
@@ -33,19 +34,14 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
}
|
||||
}
|
||||
|
||||
var descriptor;
|
||||
try {
|
||||
descriptor = Object.getOwnPropertyDescriptor(obj, methodName);
|
||||
} catch(e) {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
}
|
||||
var descriptor = Object.getOwnPropertyDescriptor(obj, methodName);
|
||||
|
||||
if (descriptor && !(descriptor.writable || descriptor.set)) {
|
||||
throw new Error(getErrorMsg(methodName + ' is not declared writable or has no setter'));
|
||||
}
|
||||
|
||||
var originalMethod = obj[methodName],
|
||||
spiedMethod = j$.createSpy(methodName, originalMethod),
|
||||
spiedMethod = createSpy(methodName, originalMethod),
|
||||
restoreStrategy;
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(obj, methodName) || (obj === global && methodName === 'onerror')) {
|
||||
@@ -80,12 +76,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
throw new Error('No property name supplied');
|
||||
}
|
||||
|
||||
var descriptor;
|
||||
try {
|
||||
descriptor = j$.util.getPropertyDescriptor(obj, propertyName);
|
||||
} catch(e) {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
}
|
||||
var descriptor = j$.util.getPropertyDescriptor(obj, propertyName);
|
||||
|
||||
if (!descriptor) {
|
||||
throw new Error(propertyName + ' property does not exist');
|
||||
@@ -105,7 +96,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
}
|
||||
|
||||
var originalDescriptor = j$.util.clone(descriptor),
|
||||
spy = j$.createSpy(propertyName, descriptor[accessType]),
|
||||
spy = createSpy(propertyName, descriptor[accessType]),
|
||||
restoreStrategy;
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(obj, propertyName)) {
|
||||
|
||||
@@ -1,110 +1,130 @@
|
||||
getJasmineRequireObj().SpyStrategy = function(j$) {
|
||||
|
||||
/**
|
||||
* @namespace Spy#and
|
||||
* @interface SpyStrategy
|
||||
*/
|
||||
function SpyStrategy(options) {
|
||||
options = options || {};
|
||||
|
||||
var identity = options.name || 'unknown',
|
||||
originalFn = options.fn || function() {},
|
||||
getSpy = options.getSpy || function() {},
|
||||
plan = function() {};
|
||||
|
||||
/**
|
||||
* Return the identifying information for the spy.
|
||||
* @name Spy#and#identity
|
||||
* @function
|
||||
* @returns {String}
|
||||
* Get the identifying information for the spy.
|
||||
* @name SpyStrategy#identity
|
||||
* @member
|
||||
* @type {String}
|
||||
*/
|
||||
this.identity = function() {
|
||||
return identity;
|
||||
};
|
||||
this.identity = options.name || 'unknown';
|
||||
this.originalFn = options.fn || function() {};
|
||||
this.getSpy = options.getSpy || function() {};
|
||||
this.plan = this._defaultPlan = function() {};
|
||||
|
||||
/**
|
||||
* Execute the current spy strategy.
|
||||
* @name Spy#and#exec
|
||||
* @function
|
||||
*/
|
||||
this.exec = function() {
|
||||
return plan.apply(this, arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to call through to the real implementation when invoked.
|
||||
* @name Spy#and#callThrough
|
||||
* @function
|
||||
*/
|
||||
this.callThrough = function() {
|
||||
plan = originalFn;
|
||||
return getSpy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to return the value when invoked.
|
||||
* @name Spy#and#returnValue
|
||||
* @function
|
||||
* @param {*} value The value to return.
|
||||
*/
|
||||
this.returnValue = function(value) {
|
||||
plan = function() {
|
||||
return value;
|
||||
};
|
||||
return getSpy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to return one of the specified values (sequentially) each time the spy is invoked.
|
||||
* @name Spy#and#returnValues
|
||||
* @function
|
||||
* @param {...*} values - Values to be returned on subsequent calls to the spy.
|
||||
*/
|
||||
this.returnValues = function() {
|
||||
var values = Array.prototype.slice.call(arguments);
|
||||
plan = function () {
|
||||
return values.shift();
|
||||
};
|
||||
return getSpy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to throw an error when invoked.
|
||||
* @name Spy#and#throwError
|
||||
* @function
|
||||
* @param {Error|String} something Thing to throw
|
||||
*/
|
||||
this.throwError = function(something) {
|
||||
var error = (something instanceof Error) ? something : new Error(something);
|
||||
plan = function() {
|
||||
throw error;
|
||||
};
|
||||
return getSpy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to call a fake implementation when invoked.
|
||||
* @name Spy#and#callFake
|
||||
* @function
|
||||
* @param {Function} fn The function to invoke with the passed parameters.
|
||||
*/
|
||||
this.callFake = function(fn) {
|
||||
if(!(j$.isFunction_(fn) || j$.isAsyncFunction_(fn))) {
|
||||
throw new Error('Argument passed to callFake should be a function, got ' + fn);
|
||||
var k, cs = options.customStrategies || {};
|
||||
for (k in cs) {
|
||||
if (j$.util.has(cs, k) && !this[k]) {
|
||||
this[k] = createCustomPlan(cs[k]);
|
||||
}
|
||||
plan = fn;
|
||||
return getSpy();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the spy to do nothing when invoked. This is the default.
|
||||
* @name Spy#and#stub
|
||||
* @function
|
||||
*/
|
||||
this.stub = function(fn) {
|
||||
plan = function() {};
|
||||
return getSpy();
|
||||
function createCustomPlan(factory) {
|
||||
return function() {
|
||||
var plan = factory.apply(null, arguments);
|
||||
|
||||
if (!j$.isFunction_(plan)) {
|
||||
throw new Error('Spy strategy must return a function');
|
||||
}
|
||||
|
||||
this.plan = plan;
|
||||
return this.getSpy();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the current spy strategy.
|
||||
* @name SpyStrategy#exec
|
||||
* @function
|
||||
*/
|
||||
SpyStrategy.prototype.exec = function(context, args) {
|
||||
return this.plan.apply(context, args);
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to call through to the real implementation when invoked.
|
||||
* @name SpyStrategy#callThrough
|
||||
* @function
|
||||
*/
|
||||
SpyStrategy.prototype.callThrough = function() {
|
||||
this.plan = this.originalFn;
|
||||
return this.getSpy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to return the value when invoked.
|
||||
* @name SpyStrategy#returnValue
|
||||
* @function
|
||||
* @param {*} value The value to return.
|
||||
*/
|
||||
SpyStrategy.prototype.returnValue = function(value) {
|
||||
this.plan = function() {
|
||||
return value;
|
||||
};
|
||||
return this.getSpy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to return one of the specified values (sequentially) each time the spy is invoked.
|
||||
* @name SpyStrategy#returnValues
|
||||
* @function
|
||||
* @param {...*} values - Values to be returned on subsequent calls to the spy.
|
||||
*/
|
||||
SpyStrategy.prototype.returnValues = function() {
|
||||
var values = Array.prototype.slice.call(arguments);
|
||||
this.plan = function () {
|
||||
return values.shift();
|
||||
};
|
||||
return this.getSpy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to throw an error when invoked.
|
||||
* @name SpyStrategy#throwError
|
||||
* @function
|
||||
* @param {Error|String} something Thing to throw
|
||||
*/
|
||||
SpyStrategy.prototype.throwError = function(something) {
|
||||
var error = (something instanceof Error) ? something : new Error(something);
|
||||
this.plan = function() {
|
||||
throw error;
|
||||
};
|
||||
return this.getSpy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to call a fake implementation when invoked.
|
||||
* @name SpyStrategy#callFake
|
||||
* @function
|
||||
* @param {Function} fn The function to invoke with the passed parameters.
|
||||
*/
|
||||
SpyStrategy.prototype.callFake = function(fn) {
|
||||
if(!(j$.isFunction_(fn) || j$.isAsyncFunction_(fn))) {
|
||||
throw new Error('Argument passed to callFake should be a function, got ' + fn);
|
||||
}
|
||||
this.plan = fn;
|
||||
return this.getSpy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Tell the spy to do nothing when invoked. This is the default.
|
||||
* @name SpyStrategy#stub
|
||||
* @function
|
||||
*/
|
||||
SpyStrategy.prototype.stub = function(fn) {
|
||||
this.plan = function() {};
|
||||
return this.getSpy();
|
||||
};
|
||||
|
||||
SpyStrategy.prototype.isConfigured = function() {
|
||||
return this.plan !== this._defaultPlan;
|
||||
};
|
||||
|
||||
return SpyStrategy;
|
||||
};
|
||||
|
||||
80
src/core/StackTrace.js
Normal file
80
src/core/StackTrace.js
Normal file
@@ -0,0 +1,80 @@
|
||||
getJasmineRequireObj().StackTrace = function(j$) {
|
||||
function StackTrace(rawTrace) {
|
||||
var lines = rawTrace
|
||||
.split('\n')
|
||||
.filter(function(line) { return line !== ''; });
|
||||
|
||||
if (lines[0].match(/^Error/)) {
|
||||
this.message = lines.shift();
|
||||
} else {
|
||||
this.message = undefined;
|
||||
}
|
||||
|
||||
var parseResult = tryParseFrames(lines);
|
||||
this.frames = parseResult.frames;
|
||||
this.style = parseResult.style;
|
||||
}
|
||||
|
||||
var framePatterns = [
|
||||
// PhantomJS on Linux, Node, Chrome, IE, Edge
|
||||
// e.g. " at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)"
|
||||
// Note that the "function name" can include a surprisingly large set of
|
||||
// characters, including angle brackets and square brackets.
|
||||
{ re: /^\s*at ([^\)]+) \(([^\)]+)\)$/, fnIx: 1, fileLineColIx: 2, style: 'v8' },
|
||||
|
||||
// NodeJS alternate form, often mixed in with the Chrome style
|
||||
// e.g. " at /some/path:4320:20
|
||||
{ re: /\s*at (.+)$/, fileLineColIx: 1, style: 'v8' },
|
||||
|
||||
// PhantomJS on OS X, Safari, Firefox
|
||||
// e.g. "run@http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||
{ re: /^(([^@\s]+)@)?([^\s]+)$/, fnIx: 2, fileLineColIx: 3, style: 'webkit' }
|
||||
];
|
||||
|
||||
// regexes should capture the function name (if any) as group 1
|
||||
// and the file, line, and column as group 2.
|
||||
function tryParseFrames(lines) {
|
||||
var style = null;
|
||||
var frames = lines.map(function(line) {
|
||||
var convertedLine = first(framePatterns, function(pattern) {
|
||||
var overallMatch = line.match(pattern.re),
|
||||
fileLineColMatch;
|
||||
if (!overallMatch) { return null; }
|
||||
|
||||
fileLineColMatch = overallMatch[pattern.fileLineColIx].match(
|
||||
/^(.*):(\d+):\d+$/);
|
||||
if (!fileLineColMatch) { return null; }
|
||||
|
||||
style = style || pattern.style;
|
||||
return {
|
||||
raw: line,
|
||||
file: fileLineColMatch[1],
|
||||
line: parseInt(fileLineColMatch[2], 10),
|
||||
func: overallMatch[pattern.fnIx]
|
||||
};
|
||||
});
|
||||
|
||||
return convertedLine || { raw: line };
|
||||
});
|
||||
|
||||
return {
|
||||
style: style,
|
||||
frames: frames
|
||||
};
|
||||
}
|
||||
|
||||
function first(items, fn) {
|
||||
var i, result;
|
||||
|
||||
for (i = 0; i < items.length; i++) {
|
||||
result = fn(items[i]);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return StackTrace;
|
||||
};
|
||||
@@ -67,6 +67,19 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
this.afterAllFns.unshift(fn);
|
||||
};
|
||||
|
||||
function removeFns(queueableFns) {
|
||||
for(var i = 0; i < queueableFns.length; i++) {
|
||||
queueableFns[i].fn = null;
|
||||
}
|
||||
}
|
||||
|
||||
Suite.prototype.cleanupBeforeAfter = function() {
|
||||
removeFns(this.beforeAllFns);
|
||||
removeFns(this.afterAllFns);
|
||||
removeFns(this.beforeFns);
|
||||
removeFns(this.afterFns);
|
||||
};
|
||||
|
||||
Suite.prototype.addChild = function(child) {
|
||||
this.children.push(child);
|
||||
};
|
||||
@@ -79,14 +92,10 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
if (this.result.failedExpectations.length > 0) {
|
||||
return 'failed';
|
||||
} else {
|
||||
return 'finished';
|
||||
return 'passed';
|
||||
}
|
||||
};
|
||||
|
||||
Suite.prototype.isExecutable = function() {
|
||||
return !this.markedPending;
|
||||
};
|
||||
|
||||
Suite.prototype.canBeReentered = function() {
|
||||
return this.beforeAllFns.length === 0 && this.afterAllFns.length === 0;
|
||||
};
|
||||
@@ -113,39 +122,29 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(isAfterAll(this.children)) {
|
||||
var data = {
|
||||
matcherName: '',
|
||||
passed: false,
|
||||
expected: '',
|
||||
actual: '',
|
||||
error: arguments[0]
|
||||
};
|
||||
this.result.failedExpectations.push(this.expectationResultFactory(data));
|
||||
} else {
|
||||
for (var i = 0; i < this.children.length; i++) {
|
||||
var child = this.children[i];
|
||||
child.onException.apply(child, arguments);
|
||||
}
|
||||
var data = {
|
||||
matcherName: '',
|
||||
passed: false,
|
||||
expected: '',
|
||||
actual: '',
|
||||
error: arguments[0]
|
||||
};
|
||||
var failedExpectation = this.expectationResultFactory(data);
|
||||
|
||||
if (!this.parentSuite) {
|
||||
failedExpectation.globalErrorType = 'afterAll';
|
||||
}
|
||||
|
||||
this.result.failedExpectations.push(failedExpectation);
|
||||
};
|
||||
|
||||
Suite.prototype.addExpectationResult = function () {
|
||||
if(isAfterAll(this.children) && isFailure(arguments)){
|
||||
if(isFailure(arguments)) {
|
||||
var data = arguments[1];
|
||||
this.result.failedExpectations.push(this.expectationResultFactory(data));
|
||||
if(this.throwOnExpectationFailure) {
|
||||
throw new j$.errors.ExpectationFailed();
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < this.children.length; i++) {
|
||||
var child = this.children[i];
|
||||
try {
|
||||
child.addExpectationResult.apply(child, arguments);
|
||||
} catch(e) {
|
||||
// keep going
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -153,10 +152,6 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
this.result.deprecationWarnings.push(this.expectationResultFactory({ message: msg }));
|
||||
};
|
||||
|
||||
function isAfterAll(children) {
|
||||
return children && children[0].result.status;
|
||||
}
|
||||
|
||||
function isFailure(args) {
|
||||
return !args[0];
|
||||
}
|
||||
|
||||
@@ -6,13 +6,14 @@ getJasmineRequireObj().TreeProcessor = function() {
|
||||
nodeStart = attrs.nodeStart || function() {},
|
||||
nodeComplete = attrs.nodeComplete || function() {},
|
||||
orderChildren = attrs.orderChildren || function(node) { return node.children; },
|
||||
excludeNode = attrs.excludeNode || function(node) { return false; },
|
||||
stats = { valid: true },
|
||||
processed = false,
|
||||
defaultMin = Infinity,
|
||||
defaultMax = 1 - Infinity;
|
||||
|
||||
this.processTree = function() {
|
||||
processNode(tree, false);
|
||||
processNode(tree, true);
|
||||
processed = true;
|
||||
return stats;
|
||||
};
|
||||
@@ -46,18 +47,18 @@ getJasmineRequireObj().TreeProcessor = function() {
|
||||
}
|
||||
}
|
||||
|
||||
function processNode(node, parentEnabled) {
|
||||
function processNode(node, parentExcluded) {
|
||||
var executableIndex = runnableIndex(node.id);
|
||||
|
||||
if (executableIndex !== undefined) {
|
||||
parentEnabled = true;
|
||||
parentExcluded = false;
|
||||
}
|
||||
|
||||
parentEnabled = parentEnabled && node.isExecutable();
|
||||
|
||||
if (!node.children) {
|
||||
var excluded = parentExcluded || excludeNode(node);
|
||||
stats[node.id] = {
|
||||
executable: parentEnabled && node.isExecutable(),
|
||||
excluded: excluded,
|
||||
willExecute: !excluded && !node.markedPending,
|
||||
segments: [{
|
||||
index: 0,
|
||||
owner: node,
|
||||
@@ -74,7 +75,7 @@ getJasmineRequireObj().TreeProcessor = function() {
|
||||
for (var i = 0; i < orderedChildren.length; i++) {
|
||||
var child = orderedChildren[i];
|
||||
|
||||
processNode(child, parentEnabled);
|
||||
processNode(child, parentExcluded);
|
||||
|
||||
if (!stats.valid) {
|
||||
return;
|
||||
@@ -82,11 +83,12 @@ getJasmineRequireObj().TreeProcessor = function() {
|
||||
|
||||
var childStats = stats[child.id];
|
||||
|
||||
hasExecutableChild = hasExecutableChild || childStats.executable;
|
||||
hasExecutableChild = hasExecutableChild || childStats.willExecute;
|
||||
}
|
||||
|
||||
stats[node.id] = {
|
||||
executable: hasExecutableChild
|
||||
excluded: parentExcluded,
|
||||
willExecute: hasExecutableChild
|
||||
};
|
||||
|
||||
segmentChildren(node, orderedChildren, stats[node.id], executableIndex);
|
||||
@@ -164,16 +166,20 @@ getJasmineRequireObj().TreeProcessor = function() {
|
||||
if (node.children) {
|
||||
return {
|
||||
fn: function(done) {
|
||||
nodeStart(node);
|
||||
var onStart = {
|
||||
fn: function(next) {
|
||||
nodeStart(node, next);
|
||||
}
|
||||
};
|
||||
|
||||
queueRunnerFactory({
|
||||
onComplete: function() {
|
||||
nodeComplete(node, node.getResult());
|
||||
done();
|
||||
onComplete: function () {
|
||||
node.cleanupBeforeAfter();
|
||||
nodeComplete(node, node.getResult(), done);
|
||||
},
|
||||
queueableFns: wrapChildren(node, segmentNumber),
|
||||
queueableFns: [onStart].concat(wrapChildren(node, segmentNumber)),
|
||||
userContext: node.sharedUserContext(),
|
||||
onException: function() {
|
||||
onException: function () {
|
||||
node.onException.apply(node, arguments);
|
||||
}
|
||||
});
|
||||
@@ -181,7 +187,7 @@ getJasmineRequireObj().TreeProcessor = function() {
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
fn: function(done) { node.execute(done, stats[node.id].executable); }
|
||||
fn: function(done) { node.execute(done, stats[node.id].excluded); }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -194,7 +200,7 @@ getJasmineRequireObj().TreeProcessor = function() {
|
||||
result.push(executeNode(segmentChildren[i].owner, segmentChildren[i].index));
|
||||
}
|
||||
|
||||
if (!stats[node.id].executable) {
|
||||
if (!stats[node.id].willExecute) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,7 @@ getJasmineRequireObj().Any = function(j$) {
|
||||
}
|
||||
|
||||
if (this.expectedObject == Object) {
|
||||
if (other === null) {
|
||||
j$.getEnv().deprecated('jasmine.Any(Object) will no longer match null in Jasmine 3.0');
|
||||
}
|
||||
return typeof other == 'object';
|
||||
return other !== null && typeof other == 'object';
|
||||
}
|
||||
|
||||
if (this.expectedObject == Boolean) {
|
||||
|
||||
@@ -85,6 +85,17 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return j$.getType_(value) === '[object ' + typeName + ']';
|
||||
};
|
||||
|
||||
j$.isError_ = function(value) {
|
||||
if (value instanceof Error) {
|
||||
return true;
|
||||
}
|
||||
if (value && value.constructor && value.constructor.constructor &&
|
||||
(value instanceof (value.constructor.constructor('return this')()).Error)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
j$.getType_ = function(value) {
|
||||
return Object.prototype.toString.apply(value);
|
||||
};
|
||||
@@ -181,18 +192,6 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return new j$.ArrayWithExactContents(sample);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a bare {@link Spy} object. This won't be installed anywhere and will not have any implementation behind it.
|
||||
* @name jasmine.createSpy
|
||||
* @function
|
||||
* @param {String} [name] - Name to give the spy. This will be displayed in failure messages.
|
||||
* @param {Function} [originalFn] - Function to act as the real implementation.
|
||||
* @return {Spy}
|
||||
*/
|
||||
j$.createSpy = function(name, originalFn) {
|
||||
return j$.Spy(name, originalFn);
|
||||
};
|
||||
|
||||
j$.isSpy = function(putativeSpy) {
|
||||
if (!putativeSpy) {
|
||||
return false;
|
||||
@@ -200,45 +199,4 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return putativeSpy.and instanceof j$.SpyStrategy &&
|
||||
putativeSpy.calls instanceof j$.CallTracker;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an object with multiple {@link Spy}s as its members.
|
||||
* @name jasmine.createSpyObj
|
||||
* @function
|
||||
* @param {String} [baseName] - Base name for the spies in the object.
|
||||
* @param {String[]|Object} methodNames - Array of method names to create spies for, or Object whose keys will be method names and values the {@link Spy#and#returnValue|returnValue}.
|
||||
* @return {Object}
|
||||
*/
|
||||
j$.createSpyObj = function(baseName, methodNames) {
|
||||
var baseNameIsCollection = j$.isObject_(baseName) || j$.isArray_(baseName);
|
||||
|
||||
if (baseNameIsCollection && j$.util.isUndefined(methodNames)) {
|
||||
methodNames = baseName;
|
||||
baseName = 'unknown';
|
||||
}
|
||||
|
||||
var obj = {};
|
||||
var spiesWereSet = false;
|
||||
|
||||
if (j$.isArray_(methodNames)) {
|
||||
for (var i = 0; i < methodNames.length; i++) {
|
||||
obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]);
|
||||
spiesWereSet = true;
|
||||
}
|
||||
} else if (j$.isObject_(methodNames)) {
|
||||
for (var key in methodNames) {
|
||||
if (methodNames.hasOwnProperty(key)) {
|
||||
obj[key] = j$.createSpy(baseName + '.' + key);
|
||||
obj[key].and.returnValue(methodNames[key]);
|
||||
spiesWereSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!spiesWereSet) {
|
||||
throw 'createSpyObj requires a non-empty array or object of method names to create spies for';
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -182,28 +182,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
||||
var bIsDomNode = j$.isDomNode(b);
|
||||
if (aIsDomNode && bIsDomNode) {
|
||||
// At first try to use DOM3 method isEqualNode
|
||||
if (a.isEqualNode) {
|
||||
result = a.isEqualNode(b);
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// IE8 doesn't support isEqualNode, try to use outerHTML && innerText
|
||||
var aIsElement = a instanceof Element;
|
||||
var bIsElement = b instanceof Element;
|
||||
if (aIsElement && bIsElement) {
|
||||
result = a.outerHTML == b.outerHTML;
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (aIsElement || bIsElement) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
result = a.innerText == b.innerText && a.textContent == b.textContent;
|
||||
result = a.isEqualNode(b);
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
|
||||
'toHaveBeenCalledWith',
|
||||
'toMatch',
|
||||
'toThrow',
|
||||
'toThrowError'
|
||||
'toThrowError',
|
||||
'toThrowMatching',
|
||||
],
|
||||
matchers = {};
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
|
||||
result.pass = actual.calls.any();
|
||||
|
||||
result.message = result.pass ?
|
||||
'Expected spy ' + actual.and.identity() + ' not to have been called.' :
|
||||
'Expected spy ' + actual.and.identity() + ' to have been called.';
|
||||
'Expected spy ' + actual.and.identity + ' not to have been called.' :
|
||||
'Expected spy ' + actual.and.identity + ' to have been called.';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ getJasmineRequireObj().toHaveBeenCalledBefore = function(j$) {
|
||||
var result = { pass: false };
|
||||
|
||||
if (!firstSpy.calls.count()) {
|
||||
result.message = 'Expected spy ' + firstSpy.and.identity() + ' to have been called.';
|
||||
result.message = 'Expected spy ' + firstSpy.and.identity + ' to have been called.';
|
||||
return result;
|
||||
}
|
||||
if (!latterSpy.calls.count()) {
|
||||
result.message = 'Expected spy ' + latterSpy.and.identity() + ' to have been called.';
|
||||
result.message = 'Expected spy ' + latterSpy.and.identity + ' to have been called.';
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -37,17 +37,17 @@ getJasmineRequireObj().toHaveBeenCalledBefore = function(j$) {
|
||||
result.pass = latest1stSpyCall < first2ndSpyCall;
|
||||
|
||||
if (result.pass) {
|
||||
result.message = 'Expected spy ' + firstSpy.and.identity() + ' to not have been called before spy ' + latterSpy.and.identity() + ', but it was';
|
||||
result.message = 'Expected spy ' + firstSpy.and.identity + ' to not have been called before spy ' + latterSpy.and.identity + ', but it was';
|
||||
} else {
|
||||
var first1stSpyCall = firstSpy.calls.first().invocationOrder;
|
||||
var latest2ndSpyCall = latterSpy.calls.mostRecent().invocationOrder;
|
||||
|
||||
if(first1stSpyCall < first2ndSpyCall) {
|
||||
result.message = 'Expected latest call to spy ' + firstSpy.and.identity() + ' to have been called before first call to spy ' + latterSpy.and.identity() + ' (no interleaved calls)';
|
||||
result.message = 'Expected latest call to spy ' + firstSpy.and.identity + ' to have been called before first call to spy ' + latterSpy.and.identity + ' (no interleaved calls)';
|
||||
} else if (latest2ndSpyCall > latest1stSpyCall) {
|
||||
result.message = 'Expected first call to spy ' + latterSpy.and.identity() + ' to have been called after latest call to spy ' + firstSpy.and.identity() + ' (no interleaved calls)';
|
||||
result.message = 'Expected first call to spy ' + latterSpy.and.identity + ' to have been called after latest call to spy ' + firstSpy.and.identity + ' (no interleaved calls)';
|
||||
} else {
|
||||
result.message = 'Expected spy ' + firstSpy.and.identity() + ' to have been called before spy ' + latterSpy.and.identity();
|
||||
result.message = 'Expected spy ' + firstSpy.and.identity + ' to have been called before spy ' + latterSpy.and.identity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
|
||||
var timesMessage = expected === 1 ? 'once' : expected + ' times';
|
||||
result.pass = calls === expected;
|
||||
result.message = result.pass ?
|
||||
'Expected spy ' + actual.and.identity() + ' not to have been called ' + timesMessage + '. It was called ' + calls + ' times.' :
|
||||
'Expected spy ' + actual.and.identity() + ' to have been called ' + timesMessage + '. It was called ' + calls + ' times.';
|
||||
'Expected spy ' + actual.and.identity + ' not to have been called ' + timesMessage + '. It was called ' + calls + ' times.' :
|
||||
'Expected spy ' + actual.and.identity + ' to have been called ' + timesMessage + '. It was called ' + calls + ' times.';
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,15 +23,15 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
|
||||
}
|
||||
|
||||
if (!actual.calls.any()) {
|
||||
result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; };
|
||||
result.message = function() { return 'Expected spy ' + actual.and.identity + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; };
|
||||
return result;
|
||||
}
|
||||
|
||||
if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) {
|
||||
result.pass = true;
|
||||
result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; };
|
||||
result.message = function() { return 'Expected spy ' + actual.and.identity + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; };
|
||||
} else {
|
||||
result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; };
|
||||
result.message = function() { return 'Expected spy ' + actual.and.identity + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; };
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -18,73 +18,61 @@ getJasmineRequireObj().toThrowError = function(j$) {
|
||||
function toThrowError () {
|
||||
return {
|
||||
compare: function(actual) {
|
||||
var threw = false,
|
||||
pass = {pass: true},
|
||||
fail = {pass: false},
|
||||
var errorMatcher = getMatcher.apply(null, arguments),
|
||||
thrown;
|
||||
|
||||
if (typeof actual != 'function') {
|
||||
throw new Error(getErrorMsg('Actual is not a Function'));
|
||||
}
|
||||
|
||||
var errorMatcher = getMatcher.apply(null, arguments);
|
||||
|
||||
try {
|
||||
actual();
|
||||
return fail('Expected function to throw an Error.');
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
thrown = e;
|
||||
}
|
||||
|
||||
if (!threw) {
|
||||
fail.message = 'Expected function to throw an Error.';
|
||||
return fail;
|
||||
if (!j$.isError_(thrown)) {
|
||||
return fail(function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; });
|
||||
}
|
||||
|
||||
// Get Error constructor of thrown
|
||||
if (!isErrorObject(thrown)) {
|
||||
fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; };
|
||||
return fail;
|
||||
}
|
||||
|
||||
if (errorMatcher.hasNoSpecifics()) {
|
||||
pass.message = 'Expected function not to throw an Error, but it threw ' + j$.fnNameFor(thrown) + '.';
|
||||
return pass;
|
||||
}
|
||||
|
||||
if (errorMatcher.matches(thrown)) {
|
||||
pass.message = function() {
|
||||
return 'Expected function not to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + '.';
|
||||
};
|
||||
return pass;
|
||||
} else {
|
||||
fail.message = function() {
|
||||
return 'Expected function to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() +
|
||||
', but it threw ' + errorMatcher.thrownDescription(thrown) + '.';
|
||||
};
|
||||
return fail;
|
||||
}
|
||||
return errorMatcher.match(thrown);
|
||||
}
|
||||
};
|
||||
|
||||
function getMatcher() {
|
||||
var expected = null,
|
||||
errorType = null;
|
||||
var expected, errorType;
|
||||
|
||||
if (arguments.length == 2) {
|
||||
expected = arguments[1];
|
||||
if (isAnErrorType(expected)) {
|
||||
errorType = expected;
|
||||
expected = null;
|
||||
}
|
||||
} else if (arguments.length > 2) {
|
||||
if (arguments[2]) {
|
||||
errorType = arguments[1];
|
||||
expected = arguments[2];
|
||||
if (!isAnErrorType(errorType)) {
|
||||
throw new Error(getErrorMsg('Expected error type is not an Error.'));
|
||||
}
|
||||
}
|
||||
|
||||
return exactMatcher(expected, errorType);
|
||||
} else if (arguments[1]) {
|
||||
expected = arguments[1];
|
||||
|
||||
if (isAnErrorType(arguments[1])) {
|
||||
return exactMatcher(null, arguments[1]);
|
||||
} else {
|
||||
return exactMatcher(arguments[1], null);
|
||||
}
|
||||
} else {
|
||||
return anyMatcher();
|
||||
}
|
||||
}
|
||||
|
||||
function anyMatcher() {
|
||||
return {
|
||||
match: function(error) {
|
||||
return pass('Expected function not to throw an Error, but it threw ' + j$.fnNameFor(error) + '.');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function exactMatcher(expected, errorType) {
|
||||
if (expected && !isStringOrRegExp(expected)) {
|
||||
if (errorType) {
|
||||
throw new Error(getErrorMsg('Expected error message is not a string or RegExp.'));
|
||||
@@ -101,33 +89,46 @@ getJasmineRequireObj().toThrowError = function(j$) {
|
||||
}
|
||||
}
|
||||
|
||||
var errorTypeDescription = errorType ? j$.fnNameFor(errorType) : 'an exception';
|
||||
|
||||
function thrownDescription(thrown) {
|
||||
var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception',
|
||||
thrownMessage = '';
|
||||
|
||||
if (expected) {
|
||||
thrownMessage = ' with message ' + j$.pp(thrown.message);
|
||||
}
|
||||
|
||||
return thrownName + thrownMessage;
|
||||
}
|
||||
|
||||
function messageDescription() {
|
||||
if (expected === null) {
|
||||
return '';
|
||||
} else if (expected instanceof RegExp) {
|
||||
return ' with a message matching ' + j$.pp(expected);
|
||||
} else {
|
||||
return ' with message ' + j$.pp(expected);
|
||||
}
|
||||
}
|
||||
|
||||
function matches(error) {
|
||||
return (errorType === null || error instanceof errorType) &&
|
||||
(expected === null || messageMatch(error.message));
|
||||
}
|
||||
|
||||
return {
|
||||
errorTypeDescription: errorType ? j$.fnNameFor(errorType) : 'an exception',
|
||||
thrownDescription: function(thrown) {
|
||||
var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception',
|
||||
thrownMessage = '';
|
||||
|
||||
if (expected) {
|
||||
thrownMessage = ' with message ' + j$.pp(thrown.message);
|
||||
}
|
||||
|
||||
return thrownName + thrownMessage;
|
||||
},
|
||||
messageDescription: function() {
|
||||
if (expected === null) {
|
||||
return '';
|
||||
} else if (expected instanceof RegExp) {
|
||||
return ' with a message matching ' + j$.pp(expected);
|
||||
match: function(thrown) {
|
||||
if (matches(thrown)) {
|
||||
return pass(function() {
|
||||
return 'Expected function not to throw ' + errorTypeDescription + messageDescription() + '.';
|
||||
});
|
||||
} else {
|
||||
return ' with message ' + j$.pp(expected);
|
||||
return fail(function() {
|
||||
return 'Expected function to throw ' + errorTypeDescription + messageDescription() +
|
||||
', but it threw ' + thrownDescription(thrown) + '.';
|
||||
});
|
||||
}
|
||||
},
|
||||
hasNoSpecifics: function() {
|
||||
return expected === null && errorType === null;
|
||||
},
|
||||
matches: function(error) {
|
||||
return (errorType === null || error instanceof errorType) &&
|
||||
(expected === null || messageMatch(error.message));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -143,19 +144,22 @@ getJasmineRequireObj().toThrowError = function(j$) {
|
||||
|
||||
var Surrogate = function() {};
|
||||
Surrogate.prototype = type.prototype;
|
||||
return isErrorObject(new Surrogate());
|
||||
return j$.isError_(new Surrogate());
|
||||
}
|
||||
}
|
||||
|
||||
function isErrorObject(thrown) {
|
||||
if (thrown instanceof Error) {
|
||||
return true;
|
||||
}
|
||||
if (thrown && thrown.constructor && thrown.constructor.constructor &&
|
||||
(thrown instanceof (thrown.constructor.constructor('return this')()).Error)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function pass(message) {
|
||||
return {
|
||||
pass: true,
|
||||
message: message
|
||||
};
|
||||
}
|
||||
|
||||
function fail(message) {
|
||||
return {
|
||||
pass: false,
|
||||
message: message
|
||||
};
|
||||
}
|
||||
|
||||
return toThrowError;
|
||||
|
||||
68
src/core/matchers/toThrowMatching.js
Normal file
68
src/core/matchers/toThrowMatching.js
Normal file
@@ -0,0 +1,68 @@
|
||||
getJasmineRequireObj().toThrowMatching = function(j$) {
|
||||
var usageError = j$.formatErrorMsg('<toThrowMatching>', 'expect(function() {<expectation>}).toThrowMatching(<Predicate>)');
|
||||
|
||||
/**
|
||||
* {@link expect} a function to `throw` something matching a predicate.
|
||||
* @function
|
||||
* @name matchers#toThrowMatching
|
||||
* @param {Function} predicate - A function that takes the thrown exception as its parameter and returns true if it matches.
|
||||
* @example
|
||||
* expect(function() { throw new Error('nope'); }).toThrowMatching(function(thrown) { return thrown.message === 'nope'; });
|
||||
*/
|
||||
function toThrowMatching() {
|
||||
return {
|
||||
compare: function(actual, predicate) {
|
||||
var thrown;
|
||||
|
||||
if (typeof actual !== 'function') {
|
||||
throw new Error(usageError('Actual is not a Function'));
|
||||
}
|
||||
|
||||
if (typeof predicate !== 'function') {
|
||||
throw new Error(usageError('Predicate is not a Function'));
|
||||
}
|
||||
|
||||
try {
|
||||
actual();
|
||||
return fail('Expected function to throw an exception.');
|
||||
} catch (e) {
|
||||
thrown = e;
|
||||
}
|
||||
|
||||
if (predicate(thrown)) {
|
||||
return pass('Expected function not to throw an exception matching a predicate.');
|
||||
} else {
|
||||
return fail(function() {
|
||||
return 'Expected function to throw an exception matching a predicate, ' +
|
||||
'but it threw ' + thrownDescription(thrown) + '.';
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function thrownDescription(thrown) {
|
||||
if (thrown && thrown.constructor) {
|
||||
return j$.fnNameFor(thrown.constructor) + ' with message ' +
|
||||
j$.pp(thrown.message);
|
||||
} else {
|
||||
return j$.pp(thrown);
|
||||
}
|
||||
}
|
||||
|
||||
function pass(message) {
|
||||
return {
|
||||
pass: true,
|
||||
message: message
|
||||
};
|
||||
}
|
||||
|
||||
function fail(message) {
|
||||
return {
|
||||
pass: false,
|
||||
message: message
|
||||
};
|
||||
}
|
||||
|
||||
return toThrowMatching;
|
||||
};
|
||||
@@ -34,7 +34,8 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
j$.Clock = jRequire.Clock();
|
||||
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(j$);
|
||||
j$.Env = jRequire.Env(j$);
|
||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter();
|
||||
j$.StackTrace = jRequire.StackTrace(j$);
|
||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
|
||||
j$.Expectation = jRequire.Expectation();
|
||||
j$.buildExpectationResult = jRequire.buildExpectationResult();
|
||||
j$.JsApiReporter = jRequire.JsApiReporter();
|
||||
@@ -47,6 +48,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
j$.ReportDispatcher = jRequire.ReportDispatcher(j$);
|
||||
j$.Spec = jRequire.Spec(j$);
|
||||
j$.Spy = jRequire.Spy(j$);
|
||||
j$.SpyFactory = jRequire.SpyFactory(j$);
|
||||
j$.SpyRegistry = jRequire.SpyRegistry(j$);
|
||||
j$.SpyStrategy = jRequire.SpyStrategy(j$);
|
||||
j$.StringMatching = jRequire.StringMatching(j$);
|
||||
|
||||
@@ -256,5 +256,42 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
return env.clock;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a bare {@link Spy} object. This won't be installed anywhere and will not have any implementation behind it.
|
||||
* @name jasmine.createSpy
|
||||
* @function
|
||||
* @param {String} [name] - Name to give the spy. This will be displayed in failure messages.
|
||||
* @param {Function} [originalFn] - Function to act as the real implementation.
|
||||
* @return {Spy}
|
||||
*/
|
||||
jasmine.createSpy = function(name, originalFn) {
|
||||
return env.createSpy(name, originalFn);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an object with multiple {@link Spy}s as its members.
|
||||
* @name jasmine.createSpyObj
|
||||
* @function
|
||||
* @param {String} [baseName] - Base name for the spies in the object.
|
||||
* @param {String[]|Object} methodNames - Array of method names to create spies for, or Object whose keys will be method names and values the {@link Spy#and#returnValue|returnValue}.
|
||||
* @return {Object}
|
||||
*/
|
||||
jasmine.createSpyObj = function(baseName, methodNames) {
|
||||
return env.createSpyObj(baseName, methodNames);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a custom spy strategy for the current scope of specs.
|
||||
*
|
||||
* _Note:_ This is only callable from within a {@link beforeEach}, {@link it}, or {@link beforeAll}.
|
||||
* @name jasmine.addSpyStrategy
|
||||
* @function
|
||||
* @param {String} name - The name of the strategy (i.e. what you call from `and`)
|
||||
* @param {Function} factory - Factory function that returns the plan to be executed.
|
||||
*/
|
||||
jasmine.addSpyStrategy = function(name, factory) {
|
||||
return env.addSpyStrategy(name, factory);
|
||||
};
|
||||
|
||||
return jasmineInterface;
|
||||
};
|
||||
|
||||
@@ -100,5 +100,53 @@ getJasmineRequireObj().util = function(j$) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
};
|
||||
|
||||
function anyMatch(pattern, lines) {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
if (lines[i].match(pattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function errorWithStack() {
|
||||
// Don't throw and catch if we don't have to, because it makes it harder
|
||||
// for users to debug their code with exception breakpoints.
|
||||
var error = new Error();
|
||||
|
||||
if (error.stack) {
|
||||
return error;
|
||||
}
|
||||
|
||||
// But some browsers (e.g. Phantom) only provide a stack trace if we throw.
|
||||
try {
|
||||
throw new Error();
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
function callerFile() {
|
||||
var trace = new j$.StackTrace(errorWithStack().stack);
|
||||
return trace.frames[2].file;
|
||||
}
|
||||
|
||||
util.jasmineFile = (function() {
|
||||
var result;
|
||||
|
||||
return function() {
|
||||
var trace;
|
||||
|
||||
if (!result) {
|
||||
result = callerFile();
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}());
|
||||
|
||||
return util;
|
||||
};
|
||||
|
||||
@@ -19,9 +19,14 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.suiteDone = function(result) {
|
||||
this.currentParent.updateResult(result);
|
||||
if (this.currentParent !== this.topResults) {
|
||||
this.currentParent = this.currentParent.parent;
|
||||
}
|
||||
|
||||
if (result.status === 'failed') {
|
||||
this.failureCount++;
|
||||
}
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.specStarted = function(result) {
|
||||
@@ -30,7 +35,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
ResultsStateBuilder.prototype.specDone = function(result) {
|
||||
this.currentParent.addChild(result, 'spec');
|
||||
|
||||
if (result.status !== 'disabled') {
|
||||
if (result.status !== 'excluded') {
|
||||
this.specsExecuted++;
|
||||
}
|
||||
|
||||
@@ -50,16 +55,12 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
getContainer = options.getContainer,
|
||||
createElement = options.createElement,
|
||||
createTextNode = options.createTextNode,
|
||||
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
|
||||
onThrowExpectationsClick = options.onThrowExpectationsClick || function() {},
|
||||
onRandomClick = options.onRandomClick || function() {},
|
||||
navigateWithNewParam = options.navigateWithNewParam || function() {},
|
||||
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
|
||||
filterSpecs = options.filterSpecs,
|
||||
timer = options.timer || noopTimer,
|
||||
results = [],
|
||||
htmlReporterMain,
|
||||
symbols,
|
||||
failedSuites = [],
|
||||
deprecationWarnings = [];
|
||||
|
||||
this.initialize = function() {
|
||||
@@ -93,11 +94,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
};
|
||||
|
||||
this.suiteDone = function(result) {
|
||||
if (result.status == 'failed') {
|
||||
failedSuites.push(result);
|
||||
}
|
||||
|
||||
stateBuilder.suiteDone(result);
|
||||
|
||||
if (result.status === 'failed') {
|
||||
failures.push(failureDom(result));
|
||||
}
|
||||
addDeprecationWarnings(result);
|
||||
};
|
||||
|
||||
@@ -124,23 +125,8 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
));
|
||||
|
||||
if (result.status == 'failed') {
|
||||
var failure =
|
||||
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
|
||||
createDom('div', {className: 'jasmine-description'},
|
||||
createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName)
|
||||
),
|
||||
createDom('div', {className: 'jasmine-messages'})
|
||||
);
|
||||
var messages = failure.childNodes[1];
|
||||
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
var expectation = result.failedExpectations[i];
|
||||
messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
|
||||
messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
|
||||
}
|
||||
|
||||
failures.push(failure);
|
||||
if (result.status === 'failed') {
|
||||
failures.push(failureDom(result));
|
||||
}
|
||||
|
||||
addDeprecationWarnings(result);
|
||||
@@ -152,59 +138,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
var order = doneResult && doneResult.order;
|
||||
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
|
||||
|
||||
banner.appendChild(
|
||||
createDom('div', { className: 'jasmine-run-options' },
|
||||
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
|
||||
createDom('div', { className: 'jasmine-payload' },
|
||||
createDom('div', { className: 'jasmine-exceptions' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-raise',
|
||||
id: 'jasmine-raise-exceptions',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
|
||||
createDom('div', { className: 'jasmine-throw-failures' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-throw',
|
||||
id: 'jasmine-throw-failures',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
|
||||
createDom('div', { className: 'jasmine-random-order' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-random',
|
||||
id: 'jasmine-random-order',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
|
||||
)
|
||||
));
|
||||
|
||||
var raiseCheckbox = find('#jasmine-raise-exceptions');
|
||||
|
||||
raiseCheckbox.checked = !env.catchingExceptions();
|
||||
raiseCheckbox.onclick = onRaiseExceptionsClick;
|
||||
|
||||
var throwCheckbox = find('#jasmine-throw-failures');
|
||||
throwCheckbox.checked = env.throwingExpectationFailures();
|
||||
throwCheckbox.onclick = onThrowExpectationsClick;
|
||||
|
||||
var randomCheckbox = find('#jasmine-random-order');
|
||||
randomCheckbox.checked = env.randomTests();
|
||||
randomCheckbox.onclick = onRandomClick;
|
||||
|
||||
var optionsMenu = find('.jasmine-run-options'),
|
||||
optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'),
|
||||
optionsPayload = optionsMenu.querySelector('.jasmine-payload'),
|
||||
isOpen = /\bjasmine-open\b/;
|
||||
|
||||
optionsTrigger.onclick = function() {
|
||||
if (isOpen.test(optionsPayload.className)) {
|
||||
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
|
||||
} else {
|
||||
optionsPayload.className += ' jasmine-open';
|
||||
}
|
||||
};
|
||||
banner.appendChild(optionsMenu(env));
|
||||
|
||||
if (stateBuilder.specsExecuted < totalSpecsDefined) {
|
||||
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
|
||||
@@ -216,15 +150,22 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
);
|
||||
}
|
||||
var statusBarMessage = '';
|
||||
var statusBarClassName = 'jasmine-bar ';
|
||||
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
|
||||
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
|
||||
var failed = stateBuilder.failureCount + globalFailures.length > 0;
|
||||
|
||||
if (totalSpecsDefined > 0) {
|
||||
if (totalSpecsDefined > 0 || failed) {
|
||||
statusBarMessage += pluralize('spec', stateBuilder.specsExecuted) + ', ' + pluralize('failure', stateBuilder.failureCount);
|
||||
if (stateBuilder.pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', stateBuilder.pendingSpecCount); }
|
||||
statusBarClassName += (stateBuilder.failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed';
|
||||
}
|
||||
|
||||
if (doneResult.overallStatus === 'passed') {
|
||||
statusBarClassName += ' jasmine-passed ';
|
||||
} else if (doneResult.overallStatus === 'incomplete') {
|
||||
statusBarClassName += ' jasmine-incomplete ';
|
||||
statusBarMessage = 'Incomplete: ' + doneResult.incompleteReason + ', ' + statusBarMessage;
|
||||
} else {
|
||||
statusBarClassName += 'jasmine-skipped';
|
||||
statusBarMessage += 'No specs found';
|
||||
statusBarClassName += ' jasmine-failed ';
|
||||
}
|
||||
|
||||
var seedBar;
|
||||
@@ -238,19 +179,24 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar));
|
||||
|
||||
var errorBarClassName = 'jasmine-bar jasmine-errored';
|
||||
var errorBarMessagePrefix = 'AfterAll ';
|
||||
var afterAllMessagePrefix = 'AfterAll ';
|
||||
|
||||
for(var i = 0; i < failedSuites.length; i++) {
|
||||
var failedSuite = failedSuites[i];
|
||||
for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
|
||||
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failedSuite.failedExpectations[j].message));
|
||||
}
|
||||
for(i = 0; i < globalFailures.length; i++) {
|
||||
alert.appendChild(createDom('span', {className: errorBarClassName}, globalFailureMessage(globalFailures[i])));
|
||||
}
|
||||
|
||||
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
|
||||
for(i = 0; i < globalFailures.length; i++) {
|
||||
var failure = globalFailures[i];
|
||||
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failure.message));
|
||||
function globalFailureMessage(failure) {
|
||||
if (failure.globalErrorType === 'load') {
|
||||
var prefix = 'Error during loading: ' + failure.message;
|
||||
|
||||
if (failure.filename) {
|
||||
return prefix + ' in ' + failure.filename + ' line ' + failure.lineno;
|
||||
} else {
|
||||
return prefix;
|
||||
}
|
||||
} else {
|
||||
return afterAllMessagePrefix + failure.message;
|
||||
}
|
||||
}
|
||||
|
||||
addDeprecationWarnings(doneResult);
|
||||
@@ -266,47 +212,6 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
summaryList(stateBuilder.topResults, summary);
|
||||
|
||||
function summaryList(resultsTree, domParent) {
|
||||
var specListNode;
|
||||
for (var i = 0; i < resultsTree.children.length; i++) {
|
||||
var resultNode = resultsTree.children[i];
|
||||
if (filterSpecs && !hasActiveSpec(resultNode)) {
|
||||
continue;
|
||||
}
|
||||
if (resultNode.type == 'suite') {
|
||||
var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
|
||||
createDom('li', {className: 'jasmine-suite-detail'},
|
||||
createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
|
||||
)
|
||||
);
|
||||
|
||||
summaryList(resultNode, suiteListNode);
|
||||
domParent.appendChild(suiteListNode);
|
||||
}
|
||||
if (resultNode.type == 'spec') {
|
||||
if (domParent.getAttribute('class') != 'jasmine-specs') {
|
||||
specListNode = createDom('ul', {className: 'jasmine-specs'});
|
||||
domParent.appendChild(specListNode);
|
||||
}
|
||||
var specDescription = resultNode.result.description;
|
||||
if(noExpectations(resultNode.result)) {
|
||||
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
|
||||
}
|
||||
if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
|
||||
specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
|
||||
}
|
||||
specListNode.appendChild(
|
||||
createDom('li', {
|
||||
className: 'jasmine-' + resultNode.result.status,
|
||||
id: 'spec-' + resultNode.result.id
|
||||
},
|
||||
createDom('a', {href: specHref(resultNode.result)}, specDescription)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failures.length) {
|
||||
alert.appendChild(
|
||||
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'},
|
||||
@@ -335,6 +240,153 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
return this;
|
||||
|
||||
function failureDom(result) {
|
||||
var failure =
|
||||
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
|
||||
failureDescription(result, stateBuilder.currentParent),
|
||||
createDom('div', {className: 'jasmine-messages'})
|
||||
);
|
||||
var messages = failure.childNodes[1];
|
||||
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
var expectation = result.failedExpectations[i];
|
||||
messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
|
||||
messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
|
||||
}
|
||||
|
||||
return failure;
|
||||
}
|
||||
|
||||
function summaryList(resultsTree, domParent) {
|
||||
var specListNode;
|
||||
for (var i = 0; i < resultsTree.children.length; i++) {
|
||||
var resultNode = resultsTree.children[i];
|
||||
if (filterSpecs && !hasActiveSpec(resultNode)) {
|
||||
continue;
|
||||
}
|
||||
if (resultNode.type === 'suite') {
|
||||
var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
|
||||
createDom('li', {className: 'jasmine-suite-detail jasmine-' + resultNode.result.status},
|
||||
createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
|
||||
)
|
||||
);
|
||||
|
||||
summaryList(resultNode, suiteListNode);
|
||||
domParent.appendChild(suiteListNode);
|
||||
}
|
||||
if (resultNode.type === 'spec') {
|
||||
if (domParent.getAttribute('class') !== 'jasmine-specs') {
|
||||
specListNode = createDom('ul', {className: 'jasmine-specs'});
|
||||
domParent.appendChild(specListNode);
|
||||
}
|
||||
var specDescription = resultNode.result.description;
|
||||
if(noExpectations(resultNode.result)) {
|
||||
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
|
||||
}
|
||||
if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
|
||||
specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
|
||||
}
|
||||
specListNode.appendChild(
|
||||
createDom('li', {
|
||||
className: 'jasmine-' + resultNode.result.status,
|
||||
id: 'spec-' + resultNode.result.id
|
||||
},
|
||||
createDom('a', {href: specHref(resultNode.result)}, specDescription)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function optionsMenu(env) {
|
||||
var optionsMenuDom = createDom('div', { className: 'jasmine-run-options' },
|
||||
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
|
||||
createDom('div', { className: 'jasmine-payload' },
|
||||
createDom('div', { className: 'jasmine-stop-on-failure' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-fail-fast',
|
||||
id: 'jasmine-fail-fast',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-fail-fast' }, 'stop execution on spec failure')),
|
||||
createDom('div', { className: 'jasmine-throw-failures' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-throw',
|
||||
id: 'jasmine-throw-failures',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
|
||||
createDom('div', { className: 'jasmine-random-order' },
|
||||
createDom('input', {
|
||||
className: 'jasmine-random',
|
||||
id: 'jasmine-random-order',
|
||||
type: 'checkbox'
|
||||
}),
|
||||
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
|
||||
)
|
||||
);
|
||||
|
||||
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
|
||||
failFastCheckbox.checked = env.stoppingOnSpecFailure();
|
||||
failFastCheckbox.onclick = function() {
|
||||
navigateWithNewParam('failFast', !env.stoppingOnSpecFailure());
|
||||
};
|
||||
|
||||
var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
|
||||
throwCheckbox.checked = env.throwingExpectationFailures();
|
||||
throwCheckbox.onclick = function() {
|
||||
navigateWithNewParam('throwFailures', !env.throwingExpectationFailures());
|
||||
};
|
||||
|
||||
var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
|
||||
randomCheckbox.checked = env.randomTests();
|
||||
randomCheckbox.onclick = function() {
|
||||
navigateWithNewParam('random', !env.randomTests());
|
||||
};
|
||||
|
||||
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),
|
||||
optionsPayload = optionsMenuDom.querySelector('.jasmine-payload'),
|
||||
isOpen = /\bjasmine-open\b/;
|
||||
|
||||
optionsTrigger.onclick = function() {
|
||||
if (isOpen.test(optionsPayload.className)) {
|
||||
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
|
||||
} else {
|
||||
optionsPayload.className += ' jasmine-open';
|
||||
}
|
||||
};
|
||||
|
||||
return optionsMenuDom;
|
||||
}
|
||||
|
||||
function failureDescription(result, suite) {
|
||||
var wrapper = createDom('div', {className: 'jasmine-description'},
|
||||
createDom('a', {title: result.description, href: specHref(result)}, result.description)
|
||||
);
|
||||
var suiteLink;
|
||||
|
||||
while (suite && suite.parent) {
|
||||
wrapper.insertBefore(createTextNode(' > '), wrapper.firstChild);
|
||||
suiteLink = createDom('a', {href: suiteHref(suite)}, suite.result.description);
|
||||
wrapper.insertBefore(suiteLink, wrapper.firstChild);
|
||||
|
||||
suite = suite.parent;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function suiteHref(suite) {
|
||||
var els = [];
|
||||
|
||||
while (suite && suite.parent) {
|
||||
els.unshift(suite.result.description);
|
||||
suite = suite.parent;
|
||||
}
|
||||
|
||||
return addToExistingQueryString('spec', els.join(' '));
|
||||
}
|
||||
|
||||
function addDeprecationWarnings(result) {
|
||||
if (result && result.deprecationWarnings) {
|
||||
for(var i = 0; i < result.deprecationWarnings.length; i++) {
|
||||
@@ -413,7 +465,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function hasActiveSpec(resultNode) {
|
||||
if (resultNode.type == 'spec' && resultNode.result.status != 'disabled') {
|
||||
if (resultNode.type == 'spec' && resultNode.result.status != 'excluded') {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,10 @@ jasmineRequire.ResultsNode = function() {
|
||||
this.last = function() {
|
||||
return this.children[this.children.length - 1];
|
||||
};
|
||||
|
||||
this.updateResult = function(result) {
|
||||
this.result = result;
|
||||
};
|
||||
}
|
||||
|
||||
return ResultsNode;
|
||||
|
||||
@@ -135,7 +135,7 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
&.jasmine-disabled {
|
||||
&.jasmine-excluded {
|
||||
font-size: 14px;
|
||||
|
||||
&:before {
|
||||
@@ -200,20 +200,22 @@ body {
|
||||
display: block;
|
||||
color: #eee;
|
||||
|
||||
&.jasmine-failed {
|
||||
&.jasmine-failed, &.jasmine-errored {
|
||||
background-color: $failing-color;
|
||||
border-bottom: 1px solid $page-background-color;
|
||||
}
|
||||
|
||||
&.jasmine-passed {
|
||||
background-color: $passing-color;
|
||||
}
|
||||
|
||||
&.jasmine-skipped {
|
||||
&.jasmine-incomplete {
|
||||
background-color: $neutral-color;
|
||||
}
|
||||
|
||||
&.jasmine-errored {
|
||||
background-color: $failing-color;
|
||||
|
||||
&.jasmine-skipped {
|
||||
background-color: $neutral-color;
|
||||
}
|
||||
|
||||
&.jasmine-warning {
|
||||
@@ -290,7 +292,7 @@ body {
|
||||
color: $pending-color;
|
||||
}
|
||||
|
||||
&.jasmine-disabled a {
|
||||
&.jasmine-excluded a {
|
||||
color: $neutral-color;
|
||||
}
|
||||
}
|
||||
@@ -316,6 +318,7 @@ body {
|
||||
|
||||
.jasmine-description {
|
||||
background-color: $failing-color;
|
||||
color: white;
|
||||
|
||||
a {
|
||||
color: white;
|
||||
|
||||
33
src/html/matchers/toHaveClass.js
Normal file
33
src/html/matchers/toHaveClass.js
Normal file
@@ -0,0 +1,33 @@
|
||||
jasmineRequire.toHaveClass = function(j$) {
|
||||
/**
|
||||
* {@link expect} the actual value to be a DOM element that has the expected class
|
||||
* @function
|
||||
* @name matchers#toHaveClass
|
||||
* @param {Object} expected - The class name to test for
|
||||
* @example
|
||||
* var el = document.createElement('div');
|
||||
* el.className = 'foo bar baz';
|
||||
* expect(el).toHaveClass('bar');
|
||||
*/
|
||||
function toHaveClass(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
if (!isElement(actual)) {
|
||||
throw new Error(j$.pp(actual) + ' is not a DOM element');
|
||||
}
|
||||
|
||||
return {
|
||||
pass: actual.classList.contains(expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function isElement(maybeEl) {
|
||||
return maybeEl &&
|
||||
maybeEl.classList &&
|
||||
j$.isFunction_(maybeEl.classList.contains);
|
||||
}
|
||||
|
||||
return toHaveClass;
|
||||
};
|
||||
@@ -3,4 +3,5 @@ jasmineRequire.html = function(j$) {
|
||||
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
|
||||
j$.QueryString = jasmineRequire.QueryString();
|
||||
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
|
||||
j$.matchers.toHaveClass = jasmineRequire.toHaveClass(j$);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user