Compare commits

..

84 Commits

Author SHA1 Message Date
Gregg Van Hove
8fca3b4c11 Fix links in 3.4 release notes 2019-04-03 17:13:18 -07:00
Gregg Van Hove
e636f5f822 Bump version to 3.4 2019-04-03 17:03:07 -07:00
Gregg Van Hove
74fd0e08e7 No fit in the suite 2019-04-01 21:01:22 -07:00
Gregg Van Hove
618e24b2f8 Handle WebSocket events in IE when detecting Errors
- Fixes #1623
2019-04-01 18:52:27 -07:00
Gregg Van Hove
5c7e25e228 Allow excluded specs in CI without breaking the output 2019-04-01 18:52:01 -07:00
Gregg Van Hove
54af109d40 Merge branch 'wood1986-fix/npm-audit-dependencies-and-fast-glob-only-failed-tests'
- Merges #1672 from @wood1986
2019-03-26 17:12:53 -07:00
wood
873a237e3d Consolidate some dev dependencies and use more maintained versions 2019-03-26 17:12:21 -07:00
Gregg Van Hove
8ca4463e01 Make node execution default and override for browsers 2019-03-25 18:37:50 -07:00
Gregg Van Hove
449eb516cc Fix sauce status codes and try travis built-in node support 2019-03-25 18:33:39 -07:00
Gregg Van Hove
a5df5a6ee9 Use the correct env var from travis for tunnels 2019-03-25 18:12:15 -07:00
Gregg Van Hove
be583232b4 bump dependencies for security fixes 2019-03-25 18:01:13 -07:00
Gregg Van Hove
d389d3c002 Merge branch 'wood1986-features/no-ruby'
- Merges #1658 from @wood1986
- Fixes #883
2019-03-25 17:56:19 -07:00
Gregg Van Hove
994d11d4f3 update node CI script to work with SauceLabs 2019-03-25 17:56:06 -07:00
wood
828d14f48e Use node.js for browser-based CI 2019-03-25 17:55:53 -07:00
Gregg Van Hove
f5663a9076 Merge branch 'johnjbarton-duration'
- Merges #1660 from @johnjbarton
- Fixes #1646
2019-03-14 19:12:39 -07:00
johnjbarton
a8c2399dd8 feat(result.duration): report test duration in ms
Wrap spec start/complete in Timer start/elapsed.
configuration.timeSpecDuration = false will disable feature.

 * Add Suite result.duration, elapsed time in ms

 * Remove timeSpecDuration option.

 * Respond to review, use noopTimer
2019-03-14 09:13:57 -07:00
Gregg Van Hove
7c0f013003 Merge branch 'johnjbarton-noop-timer'
- Merges #1669 from @johnjbarton
2019-03-13 17:34:12 -07:00
johnjbarton
ca2b62b00e refactor(Timer): share htmlReporter noopTimer via Timer.js 2019-03-12 16:26:04 -07:00
Gregg Van Hove
4108deca02 Build distribution for various typo PRs 2019-03-11 17:39:03 -07:00
Gregg Van Hove
def278f90f Merge branch 'typo-suites' of https://github.com/FelixRilling/jasmine into FelixRilling-typo-suites
- Merges #1666 from @FelixRilling
2019-03-11 17:38:29 -07:00
Gregg Van Hove
6bd4a29360 Merge branch 'jsdoc-validation' of https://github.com/FelixRilling/jasmine into FelixRilling-jsdoc-validation
- Merges #1667 from @FelixRilling
2019-03-11 17:37:43 -07:00
Gregg Van Hove
fd037f53a3 Merge branch 'typo-comments' of https://github.com/FelixRilling/jasmine into FelixRilling-typo-comments
- Merges #1665 from @FelixRilling
2019-03-11 17:34:44 -07:00
Gregg Van Hove
348242b712 Merge branch 'FelixRilling-typo-received'
- Merges #1664 from @FelixRilling
- Fixes #1663
2019-03-11 17:32:32 -07:00
Felix Rilling
b74e0abee1 Fixed flipped JSDoc. 2019-03-10 11:17:50 +01:00
Felix Rilling
e33b12b17c Fixed typos in test suite descriptions. 2019-03-10 11:07:40 +01:00
Felix Rilling
dde93ade18 Fixed typos in comments. 2019-03-10 11:04:33 +01:00
Felix Rilling
63f900287c Fixed typo "receieved" to "received", Adapted test. 2019-03-10 10:59:56 +01:00
Gregg Van Hove
239a615770 No longer run Node.js v4 on Travis
- Jasmine should still work in Node.js v4, but the jshint task isn't
  working correctly
2019-02-11 13:38:00 -08:00
Gregg Van Hove
92d5957a59 Attempt to skip jshint for node.js v4 2019-02-11 09:46:36 -08:00
Gregg Van Hove
4991f2a713 Merge branch 'print_global_error_type' of https://github.com/jbunton-atlassian/jasmine into jbunton-atlassian-print_global_error_type
- Merges #1632 from @jbunton-atlassian
2019-02-11 09:02:16 -08:00
Gregg Van Hove
0d6db64eb1 Merge branch 'onerror' of https://github.com/johnjbarton/jasmine into johnjbarton-onerror
- Merges #1644 from @jognjbarton
2019-01-30 17:38:27 -08:00
Gregg Van Hove
489fb79d6e fall back to older jshint for older node 2019-01-09 11:08:32 -08:00
Gregg Van Hove
eba8c775f3 update npm dependencies 2019-01-08 17:47:53 -08:00
johnjbarton
c36a005893 Support Error.stack in globalErrors.
See https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror#window.onerror
2019-01-03 16:14:23 -08:00
Gregg Van Hove
37dfe50d99 Stop treating objects with a nodeType as if they are DOM Nodes
- Fixes #1638
2018-12-17 17:10:53 -08:00
Gregg Van Hove
c67a5b830c Fix 3.0 breaking changes list to include note about Spy identity 2018-12-11 17:56:17 -08:00
James Bunton
d803bd12a6 When catching a global error in Node.js, print the type of error 2018-12-11 08:32:45 +11:00
Gregg Van Hove
a621d05fa7 Merge branch 'Havunen-fix-to-equal-ie'
- Merges #1621 from @Havunen
- Fixes #1618
2018-12-03 17:45:06 -08:00
Sampo Kivistö
473f5cd359 Re-use attr variable 2018-11-04 10:44:54 +02:00
Sampo Kivistö
a81e9626df Fixes issue where PhantomJS 2 and IE 10 - 11 crashed when reporting SVG element equality 2018-11-04 10:31:33 +02:00
Gregg Van Hove
b3ccd4312c Bump version to 3.3.0 2018-10-25 09:47:09 -07:00
Gregg Van Hove
5524207658 Add api docs for .not and .withContext 2018-10-24 16:49:31 -07:00
Gregg Van Hove
1b5e0c0c10 Merge branch 'expect-context'
- Fixes #641
2018-10-24 16:32:28 -07:00
Gregg Van Hove
2d303a6e46 Merge common async/sync expectation stuff 2018-10-24 16:17:30 -07:00
Gregg Van Hove
1e47dcf2cc Pull async matchers out to their own functions
- Makes AsyncExpectation closer to Expectation
2018-10-23 16:02:31 -07:00
Gregg Van Hove
ba1e8f8008 Implement withContext for async expectations too 2018-10-22 16:42:36 -07:00
Gregg Van Hove
a91db0dfc2 more rejected to -> rejected with 2018-10-22 16:08:57 -07:00
Gregg Van Hove
1d130036f4 Merge branch 'master' into expect-context 2018-10-22 14:55:20 -07:00
Gregg Van Hove
e6a60a7bef Merge branch 'codymikol-toBeRejectedWith'
- Merges #1615 from @codymikol
- Closes #1600
- Fixes #1595
2018-10-22 11:20:03 -07:00
Gregg Van Hove
fe042fdf82 Use toBeRejectedWith instead of toBeRejectedTo 2018-10-22 11:18:56 -07:00
Gregg Van Hove
06854fe435 Merge branch 'toBeRejectedWith' of https://github.com/codymikol/jasmine into codymikol-toBeRejectedWith 2018-10-22 11:15:05 -07:00
Gregg Van Hove
7b9fc80b8f Merge branch 'tdurtschi-master'
- Merges #1616 from @tdurtshi
- Fixes #1614
2018-10-22 10:59:03 -07:00
Gregg Van Hove
3c47e71619 Also show tip for .not cases 2018-10-22 10:57:16 -07:00
Teagan Durtschi
7cbedcdda7 Add custom message for toBe() matcher when object equality check fails 2018-10-21 12:46:49 -04:00
Cody Mikol
3aa0115ae4 feat(toBeRejectedTo): implement toBeRejectedTo functionality
add functionality to determine whether a promise has been rejected to a
specific value via expectAsync

Fixes: #1595
2018-10-19 23:23:42 -04:00
Gregg Van Hove
440b6934aa Merge branch 'codymikol-assertAsync-promiseLike-support'
- Merges #1613 from @codymikol
- Fixes #1612
2018-10-19 16:24:30 -07:00
Cody Mikol
591bf1144b bugfix(assertAsync): add promiseLike support for angularJS promises
implement a promiseLike method so libraries using non-browser promise
implementations can still utilize assertAsync functionality.

Fixes: #1612
2018-10-18 21:28:32 -04:00
Gregg Van Hove
3ae61b14ad Merge branch 'm1010j-m1010j-add-status-marks-to-standalone'
- Merges #1610 from @m1010j
- Fixes #1596
2018-10-01 12:25:23 -07:00
Matthias Jenny
705a6508d4 Add status marks to standalone 2018-09-26 21:10:20 -04:00
Gregg Van Hove
306882f636 Merge branch 'nitobuendia-patch-1' 2018-09-25 17:29:10 -07:00
Gregg Van Hove
16fef04629 Merge branch 'patch-1' of https://github.com/nitobuendia/jasmine into nitobuendia-patch-1
- Merges #1601 from @nitobuendia
- Fixes #1594
2018-09-25 17:28:57 -07:00
Gregg Van Hove
d180c2026e Merge branch 'master' of https://github.com/Havunen/jasmine into Havunen-master
- Merges #1599 from @Havunen
2018-09-25 17:14:49 -07:00
Gregg Van Hove
92d0882a32 Introduce a configuration object to Env deprecating old single use functions
[finishes #159158038]
2018-09-25 17:08:41 -07:00
Nito Buendia
04679622b0 Add tests for formatting empty content errors. 2018-09-13 20:02:30 +08:00
Nito Buendia
b4cd1ec1ae Format according to style. 2018-09-13 19:48:53 +08:00
Nito Buendia
963b1cca22 Add tests for new unnamed errors. 2018-09-13 19:48:10 +08:00
Nito Buendia
d4f9b41eda Print error message when available
With the current set up, error message is only printed out when error name is available.
There are situations where the ErrorEvent object does not have a `name` property, but the message is still relevant.

For more details see #1594
2018-09-11 23:25:28 +08:00
Sampo Kivistö
1019b045cd Optimized clearTimeout cpu usage 2018-09-06 21:11:05 +03:00
Gregg Van Hove
6b9ae2db7e Merge pull request #1597 from limonte/patch-1
chore(package.json): http -> https
2018-09-04 12:27:05 -07:00
Limon Monte
33d8d2d3f4 chore(package.json): http -> https 2018-09-01 10:16:30 +03:00
Gregg Van Hove
12f56fdb7d bump version to 3.2.1 2018-08-14 17:19:23 -07:00
Gregg Van Hove
afa18e554c Correctly expost spyOnAllFunctions
- See #1581
2018-08-14 17:11:50 -07:00
Gregg Van Hove
7205d07c67 Merge pull request #1588 from fossabot/master
Add license scan report and status
2018-08-08 19:04:21 -07:00
fossabot
f05ab79731 Add license scan report and status
Signed-off-by: fossabot <badges@fossa.io>
2018-08-07 17:47:31 -07:00
Steve Gravrock
ac07c9ea97 Simplified ExpectationFilterChain#modifyFailureMessage 2018-06-09 12:34:30 -07:00
Steve Gravrock
0842a80c68 Cleanup 2018-06-09 12:26:34 -07:00
Steve Gravrock
8a01e1f26c .withContext() works with .not 2018-06-02 22:06:53 -07:00
Steve Gravrock
321f161ce5 Made ExpectationFilterChain immutable 2018-06-02 13:57:29 -07:00
Steve Gravrock
202a677637 ExpectationFilterChain WIP 2018-06-02 13:57:07 -07:00
Steve Gravrock
e2897ce619 Added expect().withContext() to provide additional information in failure messages 2018-05-14 21:18:55 -07:00
Steve Gravrock
282c436463 Implemented matcher negation as a filter 2018-05-13 23:01:55 -07:00
Steve Gravrock
5cc22740c9 Test the public-ish interface 2018-05-13 22:48:58 -07:00
Steve Gravrock
533bda5d24 Split Expectation#wrapCompare into several smaller functions 2018-05-13 22:48:58 -07:00
Steve Gravrock
9fe9569b24 Additional tests for negated matcher failure messages 2018-05-13 22:48:20 -07:00
76 changed files with 3288 additions and 1144 deletions

View File

@@ -1,19 +1,16 @@
language: ruby
cache: bundler
sudo: false
language: node_js
node_js:
- "11"
- "10"
- "8"
rvm: 2.5
before_install:
- gem update --system
- gem install bundler
script: $TEST_COMMAND
env:
global:
- USE_SAUCE=true
- USE_SAUCE=false
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
- TEST_COMMAND="bash travis-core-script.sh"
- TEST_COMMAND="npm test"
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
@@ -23,46 +20,55 @@ addons:
matrix:
include:
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v4"
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v8"
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v9"
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.12"
- SAUCE_BROWSER_VERSION=10
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.11"
- SAUCE_BROWSER_VERSION=9
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.10"
- SAUCE_BROWSER_VERSION=8
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="MicrosoftEdge"
- SAUCE_OS="Windows 10"
- SAUCE_BROWSER_VERSION="15"
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 8.1"
- SAUCE_BROWSER_VERSION=11
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 8"
- SAUCE_BROWSER_VERSION=10
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="chrome"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="phantomjs"
- USE_SAUCE=false

View File

@@ -6,15 +6,16 @@ module.exports = function(grunt) {
pkg: pkg,
jshint: require('./grunt/config/jshint.js'),
concat: require('./grunt/config/concat.js'),
compass: require('./grunt/config/compass.js'),
compress: require('./grunt/config/compress.js')
sass: require('./grunt/config/sass.js'),
compress: require('./grunt/config/compress.js'),
cssUrlEmbed: require('./grunt/config/cssUrlEmbed.js')
});
require('load-grunt-tasks')(grunt);
grunt.loadTasks('grunt/tasks');
grunt.registerTask('default', ['jshint:all']);
grunt.registerTask('default', ['jshint:all', 'sass:dist', "cssUrlEmbed"]);
var version = require('./grunt/tasks/version.js');
@@ -25,11 +26,11 @@ module.exports = function(grunt) {
grunt.registerTask('buildDistribution',
'Builds and lints jasmine.js, jasmine-html.js, jasmine.css',
[
'compass',
'sass:dist',
"cssUrlEmbed",
'jshint:beforeConcat',
'concat',
'jshint:afterConcat',
'build:copyVersionToGem'
'jshint:afterConcat'
]
);

View File

@@ -2,6 +2,7 @@
[![Build Status](https://travis-ci.org/jasmine/jasmine.svg?branch=master)](https://travis-ci.org/jasmine/jasmine)
[![Open Source Helpers](https://www.codetriage.com/jasmine/jasmine/badges/users.svg)](https://www.codetriage.com/jasmine/jasmine)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_shield)
# A JavaScript Testing Framework
@@ -75,3 +76,7 @@ Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, M
* Sheel Choksi
Copyright (c) 2008-2018 Pivotal Labs. This software is licensed under the MIT License.
## License
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_large)

208
ci.js Normal file
View File

@@ -0,0 +1,208 @@
const path = require("path"),
fs = require('fs'),
port = 5555,
colors = {
"passed" : "\x1B[32m",
"failed": "\x1B[31m",
"pending": "\x1B[33m",
"excluded": "\x1B[0m",
"none": "\x1B[0m"
},
symbols = {
"passed" : ".",
"failed": "F",
"pending": "*",
"excluded": "",
"none": ""
},
host = `http://localhost:${port}`,
useSauce = process.env.USE_SAUCE === 'true';
let driver, server;
function pageGenerator() {
const ejs = require("ejs"),
fg = require("fast-glob"),
templatePath = path.resolve(__dirname, 'spec/support/index.html.ejs'),
template = ejs.compile(fs.readFileSync(templatePath).toString()),
patterns = [
"lib/jasmine-core/jasmine.js",
"lib/jasmine-core/json2.js",
"lib/jasmine-core/jasmine-html.js",
"lib/jasmine-core/boot.js",
"src/core/requireCore.js",
"src/core/base.js",
"src/core/util.js",
"src/core/Spec.js",
"src/core/Env.js",
"src/**/*.js",
"spec/helpers/*.js",
"spec/**/*[Ss]pec.js"
],
ignore = [
"spec/helpers/nodeDefineJasmineUnderTest.js",
"spec/npmPackage/**/*",
"lib/jasmine-core/node_boot.js"
];
return function toHtml() {
const files = fg.sync(patterns, {ignore});
return template({files});
}
}
function buildWebdriver() {
const webdriver = require("selenium-webdriver"),
Capability = webdriver.Capability;
if (useSauce) {
const username = process.env['SAUCE_USERNAME'],
accessKey = process.env['SAUCE_ACCESS_KEY'];
return new webdriver.Builder()
.withCapabilities({
name: `jasmine-core ${new Date().toISOString()}`,
[Capability.PLATFORM]: process.env['SAUCE_OS'],
[Capability.BROWSER_NAME]: process.env['JASMINE_BROWSER'],
[Capability.VERSION]: process.env['SAUCE_BROWSER_VERSION'],
build: `Core ${process.env['TRAVIS_BUILD_NUMBER'] || 'Ran locally'}`,
tags: ['Jasmine-Core'],
"tunnel-identifier": process.env['TRAVIS_JOB_NUMBER'] ? process.env['TRAVIS_JOB_NUMBER'].toString() : null
})
.usingServer(`http://${username}:${accessKey}@localhost:4445/wd/hub`)
.build();
} else {
return new webdriver.Builder()
.forBrowser(process.env["JASMINE_BROWSER"] || "firefox")
.build();
}
}
async function resultsWithoutCircularReferences(driver, resultType, index, batchSize) {
return await driver.executeScript(
`var results = jsApiReporter.${resultType}Results(${index}, ${batchSize});\n` +
'for (var i = 0; i < results.length; i++) {\n' +
'var expectations = results[i].failedExpectations;\n' +
'if (results[i].passedExpectations) {\n' +
'expectations = expectations.concat(results[i].passedExpectations);\n' +
'}\n' +
'for (var j = 0; j < expectations.length; j++) {\n' +
'var expectation = expectations[j];\n' +
"try { JSON.stringify(expectation.expected); } catch (e) { expectation.expected = '<circular expected>'; }\n" +
"try { JSON.stringify(expectation.actual); } catch (e) { expectation.actual = '<circular actual>'; }\n" +
'}\n' +
'}\n' +
'return results;'
);
}
function flatten(arr) {
return Array.prototype.concat.apply([], arr);
}
async function getResults(driver) {
const batchSize = 50,
specResults = [],
failedSuiteResults = [];
let index = 0,
slice = [];
do {
slice = await resultsWithoutCircularReferences(driver, 'spec', index, batchSize);
specResults.push(slice);
index += batchSize;
} while (slice.length === batchSize);
index = 0;
do {
slice = await resultsWithoutCircularReferences(driver, 'suite', index, batchSize);
failedSuiteResults.push(slice.filter(function(suite) { return suite.status === 'failed' }));
index += batchSize;
} while (slice.length === batchSize);
return {specResults: flatten(specResults), failedSuiteResults: flatten(failedSuiteResults)};
}
(async function () {
await new Promise(resolve => {
console.log("Creating an express app for browers to run the tests...")
const express = require("express"),
app = express(),
html = pageGenerator();
app.use(express.static(__dirname));
app.get("/", (req, res) => res.send(html()));
server = app.listen(port, resolve);
});
console.log("Running the tests in browser...")
driver = buildWebdriver();
await driver.get(`${host}/?throwFailures=false&failFast=false&random=true`)
await new Promise(resolve => {
const intervalId = setInterval(async () => {
const isFinished = await driver.executeScript("return jsApiReporter && jsApiReporter.finished")
if (isFinished) {
clearInterval(intervalId)
resolve();
}
}, 500)
});
const {specResults, failedSuiteResults} = await getResults(driver);
console.log(specResults.map(spec => `${colors[spec.status]}${symbols[spec.status]}`).join("") + colors["none"]);
const result = specResults.reduce((result, spec) => {
result[spec.status] = [...result[spec.status], spec];
return result;
}, {pending: [], failed: [], passed: [], excluded: []});
if (result.pending.length) {
console.log(`${colors["pending"]}Pending:`);
result.pending.forEach((spec, index) => {
console.log(`${colors["none"]}${index}) ${spec.fullName}`)
console.group();
console.log(`${colors["pending"]}${spec.pendingReason || "no reason given"}`);
console.groupEnd();
console.log();
});
}
if (result.failed.length) {
console.log(`${colors["failed"]}Failed:`);
result["failed"].forEach((spec, index) => {
console.log(`${colors["none"]}${index}) ${spec.fullName}`)
console.group();
spec.failedExpectations.forEach((expect) => {
console.log(`${colors["none"]}Message:`);
console.group();
console.log(`${colors["failed"]}${expect.message}`);
console.groupEnd();
console.log(`${colors["none"]}Stack:`);
console.group();
console.log(`${colors["failed"]}${expect.stack}`);
console.groupEnd();
console.groupEnd();
})
console.groupEnd();
console.log();
});
}
const details = await driver.executeScript(`
return {
overallStatus: jsApiReporter.runDetails.overallStatus,
executionTime: jsApiReporter.executionTime(),
random: jsApiReporter.runDetails.order.random,
seed: jsApiReporter.runDetails.order.seed
}`);
console.log(`${colors["none"]}${specResults.length} spec(s), ${result.failed.length} failure(s), ${result.pending.length} pending spec(s)`);
console.log(`Finished in ${details.executionTime / 1000} second(s)`);
console.log(`Randomized with seed ${details.seed} ( ${host}/?random=${details.random}&seed=${details.seed} )`);
process.exitCode = details.overallStatus === 'passed' ? 0 : 1;
if (useSauce) {
driver.executeScript(`sauce:job-result=${process.exitCode === 0}`);
}
})().finally(() => {
return Promise.all([driver.close(), new Promise(resolve => server.close(resolve))]);
});

View File

@@ -1,11 +0,0 @@
module.exports = {
jasmine: {
options: {
cssDir: 'lib/jasmine-core/',
sassDir: 'src/html',
outputStyle: 'compact',
noLineComments: true,
bundleExec: true
}
}
};

View File

@@ -0,0 +1,7 @@
module.exports = {
encodeWithBaseDir: {
files: {
"lib/jasmine-core/jasmine.css": ["lib/jasmine-core/jasmine.css"]
}
}
};

14
grunt/config/sass.js Normal file
View File

@@ -0,0 +1,14 @@
const sass = require('node-sass');
module.exports = {
options: {
implementation: sass,
outputStyle: 'compact',
sourceComments: false
},
dist: {
files: {
"lib/jasmine-core/jasmine.css": "src/html/jasmine.scss"
}
}
};

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Copyright (c) 2008-2019 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -73,24 +73,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var filterSpecs = !!queryString.getParam("spec");
var stoppingOnSpecFailure = queryString.getParam("failFast");
env.stopOnSpecFailure(stoppingOnSpecFailure);
var throwingExpectationFailures = queryString.getParam("throwFailures");
env.throwOnExpectationFailure(throwingExpectationFailures);
var hideDisabled = queryString.getParam("hideDisabled");
env.hideDisabled(hideDisabled);
var config = {
failFast: queryString.getParam("failFast"),
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
hideDisabled: queryString.getParam("hideDisabled")
};
var random = queryString.getParam("random");
if (random !== undefined && random !== "") {
env.randomizeTests(random);
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
config.seed = seed;
}
/**
@@ -121,10 +118,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
filterString: function() { return queryString.getParam("spec"); }
});
env.specFilter = function(spec) {
config.specFilter = function(spec) {
return specFilter.matches(spec.getFullName());
};
env.configure(config);
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/

View File

@@ -51,24 +51,21 @@
var filterSpecs = !!queryString.getParam("spec");
var stoppingOnSpecFailure = queryString.getParam("failFast");
env.stopOnSpecFailure(stoppingOnSpecFailure);
var throwingExpectationFailures = queryString.getParam("throwFailures");
env.throwOnExpectationFailure(throwingExpectationFailures);
var hideDisabled = queryString.getParam("hideDisabled");
env.hideDisabled(hideDisabled);
var config = {
failFast: queryString.getParam("failFast"),
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
hideDisabled: queryString.getParam("hideDisabled")
};
var random = queryString.getParam("random");
if (random !== undefined && random !== "") {
env.randomizeTests(random);
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
config.seed = seed;
}
/**
@@ -99,10 +96,12 @@
filterString: function() { return queryString.getParam("spec"); }
});
env.specFilter = function(spec) {
config.specFilter = function(spec) {
return specFilter.matches(spec.getFullName());
};
env.configure(config);
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Copyright (c) 2008-2019 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -28,12 +28,6 @@ jasmineRequire.html = function(j$) {
};
jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = {
start: function() {},
elapsed: function() { return 0; }
};
function ResultsStateBuilder() {
this.topResults = new j$.ResultsNode({}, '', null);
this.currentParent = this.topResults;
@@ -80,14 +74,14 @@ jasmineRequire.HtmlReporter = function(j$) {
function HtmlReporter(options) {
var env = options.env || {},
var config = function() { return (options.env && options.env.configuration()) || {}; },
getContainer = options.getContainer,
createElement = options.createElement,
createTextNode = options.createTextNode,
navigateWithNewParam = options.navigateWithNewParam || function() {},
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
filterSpecs = options.filterSpecs,
timer = options.timer || noopTimer,
timer = options.timer || j$.noopTimer,
htmlReporterMain,
symbols,
deprecationWarnings = [];
@@ -167,9 +161,9 @@ jasmineRequire.HtmlReporter = function(j$) {
this.resultStatus = function(status) {
if(status === 'excluded') {
return env.hidingDisabled() ? 'jasmine-excluded-no-display' : 'jasmine-excluded';
}
return 'jasmine-' + status;
return config().hideDisabled ? 'jasmine-excluded-no-display' : 'jasmine-excluded';
}
return 'jasmine-' + status;
};
this.jasmineDone = function(doneResult) {
@@ -179,7 +173,7 @@ jasmineRequire.HtmlReporter = function(j$) {
var i;
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
banner.appendChild(optionsMenu(env));
banner.appendChild(optionsMenu(config()));
if (stateBuilder.specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
@@ -339,7 +333,7 @@ jasmineRequire.HtmlReporter = function(j$) {
}
}
function optionsMenu(env) {
function optionsMenu(config) {
var optionsMenuDom = createDom('div', { className: 'jasmine-run-options' },
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
createDom('div', { className: 'jasmine-payload' },
@@ -375,27 +369,27 @@ jasmineRequire.HtmlReporter = function(j$) {
);
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
failFastCheckbox.checked = env.stoppingOnSpecFailure();
failFastCheckbox.checked = config.failFast;
failFastCheckbox.onclick = function() {
navigateWithNewParam('failFast', !env.stoppingOnSpecFailure());
navigateWithNewParam('failFast', !config.failFast);
};
var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
throwCheckbox.checked = env.throwingExpectationFailures();
throwCheckbox.checked = config.oneFailurePerSpec;
throwCheckbox.onclick = function() {
navigateWithNewParam('throwFailures', !env.throwingExpectationFailures());
navigateWithNewParam('throwFailures', !config.oneFailurePerSpec);
};
var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
randomCheckbox.checked = env.randomTests();
randomCheckbox.checked = config.random;
randomCheckbox.onclick = function() {
navigateWithNewParam('random', !env.randomTests());
navigateWithNewParam('random', !config.random);
};
var hideDisabled = optionsMenuDom.querySelector('#jasmine-hide-disabled');
hideDisabled.checked = env.hidingDisabled();
hideDisabled.checked = config.hideDisabled;
hideDisabled.onclick = function() {
navigateWithNewParam('hideDisabled', !env.hidingDisabled());
navigateWithNewParam('hideDisabled', !config.hideDisabled);
};
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Copyright (c) 2008-2019 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -4,6 +4,6 @@
#
module Jasmine
module Core
VERSION = "3.2.0"
VERSION = "3.4.0"
end
end

View File

@@ -1,7 +1,7 @@
{
"name": "jasmine-core",
"license": "MIT",
"version": "3.2.0",
"version": "3.4.0",
"repository": {
"type": "git",
"url": "https://github.com/jasmine/jasmine.git"
@@ -16,20 +16,25 @@
"test": "grunt jshint execSpecsInNode"
},
"description": "Official packaging of Jasmine's core files for use by Node.js projects.",
"homepage": "http://jasmine.github.io",
"homepage": "https://jasmine.github.io",
"main": "./lib/jasmine-core.js",
"devDependencies": {
"glob": "~7.1.2",
"grunt": "^1.0.1",
"grunt-cli": "^1.2.0",
"grunt-contrib-compass": "^1.1.1",
"ejs": "^2.5.5",
"express": "^4.16.4",
"fast-glob": "^2.2.6",
"grunt": "^1.0.4",
"grunt-cli": "^1.3.2",
"grunt-contrib-compress": "^1.3.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-jshint": "^1.0.0",
"jasmine": "^3.0.0",
"jsdom": "^9.12.0",
"load-grunt-tasks": "^0.4.0",
"shelljs": "^0.7.0",
"temp": "~0.8.1"
"grunt-contrib-jshint": "^2.0.0",
"grunt-css-url-embed": "^1.11.1",
"grunt-sass": "^3.0.2",
"jasmine": "^3.3.1",
"jsdom": "^13.1.0",
"load-grunt-tasks": "^4.0.0",
"node-sass": "^4.11.0",
"selenium-webdriver": "^3.6.0",
"shelljs": "^0.8.3",
"temp": "^0.9.0"
}
}

View File

@@ -29,6 +29,8 @@ There is also a 2.99 release of Jasmine that will present deprecation warnings f
* Default to running tests in random order
* The `identity` of a Jasmnine Spy is now a property and no longer a method
* Additionally, Jasmine 3.0 drops support for older browsers and environments. Notably:
- Internet Explorer 8 and 9
- Ruby 1.x (for the Ruby gem)

11
release_notes/3.2.1.md Normal file
View File

@@ -0,0 +1,11 @@
# Jasmine-Core 3.2.1 Release Notes
## Changes
* Correctly expose `spyOnAllFunctions`
- See [#1581](https://github.com/jasmine/jasmine/issues/1581)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

47
release_notes/3.3.0.md Normal file
View File

@@ -0,0 +1,47 @@
# Jasmine Core 3.3 Release Notes
## Summary
This release includes a new way to configure Jasmine, the ability to provide additional
context with your expectations, and other things
## Changes
* Added expect().withContext() to provide additional information in failure messages
* Implement `withContext` for async expectations too
- Fixes [#641](https://github.com/jasmine/jasmine/issues/641)
* New asynchronous matcher `toBeRejectedWith`
- Merges [#1615](https://github.com/jasmine/jasmine/issues/1615) from @codymikol
- Closes [#1600](https://github.com/jasmine/jasmine/issues/1600)
- Fixes [#1595](https://github.com/jasmine/jasmine/issues/1595)
* Show a tip for `toBe` failures for how to get deep equality
- Merges [#1616](https://github.com/jasmine/jasmine/issues/1616) from @tdurtshi
- Fixes [#1614](https://github.com/jasmine/jasmine/issues/1614)
* `expectAsync` now works with non-native promies
- Merges [#1613](https://github.com/jasmine/jasmine/issues/1613) from @codymikol
- Fixes [#1612](https://github.com/jasmine/jasmine/issues/1612)
* Show status marks next to spec description in HTML reporter
- Merges [#1610](https://github.com/jasmine/jasmine/issues/1610) from @m1010j
- Fixes [#1596](https://github.com/jasmine/jasmine/issues/1596)
* Show error messages for `Error`s without a name
- Merges [#1601](https://github.com/jasmine/jasmine/issues/1601) from @nitobuendia
- Fixes [#1594](https://github.com/jasmine/jasmine/issues/1594)
* Optimized clearTimeout cpu usage
- Merges [#1599](https://github.com/jasmine/jasmine/issues/1599) from @Havunen
* Introduce a configuration object to `Env` deprecating old single use functions
- [finishes #159158038](http://www.pivotaltracker.com/story/159158038)
* Specify https for github urls in package.json
- Merges [#1597](https://github.com/jasmine/jasmine/issues/1597) @limonte
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

49
release_notes/3.4.0.md Normal file
View File

@@ -0,0 +1,49 @@
# Jasmine Core 3.4 Release Notes
## Summary
This is a maintenance release of Jasmine with a number of new features and fixes
## Changes
* Handle WebSocket events in IE when detecting Errors
- Fixes [#1623](https://github.com/jasmine/jasmine/issues/1623)
* bump dependencies for security fixes
- Merges [#1672](https://github.com/jasmine/jasmine/issues/1672) from @wood1986
* Make node execution default and override for browsers
- Merges [#1658](https://github.com/jasmine/jasmine/issues/1658) from @wood1986
- Fixes [#883](https://github.com/jasmine/jasmine/issues/883)
* feat(result.duration): report test duration in ms
- Merges [#1660](https://github.com/jasmine/jasmine/issues/1660) from @johnjbarton
- Fixes [#1646](https://github.com/jasmine/jasmine/issues/1646)
* refactor(Timer): share htmlReporter noopTimer via Timer.js
- Merges [#1669](https://github.com/jasmine/jasmine/issues/1669) from @johnjbarton
* Fix various typos
- Merges [#1666](https://github.com/jasmine/jasmine/issues/1666) from @FelixRilling
- Merges [#1667](https://github.com/jasmine/jasmine/issues/1667) from @FelixRilling
- Merges [#1665](https://github.com/jasmine/jasmine/issues/1665) from @FelixRilling
- Merges [#1664](https://github.com/jasmine/jasmine/issues/1664) from @FelixRilling
- Fixes [#1663](https://github.com/jasmine/jasmine/issues/1663)
* When catching a global error in Node.js, print the type of error
- Merges [#1632](https://github.com/jasmine/jasmine/issues/1632) from @jbunton-atlassian
* Support Error.stack in globalErrors.
- Merges [#1644](https://github.com/jasmine/jasmine/issues/1644) from @johnjbarton
* Stop treating objects with a `nodeType` as if they are DOM Nodes
- Fixes [#1638](https://github.com/jasmine/jasmine/issues/1638)
* Fixes issue where PhantomJS 2 and IE 10 - 11 crashed when reporting SVG element equality
- Merges [#1621](https://github.com/jasmine/jasmine/issues/1621) from @Havunen
- Fixes [#1618](https://github.com/jasmine/jasmine/issues/1618)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

View File

@@ -1,235 +1,39 @@
describe('AsyncExpectation', function() {
beforeEach(function() {
jasmineUnderTest.Expectation.addAsyncCoreMatchers(jasmineUnderTest.asyncMatchers);
});
describe('Factory', function() {
it('throws an Error if promises are not available', function() {
var thenable = {then: function() {}},
options = {global: {}, actual: thenable}
function f() { jasmineUnderTest.AsyncExpectation.factory(options); }
function f() { jasmineUnderTest.Expectation.asyncFactory(options); }
expect(f).toThrowError('expectAsync is unavailable because the environment does not support promises.');
});
it('throws an Error if the argument is not a promise', function() {
jasmine.getEnv().requirePromises();
function f() {
jasmineUnderTest.AsyncExpectation.factory({actual: 'not a promise'});
jasmineUnderTest.Expectation.asyncFactory({actual: 'not a promise'});
}
expect(f).toThrowError('Expected expectAsync to be called with a promise.');
});
});
describe('#toBeResolved', function() {
it('passes if the actual is resolved', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve(),
expectation = new jasmineUnderTest.AsyncExpectation({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.toBeResolved().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: 'toBeResolved',
passed: true,
message: '',
error: undefined,
errorForStack: jasmine.any(Error),
actual: actual
});
});
});
it('fails if the actual is rejected', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.reject('AsyncExpectationSpec rejection'),
expectation = new jasmineUnderTest.AsyncExpectation({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.toBeResolved().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toBeResolved',
passed: false,
message: 'Expected a promise to be resolved.',
error: undefined,
errorForStack: jasmine.any(Error),
actual: actual
});
});
});
});
describe('#toBeRejected', function() {
it('passes if the actual is rejected', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.reject('AsyncExpectationSpec rejection'),
expectation = new jasmineUnderTest.AsyncExpectation({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.toBeRejected().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: 'toBeRejected',
passed: true,
message: '',
error: undefined,
errorForStack: jasmine.any(Error),
actual: actual
});
});
});
it('fails if the actual is resolved', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve(),
expectation = new jasmineUnderTest.AsyncExpectation({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.toBeRejected().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toBeRejected',
passed: false,
message: 'Expected a promise to be rejected.',
error: undefined,
errorForStack: jasmine.any(Error),
actual: actual
});
});
});
});
describe('#toBeResolvedTo', function() {
it('passes if the promise is resolved to the expected value', function() {
jasmine.getEnv().requirePromises();
var actual = Promise.resolve({foo: 42});
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = new jasmineUnderTest.AsyncExpectation({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.toBeResolvedTo({foo: 42}).then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: 'toBeResolvedTo',
passed: true,
message: '',
error: undefined,
errorForStack: jasmine.any(Error),
actual: actual
});
});
});
it('fails if the promise is rejected', function() {
jasmine.getEnv().requirePromises();
var actual = Promise.reject('AsyncExpectationSpec error');
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = new jasmineUnderTest.AsyncExpectation({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.toBeResolvedTo('').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toBeResolvedTo',
passed: false,
message: "Expected a promise to be resolved to '' but it was rejected.",
error: undefined,
errorForStack: jasmine.any(Error),
actual: actual
});
});
});
it('fails if the promise is resolved to a different value', function() {
jasmine.getEnv().requirePromises();
var actual = Promise.resolve({foo: 17});
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = new jasmineUnderTest.AsyncExpectation({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.toBeResolvedTo({foo: 42}).then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toBeResolvedTo',
passed: false,
message: 'Expected a promise to be resolved to Object({ foo: 42 }) but it was resolved to Object({ foo: 17 }).',
error: undefined,
errorForStack: jasmine.any(Error),
actual: actual
});
});
});
it('builds its message correctly when negated', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.AsyncExpectation.factory({
util: jasmineUnderTest.matchersUtil,
actual: Promise.resolve(true),
addExpectationResult: addExpectationResult
});
return expectation.not.toBeResolvedTo(true).then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
passed: false,
message: 'Expected a promise not to be resolved to true.'
})
);
});
});
it('supports custom equality testers', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = new jasmineUnderTest.AsyncExpectation({
util: jasmineUnderTest.matchersUtil,
customEqualityTesters: [function() { return true; }],
actual: Promise.resolve('actual'),
addExpectationResult: addExpectationResult
});
return expectation.toBeResolvedTo('expected').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(true,
jasmine.objectContaining({passed: true}));
});
});
});
describe('#not', function() {
it('converts a pass to a fail', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve(),
expectation = jasmineUnderTest.AsyncExpectation.factory({
expectation = jasmineUnderTest.Expectation.asyncFactory({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.not.toBeResolved().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
passed: false,
message: 'Expected a promise not to be resolved.'
@@ -243,14 +47,14 @@ describe('AsyncExpectation', function() {
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.reject(),
expectation = jasmineUnderTest.AsyncExpectation.factory({
expectation = jasmineUnderTest.Expectation.asyncFactory({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.not.toBeResolved().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(true,
expect(addExpectationResult).toHaveBeenCalledWith(true,
jasmine.objectContaining({
passed: true,
message: ''
@@ -262,18 +66,19 @@ describe('AsyncExpectation', function() {
it('propagates rejections from the comparison function', function() {
jasmine.getEnv().requirePromises();
var error = new Error('AsyncExpectationSpec failure');
var error = new Error('ExpectationSpec failure');
spyOn(jasmineUnderTest.AsyncExpectation.prototype, 'toBeResolved')
.and.returnValue(Promise.reject(error));
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = dummyPromise(),
expectation = new jasmineUnderTest.AsyncExpectation({
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult
});
spyOn(expectation, 'toBeResolved')
.and.returnValue(Promise.reject(error));
return expectation.toBeResolved()
.then(
function() { fail('Expected a rejection'); },
@@ -281,6 +86,121 @@ describe('AsyncExpectation', function() {
);
});
describe('#withContext', function() {
it("prepends the context to the generated failure message", function() {
jasmine.getEnv().requirePromises();
var util = {
buildFailureMessage: function() { return 'failure message'; }
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: Promise.reject('rejected'),
addExpectationResult: addExpectationResult,
util: util
});
return expectation.withContext('Some context').toBeResolved()
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: 'Some context: failure message'
}));
});
});
it("prepends the context to a custom failure message", function() {
jasmine.getEnv().requirePromises();
var util = {
buildFailureMessage: function() { return 'failure message'; }
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: Promise.reject('b'),
addExpectationResult: addExpectationResult,
util: util
});
return expectation.withContext('Some context').toBeResolvedTo('a')
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: Expected a promise to be resolved to 'a' but it was rejected."
}));
});
});
it("prepends the context to a custom failure message from a function", function() {
pending('should actually work, but no custom matchers for async yet');
jasmine.getEnv().requirePromises();
var util = {
buildFailureMessage: function() { return 'failure message'; }
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.reject(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult,
util: util
});
return expectation.withContext('Some context').toBeResolved()
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: 'Some context: msg'
}));
});
});
it("works with #not", function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult,
util: jasmineUnderTest.matchersUtil
});
return expectation.withContext('Some context').not.toBeResolved()
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: 'Some context: Expected a promise not to be resolved.'
}));
});
});
it("works with #not and a custom message", function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve('a'),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult,
util: jasmineUnderTest.matchersUtil
});
return expectation.withContext('Some context').not.toBeResolvedTo('a')
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: Expected a promise not to be resolved to 'a'."
}));
});
});
});
function dummyPromise() {
return new Promise(function(resolve, reject) {
});

View File

@@ -27,7 +27,7 @@ describe("Env", function() {
});
it('can configure specs to throw errors on expectation failures', function() {
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
spyOn(jasmineUnderTest, 'Spec');
env.it('foo', function() {});
@@ -37,7 +37,7 @@ describe("Env", function() {
});
it('can configure suites to throw errors on expectation failures', function() {
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
spyOn(jasmineUnderTest, 'Suite');
env.describe('foo', function() {});
@@ -46,6 +46,22 @@ describe("Env", function() {
}));
});
it('defaults to multiple failures for specs', function() {
spyOn(jasmineUnderTest, 'Spec');
env.it('bar', function() {});
expect(jasmineUnderTest.Spec).toHaveBeenCalledWith(jasmine.objectContaining({
throwOnExpectationFailure: false
}));
});
it('defaults to multiple failures for suites', function() {
spyOn(jasmineUnderTest, 'Suite');
env.describe('foo', function() {});
expect(jasmineUnderTest.Suite).toHaveBeenCalledWith(jasmine.objectContaining({
throwOnExpectationFailure: false
}));
});
describe('#describe', function () {
it("throws an error when given arguments", function() {
expect(function() {

View File

@@ -37,6 +37,28 @@ describe("ExceptionFormatter", function() {
expect(message).toEqual('A Classic Mistake: you got your foo in my bar');
});
it('formats unnamed exceptions with message', function() {
var unnamedError = {message: 'This is an unnamed error message.'};
var exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(unnamedError);
expect(message).toEqual('This is an unnamed error message.');
});
it('formats empty exceptions with toString format', function() {
var EmptyError = function() {};
EmptyError.prototype.toString = function() {
return '[EmptyError]';
};
var emptyError = new EmptyError();
var exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(emptyError);
expect(message).toEqual('[EmptyError] thrown');
});
it("formats thrown exceptions that aren't errors", function() {
var thrown = "crazy error",
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
@@ -74,7 +96,7 @@ describe("ExceptionFormatter", function() {
);
});
it("filters Jamine stack frames from Webkit style traces", function() {
it("filters Jasmine 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' +

View File

@@ -0,0 +1,113 @@
describe('ExpectationFilterChain', function() {
describe('#addFilter', function() {
it('returns a new filter chain with the added filter', function() {
var first = jasmine.createSpy('first'),
second = jasmine.createSpy('second'),
orig = new jasmineUnderTest.ExpectationFilterChain({
modifyFailureMessage: first
}),
added = orig.addFilter({selectComparisonFunc: second});
added.modifyFailureMessage();
expect(first).toHaveBeenCalled();
added.selectComparisonFunc();
expect(second).toHaveBeenCalled();
});
it('does not modify the original filter chain', function() {
var orig = new jasmineUnderTest.ExpectationFilterChain({}),
f = jasmine.createSpy('f');
orig.addFilter({selectComparisonFunc: f});
orig.selectComparisonFunc();
expect(f).not.toHaveBeenCalled();
});
});
describe('#selectComparisonFunc', function() {
describe('When no filters have #selectComparisonFunc', function() {
it('returns undefined', function() {
var chain = new jasmineUnderTest.ExpectationFilterChain();
chain.addFilter({});
expect(chain.selectComparisonFunc()).toBeUndefined();
});
});
describe('When some filters have #selectComparisonFunc', function() {
it('calls the first filter that has #selectComparisonFunc', function() {
var first = jasmine.createSpy('first').and.returnValue('first'),
second = jasmine.createSpy('second').and.returnValue('second'),
chain = new jasmineUnderTest.ExpectationFilterChain()
.addFilter({selectComparisonFunc: first})
.addFilter({selectComparisonFunc: second}),
matcher = {},
result;
result = chain.selectComparisonFunc(matcher);
expect(first).toHaveBeenCalledWith(matcher);
expect(second).not.toHaveBeenCalled();
expect(result).toEqual('first');
});
});
});
describe('#buildFailureMessage', function() {
describe('When no filters have #buildFailureMessage', function() {
it('returns undefined', function() {
var chain = new jasmineUnderTest.ExpectationFilterChain();
chain.addFilter({});
expect(chain.buildFailureMessage()).toBeUndefined();
});
});
describe('When some filters have #buildFailureMessage', function() {
it('calls the first filter that has #buildFailureMessage', function() {
var first = jasmine.createSpy('first').and.returnValue('first'),
second = jasmine.createSpy('second').and.returnValue('second'),
chain = new jasmineUnderTest.ExpectationFilterChain()
.addFilter({buildFailureMessage: first})
.addFilter({buildFailureMessage: second}),
matcherResult = {pass: false},
matcherName = 'foo',
args = [],
util = {},
result;
result = chain.buildFailureMessage(matcherResult, matcherName, args, util);
expect(first).toHaveBeenCalledWith(matcherResult, matcherName, args, util);
expect(second).not.toHaveBeenCalled();
expect(result).toEqual('first');
});
});
});
describe('#modifyFailureMessage', function() {
describe('When no filters have #modifyFailureMessage', function() {
it('returns the original message', function() {
var chain = new jasmineUnderTest.ExpectationFilterChain();
chain.addFilter({});
expect(chain.modifyFailureMessage('msg')).toEqual('msg');
});
});
describe('When some filters have #modifyFailureMessage', function() {
it('calls the first filter that has #modifyFailureMessage', function() {
var first = jasmine.createSpy('first').and.returnValue('first'),
second = jasmine.createSpy('second').and.returnValue('second'),
chain = new jasmineUnderTest.ExpectationFilterChain()
.addFilter({modifyFailureMessage: first})
.addFilter({modifyFailureMessage: second}),
result;
result = chain.modifyFailureMessage('original');
expect(first).toHaveBeenCalledWith('original');
expect(second).not.toHaveBeenCalled();
expect(result).toEqual('first');
});
});
});
});

View File

@@ -6,7 +6,7 @@ describe("Expectation", function() {
},
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers
});
@@ -22,31 +22,25 @@ describe("Expectation", function() {
jasmineUnderTest.Expectation.addCoreMatchers(coreMatchers);
expectation = new jasmineUnderTest.Expectation({});
expectation = jasmineUnderTest.Expectation.factory({});
expect(expectation.toQuux).toBeDefined();
});
it("Factory builds an expectation/negative expectation", function() {
var builtExpectation = jasmineUnderTest.Expectation.Factory();
expect(builtExpectation instanceof jasmineUnderTest.Expectation).toBe(true);
expect(builtExpectation.not instanceof jasmineUnderTest.Expectation).toBe(true);
expect(builtExpectation.not.isNot).toBe(true);
});
it("wraps matchers's compare functions, passing in matcher dependencies", function() {
var fakeCompare = function() { return { pass: true }; },
matcherFactory = jasmine.createSpy("matcher").and.returnValue({ compare: fakeCompare }),
matchers = {
toFoo: matcherFactory
},
util = {},
util = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
customEqualityTesters = ['a'],
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
util: util,
customMatchers: matchers,
customEqualityTesters: customEqualityTesters,
@@ -74,7 +68,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
util: util,
customMatchers: matchers,
actual: "an actual",
@@ -100,7 +94,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: util,
actual: "an actual",
@@ -115,7 +109,8 @@ describe("Expectation", function() {
message: "",
error: undefined,
expected: "hello",
actual: "an actual"
actual: "an actual",
errorForStack: undefined
});
});
@@ -133,7 +128,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: util,
actual: "an actual",
@@ -148,7 +143,8 @@ describe("Expectation", function() {
expected: "hello",
actual: "an actual",
message: "",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -168,7 +164,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
@@ -182,7 +178,8 @@ describe("Expectation", function() {
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -202,7 +199,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult
@@ -216,7 +213,8 @@ describe("Expectation", function() {
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -235,12 +233,11 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
@@ -250,7 +247,8 @@ describe("Expectation", function() {
message: "",
error: undefined,
expected: "hello",
actual: actual
actual: actual,
errorForStack: undefined
});
});
@@ -269,13 +267,12 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
util: util,
addExpectationResult: addExpectationResult,
isNot: true
});
}).not;
expectation.toFoo("hello");
@@ -285,7 +282,8 @@ describe("Expectation", function() {
expected: "hello",
actual: actual,
message: "default message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -306,12 +304,11 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
@@ -321,7 +318,8 @@ describe("Expectation", function() {
expected: "hello",
actual: actual,
message: "I am a custom message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -338,12 +336,11 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
@@ -353,7 +350,8 @@ describe("Expectation", function() {
expected: "hello",
actual: actual,
message: "",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -375,12 +373,11 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
}).not;
expectation.toFoo("hello");
@@ -390,10 +387,11 @@ describe("Expectation", function() {
expected: "hello",
actual: actual,
message: "I'm a custom message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
it("reports a custom error message to the spec", function() {
var customError = new Error("I am a custom error");
var matchers = {
@@ -412,7 +410,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
@@ -426,9 +424,222 @@ describe("Expectation", function() {
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: customError
error: customError,
errorForStack: undefined
});
});
it("reports a custom message to the spec when a 'not' comparison fails", function() {
var customError = new Error("I am a custom error");
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: "I am a custom message",
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: customError,
errorForStack: undefined
});
});
it("reports a custom message func to the spec when a 'not' comparison fails", function() {
var customError = new Error("I am a custom error");
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: function() { return "I am a custom message"; },
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: customError,
errorForStack: undefined
});
});
describe("#withContext", function() {
it("prepends the context to the generated failure message", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: false }; }
};
}
},
util = {
buildFailureMessage: function() { return "failure message"; }
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: util,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: failure message"
})
);
});
it("prepends the context to a custom failure message", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: false, message: "msg" }; }
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: msg"
})
);
});
it("prepends the context to a custom failure message from a function", function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: false,
message: function() { return "msg"; }
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: msg"
})
);
});
it("works with #not", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; }
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: jasmineUnderTest.matchersUtil,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").not.toFoo();
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: Expected 'an actual' not to foo."
})
);
});
it("works with #not and a custom message", function() {
var customError = new Error("I am a custom error");
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: function() { return "I am a custom message"; },
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").not.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: I am a custom message",
})
);
});
});
});

View File

@@ -101,6 +101,7 @@ describe("GlobalErrors", function() {
addedListener(new Error('bar'));
expect(handler).toHaveBeenCalledWith(new Error('bar'));
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe('Uncaught exception: Error: bar');
errors.uninstall();
@@ -127,10 +128,11 @@ describe("GlobalErrors", function() {
errors.pushListener(handler);
var addedListener = fakeGlobal.process.on.calls.argsFor(0)[1];
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
addedListener(new Error('bar'));
expect(handler).toHaveBeenCalledWith(new Error('bar'));
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe('Unhandled promise rejection: Error: bar');
errors.uninstall();

View File

@@ -209,7 +209,7 @@ describe("JsApiReporter", function() {
expect(reporter.suiteResults(1, 1)).toEqual([suiteResult2]);
});
it("returns nothing for out of bounds indicies", function() {
it("returns nothing for out of bounds indices", function() {
expect(reporter.suiteResults(0, 3)).toEqual([suiteResult1, suiteResult2]);
expect(reporter.suiteResults(2, 3)).toEqual([]);
});

View File

@@ -23,7 +23,7 @@ describe("jasmineUnderTest.pp", function () {
expect(jasmineUnderTest.pp(set)).toEqual("Set( 1, 2 )");
});
it("should truncate sets with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
it("should truncate sets with more elements than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
jasmine.getEnv().requireFunctioningSets();
var originalMaxSize = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
@@ -48,7 +48,7 @@ describe("jasmineUnderTest.pp", function () {
expect(jasmineUnderTest.pp(map)).toEqual("Map( [ 1, 2 ] )");
});
it("should truncate maps with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
it("should truncate maps with more elements than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
jasmine.getEnv().requireFunctioningMaps();
var originalMaxSize = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
@@ -132,6 +132,10 @@ describe("jasmineUnderTest.pp", function () {
}, bar: [1, 2, 3]})).toEqual("Object({ foo: Function, bar: [ 1, 2, 3 ] })");
});
it("should stringify objects that almost look like DOM nodes", function() {
expect(jasmineUnderTest.pp({nodeType: 1})).toEqual("Object({ nodeType: 1 })");
});
it("should truncate objects with too many keys", function () {
var originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
var long = {a: 1, b: 2, c: 3};

View File

@@ -207,7 +207,8 @@ describe("Spec", function() {
failedExpectations: [],
passedExpectations: [],
deprecationWarnings: [],
pendingReason: ''
pendingReason: '',
duration: null,
}, 'things');
});
@@ -242,6 +243,22 @@ describe("Spec", function() {
expect(done).toHaveBeenCalledWith(jasmine.any(jasmineUnderTest.StopExecutionError));
});
it("should report the duration of the test", function() {
var done = jasmine.createSpy('done callback'),
timer = jasmine.createSpyObj('timer', {'start': null, elapsed: 77000}),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy("spec body")},
catchExceptions: function() { return false; },
resultCallback: function() {},
queueRunnerFactory: function(attrs) {
attrs.onComplete();
},
timer: timer,
});
spec.execute(done);
expect(spec.result.duration).toBe(77000);
});
it("#status returns passing by default", function() {
var spec = new jasmineUnderTest.Spec({queueableFn: { fn: jasmine.createSpy("spec body")} });
expect(spec.status()).toBe('passed');

View File

@@ -183,7 +183,7 @@ describe('Spies', 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.');
expect(function() { spy('baz', {qux: 42}); }).toThrowError('Spy \'foo\' received a call with arguments [ \'baz\', Object({ qux: 42 }) ] but all configured strategies specify other arguments.');
});
});
});

View File

@@ -111,6 +111,19 @@ describe("Suite", function() {
expect(suite.getResult().failedExpectations).toEqual([]);
});
it("calls timer to compute duration", function(){
var env = new jasmineUnderTest.Env(),
suite = new jasmineUnderTest.Suite({
env: env,
id: 456,
description: "I am a suite",
timer: jasmine.createSpyObj('timer', {'start': null, elapsed: 77000}),
});
suite.startTimer();
suite.endTimer();
expect(suite.getResult().duration).toEqual(77000);
});
describe('#sharedUserContext', function() {
beforeEach(function() {
this.suite = new jasmineUnderTest.Suite({});

View File

@@ -31,6 +31,105 @@ describe("jasmineUnderTest.util", function() {
});
});
describe("promise utils", function () {
var mockNativePromise,
mockPromiseLikeObject;
var mockPromiseLike = function () {this.then = function () {};};
beforeEach(function () {
jasmine.getEnv().requirePromises();
mockNativePromise = new Promise(function (res, rej) {});
mockPromiseLikeObject = new mockPromiseLike();
});
describe("isPromise", function () {
it("should return true when passed a native promise", function () {
expect(jasmineUnderTest.isPromise(mockNativePromise)).toBe(true);
});
it("should return false for promise like objects", function () {
expect(jasmineUnderTest.isPromise(mockPromiseLikeObject)).toBe(false);
});
it("should return false for strings", function () {
expect(jasmineUnderTest.isPromise("hello")).toBe(false);
});
it("should return false for numbers", function () {
expect(jasmineUnderTest.isPromise(3)).toBe(false);
});
it("should return false for null", function () {
expect(jasmineUnderTest.isPromise(null)).toBe(false);
});
it("should return false for undefined", function () {
expect(jasmineUnderTest.isPromise(undefined)).toBe(false);
});
it("should return false for arrays", function () {
expect(jasmineUnderTest.isPromise([])).toBe(false);
});
it("should return false for objects", function () {
expect(jasmineUnderTest.isPromise({})).toBe(false);
});
it("should return false for boolean values", function () {
expect(jasmineUnderTest.isPromise(true)).toBe(false);
});
});
describe("isPromiseLike", function () {
it("should return true when passed a native promise", function () {
expect(jasmineUnderTest.isPromiseLike(mockNativePromise)).toBe(true);
});
it("should return true for promise like objects", function () {
expect(jasmineUnderTest.isPromiseLike(mockPromiseLikeObject)).toBe(true);
});
it("should return false if then is not a function", function () {
expect(jasmineUnderTest.isPromiseLike({then:{its:"Not a function :O"}})).toBe(false);
});
it("should return false for strings", function () {
expect(jasmineUnderTest.isPromiseLike("hello")).toBe(false);
});
it("should return false for numbers", function () {
expect(jasmineUnderTest.isPromiseLike(3)).toBe(false);
});
it("should return false for null", function () {
expect(jasmineUnderTest.isPromiseLike(null)).toBe(false);
});
it("should return false for undefined", function () {
expect(jasmineUnderTest.isPromiseLike(undefined)).toBe(false);
});
it("should return false for arrays", function () {
expect(jasmineUnderTest.isPromiseLike([])).toBe(false);
});
it("should return false for objects", function () {
expect(jasmineUnderTest.isPromiseLike({})).toBe(false);
});
it("should return false for boolean values", function () {
expect(jasmineUnderTest.isPromiseLike(true)).toBe(false);
});
});
});
describe("isUndefined", function() {
it("reports if a variable is defined", function() {
var a;

30
spec/core/baseSpec.js Normal file
View File

@@ -0,0 +1,30 @@
describe('base helpers', function() {
describe('isError_', function() {
it("correctly handles WebSocket events", function(done) {
if (typeof jasmine.getGlobal().WebSocket === 'undefined') {
done();
return;
}
var obj = (function() {
var sock = new WebSocket('ws://localhost');
var event;
sock.onerror = function(e) {
event = e
};
return function() { return event };
})();
var left = 20;
var int = setInterval(function() {
if (obj() || left === 0) {
var result = jasmineUnderTest.isError_(obj());
expect(result).toBe(false);
done();
} else {
left--;
}
}, 100);
});
});
});

View File

@@ -4,7 +4,7 @@ describe("Custom Matchers (Integration)", function() {
beforeEach(function() {
env = new jasmineUnderTest.Env();
env.randomizeTests(false);
env.configure({random: false});
});
it("allows adding more matchers local to a spec", function(done) {

View File

@@ -3,7 +3,7 @@ describe('Custom Spy Strategies (Integration)', function() {
beforeEach(function() {
env = new jasmineUnderTest.Env();
env.randomizeTests(false);
env.configure({random: false});
});
it('allows adding more strategies local to a suite', function(done) {

View File

@@ -17,7 +17,7 @@ describe("Env integration", function() {
};
env.addReporter({ jasmineDone: assertions});
env.randomizeTests(false);
env.configure({random: false});
env.describe("A Suite", function() {
env.it("with a spec", function() {
@@ -46,7 +46,7 @@ describe("Env integration", function() {
};
env.addReporter({ jasmineDone: assertions });
env.randomizeTests(false);
env.configure({random: false});
env.describe("Outer suite", function() {
env.it("an outer spec", function() {
@@ -81,7 +81,7 @@ describe("Env integration", function() {
};
env.addReporter({ jasmineDone: assertions });
env.randomizeTests(false);
env.configure({random: false});
env.describe("Outer suite", function() {
@@ -200,7 +200,7 @@ describe("Env integration", function() {
var env = new jasmineUnderTest.Env();
env.addReporter({jasmineDone: done});
env.randomizeTests(false);
env.configure({random: false});
env.describe("tests", function() {
var firstTimeThrough = true, firstSpecContext, secondSpecContext;
@@ -783,9 +783,11 @@ describe("Env integration", function() {
});
});
env.specFilter = function(spec) {
return /^first suite/.test(spec.getFullName());
};
env.configure({
specFilter: function(spec) {
return /^first suite/.test(spec.getFullName());
}
});
env.execute();
});
@@ -953,7 +955,7 @@ describe("Env integration", function() {
};
env.addReporter({ jasmineDone: assertions });
env.randomizeTests(false);
env.configure({random: false});
env.describe("tests", function() {
env.it("test with mock clock", function() {
@@ -1434,6 +1436,9 @@ describe("Env integration", function() {
status: 'pending'
}));
var suiteDone = reporter.suiteDone.calls.argsFor(0)[0];
expect(typeof suiteDone.duration).toBe('number');
var suiteResult = reporter.suiteStarted.calls.argsFor(0)[0];
expect(suiteResult.description).toEqual("A Suite");
@@ -1476,8 +1481,7 @@ describe("Env integration", function() {
"specStarted",
"specDone"
]);
env.randomizeTests(true);
env.seed('123456');
env.configure({random: true, seed: '123456'});
reporter.jasmineDone.and.callFake(function(doneArg) {
expect(reporter.jasmineStarted).toHaveBeenCalled();
@@ -1491,7 +1495,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(true);
env.configure({random: true});
env.execute();
});
@@ -1662,7 +1666,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(false);
env.configure({random: false});
env.describe("testing custom equality testers", function() {
env.it("with a custom tester", function() {
@@ -1698,7 +1702,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(false);
env.configure({random: false});
env.describe("testing custom equality testers", function() {
env.beforeAll(function() { env.addCustomEqualityTester(function(a, b) { return true; }); });
@@ -1739,7 +1743,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(false);
env.configure({random: false});
env.describe("testing custom equality testers", function() {
env.it("with a custom tester", function() {
@@ -1792,7 +1796,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(false);
env.configure({random: false});
env.describe("testing custom equality testers", function() {
env.beforeAll(function() { env.addCustomEqualityTester(function(a, b) { return true; })});
@@ -1941,10 +1945,10 @@ describe("Env integration", function() {
reporter.jasmineDone.and.callFake(function() {
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('async suite', [
/^(((Uncaught )?Error: suite( thrown)?)|(suite thrown))$/
/^(((Uncaught )?(exception: )?Error: suite( thrown)?)|(suite thrown))$/
]);
expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite async spec', [
/^(((Uncaught )?Error: spec( thrown)?)|(spec thrown))$/
/^(((Uncaught )?(exception: )?Error: spec( thrown)?)|(spec thrown))$/
]);
done();
});
@@ -2045,6 +2049,7 @@ describe("Env integration", function() {
passed: false,
globalErrorType: 'load',
message: 'Uncaught SyntaxError: Unexpected end of input',
stack: 'a stack',
filename: 'borkenSpec.js',
lineno: 42
},
@@ -2052,6 +2057,7 @@ describe("Env integration", function() {
passed: false,
globalErrorType: 'load',
message: 'Uncaught Error: ENOCHEESE',
stack: undefined,
filename: undefined,
lineno: undefined
}
@@ -2061,7 +2067,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
global.onerror('Uncaught SyntaxError: Unexpected end of input', 'borkenSpec.js', 42);
global.onerror('Uncaught SyntaxError: Unexpected end of input', 'borkenSpec.js', 42, undefined, {stack: 'a stack'});
global.onerror('Uncaught Error: ENOCHEESE');
env.execute();
@@ -2311,7 +2317,7 @@ describe("Env integration", function() {
var env = new jasmineUnderTest.Env(),
reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']);
// prevent deprecation from being desplayed
// prevent deprecation from being displayed
spyOn(console, "error");
reporter.jasmineDone.and.callFake(function(result) {
@@ -2363,7 +2369,7 @@ describe("Env integration", function() {
try { throw new Error('suite level deprecation') } catch (err) { suiteLevelError = err; }
try { throw new Error('spec level deprecation') } catch (err) { specLevelError = err; }
// prevent deprecation from being desplayed
// prevent deprecation from being displayed
spyOn(console, "error");
reporter.jasmineDone.and.callFake(function(result) {

View File

@@ -4,7 +4,7 @@ describe("spec running", function () {
beforeEach(function() {
jasmine.getEnv().registerIntegrationMatchers();
env = new jasmineUnderTest.Env();
env.randomizeTests(false);
env.configure({random: false});
});
it('should assign spec ids sequentially', function() {
@@ -740,8 +740,7 @@ describe("spec running", function () {
it("should run the tests in a consistent order when a seed is supplied", function(done) {
var actions = [];
env.seed('123456');
env.randomizeTests(true);
env.configure({random: true, seed: '123456'});
env.beforeEach(function () {
actions.push('topSuite beforeEach');
@@ -865,7 +864,7 @@ describe("spec running", function () {
});
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
var assertions = function() {
expect(actions).toEqual([
@@ -900,7 +899,7 @@ describe("spec running", function () {
});
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
var assertions = function() {
expect(actions).toEqual([
@@ -932,6 +931,89 @@ describe("spec running", function () {
});
});
env.configure({oneFailurePerSpec: true});
var assertions = function() {
expect(actions).toEqual([
'beforeEach',
'afterEach'
]);
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
it("skips to cleanup functions after an error with deprecations", function(done) {
var actions = [];
spyOn(env, 'deprecated');
env.describe('Something', function() {
env.beforeEach(function() {
actions.push('outer beforeEach');
throw new Error("error");
});
env.afterEach(function() {
actions.push('outer afterEach');
});
env.describe('Inner', function() {
env.beforeEach(function() {
actions.push('inner beforeEach');
});
env.afterEach(function() {
actions.push('inner afterEach');
});
env.it('does it' , function() {
actions.push('inner it');
});
});
});
env.throwOnExpectationFailure(true);
var assertions = function() {
expect(actions).toEqual([
'outer beforeEach',
'inner afterEach',
'outer afterEach'
]);
expect(env.deprecated).toHaveBeenCalled();
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
it("skips to cleanup functions after done.fail is called with deprecations", function(done) {
var actions = [];
spyOn(env, 'deprecated');
env.describe('Something', function() {
env.beforeEach(function(done) {
actions.push('beforeEach');
done.fail('error');
actions.push('after done.fail');
});
env.afterEach(function() {
actions.push('afterEach');
});
env.it('does it' , function() {
actions.push('it');
});
});
env.throwOnExpectationFailure(true);
var assertions = function() {
@@ -939,6 +1021,42 @@ describe("spec running", function () {
'beforeEach',
'afterEach'
]);
expect(env.deprecated).toHaveBeenCalled();
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
it("skips to cleanup functions when an async function times out with deprecations", function(done) {
var actions = [];
spyOn(env, 'deprecated');
env.describe('Something', function() {
env.beforeEach(function(innerDone) {
actions.push('beforeEach');
}, 1);
env.afterEach(function() {
actions.push('afterEach');
});
env.it('does it' , function() {
actions.push('it');
});
});
env.throwOnExpectationFailure(true);
var assertions = function() {
expect(actions).toEqual([
'beforeEach',
'afterEach'
]);
expect(env.deprecated).toHaveBeenCalled();
done();
};
@@ -965,8 +1083,7 @@ describe("spec running", function () {
});
});
env.randomizeTests(false);
env.stopOnSpecFailure(true);
env.configure({random: false, failFast: true});
var assertions = function() {
expect(actions).toEqual(['fails']);
@@ -976,5 +1093,36 @@ describe("spec running", function () {
env.addReporter({ jasmineDone: assertions });
env.execute();
});
it("does not run further specs when one fails when configured with deprecated option", function(done) {
var actions = [];
spyOn(env, 'deprecated');
env.describe('wrapper', function() {
env.it('fails', function() {
actions.push('fails');
env.expect(1).toBe(2);
});
});
env.describe('holder', function() {
env.it('does not run', function() {
actions.push('does not run');
});
});
env.configure({random: false});
env.stopOnSpecFailure(true);
var assertions = function() {
expect(actions).toEqual(['fails']);
expect(env.deprecated).toHaveBeenCalled();
done();
};
env.addReporter({ jasmineDone: assertions });
env.execute();
});
});
});

View File

@@ -0,0 +1,23 @@
describe('toBeRejected', function() {
it('passes if the actual is rejected', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejected(jasmineUnderTest.matchersUtil),
actual = Promise.reject('AsyncExpectationSpec rejection');
return matcher.compare(actual).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
it('fails if the actual is resolved', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejected(jasmineUnderTest.matchersUtil),
actual = Promise.resolve();
return matcher.compare(actual).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: false}));
});
});
});

View File

@@ -0,0 +1,63 @@
describe('#toBeRejectedWith', function () {
it('should return true if the promise is rejected with the expected value', function () {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil),
actual = Promise.reject({error: 'PEBCAK'});
return matcher.compare(actual, {error: 'PEBCAK'}).then(function (result) {
expect(result).toEqual(jasmine.objectContaining({ pass: true }));
});
});
it('should fail if the promise resolves', function () {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil),
actual = Promise.resolve();
return matcher.compare(actual, '').then(function (result) {
expect(result).toEqual(jasmine.objectContaining({ pass: false }));
});
});
it('should fail if the promise is rejected with a different value', function () {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil),
actual = Promise.reject('A Bad Apple');
return matcher.compare(actual, 'Some Cool Thing').then(function (result) {
expect(result).toEqual(jasmine.objectContaining({
pass: false,
message: "Expected a promise to be rejected with 'Some Cool Thing' but it was rejected with 'A Bad Apple'.",
}));
});
});
it('should build its error correctly when negated', function () {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil),
actual = Promise.reject(true);
return matcher.compare(actual, true).then(function (result) {
expect(result).toEqual(jasmine.objectContaining({
pass: true,
message: 'Expected a promise not to be rejected with true.'
}));
});
});
it('should support custom equality testers', function () {
jasmine.getEnv().requirePromises();
var customEqualityTesters = [function() { return true; }],
matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil, customEqualityTesters),
actual = Promise.reject('actual');
return matcher.compare(actual, 'expected').then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
});

View File

@@ -0,0 +1,23 @@
describe('toBeResolved', function() {
it('passes if the actual is resolved', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolved(jasmineUnderTest.matchersUtil),
actual = Promise.resolve();
return matcher.compare(actual).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
it('fails if the actual is rejected', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolved(jasmineUnderTest.matchersUtil),
actual = Promise.reject('AsyncExpectationSpec rejection');
return matcher.compare(actual).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: false}));
});
});
});

View File

@@ -0,0 +1,66 @@
describe('#toBeResolvedTo', function() {
it('passes if the promise is resolved to the expected value', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil),
actual = Promise.resolve({foo: 42});
return matcher.compare(actual, {foo: 42}).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
it('fails if the promise is rejected', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil),
actual = Promise.reject('AsyncExpectationSpec error');
return matcher.compare(actual, '').then(function(result) {
expect(result).toEqual(jasmine.objectContaining({
pass: false,
message: "Expected a promise to be resolved to '' but it was rejected.",
}));
});
});
it('fails if the promise is resolved to a different value', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil),
actual = Promise.resolve({foo: 17});
return matcher.compare(actual, {foo: 42}).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({
pass: false,
message: 'Expected a promise to be resolved to Object({ foo: 42 }) but it was resolved to Object({ foo: 17 }).',
}));
});
});
it('builds its message correctly when negated', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil),
actual = Promise.resolve(true);
return matcher.compare(actual, true).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({
pass: true,
message: 'Expected a promise not to be resolved to true.'
}));
});
});
it('supports custom equality testers', function() {
jasmine.getEnv().requirePromises();
var customEqualityTesters = [function() { return true; }],
matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil, customEqualityTesters),
actual = Promise.resolve('actual');
return matcher.compare(actual, 'expected').then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
});

View File

@@ -1,17 +1,56 @@
describe("toBe", function() {
it("passes when actual === expected", function() {
var matcher = jasmineUnderTest.matchers.toBe(),
it("passes with no message when actual === expected", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result;
result = matcher.compare(1, 1);
expect(result.pass).toBe(true);
});
it("fails when actual !== expected", function() {
var matcher = jasmineUnderTest.matchers.toBe(),
it("passes with a custom message when expected is an array", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result,
array = [1];
result = matcher.compare(array, array);
expect(result.pass).toBe(true);
expect(result.message).toBe("Expected [ 1 ] not to be [ 1 ]. Tip: To check for deep equality, use .toEqual() instead of .toBe().")
});
it("passes with a custom message when expected is an object", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result,
obj = {foo: "bar"};
result = matcher.compare(obj, obj);
expect(result.pass).toBe(true);
expect(result.message).toBe("Expected Object({ foo: 'bar' }) not to be Object({ foo: 'bar' }). Tip: To check for deep equality, use .toEqual() instead of .toBe().")
});
it("fails with no message when actual !== expected", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result;
result = matcher.compare(1, 2);
expect(result.pass).toBe(false);
expect(result.message).toBeUndefined();
});
it("fails with a custom message when expected is an array", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result;
result = matcher.compare([1], [1]);
expect(result.pass).toBe(false);
expect(result.message).toBe("Expected [ 1 ] to be [ 1 ]. Tip: To check for deep equality, use .toEqual() instead of .toBe().")
});
it("fails with a custom message when expected is an object", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result;
result = matcher.compare({foo: "bar"}, {foo: "bar"});
expect(result.pass).toBe(false);
expect(result.message).toBe("Expected Object({ foo: 'bar' }) to be Object({ foo: 'bar' }). Tip: To check for deep equality, use .toEqual() instead of .toBe().")
});
});

View File

@@ -575,23 +575,15 @@ describe("toEqual", function() {
return typeof document === 'undefined'
}
beforeEach(function(done) {
beforeEach(function() {
this.nonBrowser = isNotRunningInBrowser();
if (this.nonBrowser) {
var jsdom = require('jsdom');
var self = this;
jsdom.env('', function(err, win) {
if (err) {
done.fail(err);
} else {
jasmineUnderTest.getGlobal().Node = win.Node;
self.doc = win.document;
done();
}
});
var JSDOM = require('jsdom').JSDOM;
var dom = new JSDOM();
jasmineUnderTest.getGlobal().Node = dom.window.Node;
this.doc = dom.window.document;
} else {
this.doc = document;
done();
}
});
@@ -624,6 +616,99 @@ describe("toEqual", function() {
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("reports mismatches between SVG nodes", function () {
var nodeA = this.doc.createElementNS('http://www.w3.org/2000/svg', 'svg'),
nodeB = this.doc.createElementNS('http://www.w3.org/2000/svg', 'svg');
nodeA.setAttribute('height', '50');
nodeB.setAttribute('height', '30');
var rect = this.doc.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('width', '50');
nodeA.appendChild(rect);
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <svg height="50">...</svg> to equal <svg height="30">.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("reports whole DOM node when attribute contains > character", function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.setAttribute('thing', '>>>');
nodeB.setAttribute('thing', 'bar');
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div thing=">>>"> to equal <div thing="bar">.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it('reports no content when DOM node has multiple empty text nodes', function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.appendChild(this.doc.createTextNode(''));
nodeA.appendChild(this.doc.createTextNode(''));
nodeA.appendChild(this.doc.createTextNode(''));
nodeA.appendChild(this.doc.createTextNode(''));
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div> to equal <div>.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it('reports content when DOM node has non empty text node', function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.appendChild(this.doc.createTextNode('Hello Jasmine!'));
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div>...</div> to equal <div>.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it('reports empty DOM attributes', function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.setAttribute('contenteditable', '');
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div contenteditable> to equal <div>.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it('reports 0 attr value as non empty DOM attribute', function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.setAttribute('contenteditable', 0);
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div contenteditable="0"> to equal <div>.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("reports mismatches between a DOM node and a bare Object", function() {
var actual = {a: this.doc.createElement('div')},
expected = {a: {}},

View File

@@ -1,5 +1,5 @@
describe('toHaveClass', function() {
beforeEach(function(done) {
beforeEach(function() {
this.createElementWithClassName = function(className) {
var el = this.doc.createElement('div');
el.className = className;
@@ -8,18 +8,10 @@ describe('toHaveClass', function() {
if (typeof document !== 'undefined') {
this.doc = document;
done();
} else {
var jsdom = require('jsdom');
var self = this;
jsdom.env('', function(err, win) {
if (err) {
done.fail(err);
} else {
self.doc = win.document;
done();
}
});
var JSDOM = require('jsdom').JSDOM;
var dom = new JSDOM();
this.doc = dom.window.document;
}
});

View File

@@ -1,8 +1,6 @@
(function() {
var path = require("path"),
fs = require("fs");
var glob = require("glob");
fg = require("fast-glob");
var jasmineUnderTestRequire = require(path.join(__dirname, "../../src/core/requireCore.js"));
@@ -16,12 +14,12 @@
}
function getSourceFiles() {
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) {
require(resolvedFile);
});
var src_files = ['core/**/*.js', 'version.js'].map(function(file) {
return path.join(__dirname, "../../", 'src/', file);
});
fg.sync(src_files).forEach(function(resolvedFile) {
require(resolvedFile);
});
}

View File

@@ -518,7 +518,7 @@ describe("HtmlReporter", function() {
}
});
env.stopOnSpecFailure(true);
env.configure({failFast: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -574,7 +574,7 @@ describe("HtmlReporter", function() {
}
});
env.stopOnSpecFailure(true);
env.configure({failFast: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -628,7 +628,7 @@ describe("HtmlReporter", function() {
}
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -684,7 +684,7 @@ describe("HtmlReporter", function() {
}
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -713,7 +713,7 @@ describe("HtmlReporter", function() {
}
});
env.hideDisabled(false);
env.configure({hideDisabled: false});
reporter.initialize();
reporter.jasmineDone({});
@@ -738,7 +738,7 @@ describe("HtmlReporter", function() {
}
});
env.hideDisabled(true);
env.configure({hideDisabled: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -748,27 +748,24 @@ describe("HtmlReporter", function() {
it("should not display specs that have been disabled", 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); }
});
env.hideDisabled(true);
reporter.initialize();
reporter.specDone({
id: 789,
status: "excluded",
fullName: "symbols should have titles",
passedExpectations: [],
failedExpectations: []
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); }
});
env.configure({hideDisabled: true});
reporter.initialize();
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-excluded-no-display");
@@ -792,7 +789,7 @@ describe("HtmlReporter", function() {
}
});
env.randomizeTests(false);
env.configure({random: false});
reporter.initialize();
reporter.jasmineDone({});
@@ -817,7 +814,7 @@ describe("HtmlReporter", function() {
}
});
env.randomizeTests(true);
env.configure({random: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -844,7 +841,7 @@ describe("HtmlReporter", function() {
}
});
env.randomizeTests(false);
env.configure({random: false});
reporter.initialize();
reporter.jasmineDone({});
@@ -873,7 +870,7 @@ describe("HtmlReporter", function() {
}
});
env.randomizeTests(true);
env.configure({random: true});
reporter.initialize();
reporter.jasmineDone({});

View File

@@ -28,7 +28,7 @@ describe('Printing a big object', function(){
return object;
}
it('takes a resonable amount of time', function(){
it('takes a reasonable amount of time', function(){
bigObject = generateObject(0);
expect(jasmineUnderTest.pp(bigObject)).toMatch(/cycle/);
});

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Jasmine suite</title>
<link rel="shortcut icon" href="images/jasmine_favicon.png" type="image/png" />
<link rel="stylesheet" href="lib/jasmine-core/jasmine.css" type="text/css" media="screen" />
<% files.forEach(function(file) { %>
<script src="<%= file %>" type="text/javascript"></script>
<% }) %>
<body>
</body>
</html>

View File

@@ -1,153 +0,0 @@
getJasmineRequireObj().AsyncExpectation = function(j$) {
var promiseForMessage = {
jasmineToString: function() { return 'a promise'; }
};
/**
* Asynchronous matchers.
* @namespace async-matchers
*/
function AsyncExpectation(options) {
var global = options.global || j$.getGlobal();
this.util = options.util || { buildFailureMessage: function() {} };
this.customEqualityTesters = options.customEqualityTesters || [];
this.addExpectationResult = options.addExpectationResult || function(){};
this.actual = options.actual;
this.isNot = options.isNot;
if (!global.Promise) {
throw new Error('expectAsync is unavailable because the environment does not support promises.');
}
if (!j$.isPromise(this.actual)) {
throw new Error('Expected expectAsync to be called with a promise.');
}
['toBeResolved', 'toBeRejected', 'toBeResolvedTo'].forEach(wrapCompare.bind(this));
}
function wrapCompare(name) {
var compare = this[name];
this[name] = function() {
var self = this;
var args = Array.prototype.slice.call(arguments);
args.unshift(this.actual);
// Capture the call stack here, before we go async, so that it will
// contain frames that are relevant to the user instead of just parts
// of Jasmine.
var errorForStack = j$.util.errorWithStack();
return compare.apply(self, args).then(function(result) {
var message;
if (self.isNot) {
result.pass = !result.pass;
}
args[0] = promiseForMessage;
message = j$.Expectation.finalizeMessage(self.util, name, self.isNot, args, result);
self.addExpectationResult(result.pass, {
matcherName: name,
passed: result.pass,
message: message,
error: undefined,
errorForStack: errorForStack,
actual: self.actual
});
});
};
}
/**
* Expect a promise to be resolved.
* @function
* @async
* @name async-matchers#toBeResolved
* @example
* await expectAsync(aPromise).toBeResolved();
* @example
* return expectAsync(aPromise).toBeResolved();
*/
AsyncExpectation.prototype.toBeResolved = function(actual) {
return actual.then(
function() { return {pass: true}; },
function() { return {pass: false}; }
);
};
/**
* Expect a promise to be rejected.
* @function
* @async
* @name async-matchers#toBeRejected
* @example
* await expectAsync(aPromise).toBeRejected();
* @example
* return expectAsync(aPromise).toBeRejected();
*/
AsyncExpectation.prototype.toBeRejected = function(actual) {
return actual.then(
function() { return {pass: false}; },
function() { return {pass: true}; }
);
};
/**
* Expect a promise to be resolved to a value equal to the expected, using deep equality comparison.
* @function
* @async
* @name async-matchers#toBeResolvedTo
* @param {Object} expected - Value that the promise is expected to resolve to
* @example
* await expectAsync(aPromise).toBeResolvedTo({prop: 'value'});
* @example
* return expectAsync(aPromise).toBeResolvedTo({prop: 'value'});
*/
AsyncExpectation.prototype.toBeResolvedTo = function(actualPromise, expectedValue) {
var self = this;
function prefix(passed) {
return 'Expected a promise ' +
(passed ? 'not ' : '') +
'to be resolved to ' + j$.pp(expectedValue);
}
return actualPromise.then(
function(actualValue) {
if (self.util.equals(actualValue, expectedValue, self.customEqualityTesters)) {
return {
pass: true,
message: prefix(true) + '.'
};
} else {
return {
pass: false,
message: prefix(false) + ' but it was resolved to ' + j$.pp(actualValue) + '.'
};
}
},
function() {
return {
pass: false,
message: prefix(false) + ' but it was rejected.'
};
}
);
};
AsyncExpectation.factory = function(options) {
var expect = new AsyncExpectation(options);
options = j$.util.clone(options);
options.isNot = true;
expect.not = new AsyncExpectation(options);
return expect;
};
return AsyncExpectation;
};

View File

@@ -66,7 +66,7 @@ getJasmineRequireObj().Clock = function() {
* The clock will be {@link Clock#install|install}ed before the function is called and {@link Clock#uninstall|uninstall}ed in a `finally` after the function completes.
* @name Clock#withMock
* @function
* @param {closure} Function The function to be called.
* @param {Function} closure The function to be called.
*/
self.withMock = function(closure) {
this.install();

View File

@@ -23,14 +23,62 @@ getJasmineRequireObj().Env = function(j$) {
var currentSpec = null;
var currentlyExecutingSuites = [];
var currentDeclarationSuite = null;
var throwOnExpectationFailure = false;
var stopOnSpecFailure = false;
var random = true;
var hidingDisabled = false;
var seed = null;
var handlingLoadErrors = true;
var hasFailures = false;
/**
* This represents the available options to configure Jasmine.
* Options that are not provided will use their default values
* @interface Configuration
*/
var config = {
/**
* Whether to randomize spec execution order
* @name Configuration#random
* @type Boolean
* @default true
*/
random: true,
/**
* Seed to use as the basis of randomization.
* Null causes the seed to be determined randomly at the start of execution.
* @name Configuration#seed
* @type function
* @default null
*/
seed: null,
/**
* Whether to stop execution of the suite after the first spec failure
* @name Configuration#failFast
* @type Boolean
* @default false
*/
failFast: false,
/**
* Whether to cause specs to only have one expectation failure.
* @name Configuration#oneFailurePerSpec
* @type Boolean
* @default false
*/
oneFailurePerSpec: false,
/**
* Function to use to filter specs
* @name Configuration#specFilter
* @type function
* @default true
*/
specFilter: function() {
return true;
},
/**
* Whether or not reporters should hide disabled specs from their output.
* Currently only supported by Jasmine's HTMLReporter
* @name Configuration#hideDisabled
* @type Boolean
* @default false
*/
hideDisabled: false
};
var currentSuite = function() {
return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
};
@@ -52,21 +100,75 @@ getJasmineRequireObj().Env = function(j$) {
if (!options.suppressLoadErrors) {
installGlobalErrors();
globalErrors.pushListener(function(message, filename, lineno) {
globalErrors.pushListener(function(message, filename, lineno, colNo, err) {
topSuite.result.failedExpectations.push({
passed: false,
globalErrorType: 'load',
message: message,
stack: err && err.stack,
filename: filename,
lineno: lineno
});
});
}
this.specFilter = function() {
return true;
/**
* Configure your jasmine environment
* @name Env#configure
* @argument {Configuration} configuration
* @function
*/
this.configure = function(configuration) {
if (configuration.specFilter) {
config.specFilter = configuration.specFilter;
}
if (configuration.hasOwnProperty('random')) {
config.random = !!configuration.random;
}
if (configuration.hasOwnProperty('seed')) {
config.seed = configuration.seed;
}
if (configuration.hasOwnProperty('failFast')) {
config.failFast = configuration.failFast;
}
if (configuration.hasOwnProperty('oneFailurePerSpec')) {
config.oneFailurePerSpec = configuration.oneFailurePerSpec;
}
if (configuration.hasOwnProperty('hideDisabled')) {
config.hideDisabled = configuration.hideDisabled;
}
};
/**
* Get the current configuration for your jasmine environment
* @name Env#configuration
* @function
* @returns {Configuration}
*/
this.configuration = function() {
var result = {};
for (var property in config) {
result[property] = config[property];
}
return result;
};
Object.defineProperty(this, 'specFilter', {
get: function() {
self.deprecated('Getting specFilter directly from Env is deprecated, please check the specFilter option from `configuration`');
return config.specFilter;
},
set: function(val) {
self.deprecated('Setting specFilter directly on Env is deprecated, please use the specFilter option in `configure`');
config.specFilter = val;
}
});
this.addSpyStrategy = function(name, fn) {
if(!currentRunnable()) {
throw new Error('Custom spy strategies must be added in a before function or a spec');
@@ -92,6 +194,7 @@ getJasmineRequireObj().Env = function(j$) {
};
j$.Expectation.addCoreMatchers(j$.matchers);
j$.Expectation.addAsyncCoreMatchers(j$.asyncMatchers);
var nextSpecId = 0;
var getNextSpecId = function() {
@@ -104,7 +207,7 @@ getJasmineRequireObj().Env = function(j$) {
};
var expectationFactory = function(actual, spec) {
return j$.Expectation.Factory({
return j$.Expectation.factory({
util: j$.matchersUtil,
customEqualityTesters: runnableResources[spec.id].customEqualityTesters,
customMatchers: runnableResources[spec.id].customMatchers,
@@ -118,7 +221,7 @@ getJasmineRequireObj().Env = function(j$) {
};
var asyncExpectationFactory = function(actual, spec) {
return j$.AsyncExpectation.factory({
return j$.Expectation.asyncFactory({
util: j$.matchersUtil,
customEqualityTesters: runnableResources[spec.id].customEqualityTesters,
actual: actual,
@@ -194,13 +297,16 @@ getJasmineRequireObj().Env = function(j$) {
* @name Env#throwOnExpectationFailure
* @function
* @param {Boolean} value Whether to throw when a expectation fails
* @deprecated Use the `oneFailurePerSpec` option with {@link Env#configure}
*/
this.throwOnExpectationFailure = function(value) {
throwOnExpectationFailure = !!value;
this.deprecated('Setting throwOnExpectationFailure directly on Env is deprecated, please use the oneFailurePerSpec option in `configure`');
this.configure({oneFailurePerSpec: !!value});
};
this.throwingExpectationFailures = function() {
return throwOnExpectationFailure;
this.deprecated('Getting throwingExpectationFailures directly from Env is deprecated, please check the oneFailurePerSpec option from `configuration`');
return config.oneFailurePerSpec;
};
/**
@@ -208,13 +314,16 @@ getJasmineRequireObj().Env = function(j$) {
* @name Env#stopOnSpecFailure
* @function
* @param {Boolean} value Whether to stop suite execution when a spec fails
* @deprecated Use the `failFast` option with {@link Env#configure}
*/
this.stopOnSpecFailure = function(value) {
stopOnSpecFailure = !!value;
this.deprecated('Setting stopOnSpecFailure directly is deprecated, please use the failFast option in `configure`');
this.configure({failFast: !!value});
};
this.stoppingOnSpecFailure = function() {
return stopOnSpecFailure;
this.deprecated('Getting stoppingOnSpecFailure directly from Env is deprecated, please check the failFast option from `configuration`');
return config.failFast;
};
/**
@@ -222,13 +331,16 @@ getJasmineRequireObj().Env = function(j$) {
* @name Env#randomizeTests
* @function
* @param {Boolean} value Whether to randomize execution order
* @deprecated Use the `random` option with {@link Env#configure}
*/
this.randomizeTests = function(value) {
random = !!value;
this.deprecated('Setting randomizeTests directly is deprecated, please use the random option in `configure`');
config.random = !!value;
};
this.randomTests = function() {
return random;
this.deprecated('Getting randomTests directly from Env is deprecated, please check the random option from `configuration`');
return config.random;
};
/**
@@ -236,16 +348,19 @@ getJasmineRequireObj().Env = function(j$) {
* @name Env#seed
* @function
* @param {Number} value The seed value
* @deprecated Use the `seed` option with {@link Env#configure}
*/
this.seed = function(value) {
this.deprecated('Setting seed directly is deprecated, please use the seed option in `configure`');
if (value) {
seed = value;
config.seed = value;
}
return seed;
return config.seed;
};
this.hidingDisabled = function(value) {
return hidingDisabled;
this.deprecated('Getting hidingDisabled directly from Env is deprecated, please check the hideDisabled option from `configuration`');
return config.hideDisabled;
};
/**
@@ -253,7 +368,8 @@ getJasmineRequireObj().Env = function(j$) {
* @function
*/
this.hideDisabled = function(value) {
hidingDisabled = !!value;
this.deprecated('Setting hideDisabled directly is deprecated, please use the hideDisabled option in `configure`');
config.hideDisabled = !!value;
};
this.deprecated = function(deprecation) {
@@ -267,9 +383,9 @@ getJasmineRequireObj().Env = function(j$) {
var queueRunnerFactory = function(options, args) {
var failFast = false;
if (options.isLeaf) {
failFast = throwOnExpectationFailure;
failFast = config.oneFailurePerSpec;
} else if (!options.isReporter) {
failFast = stopOnSpecFailure;
failFast = config.failFast;
}
options.clearStack = options.clearStack || clearStack;
options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
@@ -384,8 +500,8 @@ getJasmineRequireObj().Env = function(j$) {
}
var order = new j$.Order({
random: random,
seed: seed
random: config.random,
seed: config.seed
});
var processor = new j$.TreeProcessor({
@@ -396,6 +512,7 @@ getJasmineRequireObj().Env = function(j$) {
currentlyExecutingSuites.push(suite);
defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
reporter.suiteStarted(suite.result, next);
suite.startTimer();
},
nodeComplete: function(suite, result, next) {
if (suite !== currentSuite()) {
@@ -408,14 +525,14 @@ getJasmineRequireObj().Env = function(j$) {
if (result.status === 'failed') {
hasFailures = true;
}
suite.endTimer();
reporter.suiteDone(result, next);
},
orderChildren: function(node) {
return order.sort(node.children);
},
excludeNode: function(spec) {
return !self.specFilter(spec);
return !config.specFilter(spec);
}
});
@@ -455,7 +572,7 @@ getJasmineRequireObj().Env = function(j$) {
/**
* Information passed to the {@link Reporter#jasmineDone} event.
* @typedef JasmineDoneInfo
* @property {OverallStatus} overallStatus - The overall result of the sute: 'passed', 'failed', or 'incomplete'.
* @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'.
* @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete.
* @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.
@@ -537,6 +654,10 @@ getJasmineRequireObj().Env = function(j$) {
return spyRegistry.spyOnProperty.apply(spyRegistry, arguments);
};
this.spyOnAllFunctions = function() {
return spyRegistry.spyOnAllFunctions.apply(spyRegistry, arguments);
};
this.createSpy = function(name, originalFn) {
if (arguments.length === 1 && j$.isFunction_(name)) {
originalFn = name;
@@ -578,7 +699,7 @@ getJasmineRequireObj().Env = function(j$) {
expectationFactory: expectationFactory,
asyncExpectationFactory: asyncExpectationFactory,
expectationResultFactory: expectationResultFactory,
throwOnExpectationFailure: throwOnExpectationFailure
throwOnExpectationFailure: config.oneFailurePerSpec
});
return suite;
@@ -684,9 +805,9 @@ getJasmineRequireObj().Env = function(j$) {
fn: fn,
timeout: timeout || 0
},
throwOnExpectationFailure: throwOnExpectationFailure
throwOnExpectationFailure: config.oneFailurePerSpec,
timer: new j$.Timer(),
});
return spec;
function specResultCallback(result, next) {
@@ -832,7 +953,7 @@ getJasmineRequireObj().Env = function(j$) {
error: error && error.message ? error : null
});
if (self.throwingExpectationFailures()) {
if (config.oneFailurePerSpec) {
throw new Error(message);
}
};

View File

@@ -1,12 +1,18 @@
getJasmineRequireObj().ExceptionFormatter = function(j$) {
var ignoredProperties = ['name', 'message', 'stack', 'fileName', 'sourceURL', 'line', 'lineNumber', 'column', 'description', 'jasmineMessage'];
function ExceptionFormatter(options) {
var jasmineFile = (options && options.jasmineFile) || j$.util.jasmineFile();
this.message = function(error) {
var message = '';
if (error.name && error.message) {
if (error.jasmineMessage) {
message += error.jasmineMessage;
} else if (error.name && error.message) {
message += error.name + ': ' + error.message;
} else if (error.message) {
message += error.message;
} else {
message += error.toString() + ' thrown';
}
@@ -61,12 +67,11 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
return;
}
var ignored = ['name', 'message', 'stack', 'fileName', 'sourceURL', 'line', 'lineNumber', 'column', 'description'];
var result = {};
var empty = true;
for (var prop in error) {
if (j$.util.arrayContains(ignored, prop)) {
if (j$.util.arrayContains(ignoredProperties, prop)) {
continue;
}
result[prop] = error[prop];

View File

@@ -1,102 +1,186 @@
getJasmineRequireObj().Expectation = function() {
getJasmineRequireObj().Expectation = function(j$) {
var promiseForMessage = {
jasmineToString: function() { return 'a promise'; }
};
/**
* Matchers that come with Jasmine out of the box.
* @namespace matchers
*/
function Expectation(options) {
this.util = options.util || { buildFailureMessage: function() {} };
this.customEqualityTesters = options.customEqualityTesters || [];
this.actual = options.actual;
this.addExpectationResult = options.addExpectationResult || function(){};
this.isNot = options.isNot;
this.expector = new j$.Expector(options);
var customMatchers = options.customMatchers || {};
for (var matcherName in customMatchers) {
this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]);
this[matcherName] = wrapSyncCompare(matcherName, customMatchers[matcherName]);
}
}
Expectation.prototype.wrapCompare = function(name, matcherFactory) {
return function() {
var args = Array.prototype.slice.call(arguments, 0),
expected = args.slice(0),
message;
args.unshift(this.actual);
var matcher = matcherFactory(this.util, this.customEqualityTesters),
matcherCompare = matcher.compare;
function defaultNegativeCompare() {
var result = matcher.compare.apply(null, args);
result.pass = !result.pass;
return result;
}
if (this.isNot) {
matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
}
var result = matcherCompare.apply(null, args);
message = Expectation.finalizeMessage(this.util, name, this.isNot, args, result);
if (expected.length == 1) {
expected = expected[0];
}
// TODO: how many of these params are needed?
this.addExpectationResult(
result.pass,
{
matcherName: name,
passed: result.pass,
message: message,
error: result.error,
actual: this.actual,
expected: expected // TODO: this may need to be arrayified/sliced
}
);
};
/**
* Add some context for an {@link expect}
* @function
* @name matchers#withContext
* @param {String} message - Additional context to show when the matcher fails
* @return {matchers}
*/
Expectation.prototype.withContext = function withContext(message) {
return addFilter(this, new ContextAddingFilter(message));
};
Expectation.finalizeMessage = function(util, name, isNot, args, result) {
if (result.pass) {
return '';
} else if (result.message) {
if (Object.prototype.toString.apply(result.message) === '[object Function]') {
/**
* Invert the matcher following this {@link expect}
* @member
* @name matchers#not
* @type {matchers}
* @example
* expect(something).not.toBe(true);
*/
Object.defineProperty(Expectation.prototype, 'not', {
get: function() {
return addFilter(this, syncNegatingFilter);
}
});
/**
* Asynchronous matchers.
* @namespace async-matchers
*/
function AsyncExpectation(options) {
var global = options.global || j$.getGlobal();
this.expector = new j$.Expector(options);
if (!global.Promise) {
throw new Error('expectAsync is unavailable because the environment does not support promises.');
}
if (!j$.isPromiseLike(this.expector.actual)) {
throw new Error('Expected expectAsync to be called with a promise.');
}
}
/**
* Add some context for an {@link expectAsync}
* @function
* @name async-matchers#withContext
* @param {String} message - Additional context to show when the async matcher fails
* @return {async-matchers}
*/
AsyncExpectation.prototype.withContext = function withContext(message) {
return addFilter(this, new ContextAddingFilter(message));
};
/**
* Invert the matcher following this {@link expectAsync}
* @member
* @name async-matchers#not
* @type {async-matchers}
* @example
* await expectAsync(myPromise).not.toBeResolved();
* @example
* return expectAsync(myPromise).not.toBeResolved();
*/
Object.defineProperty(AsyncExpectation.prototype, 'not', {
get: function() {
return addFilter(this, asyncNegatingFilter);
}
});
function wrapSyncCompare(name, matcherFactory) {
return function() {
var result = this.expector.compare(name, matcherFactory, arguments);
this.expector.processResult(result);
};
}
function wrapAsyncCompare(name, matcherFactory) {
return function() {
var self = this;
// Capture the call stack here, before we go async, so that it will contain
// frames that are relevant to the user instead of just parts of Jasmine.
var errorForStack = j$.util.errorWithStack();
return this.expector.compare(name, matcherFactory, arguments).then(function(result) {
self.expector.processResult(result, errorForStack, promiseForMessage);
});
};
}
function addCoreMatchers(prototype, matchers, wrapper) {
for (var matcherName in matchers) {
var matcher = matchers[matcherName];
prototype[matcherName] = wrapper(matcherName, matcher);
}
}
function addFilter(source, filter) {
var result = Object.create(source);
result.expector = source.expector.addFilter(filter);
return result;
}
function negatedFailureMessage(result, matcherName, args, util) {
if (result.message) {
if (j$.isFunction_(result.message)) {
return result.message();
} else {
return result.message;
}
} else {
args = args.slice();
args.unshift(isNot);
args.unshift(name);
return util.buildFailureMessage.apply(null, args);
}
args = args.slice();
args.unshift(true);
args.unshift(matcherName);
return util.buildFailureMessage.apply(null, args);
}
function negate(result) {
result.pass = !result.pass;
return result;
}
var syncNegatingFilter = {
selectComparisonFunc: function(matcher) {
function defaultNegativeCompare() {
return negate(matcher.compare.apply(null, arguments));
}
return matcher.negativeCompare || defaultNegativeCompare;
},
buildFailureMessage: negatedFailureMessage
};
var asyncNegatingFilter = {
selectComparisonFunc: function(matcher) {
function defaultNegativeCompare() {
return matcher.compare.apply(this, arguments).then(negate);
}
return defaultNegativeCompare;
},
buildFailureMessage: negatedFailureMessage
};
function ContextAddingFilter(message) {
this.message = message;
}
ContextAddingFilter.prototype.modifyFailureMessage = function(msg) {
return this.message + ': ' + msg;
};
return {
factory: function(options) {
return new Expectation(options || {});
},
addCoreMatchers: function(matchers) {
addCoreMatchers(Expectation.prototype, matchers, wrapSyncCompare);
},
asyncFactory: function(options) {
return new AsyncExpectation(options || {});
},
addAsyncCoreMatchers: function(matchers) {
addCoreMatchers(AsyncExpectation.prototype, matchers, wrapAsyncCompare);
}
};
Expectation.addCoreMatchers = function(matchers) {
var prototype = Expectation.prototype;
for (var matcherName in matchers) {
var matcher = matchers[matcherName];
prototype[matcherName] = prototype.wrapCompare(matcherName, matcher);
}
};
Expectation.Factory = function(options) {
options = options || {};
var expect = new Expectation(options);
// TODO: this would be nice as its own Object - NegativeExpectation
// TODO: copy instead of mutate options
options.isNot = true;
expect.not = new Expectation(options);
return expect;
};
return Expectation;
};

View File

@@ -0,0 +1,46 @@
getJasmineRequireObj().ExpectationFilterChain = function() {
function ExpectationFilterChain(maybeFilter, prev) {
this.filter_ = maybeFilter;
this.prev_ = prev;
}
ExpectationFilterChain.prototype.addFilter = function(filter) {
return new ExpectationFilterChain(filter, this);
};
ExpectationFilterChain.prototype.selectComparisonFunc = function(matcher) {
return this.callFirst_('selectComparisonFunc', arguments).result;
};
ExpectationFilterChain.prototype.buildFailureMessage = function(result, matcherName, args, util) {
return this.callFirst_('buildFailureMessage', arguments).result;
};
ExpectationFilterChain.prototype.modifyFailureMessage = function(msg) {
var result = this.callFirst_('modifyFailureMessage', arguments).result;
return result || msg;
};
ExpectationFilterChain.prototype.callFirst_ = function(fname, args) {
var prevResult;
if (this.prev_) {
prevResult = this.prev_.callFirst_(fname, args);
if (prevResult.found) {
return prevResult;
}
}
if (this.filter_ && this.filter_[fname]) {
return {
found: true,
result: this.filter_[fname].apply(this.filter_, args)
};
}
return {found: false};
};
return ExpectationFilterChain;
};

80
src/core/Expector.js Normal file
View File

@@ -0,0 +1,80 @@
getJasmineRequireObj().Expector = function(j$) {
function Expector(options) {
this.util = options.util || { buildFailureMessage: function() {} };
this.customEqualityTesters = options.customEqualityTesters || [];
this.actual = options.actual;
this.addExpectationResult = options.addExpectationResult || function(){};
this.filters = new j$.ExpectationFilterChain();
}
Expector.prototype.instantiateMatcher = function(matcherName, matcherFactory, args) {
this.matcherName = matcherName;
this.args = Array.prototype.slice.call(args, 0);
this.expected = this.args.slice(0);
this.args.unshift(this.actual);
var matcher = matcherFactory(this.util, this.customEqualityTesters);
var comparisonFunc = this.filters.selectComparisonFunc(matcher);
return comparisonFunc || matcher.compare;
};
Expector.prototype.buildMessage = function(result) {
var self = this;
if (result.pass) {
return '';
}
var msg = this.filters.buildFailureMessage(result, this.matcherName, this.args, this.util, defaultMessage);
return this.filters.modifyFailureMessage(msg || defaultMessage());
function defaultMessage() {
if (!result.message) {
var args = self.args.slice();
args.unshift(false);
args.unshift(self.matcherName);
return self.util.buildFailureMessage.apply(null, args);
} else if (j$.isFunction_(result.message)) {
return result.message();
} else {
return result.message;
}
}
};
Expector.prototype.compare = function(matcherName, matcherFactory, args) {
var matcherCompare = this.instantiateMatcher(matcherName, matcherFactory, args);
return matcherCompare.apply(null, this.args);
};
Expector.prototype.addFilter = function(filter) {
var result = Object.create(this);
result.filters = this.filters.addFilter(filter);
return result;
};
Expector.prototype.processResult = function(result, errorForStack, actualOverride) {
this.args[0] = actualOverride || this.args[0];
var message = this.buildMessage(result);
if (this.expected.length === 1) {
this.expected = this.expected[0];
}
this.addExpectationResult(
result.pass,
{
matcherName: this.matcherName,
passed: result.pass,
message: message,
error: errorForStack ? undefined : result.error,
errorForStack: errorForStack || undefined,
actual: this.actual,
expected: this.expected // TODO: this may need to be arrayified/sliced
}
);
};
return Expector;
};

View File

@@ -14,28 +14,44 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
};
this.originalHandlers = {};
this.installOne_ = function installOne_(errorType) {
this.jasmineHandlers = {};
this.installOne_ = function installOne_(errorType, jasmineMessage) {
function taggedOnError(error) {
error.jasmineMessage = jasmineMessage + ': ' + error;
var handler = handlers[handlers.length - 1];
if (handler) {
handler(error);
} else {
throw error;
}
}
this.originalHandlers[errorType] = global.process.listeners(errorType);
this.jasmineHandlers[errorType] = taggedOnError;
global.process.removeAllListeners(errorType);
global.process.on(errorType, onerror);
global.process.on(errorType, taggedOnError);
this.uninstall = function uninstall() {
var errorTypes = Object.keys(this.originalHandlers);
for (var iType = 0; iType < errorTypes.length; iType++) {
var errorType = errorTypes[iType];
global.process.removeListener(errorType, onerror);
global.process.removeListener(errorType, this.jasmineHandlers[errorType]);
for (var i = 0; i < this.originalHandlers[errorType].length; i++) {
global.process.on(errorType, this.originalHandlers[errorType][i]);
}
delete this.originalHandlers[errorType];
delete this.jasmineHandlers[errorType];
}
};
};
this.install = function install() {
if (global.process && global.process.listeners && j$.isFunction_(global.process.on)) {
this.installOne_('uncaughtException');
this.installOne_('unhandledRejection');
this.installOne_('uncaughtException', 'Uncaught exception');
this.installOne_('unhandledRejection', 'Unhandled promise rejection');
} else {
var originalHandler = global.onerror;
global.onerror = onerror;

View File

@@ -1,10 +1,4 @@
getJasmineRequireObj().JsApiReporter = function() {
var noopTimer = {
start: function(){},
elapsed: function(){ return 0; }
};
getJasmineRequireObj().JsApiReporter = function(j$) {
/**
* @name jsApiReporter
* @classdesc {@link Reporter} added by default in `boot.js` to record results for retrieval in javascript code. An instance is made available as `jsApiReporter` on the global object.
@@ -12,7 +6,7 @@ getJasmineRequireObj().JsApiReporter = function() {
* @hideconstructor
*/
function JsApiReporter(options) {
var timer = options.timer || noopTimer,
var timer = options.timer || j$.noopTimer,
status = 'loaded';
this.started = false;

View File

@@ -23,7 +23,7 @@ getJasmineRequireObj().Order = function() {
}
// Bob Jenkins One-at-a-Time Hash algorithm is a non-cryptographic hash function
// used to get a different output when the key changes slighly.
// used to get a different output when the key changes slightly.
// We use your return to sort the children randomly in a consistent way when
// used in conjunction with a seed

View File

@@ -34,10 +34,12 @@ getJasmineRequireObj().pp = function(j$) {
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 (j$.isDomNode(value)) {
if (value.tagName) {
this.emitDomElement(value);
} else {
this.emitScalar('HTMLNode');
}
} else if (value instanceof Date) {
this.emitScalar('Date(' + value + ')');
} else if (j$.isSet(value)) {
@@ -228,15 +230,29 @@ getJasmineRequireObj().pp = function(j$) {
};
PrettyPrinter.prototype.emitDomElement = function(el) {
var closingTag = '</' + el.tagName.toLowerCase() + '>';
var tagName = el.tagName.toLowerCase(),
attrs = el.attributes,
i,
len = attrs.length,
out = '<' + tagName,
attr;
if (el.innerHTML === '') {
this.append(el.outerHTML.replace(closingTag, ''));
} else {
var tagEnd = el.outerHTML.indexOf('>');
this.append(el.outerHTML.substring(0, tagEnd + 1));
this.append('...' + closingTag);
for (i = 0; i < len; i++) {
attr = attrs[i];
out += ' ' + attr.name;
if (attr.value !== '') {
out += '="' + attr.value + '"';
}
}
out += '>';
if (el.childElementCount !== 0 || el.textContent !== '') {
out += '...</' + tagName + '>';
}
this.append(out);
};
PrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {

View File

@@ -5,26 +5,29 @@ getJasmineRequireObj().QueueRunner = function(j$) {
function once(fn) {
var called = false;
return function() {
return function(arg) {
if (!called) {
called = true;
fn.apply(null, arguments);
// Direct call using single parameter, because cleanup/next does not need more
fn(arg);
}
return null;
};
}
function emptyFn() {}
function QueueRunner(attrs) {
var queueableFns = attrs.queueableFns || [];
this.queueableFns = queueableFns.concat(attrs.cleanupFns || []);
this.firstCleanupIx = queueableFns.length;
this.onComplete = attrs.onComplete || function() {};
this.onComplete = attrs.onComplete || emptyFn;
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.onException = attrs.onException || function() {};
this.onException = attrs.onException || emptyFn;
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.fail = attrs.fail || emptyFn;
this.globalErrors = attrs.globalErrors || { pushListener: emptyFn, popListener: emptyFn };
this.completeOnFirstError = !!attrs.completeOnFirstError;
this.errored = false;
@@ -66,14 +69,16 @@ getJasmineRequireObj().QueueRunner = function(j$) {
next(error);
},
cleanup = once(function cleanup() {
self.clearTimeout(timeoutId);
if (timeoutId !== void 0) {
self.clearTimeout(timeoutId);
}
self.globalErrors.popListener(handleError);
}),
next = once(function next(err) {
cleanup();
if (j$.isError_(err)) {
if (!(err instanceof StopExecutionError)) {
if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
self.fail(err);
}
self.errored = errored = true;

View File

@@ -14,6 +14,7 @@ getJasmineRequireObj().Spec = function(j$) {
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
this.timer = attrs.timer || j$.noopTimer;
if (!this.queueableFn.fn) {
this.pend();
@@ -29,6 +30,7 @@ getJasmineRequireObj().Spec = function(j$) {
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred during execution this spec.
* @property {String} pendingReason - If the spec is {@link pending}, this will be the reason.
* @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
* @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
*/
this.result = {
id: this.id,
@@ -37,7 +39,8 @@ getJasmineRequireObj().Spec = function(j$) {
failedExpectations: [],
passedExpectations: [],
deprecationWarnings: [],
pendingReason: ''
pendingReason: '',
duration: null,
};
}
@@ -67,6 +70,7 @@ getJasmineRequireObj().Spec = function(j$) {
var onStart = {
fn: function(done) {
self.timer.start();
self.onStart(self, done);
}
};
@@ -90,6 +94,7 @@ getJasmineRequireObj().Spec = function(j$) {
self.onException.apply(self, arguments);
},
onComplete: function() {
self.result.duration = self.timer.elapsed();
onComplete(self.result.status === 'failed' && new j$.StopExecutionError('spec failed'));
},
userContext: this.userContext()

View File

@@ -112,7 +112,7 @@ getJasmineRequireObj().Spy = function (j$) {
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.');
throw new Error('Spy \'' + strategyArgs.name + '\' received a call with arguments ' + j$.pp(Array.prototype.slice.call(args)) + ' but all configured strategies specify other arguments.');
} else {
strategy = baseStrategy;
}

View File

@@ -14,6 +14,8 @@ getJasmineRequireObj().Suite = function(j$) {
this.beforeAllFns = [];
this.afterAllFns = [];
this.timer = attrs.timer || j$.noopTimer;
this.children = [];
/**
@@ -24,13 +26,15 @@ getJasmineRequireObj().Suite = function(j$) {
* @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
* @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
* @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
*/
this.result = {
id: this.id,
description: this.description,
fullName: this.getFullName(),
failedExpectations: [],
deprecationWarnings: []
deprecationWarnings: [],
duration: null,
};
}
@@ -72,6 +76,14 @@ getJasmineRequireObj().Suite = function(j$) {
this.afterAllFns.unshift(fn);
};
Suite.prototype.startTimer = function() {
this.timer.start();
};
Suite.prototype.endTimer = function() {
this.result.duration = this.timer.elapsed();
};
function removeFns(queueableFns) {
for(var i = 0; i < queueableFns.length; i++) {
queueableFns[i].fn = null;

View File

@@ -20,3 +20,10 @@ getJasmineRequireObj().Timer = function() {
return Timer;
};
getJasmineRequireObj().noopTimer = function() {
return {
start: function() {},
elapsed: function() { return 0; }
};
};

View File

@@ -17,7 +17,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
*/
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 50;
/**
* Maximum number of charasters to display when pretty printing objects.
* Maximum number of characters to display when pretty printing objects.
* Characters past this number will be ellipised.
* @name jasmine.MAX_PRETTY_PRINT_CHARS
*/
@@ -89,9 +89,15 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
if (value instanceof Error) {
return true;
}
if (value && value.constructor && value.constructor.constructor &&
(value instanceof (value.constructor.constructor('return this')()).Error)) {
return true;
if (value && value.constructor && value.constructor.constructor) {
var valueGlobal = value.constructor.constructor('return this');
if (j$.isFunction_(valueGlobal)) {
valueGlobal = valueGlobal();
}
if (valueGlobal.Error && value instanceof valueGlobal.Error) {
return true;
}
}
return false;
};
@@ -120,7 +126,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
};
j$.isPromise = function(obj) {
return typeof jasmineGlobal.Promise !== 'undefined' && obj && obj.constructor === jasmineGlobal.Promise;
return typeof jasmineGlobal.Promise !== 'undefined' && !!obj && obj.constructor === jasmineGlobal.Promise;
};
j$.isPromiseLike = function(obj) {
return !!obj && j$.isFunction_(obj.then);
};
j$.fnNameFor = function(func) {

View File

@@ -0,0 +1,22 @@
getJasmineRequireObj().toBeRejected = function(j$) {
/**
* Expect a promise to be rejected.
* @function
* @async
* @name async-matchers#toBeRejected
* @example
* await expectAsync(aPromise).toBeRejected();
* @example
* return expectAsync(aPromise).toBeRejected();
*/
return function toBeResolved(util) {
return {
compare: function(actual) {
return actual.then(
function() { return {pass: false}; },
function() { return {pass: true}; }
);
}
};
};
};

View File

@@ -0,0 +1,46 @@
getJasmineRequireObj().toBeRejectedWith = function(j$) {
/**
* Expect a promise to be rejected with a value equal to the expected, using deep equality comparison.
* @function
* @async
* @name async-matchers#toBeRejectedWith
* @param {Object} expected - Value that the promise is expected to be rejected with
* @example
* await expectAsync(aPromise).toBeRejectedWith({prop: 'value'});
* @example
* return expectAsync(aPromise).toBeRejectedWith({prop: 'value'});
*/
return function toBeRejectedWith(util, customEqualityTesters) {
return {
compare: function(actualPromise, expectedValue) {
function prefix(passed) {
return 'Expected a promise ' +
(passed ? 'not ' : '') +
'to be rejected with ' + j$.pp(expectedValue);
}
return actualPromise.then(
function() {
return {
pass: false,
message: prefix(false) + ' but it was resolved.'
};
},
function(actualValue) {
if (util.equals(actualValue, expectedValue, customEqualityTesters)) {
return {
pass: true,
message: prefix(true) + '.'
};
} else {
return {
pass: false,
message: prefix(false) + ' but it was rejected with ' + j$.pp(actualValue) + '.'
};
}
}
);
}
};
};
};

View File

@@ -0,0 +1,22 @@
getJasmineRequireObj().toBeResolved = function(j$) {
/**
* Expect a promise to be resolved.
* @function
* @async
* @name async-matchers#toBeResolved
* @example
* await expectAsync(aPromise).toBeResolved();
* @example
* return expectAsync(aPromise).toBeResolved();
*/
return function toBeResolved(util) {
return {
compare: function(actual) {
return actual.then(
function() { return {pass: true}; },
function() { return {pass: false}; }
);
}
};
};
};

View File

@@ -0,0 +1,46 @@
getJasmineRequireObj().toBeResolvedTo = function(j$) {
/**
* Expect a promise to be resolved to a value equal to the expected, using deep equality comparison.
* @function
* @async
* @name async-matchers#toBeResolvedTo
* @param {Object} expected - Value that the promise is expected to resolve to
* @example
* await expectAsync(aPromise).toBeResolvedTo({prop: 'value'});
* @example
* return expectAsync(aPromise).toBeResolvedTo({prop: 'value'});
*/
return function toBeResolvedTo(util, customEqualityTesters) {
return {
compare: function(actualPromise, expectedValue) {
function prefix(passed) {
return 'Expected a promise ' +
(passed ? 'not ' : '') +
'to be resolved to ' + j$.pp(expectedValue);
}
return actualPromise.then(
function(actualValue) {
if (util.equals(actualValue, expectedValue, customEqualityTesters)) {
return {
pass: true,
message: prefix(true) + '.'
};
} else {
return {
pass: false,
message: prefix(false) + ' but it was resolved to ' + j$.pp(actualValue) + '.'
};
}
},
function() {
return {
pass: false,
message: prefix(false) + ' but it was rejected.'
};
}
);
}
};
};
};

View File

@@ -0,0 +1,16 @@
getJasmineRequireObj().requireAsyncMatchers = function(jRequire, j$) {
var availableMatchers = [
'toBeResolved',
'toBeRejected',
'toBeResolvedTo',
'toBeRejectedWith'
],
matchers = {};
for (var i = 0; i < availableMatchers.length; i++) {
var name = availableMatchers[i];
matchers[name] = jRequire[name](j$);
}
return matchers;
};

View File

@@ -1,4 +1,4 @@
getJasmineRequireObj().toBe = function() {
getJasmineRequireObj().toBe = function(j$) {
/**
* {@link expect} the actual value to be `===` to the expected value.
* @function
@@ -7,12 +7,20 @@ getJasmineRequireObj().toBe = function() {
* @example
* expect(thing).toBe(realThing);
*/
function toBe() {
function toBe(util) {
var tip = ' Tip: To check for deep equality, use .toEqual() instead of .toBe().';
return {
compare: function(actual, expected) {
return {
pass: actual === expected
var result = {
pass: actual === expected,
};
if (typeof expected === 'object') {
result.message = util.buildFailureMessage('toBe', result.pass, actual, expected) + tip;
}
return result;
}
};
}

View File

@@ -37,10 +37,12 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
j$.Env = jRequire.Env(j$);
j$.StackTrace = jRequire.StackTrace(j$);
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
j$.Expectation = jRequire.Expectation();
j$.AsyncExpectation = jRequire.AsyncExpectation(j$);
j$.ExpectationFilterChain = jRequire.ExpectationFilterChain();
j$.Expector = jRequire.Expector(j$);
j$.Expectation = jRequire.Expectation(j$);
j$.buildExpectationResult = jRequire.buildExpectationResult();
j$.JsApiReporter = jRequire.JsApiReporter();
j$.noopTimer = jRequire.noopTimer();
j$.JsApiReporter = jRequire.JsApiReporter(j$);
j$.matchersUtil = jRequire.matchersUtil(j$);
j$.ObjectContaining = jRequire.ObjectContaining(j$);
j$.ArrayContaining = jRequire.ArrayContaining(j$);
@@ -71,6 +73,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
j$.NotEmpty = jRequire.NotEmpty(j$);
j$.matchers = jRequire.requireMatchers(jRequire, j$);
j$.asyncMatchers = jRequire.requireAsyncMatchers(jRequire, j$);
return j$;
};

View File

@@ -237,7 +237,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
/**
* Installs spies on all writable and configurable properties of an object.
* @name spyOnProperty
* @name spyOnAllFunctions
* @function
* @global
* @param {Object} obj - The object upon which to install the {@link Spy}s

View File

@@ -1,10 +1,4 @@
jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = {
start: function() {},
elapsed: function() { return 0; }
};
function ResultsStateBuilder() {
this.topResults = new j$.ResultsNode({}, '', null);
this.currentParent = this.topResults;
@@ -51,14 +45,14 @@ jasmineRequire.HtmlReporter = function(j$) {
function HtmlReporter(options) {
var env = options.env || {},
var config = function() { return (options.env && options.env.configuration()) || {}; },
getContainer = options.getContainer,
createElement = options.createElement,
createTextNode = options.createTextNode,
navigateWithNewParam = options.navigateWithNewParam || function() {},
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
filterSpecs = options.filterSpecs,
timer = options.timer || noopTimer,
timer = options.timer || j$.noopTimer,
htmlReporterMain,
symbols,
deprecationWarnings = [];
@@ -138,9 +132,9 @@ jasmineRequire.HtmlReporter = function(j$) {
this.resultStatus = function(status) {
if(status === 'excluded') {
return env.hidingDisabled() ? 'jasmine-excluded-no-display' : 'jasmine-excluded';
}
return 'jasmine-' + status;
return config().hideDisabled ? 'jasmine-excluded-no-display' : 'jasmine-excluded';
}
return 'jasmine-' + status;
};
this.jasmineDone = function(doneResult) {
@@ -150,7 +144,7 @@ jasmineRequire.HtmlReporter = function(j$) {
var i;
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
banner.appendChild(optionsMenu(env));
banner.appendChild(optionsMenu(config()));
if (stateBuilder.specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
@@ -310,7 +304,7 @@ jasmineRequire.HtmlReporter = function(j$) {
}
}
function optionsMenu(env) {
function optionsMenu(config) {
var optionsMenuDom = createDom('div', { className: 'jasmine-run-options' },
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
createDom('div', { className: 'jasmine-payload' },
@@ -346,27 +340,27 @@ jasmineRequire.HtmlReporter = function(j$) {
);
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
failFastCheckbox.checked = env.stoppingOnSpecFailure();
failFastCheckbox.checked = config.failFast;
failFastCheckbox.onclick = function() {
navigateWithNewParam('failFast', !env.stoppingOnSpecFailure());
navigateWithNewParam('failFast', !config.failFast);
};
var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
throwCheckbox.checked = env.throwingExpectationFailures();
throwCheckbox.checked = config.oneFailurePerSpec;
throwCheckbox.onclick = function() {
navigateWithNewParam('throwFailures', !env.throwingExpectationFailures());
navigateWithNewParam('throwFailures', !config.oneFailurePerSpec);
};
var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
randomCheckbox.checked = env.randomTests();
randomCheckbox.checked = config.random;
randomCheckbox.onclick = function() {
navigateWithNewParam('random', !env.randomTests());
navigateWithNewParam('random', !config.random);
};
var hideDisabled = optionsMenuDom.querySelector('#jasmine-hide-disabled');
hideDisabled.checked = env.hidingDisabled();
hideDisabled.checked = config.hideDisabled;
hideDisabled.onclick = function() {
navigateWithNewParam('hideDisabled', !env.hidingDisabled());
navigateWithNewParam('hideDisabled', !config.hideDisabled);
};
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),

View File

@@ -1,5 +1,3 @@
@import "compass";
$line-height: 14px;
$margin-unit: 14px;
@@ -16,6 +14,11 @@ $empty-color: #eff543;
$neutral-color: #bababa;
$jasmine-color: #8a4182;
$passing-mark: "\02022";
$failing-mark: "\d7";
$pending-mark: "*";
$space: "\0020";
$font-size: 11px;
$large-font-size: 14px;
@@ -63,9 +66,12 @@ body {
}
.jasmine-banner .jasmine-title {
background: inline-image('jasmine-horizontal.png') no-repeat;
background: inline-image('jasmine-horizontal.svg') no-repeat, none;
@include background-size(100%);
background: url('../../images/jasmine-horizontal.png') no-repeat;
background: url('../../images/jasmine-horizontal.svg') no-repeat, none;
-moz-background-size: 100%;
-o-background-size: 100%;
-webkit-background-size: 100%;
background-size: 100%;
display: block;
float: left;
width: 90px;
@@ -105,7 +111,7 @@ body {
//--- Symbol summary ---//
.jasmine-symbol-summary {
@include clearfix;
overflow: hidden;
margin: $line-height 0;
li {
@@ -120,7 +126,7 @@ body {
&:before {
color: $passing-color;
content: "\02022";
content: $passing-mark;
}
}
@@ -129,7 +135,7 @@ body {
&:before {
color: $failing-color;
content: "\d7";
content: $failing-mark;
font-weight: bold;
margin-left: -1px;
}
@@ -140,7 +146,7 @@ body {
&:before {
color: $neutral-color;
content: "\02022";
content: $passing-mark;
}
}
@@ -153,7 +159,7 @@ body {
line-height: 17px;
&:before {
color: $pending-color;
content: "*";
content: $pending-mark;
}
}
@@ -162,7 +168,7 @@ body {
&:before {
color: $pending-color;
content: "\02022";
content: $passing-mark;
}
}
}
@@ -303,6 +309,30 @@ body {
}
}
.jasmine-specs {
li {
&.jasmine-passed a:before {
content: $passing-mark + $space;
}
&.jasmine-failed a:before {
content: $failing-mark + $space;
}
&.jasmine-empty a:before {
content: $pending-mark + $space;
}
&.jasmine-pending a:before {
content: $passing-mark + $space;
}
&.jasmine-excluded a:before {
content: $passing-mark + $space;
}
}
}
.jasmine-description + .jasmine-suite {
margin-top: 0;
}

View File

@@ -9,4 +9,4 @@ then
fi
fi
bundle exec rake jasmine:ci
node ci.js

View File

@@ -1,10 +0,0 @@
#!/bin/bash -e
rm -rf ~/.nvm
git clone https://github.com/creationix/nvm.git ~/.nvm
(cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`)
source ~/.nvm/nvm.sh
nvm install ${1:-"v0.12.18"}
npm install
npm test