Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cf8736cab | ||
|
|
6d0f0ed915 | ||
|
|
b2dee5cb1c | ||
|
|
1414281cff | ||
|
|
2588b442e6 | ||
|
|
af41e5ea5c | ||
|
|
8834142198 | ||
|
|
1926fc11ae | ||
|
|
e7049d3183 | ||
|
|
80dba1138a | ||
|
|
9811ff71d2 | ||
|
|
301dd4f6b5 | ||
|
|
090a6234c3 | ||
|
|
8ad9abb19a | ||
|
|
8c0a8a1b33 | ||
|
|
1db81c334d | ||
|
|
8dd0ad531c | ||
|
|
f58002f0a6 | ||
|
|
4d18e63b0f | ||
|
|
4fc177d5ae | ||
|
|
acc8c23bf4 | ||
|
|
fc6ee243e9 |
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at jasmine-maintainers@googlegroups.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -63,6 +63,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
j$.matchersUtil = jRequire.matchersUtil(j$);
|
||||
j$.ObjectContaining = jRequire.ObjectContaining(j$);
|
||||
j$.ArrayContaining = jRequire.ArrayContaining(j$);
|
||||
j$.ArrayWithExactContents = jRequire.ArrayWithExactContents(j$);
|
||||
j$.pp = jRequire.pp(j$);
|
||||
j$.QueueRunner = jRequire.QueueRunner(j$);
|
||||
j$.ReportDispatcher = jRequire.ReportDispatcher();
|
||||
@@ -92,6 +93,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
|
||||
getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
|
||||
var availableMatchers = [
|
||||
'nothing',
|
||||
'toBe',
|
||||
'toBeCloseTo',
|
||||
'toBeDefined',
|
||||
@@ -191,6 +193,18 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return j$.isA_('AsyncFunction', value);
|
||||
};
|
||||
|
||||
j$.isTypedArray_ = function(value) {
|
||||
return j$.isA_('Float32Array', value) ||
|
||||
j$.isA_('Float64Array', value) ||
|
||||
j$.isA_('Int16Array', value) ||
|
||||
j$.isA_('Int32Array', value) ||
|
||||
j$.isA_('Int8Array', value) ||
|
||||
j$.isA_('Uint16Array', value) ||
|
||||
j$.isA_('Uint32Array', value) ||
|
||||
j$.isA_('Uint8Array', value) ||
|
||||
j$.isA_('Uint8ClampedArray', value);
|
||||
};
|
||||
|
||||
j$.isA_ = function(typeName, value) {
|
||||
return j$.getType_(value) === '[object ' + typeName + ']';
|
||||
};
|
||||
@@ -208,7 +222,9 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return func.name;
|
||||
}
|
||||
|
||||
var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/);
|
||||
var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/) ||
|
||||
func.toString().match(/^\s*\[object\s*(\w*)Constructor\]/);
|
||||
|
||||
return matches ? matches[1] : '<anonymous>';
|
||||
};
|
||||
|
||||
@@ -266,6 +282,17 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return new j$.ArrayContaining(sample);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
|
||||
* that will succeed if the actual value is an `Array` that contains all of the elements in the sample in any order.
|
||||
* @name jasmine.arrayWithExactContents
|
||||
* @function
|
||||
* @param {Array} sample
|
||||
*/
|
||||
j$.arrayWithExactContents = function(sample) {
|
||||
return new j$.ArrayWithExactContents(sample);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a bare {@link Spy} object. This won't be installed anywhere and will not have any implementation behind it.
|
||||
* @name jasmine.createSpy
|
||||
@@ -436,6 +463,16 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
this.pend();
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef SpecResult
|
||||
* @property {Int} id - The unique id of this spec.
|
||||
* @property {String} description - The description passed to the {@link it} that created this spec.
|
||||
* @property {String} fullName - The full description including all ancestors of this spec.
|
||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
||||
* @property {Expectation[]} passedExpectations - The list of expectations that passed during execution of 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.
|
||||
*/
|
||||
this.result = {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
@@ -664,12 +701,56 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
return currentSpec || currentSuite();
|
||||
};
|
||||
|
||||
/**
|
||||
* This represents the available reporter callback for an object passed to {@link Env#addReporter}.
|
||||
* @interface Reporter
|
||||
*/
|
||||
var reporter = new j$.ReportDispatcher([
|
||||
/**
|
||||
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
||||
* @function
|
||||
* @name Reporter#jasmineStarted
|
||||
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
|
||||
*/
|
||||
'jasmineStarted',
|
||||
/**
|
||||
* When the entire suite has finished execution `jasmineDone` is called
|
||||
* @function
|
||||
* @name Reporter#jasmineDone
|
||||
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
|
||||
*/
|
||||
'jasmineDone',
|
||||
/**
|
||||
* `suiteStarted` is invoked when a `describe` starts to run
|
||||
* @function
|
||||
* @name Reporter#suiteStarted
|
||||
* @param {SuiteResult} result Information about the individual {@link describe} being run
|
||||
*/
|
||||
'suiteStarted',
|
||||
/**
|
||||
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
|
||||
*
|
||||
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
|
||||
* @function
|
||||
* @name Reporter#suiteDone
|
||||
* @param {SuiteResult} result
|
||||
*/
|
||||
'suiteDone',
|
||||
/**
|
||||
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
|
||||
* @function
|
||||
* @name Reporter#specStarted
|
||||
* @param {SpecResult} result Information about the individual {@link it} being run
|
||||
*/
|
||||
'specStarted',
|
||||
/**
|
||||
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
|
||||
*
|
||||
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
|
||||
* @function
|
||||
* @name Reporter#specDone
|
||||
* @param {SpecResult} result
|
||||
*/
|
||||
'specDone'
|
||||
]);
|
||||
|
||||
@@ -885,6 +966,12 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
throw new Error('Invalid order: would cause a beforeAll or afterAll to be run multiple times');
|
||||
}
|
||||
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineStarted} event.
|
||||
* @typedef JasmineStartedInfo
|
||||
* @property {Int} totalSpecsDefined - The total number of specs defined in this suite.
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
*/
|
||||
reporter.jasmineStarted({
|
||||
totalSpecsDefined: totalSpecsDefined,
|
||||
order: order
|
||||
@@ -898,6 +985,12 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
currentlyExecutingSuites.pop();
|
||||
globalErrors.uninstall();
|
||||
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineDone} event.
|
||||
* @typedef JasmineDoneInfo
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
* @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
||||
*/
|
||||
reporter.jasmineDone({
|
||||
order: order,
|
||||
failedExpectations: topSuite.result.failedExpectations
|
||||
@@ -909,6 +1002,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* Add a custom reporter to the Jasmine environment.
|
||||
* @name Env#addReporter
|
||||
* @function
|
||||
* @param {Reporter} reporterToAdd The reporter to be added.
|
||||
* @see custom_reporter
|
||||
*/
|
||||
this.addReporter = function(reporterToAdd) {
|
||||
@@ -1215,11 +1309,10 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, use the global `jsApiReporter` to retrieve the instantiated object.
|
||||
*
|
||||
* @name jsApiReporter
|
||||
* @classdesc Reporter added by default in `boot.js` to record results for retrieval in javascript code.
|
||||
* @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.
|
||||
* @class
|
||||
* @hideconstructor
|
||||
*/
|
||||
function JsApiReporter(options) {
|
||||
var timer = options.timer || noopTimer,
|
||||
@@ -1273,7 +1366,7 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
* @function
|
||||
* @param {Number} index - The position in the suites list to start from.
|
||||
* @param {Number} length - Maximum number of suite results to return.
|
||||
* @return {Object[]}
|
||||
* @return {SuiteResult[]}
|
||||
*/
|
||||
this.suiteResults = function(index, length) {
|
||||
return suites.slice(index, index + length);
|
||||
@@ -1288,7 +1381,7 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
* Get all of the suites in a single object, with their `id` as the key.
|
||||
* @name jsApiReporter#suites
|
||||
* @function
|
||||
* @return {Object}
|
||||
* @return {Object} - Map of suite id to {@link SuiteResult}
|
||||
*/
|
||||
this.suites = function() {
|
||||
return suites_hash;
|
||||
@@ -1308,7 +1401,7 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
* @function
|
||||
* @param {Number} index - The position in the specs list to start from.
|
||||
* @param {Number} length - Maximum number of specs results to return.
|
||||
* @return {Object[]}
|
||||
* @return {SpecResult[]}
|
||||
*/
|
||||
this.specResults = function(index, length) {
|
||||
return specs.slice(index, index + length);
|
||||
@@ -1318,7 +1411,7 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
* Get all spec results.
|
||||
* @name jsApiReporter#specs
|
||||
* @function
|
||||
* @return {Object[]}
|
||||
* @return {SpecResult[]}
|
||||
*/
|
||||
this.specs = function() {
|
||||
return specs;
|
||||
@@ -1403,8 +1496,9 @@ getJasmineRequireObj().ArrayContaining = function(j$) {
|
||||
}
|
||||
|
||||
ArrayContaining.prototype.asymmetricMatch = function(other, customTesters) {
|
||||
var className = Object.prototype.toString.call(this.sample);
|
||||
if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); }
|
||||
if (!j$.isArray_(this.sample)) {
|
||||
throw new Error('You must provide an array to arrayContaining, not ' + j$.pp(this.sample) + '.');
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.sample.length; i++) {
|
||||
var item = this.sample[i];
|
||||
@@ -1423,6 +1517,38 @@ getJasmineRequireObj().ArrayContaining = function(j$) {
|
||||
return ArrayContaining;
|
||||
};
|
||||
|
||||
getJasmineRequireObj().ArrayWithExactContents = function(j$) {
|
||||
|
||||
function ArrayWithExactContents(sample) {
|
||||
this.sample = sample;
|
||||
}
|
||||
|
||||
ArrayWithExactContents.prototype.asymmetricMatch = function(other, customTesters) {
|
||||
if (!j$.isArray_(this.sample)) {
|
||||
throw new Error('You must provide an array to arrayWithExactContents, not ' + j$.pp(this.sample) + '.');
|
||||
}
|
||||
|
||||
if (this.sample.length !== other.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.sample.length; i++) {
|
||||
var item = this.sample[i];
|
||||
if (!j$.matchersUtil.contains(other, item, customTesters)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
ArrayWithExactContents.prototype.jasmineToString = function() {
|
||||
return '<jasmine.arrayWithExactContents ' + j$.pp(this.sample) + '>';
|
||||
};
|
||||
|
||||
return ArrayWithExactContents;
|
||||
};
|
||||
|
||||
getJasmineRequireObj().ObjectContaining = function(j$) {
|
||||
|
||||
function ObjectContaining(sample) {
|
||||
@@ -1507,10 +1633,13 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
||||
var clonedArgs = [];
|
||||
var argsAsArray = j$.util.argsToArray(context.args);
|
||||
for(var i = 0; i < argsAsArray.length; i++) {
|
||||
if(Object.prototype.toString.apply(argsAsArray[i]).match(/^\[object/)) {
|
||||
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
||||
} else {
|
||||
var str = Object.prototype.toString.apply(argsAsArray[i]),
|
||||
primitives = /^\[object (Boolean|String|RegExp|Number)/;
|
||||
|
||||
if (argsAsArray[i] == null || str.match(primitives)) {
|
||||
clonedArgs.push(argsAsArray[i]);
|
||||
} else {
|
||||
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
||||
}
|
||||
}
|
||||
context.args = clonedArgs;
|
||||
@@ -2164,6 +2293,15 @@ getJasmineRequireObj().buildExpectationResult = function() {
|
||||
var messageFormatter = options.messageFormatter || function() {},
|
||||
stackFormatter = options.stackFormatter || function() {};
|
||||
|
||||
/**
|
||||
* @typedef Expectation
|
||||
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
||||
* @property {String} message - The failure message for the expectation.
|
||||
* @property {String} stack - The stack trace for the failure if available.
|
||||
* @property {Boolean} passed - Whether the expectation passed or failed.
|
||||
* @property {Object} expected - If the expectation failed, what was the expected value.
|
||||
* @property {Object} actual - If the expectation failed, what actual value was produced.
|
||||
*/
|
||||
var result = {
|
||||
matcherName: options.matcherName,
|
||||
message: message(),
|
||||
@@ -2374,13 +2512,17 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
||||
|
||||
if (asymmetricA) {
|
||||
result = a.asymmetricMatch(b, customTesters);
|
||||
diffBuilder.record(a, b);
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (asymmetricB) {
|
||||
result = b.asymmetricMatch(a, customTesters);
|
||||
diffBuilder.record(a, b);
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -2533,35 +2675,84 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
||||
// Recursively compare objects and arrays.
|
||||
// Compare array lengths to determine if a deep comparison is necessary.
|
||||
if (className == '[object Array]') {
|
||||
size = a.length;
|
||||
if (size !== b.length) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
var aLength = a.length;
|
||||
var bLength = b.length;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
diffBuilder.withPath('length', function() {
|
||||
if (aLength !== bLength) {
|
||||
diffBuilder.record(aLength, bLength);
|
||||
result = false;
|
||||
}
|
||||
});
|
||||
|
||||
for (i = 0; i < aLength || i < bLength; i++) {
|
||||
diffBuilder.withPath(i, function() {
|
||||
result = eq(a[i], b[i], aStack, bStack, customTesters, diffBuilder) && result;
|
||||
result = eq(i < aLength ? a[i] : void 0, i < bLength ? b[i] : void 0, aStack, bStack, customTesters, diffBuilder) && result;
|
||||
});
|
||||
}
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
} else if (className == '[object Set]' || className == '[object Map]') {
|
||||
} else if (className == '[object Map]') {
|
||||
if (a.size != b.size) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
var iterA = a.entries(), iterB = b.entries();
|
||||
var valA, valB;
|
||||
do {
|
||||
valA = iterA.next();
|
||||
valB = iterB.next();
|
||||
if (!eq(valA.value, valB.value, aStack, bStack, customTesters, j$.NullDiffBuilder())) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
|
||||
// For both sets of keys, check they map to equal values in both maps
|
||||
var mapKeys = [a.keys(), b.keys()];
|
||||
var mapIter, mapKeyIt, mapKey;
|
||||
for (i = 0; result && i < mapKeys.length; i++) {
|
||||
mapIter = mapKeys[i];
|
||||
mapKeyIt = mapIter.next();
|
||||
while (result && !mapKeyIt.done) {
|
||||
mapKey = mapKeyIt.value;
|
||||
result = eq(a.get(mapKey), b.get(mapKey), aStack, bStack, customTesters, j$.NullDiffBuilder());
|
||||
mapKeyIt = mapIter.next();
|
||||
}
|
||||
} while (!valA.done && !valB.done);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
} else if (className == '[object Set]') {
|
||||
if (a.size != b.size) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
|
||||
// For both sets, check they are all contained in the other set
|
||||
var setPairs = [[a, b], [b, a]];
|
||||
var baseIter, baseValueIt, baseValue;
|
||||
var otherSet, otherIter, otherValueIt, otherValue, found;
|
||||
for (i = 0; result && i < setPairs.length; i++) {
|
||||
baseIter = setPairs[i][0].values();
|
||||
otherSet = setPairs[i][1];
|
||||
// For each value in the base set...
|
||||
baseValueIt = baseIter.next();
|
||||
while (result && !baseValueIt.done) {
|
||||
baseValue = baseValueIt.value;
|
||||
// ... test that it is present in the other set
|
||||
otherIter = otherSet.values();
|
||||
otherValueIt = otherIter.next();
|
||||
// Optimisation: start looking for value by object identity
|
||||
found = otherSet.has(baseValue);
|
||||
// If not found, compare by value equality
|
||||
while (!found && !otherValueIt.done) {
|
||||
otherValue = otherValueIt.value;
|
||||
found = eq(baseValue, otherValue, aStack, bStack, customTesters, j$.NullDiffBuilder());
|
||||
otherValueIt = otherIter.next();
|
||||
}
|
||||
result = result && found;
|
||||
baseValueIt = baseIter.next();
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
||||
// Objects with different constructors are not equivalent, but `Object`s
|
||||
@@ -2694,6 +2885,27 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
getJasmineRequireObj().nothing = function() {
|
||||
/**
|
||||
* {@link expect} nothing explicitly.
|
||||
* @function
|
||||
* @name matchers#nothing
|
||||
* @example
|
||||
* expect().nothing();
|
||||
*/
|
||||
function nothing() {
|
||||
return {
|
||||
compare: function() {
|
||||
return {
|
||||
pass: true
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return nothing;
|
||||
};
|
||||
|
||||
getJasmineRequireObj().NullDiffBuilder = function(j$) {
|
||||
return function() {
|
||||
return {
|
||||
@@ -3716,6 +3928,8 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.emitSet(value);
|
||||
} else if (j$.getType_(value) == '[object Map]') {
|
||||
this.emitMap(value);
|
||||
} else if (j$.isTypedArray_(value)) {
|
||||
this.emitTypedArray(value);
|
||||
} else if (value.toString && typeof value === 'object' && !j$.isArray_(value) && hasCustomToString(value)) {
|
||||
this.emitScalar(value.toString());
|
||||
} else if (j$.util.arrayContains(this.seen, value)) {
|
||||
@@ -3886,6 +4100,18 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' })');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitTypedArray = function(arr) {
|
||||
var constructorName = j$.fnNameFor(arr.constructor),
|
||||
limitedArray = Array.prototype.slice.call(arr, 0, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH),
|
||||
itemsString = Array.prototype.join.call(limitedArray, ', ');
|
||||
|
||||
if (limitedArray.length !== arr.length) {
|
||||
itemsString += ', ...';
|
||||
}
|
||||
|
||||
this.append(constructorName + ' [ ' + itemsString + ' ]');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {
|
||||
this.append(property);
|
||||
this.append(': ');
|
||||
@@ -4149,6 +4375,16 @@ getJasmineRequireObj().ReportDispatcher = function() {
|
||||
|
||||
getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
var jasmineInterface = {
|
||||
/**
|
||||
* Callback passed to parts of the Jasmine base interface.
|
||||
*
|
||||
* By default Jasmine assumes this function completes synchronously.
|
||||
* If you have code that you need to test asynchronously, you can declare that you receive a `done` callback, return a Promise, or use the `async` keyword if it is supported in your environment.
|
||||
* @callback implementationCallback
|
||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a group of specs (often called a suite).
|
||||
*
|
||||
@@ -4157,7 +4393,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of the group
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites and specs
|
||||
*/
|
||||
describe: function(description, specDefinitions) {
|
||||
return env.describe(description, specDefinitions);
|
||||
@@ -4171,7 +4407,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of the group
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites and specs
|
||||
*/
|
||||
xdescribe: function(description, specDefinitions) {
|
||||
return env.xdescribe(description, specDefinitions);
|
||||
@@ -4186,7 +4422,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of the group
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites and specs
|
||||
*/
|
||||
fdescribe: function(description, specDefinitions) {
|
||||
return env.fdescribe(description, specDefinitions);
|
||||
@@ -4200,7 +4436,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of what this spec is checking
|
||||
* @param {Function} [testFunction] Function that contains the code of your test. If not provided the test will be `pending`.
|
||||
* @param {implementationCallback} [testFunction] Function that contains the code of your test. If not provided the test will be `pending`.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec.
|
||||
*/
|
||||
it: function() {
|
||||
@@ -4215,7 +4451,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of what this spec is checking.
|
||||
* @param {Function} [testFunction] Function that contains the code of your test. Will not be executed.
|
||||
* @param {implementationCallback} [testFunction] Function that contains the code of your test. Will not be executed.
|
||||
*/
|
||||
xit: function() {
|
||||
return env.xit.apply(env, arguments);
|
||||
@@ -4229,7 +4465,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of what this spec is checking.
|
||||
* @param {Function} testFunction Function that contains the code of your test.
|
||||
* @param {implementationCallback} testFunction Function that contains the code of your test.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec.
|
||||
*/
|
||||
fit: function() {
|
||||
@@ -4241,7 +4477,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @name beforeEach
|
||||
* @function
|
||||
* @global
|
||||
* @param {Function} [function] Function that contains the code to setup your specs.
|
||||
* @param {implementationCallback} [function] Function that contains the code to setup your specs.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeEach.
|
||||
*/
|
||||
beforeEach: function() {
|
||||
@@ -4253,7 +4489,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @name afterEach
|
||||
* @function
|
||||
* @global
|
||||
* @param {Function} [function] Function that contains the code to teardown your specs.
|
||||
* @param {implementationCallback} [function] Function that contains the code to teardown your specs.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterEach.
|
||||
*/
|
||||
afterEach: function() {
|
||||
@@ -4267,7 +4503,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @name beforeAll
|
||||
* @function
|
||||
* @global
|
||||
* @param {Function} [function] Function that contains the code to setup your specs.
|
||||
* @param {implementationCallback} [function] Function that contains the code to setup your specs.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeAll.
|
||||
*/
|
||||
beforeAll: function() {
|
||||
@@ -4275,13 +4511,13 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Run some shared teardown once before all of the specs in the {@link describe} are run.
|
||||
* Run some shared teardown once after all of the specs in the {@link describe} are run.
|
||||
*
|
||||
* _Note:_ Be careful, sharing the teardown from a afterAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail.
|
||||
* @name afterAll
|
||||
* @function
|
||||
* @global
|
||||
* @param {Function} [function] Function that contains the code to teardown your specs.
|
||||
* @param {implementationCallback} [function] Function that contains the code to teardown your specs.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterAll.
|
||||
*/
|
||||
afterAll: function() {
|
||||
@@ -4748,6 +4984,14 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
|
||||
this.children = [];
|
||||
|
||||
/**
|
||||
* @typedef SuiteResult
|
||||
* @property {Int} id - The unique id of this suite.
|
||||
* @property {String} description - The description text passed to the {@link describe} that made this suite.
|
||||
* @property {String} fullName - The full description including all ancestors of this suite.
|
||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
||||
* @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
|
||||
*/
|
||||
this.result = {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
@@ -5137,5 +5381,5 @@ getJasmineRequireObj().UserContext = function(j$) {
|
||||
};
|
||||
|
||||
getJasmineRequireObj().version = function() {
|
||||
return '2.7.0';
|
||||
return '2.8.0';
|
||||
};
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
#
|
||||
module Jasmine
|
||||
module Core
|
||||
VERSION = "2.7.0"
|
||||
VERSION = "2.8.0"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jasmine-core",
|
||||
"license": "MIT",
|
||||
"version": "2.7.0",
|
||||
"version": "2.8.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jasmine/jasmine.git"
|
||||
|
||||
52
release_notes/2.8.0.md
Normal file
52
release_notes/2.8.0.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Jasmine 2.8.0 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
This release contains a number of fixes and pull requests.
|
||||
2.8 should be the last 2.x release of Jasmine, as we aim for 3.0.
|
||||
|
||||
## Changes
|
||||
|
||||
* Create CODE_OF_CONDUCT.md
|
||||
* Add jsdocs for reporter events
|
||||
* Update jsApiReporter docs to link to new suite and spec results
|
||||
* Add explicit docs for the callback function passed to `it` etc.
|
||||
* Update afterAll documentation
|
||||
|
||||
## Pull Requests & Issues
|
||||
|
||||
* Add 'nothing' matcher and tests
|
||||
- Merges [#1412](https://github.com/jasmine/jasmine/issues/1412) from @ksvitkovsky
|
||||
- Fixes [#1221](https://github.com/jasmine/jasmine/issues/1221)
|
||||
|
||||
|
||||
* Make toEqual matcher report the difference between array elements when arrays have different length
|
||||
- Closes [#1375](https://github.com/jasmine/jasmine/issues/1375) from @kiewic
|
||||
|
||||
|
||||
* Add arrayWithExactContents asymmetric matcher
|
||||
- Fixes [#817](https://github.com/jasmine/jasmine/issues/817)
|
||||
|
||||
|
||||
* Ensure no message added on asym. match success
|
||||
- Closes [#1408](https://github.com/jasmine/jasmine/issues/1408) from @ksvitkovsky
|
||||
- Fixes [#1388](https://github.com/jasmine/jasmine/issues/1388)
|
||||
|
||||
|
||||
* Better primitives detection for saveArgsByValue
|
||||
- Closes [#1407](https://github.com/jasmine/jasmine/issues/1407) from @ksvitkovsky
|
||||
- Fixes [#1403](https://github.com/jasmine/jasmine/issues/1403)
|
||||
|
||||
|
||||
* Better pretty printing for typed arrays
|
||||
- Closes [#1404](https://github.com/jasmine/jasmine/issues/1404) from @ksvitkovsky
|
||||
- Fixes [#1180](https://github.com/jasmine/jasmine/issues/1180)
|
||||
|
||||
|
||||
* Rewrite ES6 Set and Map comparison to ignore insertion order
|
||||
- Merges [#1406](https://github.com/jasmine/jasmine/issues/1406) from @theefer
|
||||
- Fixes [#1402](https://github.com/jasmine/jasmine/issues/1402)
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
@@ -117,4 +117,14 @@ describe("CallTracker", function() {
|
||||
expect(callTracker.mostRecent().args[1]).not.toBe(arrayArg);
|
||||
expect(callTracker.mostRecent().args[1]).toEqual(arrayArg);
|
||||
});
|
||||
|
||||
it('saves primitive arguments by value', function() {
|
||||
var callTracker = new jasmineUnderTest.CallTracker(),
|
||||
args = [undefined, null, false, '', /\s/, 0, 1.2, NaN];
|
||||
|
||||
callTracker.saveArgumentsByValue();
|
||||
callTracker.track({ object: {}, args: args });
|
||||
|
||||
expect(callTracker.mostRecent().args).toEqual(args);
|
||||
});
|
||||
});
|
||||
|
||||
47
spec/core/asymmetric_equality/ArrayWithExactContentsSpec.js
Normal file
47
spec/core/asymmetric_equality/ArrayWithExactContentsSpec.js
Normal file
@@ -0,0 +1,47 @@
|
||||
describe("ArrayWithExactContents", function() {
|
||||
it("matches an array with the same items in a different order", function() {
|
||||
var matcher = new jasmineUnderTest.ArrayWithExactContents(['a', 2, /a/]);
|
||||
|
||||
expect(matcher.asymmetricMatch([2, 'a', /a/])).toBe(true);
|
||||
});
|
||||
|
||||
it("does not work when not passed an array", function() {
|
||||
var matcher = new jasmineUnderTest.ArrayWithExactContents("foo");
|
||||
|
||||
expect(function() {
|
||||
matcher.asymmetricMatch([]);
|
||||
}).toThrowError(/not 'foo'/);
|
||||
});
|
||||
|
||||
it("does not match when an item is missing", function() {
|
||||
var matcher = new jasmineUnderTest.ArrayWithExactContents(['a', 2, /a/]);
|
||||
|
||||
expect(matcher.asymmetricMatch(['a', 2])).toBe(false);
|
||||
expect(matcher.asymmetricMatch(['a', 2, undefined])).toBe(false);
|
||||
});
|
||||
|
||||
it("does not match when there is an extra item", function() {
|
||||
var matcher = new jasmineUnderTest.ArrayWithExactContents(['a']);
|
||||
|
||||
expect(matcher.asymmetricMatch(['a', 2])).toBe(false);
|
||||
});
|
||||
|
||||
it("jasmineToStrings itself", function() {
|
||||
var matcher = new jasmineUnderTest.ArrayWithExactContents([]);
|
||||
|
||||
expect(matcher.jasmineToString()).toMatch("<jasmine.arrayWithExactContents");
|
||||
});
|
||||
|
||||
it("uses custom equality testers", function() {
|
||||
var tester = function(a, b) {
|
||||
// All "foo*" strings match each other.
|
||||
if (typeof a == "string" && typeof b == "string" &&
|
||||
a.substr(0, 3) == "foo" && b.substr(0, 3) == "foo") {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
var matcher = new jasmineUnderTest.ArrayWithExactContents(["fooVal"]);
|
||||
|
||||
expect(matcher.asymmetricMatch(["fooBar"], [tester])).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -67,8 +67,9 @@ describe("Custom Matchers (Integration)", function() {
|
||||
};
|
||||
|
||||
env.addCustomEqualityTester(customEqualityFn);
|
||||
env.expect({foo: 'fooValue'}).toEqual(jasmine.objectContaining({foo: 'fooBar'}));
|
||||
env.expect(['fooValue']).toEqual(jasmine.arrayContaining(['fooBar']));
|
||||
env.expect({foo: 'fooValue'}).toEqual(jasmineUnderTest.objectContaining({foo: 'fooBar'}));
|
||||
env.expect(['fooValue', 'things']).toEqual(jasmineUnderTest.arrayContaining(['fooBar']));
|
||||
env.expect(['fooValue']).toEqual(jasmineUnderTest.arrayWithExactContents(['fooBar']));
|
||||
});
|
||||
|
||||
var specExpectations = function(result) {
|
||||
|
||||
@@ -786,7 +786,7 @@ describe("Env integration", function() {
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it('can be configured to allow respying on functions', function () {
|
||||
it('can be configured to allow respying on functions', function (done) {
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
foo = {
|
||||
bar: function () {
|
||||
@@ -795,6 +795,7 @@ describe("Env integration", function() {
|
||||
};
|
||||
|
||||
env.allowRespy(true);
|
||||
env.addReporter({ jasmineDone: done });
|
||||
|
||||
env.describe('test suite', function(){
|
||||
env.it('spec 0', function(){
|
||||
@@ -928,7 +929,14 @@ describe("Env integration", function() {
|
||||
});
|
||||
|
||||
it("should run async specs in order, waiting for them to complete", function(done) {
|
||||
var env = new jasmineUnderTest.Env(), mutatedVar;
|
||||
var env = new jasmineUnderTest.Env(),
|
||||
reporter = jasmine.createSpyObj('reporter', ['jasmineDone']),
|
||||
mutatedVar;
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
done();
|
||||
});
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("tests", function() {
|
||||
env.beforeEach(function() {
|
||||
@@ -939,7 +947,6 @@ describe("Env integration", function() {
|
||||
setTimeout(function() {
|
||||
expect(mutatedVar).toEqual(2);
|
||||
underTestCallback();
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
@@ -1110,14 +1117,18 @@ describe("Env integration", function() {
|
||||
|
||||
env.describe('suite', function() {
|
||||
env.afterAll(function() {
|
||||
realSetTimeout(function() {
|
||||
jasmine.clock().tick(10);
|
||||
}, 100);
|
||||
if (jasmine.getEnv().ieVersion < 9) {
|
||||
} else {
|
||||
realSetTimeout(function() {
|
||||
jasmine.clock().tick(10);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
env.describe('beforeAll', function() {
|
||||
env.beforeAll(function(innerDone) {
|
||||
jasmine.clock().tick(5001);
|
||||
innerDone();
|
||||
realSetTimeout(function() {
|
||||
jasmine.clock().tick(5001);
|
||||
}, 0);
|
||||
}, 5000);
|
||||
|
||||
env.it('times out', function() {});
|
||||
@@ -1125,8 +1136,9 @@ describe("Env integration", function() {
|
||||
|
||||
env.describe('afterAll', function() {
|
||||
env.afterAll(function(innerDone) {
|
||||
jasmine.clock().tick(2001);
|
||||
innerDone();
|
||||
realSetTimeout(function() {
|
||||
jasmine.clock().tick(2001);
|
||||
}, 0);
|
||||
}, 2000);
|
||||
|
||||
env.it('times out', function() {});
|
||||
@@ -1134,8 +1146,9 @@ describe("Env integration", function() {
|
||||
|
||||
env.describe('beforeEach', function() {
|
||||
env.beforeEach(function(innerDone) {
|
||||
jasmine.clock().tick(1001);
|
||||
innerDone();
|
||||
realSetTimeout(function() {
|
||||
jasmine.clock().tick(1001);
|
||||
}, 0);
|
||||
}, 1000);
|
||||
|
||||
env.it('times out', function() {});
|
||||
@@ -1143,16 +1156,18 @@ describe("Env integration", function() {
|
||||
|
||||
env.describe('afterEach', function() {
|
||||
env.afterEach(function(innerDone) {
|
||||
jasmine.clock().tick(4001);
|
||||
innerDone();
|
||||
realSetTimeout(function() {
|
||||
jasmine.clock().tick(4001);
|
||||
}, 0);
|
||||
}, 4000);
|
||||
|
||||
env.it('times out', function() {});
|
||||
});
|
||||
|
||||
env.it('it times out', function(innerDone) {
|
||||
jasmine.clock().tick(6001);
|
||||
innerDone();
|
||||
realSetTimeout(function() {
|
||||
jasmine.clock().tick(6001);
|
||||
}, 0);
|
||||
}, 6000);
|
||||
});
|
||||
|
||||
|
||||
@@ -393,6 +393,13 @@ describe("matchersUtil", function() {
|
||||
expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(true);
|
||||
});
|
||||
|
||||
it("passes when comparing identical sets with different insertion order", function() {
|
||||
jasmine.getEnv().requireFunctioningSets();
|
||||
var setA = new Set([3, 6]);
|
||||
var setB = new Set([6, 3]);
|
||||
expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for sets with different elements", function() {
|
||||
jasmine.getEnv().requireFunctioningSets();
|
||||
var setA = new Set([6, 3, 5]);
|
||||
@@ -407,13 +414,6 @@ describe("matchersUtil", function() {
|
||||
expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(false);
|
||||
});
|
||||
|
||||
it("fails for sets with different insertion order", function() {
|
||||
jasmine.getEnv().requireFunctioningSets();
|
||||
var setA = new Set([3, 6]);
|
||||
var setB = new Set([6, 3]);
|
||||
expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(false);
|
||||
});
|
||||
|
||||
it("passes when comparing two empty maps", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
expect(jasmineUnderTest.matchersUtil.equals(new Map(), new Map())).toBe(true);
|
||||
@@ -427,6 +427,13 @@ describe("matchersUtil", function() {
|
||||
expect(jasmineUnderTest.matchersUtil.equals(mapA, mapB)).toBe(true);
|
||||
});
|
||||
|
||||
it("passes when comparing identical maps with different insertion order", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
var mapA = new Map([['a', 3], [6, 1]]);
|
||||
var mapB = new Map([[6, 1], ['a', 3]]);
|
||||
expect(jasmineUnderTest.matchersUtil.equals(mapA, mapB)).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for maps with different elements", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
var mapA = new Map([[6, 3], [5, 1]]);
|
||||
@@ -441,13 +448,6 @@ describe("matchersUtil", function() {
|
||||
expect(jasmineUnderTest.matchersUtil.equals(mapA, mapB)).toBe(false);
|
||||
});
|
||||
|
||||
it("fails for maps with different insertion order", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
var mapA = new Map([['a', 3], [6, 1]]);
|
||||
var mapB = new Map([[6, 1], ['a', 3]]);
|
||||
expect(jasmineUnderTest.matchersUtil.equals(mapA, mapB)).toBe(false);
|
||||
});
|
||||
|
||||
describe("when running in an environment with array polyfills", function() {
|
||||
// IE 8 doesn't support `definePropery` on non-DOM nodes
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
8
spec/core/matchers/nothingSpec.js
Normal file
8
spec/core/matchers/nothingSpec.js
Normal file
@@ -0,0 +1,8 @@
|
||||
describe('nothing', function() {
|
||||
it('should pass', function() {
|
||||
var matcher = jasmineUnderTest.matchers.nothing(),
|
||||
result = matcher.compare();
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -161,8 +161,8 @@ describe("toEqual", function() {
|
||||
it("uses the default failure message given arrays with different lengths", function() {
|
||||
var actual = [1, 2],
|
||||
expected = [1, 2, 3],
|
||||
message =
|
||||
"Expected [ 1, 2 ] to equal [ 1, 2, 3 ].";
|
||||
message = 'Expected $.length = 2 to equal 3.\n' +
|
||||
'Expected $[2] = undefined to equal 3.';
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
@@ -211,6 +211,16 @@ describe("toEqual", function() {
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("reports mismatches between arrays of different types", function() {
|
||||
jasmine.getEnv().requireFunctioningTypedArrays();
|
||||
|
||||
var actual = new Uint32Array([1, 2, 3]),
|
||||
expected = new Uint16Array([1, 2, 3]),
|
||||
message = "Expected Uint32Array [ 1, 2, 3 ] to equal Uint16Array [ 1, 2, 3 ].";
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("reports mismatches involving NaN", function() {
|
||||
var actual = {x: 0},
|
||||
expected = {x: 0/0},
|
||||
@@ -359,8 +369,9 @@ describe("toEqual", function() {
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("does not report deep mismatches within Sets", function() {
|
||||
// TODO: implement deep comparison of set elements
|
||||
// == Sets ==
|
||||
|
||||
it("reports mismatches between Sets", function() {
|
||||
jasmine.getEnv().requireFunctioningSets();
|
||||
|
||||
var actual = new Set([1]),
|
||||
@@ -370,6 +381,16 @@ describe("toEqual", function() {
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("reports deep mismatches within Sets", function() {
|
||||
jasmine.getEnv().requireFunctioningSets();
|
||||
|
||||
var actual = new Set([{x: 1}]),
|
||||
expected = new Set([{x: 2}]),
|
||||
message = 'Expected Set( Object({ x: 1 }) ) to equal Set( Object({ x: 2 }) ).';
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("reports mismatches between Sets nested in objects", function() {
|
||||
jasmine.getEnv().requireFunctioningSets();
|
||||
|
||||
@@ -390,13 +411,46 @@ describe("toEqual", function() {
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("does not report deep mismatches within Maps", function() {
|
||||
// TODO: implement deep comparison of Map elements
|
||||
it("reports mismatches between Sets where actual is missing a value from expected", function() {
|
||||
jasmine.getEnv().requireFunctioningSets();
|
||||
|
||||
// Use 'duplicate' object in actual so sizes match
|
||||
var actual = new Set([{x: 1}, {x: 1}]),
|
||||
expected = new Set([{x: 1}, {x: 2}]),
|
||||
message = 'Expected Set( Object({ x: 1 }), Object({ x: 1 }) ) to equal Set( Object({ x: 1 }), Object({ x: 2 }) ).';
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("reports mismatches between Sets where actual has a value missing from expected", function() {
|
||||
jasmine.getEnv().requireFunctioningSets();
|
||||
|
||||
// Use 'duplicate' object in expected so sizes match
|
||||
var actual = new Set([{x: 1}, {x: 2}]),
|
||||
expected = new Set([{x: 1}, {x: 1}]),
|
||||
message = 'Expected Set( Object({ x: 1 }), Object({ x: 2 }) ) to equal Set( Object({ x: 1 }), Object({ x: 1 }) ).';
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
// == Maps ==
|
||||
|
||||
it("does not report mismatches between deep equal Maps", function() {
|
||||
jasmine.getEnv().requireFunctioningSets();
|
||||
|
||||
// values are the same but with different object identity
|
||||
var actual = new Map([['a', {x: 1}]]),
|
||||
expected = new Map([['a', {x: 1}]]);
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(true);
|
||||
});
|
||||
|
||||
it("reports deep mismatches within Maps", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
|
||||
var actual = new Map([['a', 1]]),
|
||||
expected = new Map([['a', 2]]),
|
||||
message = "Expected Map( [ 'a', 1 ] ) to equal Map( [ 'a', 2 ] ).";
|
||||
var actual = new Map([['a', {x: 1}]]),
|
||||
expected = new Map([['a', {x: 2}]]),
|
||||
message = "Expected Map( [ 'a', Object({ x: 1 }) ] ) to equal Map( [ 'a', Object({ x: 2 }) ] ).";
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
@@ -405,8 +459,8 @@ describe("toEqual", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
|
||||
var actual = {Maps: [new Map([['a', 1]])]},
|
||||
expected = {Maps: [new Map([['a', 2], ['b', 1]])]},
|
||||
message = "Expected $.Maps[0] = Map( [ 'a', 1 ] ) to equal Map( [ 'a', 2 ], [ 'b', 1 ] ).";
|
||||
expected = {Maps: [new Map([['a', 2]])]},
|
||||
message = "Expected $.Maps[0] = Map( [ 'a', 1 ] ) to equal Map( [ 'a', 2 ] ).";
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
@@ -415,11 +469,40 @@ describe("toEqual", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
|
||||
var actual = new Map([['a', 1]]),
|
||||
expected = new Map([['a', 2]]),
|
||||
message = "Expected Map( [ 'a', 1 ] ) to equal Map( [ 'a', 2 ] ).";
|
||||
expected = new Map([['a', 2], ['b', 1]]),
|
||||
message = "Expected Map( [ 'a', 1 ] ) to equal Map( [ 'a', 2 ], [ 'b', 1 ] ).";
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
});
|
||||
|
||||
it("reports mismatches between Maps with equal values but differing keys", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
|
||||
var actual = new Map([['a', 1]]),
|
||||
expected = new Map([['b', 1]]),
|
||||
message = "Expected Map( [ 'a', 1 ] ) to equal Map( [ 'b', 1 ] ).";
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("does not report mismatches between Maps with keys with same object identity", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
var key = {x: 1},
|
||||
actual = new Map([[key, 2]]),
|
||||
expected = new Map([[key, 2]]);
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(true);
|
||||
});
|
||||
|
||||
it("reports mismatches between Maps with identical keys with different object identity", function() {
|
||||
jasmine.getEnv().requireFunctioningMaps();
|
||||
|
||||
var actual = new Map([[{x: 1}, 2]]),
|
||||
expected = new Map([[{x: 1}, 2]]),
|
||||
message = "Expected Map( [ Object({ x: 1 }), 2 ] ) to equal Map( [ Object({ x: 1 }), 2 ] ).";
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
function isNotRunningInBrowser() {
|
||||
return typeof document === 'undefined'
|
||||
@@ -487,9 +570,9 @@ describe("toEqual", function() {
|
||||
|
||||
it("does not report a mismatch when asymmetric matchers are satisfied", function() {
|
||||
var actual = {a: 'a'},
|
||||
expected = {a: jasmineUnderTest.any(String)},
|
||||
message = 'Expected $.a = 1 to equal <jasmine.any(String)>.';
|
||||
expected = {a: jasmineUnderTest.any(String)};
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual('');
|
||||
expect(compareEquals(actual, expected).pass).toBe(true)
|
||||
});
|
||||
|
||||
@@ -530,7 +613,8 @@ describe("toEqual", function() {
|
||||
|
||||
var message =
|
||||
'Expected $.foo[0].bar = 1 to equal 2.\n' +
|
||||
"Expected $.foo[0].things = [ 'a', 'b' ] to equal [ 'a', 'b', 'c' ].\n" +
|
||||
'Expected $.foo[0].things.length = 2 to equal 3.\n' +
|
||||
"Expected $.foo[0].things[2] = undefined to equal 'c'.\n" +
|
||||
"Expected $.foo[1].things[1] = 'b' to equal 'd'.\n" +
|
||||
'Expected $.baz[0].a to have properties\n' +
|
||||
' c: 1\n' +
|
||||
@@ -544,4 +628,92 @@ describe("toEqual", function() {
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
})
|
||||
|
||||
describe("different length arrays", function() {
|
||||
it("actual array is longer", function() {
|
||||
var actual = [1, 1, 2, 3, 5],
|
||||
expected = [1, 1, 2, 3],
|
||||
message = 'Expected $.length = 5 to equal 4.\n' +
|
||||
'Expected $[4] = 5 to equal undefined.';
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(false)
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("expected array is longer", function() {
|
||||
var actual = [1, 1, 2, 3],
|
||||
expected = [1, 1, 2, 3, 5],
|
||||
message = 'Expected $.length = 4 to equal 5.\n' +
|
||||
'Expected $[4] = undefined to equal 5.';
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(false)
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("expected array is longer by 4 elements", function() {
|
||||
var actual = [1, 1, 2],
|
||||
expected = [1, 1, 2, 3, 5, 8, 13],
|
||||
message = 'Expected $.length = 3 to equal 7.\n' +
|
||||
'Expected $[3] = undefined to equal 3.\n' +
|
||||
'Expected $[4] = undefined to equal 5.\n' +
|
||||
'Expected $[5] = undefined to equal 8.\n' +
|
||||
'Expected $[6] = undefined to equal 13.';
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(false)
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("different length and different elements", function() {
|
||||
var actual = [1],
|
||||
expected = [2, 3],
|
||||
message = 'Expected $.length = 1 to equal 2.\n' +
|
||||
'Expected $[0] = 1 to equal 2.\n' +
|
||||
'Expected $[1] = undefined to equal 3.';
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(false)
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("object with nested array", function() {
|
||||
var actual = { values: [1, 1, 2, 3] },
|
||||
expected = { values: [1, 1, 2] },
|
||||
message = 'Expected $.values.length = 4 to equal 3.\n' +
|
||||
'Expected $.values[3] = 3 to equal undefined.';
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(false)
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("array with nested object", function() {
|
||||
var actual = [1, 1, 2, { value: 3 }],
|
||||
expected = [1, 1, 2],
|
||||
message = 'Expected $.length = 4 to equal 3.\n' +
|
||||
'Expected $[3] = Object({ value: 3 }) to equal undefined.';
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(false)
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("array with nested different length array", function() {
|
||||
var actual = [[1], [1, 2]],
|
||||
expected = [[1, 1], [2]],
|
||||
message = 'Expected $[0].length = 1 to equal 2.\n' +
|
||||
'Expected $[0][1] = undefined to equal 1.\n' +
|
||||
'Expected $[1].length = 2 to equal 1.\n' +
|
||||
'Expected $[1][0] = 1 to equal 2.\n' +
|
||||
'Expected $[1][1] = 2 to equal undefined.';
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(false)
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("last element of longer array is undefined", function() {
|
||||
var actual = [1, 2],
|
||||
expected = [1, 2, void 0],
|
||||
message = 'Expected $.length = 2 to equal 3.';
|
||||
|
||||
expect(compareEquals(actual, expected).pass).toBe(false)
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
20
spec/helpers/checkForTypedArrays.js
Normal file
20
spec/helpers/checkForTypedArrays.js
Normal file
@@ -0,0 +1,20 @@
|
||||
(function(env) {
|
||||
function hasFunctioningTypedArrays() {
|
||||
if (typeof Uint32Array === 'undefined') { return false; }
|
||||
|
||||
try {
|
||||
var a = new Uint32Array([1, 2, 3]);
|
||||
if (a.length !== 3) { return false; }
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
env.requireFunctioningTypedArrays = function() {
|
||||
if (!hasFunctioningTypedArrays()) {
|
||||
env.pending("Browser has incomplete or missing support for typed arrays");
|
||||
}
|
||||
};
|
||||
|
||||
})(jasmine.getEnv());
|
||||
@@ -9,6 +9,7 @@
|
||||
"helpers/asyncAwait.js",
|
||||
"helpers/checkForSet.js",
|
||||
"helpers/checkForMap.js",
|
||||
"helpers/checkForTypedArrays.js",
|
||||
"helpers/nodeDefineJasmineUnderTest.js"
|
||||
],
|
||||
"random": true
|
||||
|
||||
@@ -20,6 +20,7 @@ helpers:
|
||||
- 'helpers/BrowserFlags.js'
|
||||
- 'helpers/checkForSet.js'
|
||||
- 'helpers/checkForMap.js'
|
||||
- 'helpers/checkForTypedArrays.js'
|
||||
- 'helpers/defineJasmineUnderTest.js'
|
||||
spec_files:
|
||||
- '**/*[Ss]pec.js'
|
||||
|
||||
@@ -11,10 +11,13 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
||||
var clonedArgs = [];
|
||||
var argsAsArray = j$.util.argsToArray(context.args);
|
||||
for(var i = 0; i < argsAsArray.length; i++) {
|
||||
if(Object.prototype.toString.apply(argsAsArray[i]).match(/^\[object/)) {
|
||||
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
||||
} else {
|
||||
var str = Object.prototype.toString.apply(argsAsArray[i]),
|
||||
primitives = /^\[object (Boolean|String|RegExp|Number)/;
|
||||
|
||||
if (argsAsArray[i] == null || str.match(primitives)) {
|
||||
clonedArgs.push(argsAsArray[i]);
|
||||
} else {
|
||||
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
||||
}
|
||||
}
|
||||
context.args = clonedArgs;
|
||||
|
||||
@@ -37,12 +37,56 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
return currentSpec || currentSuite();
|
||||
};
|
||||
|
||||
/**
|
||||
* This represents the available reporter callback for an object passed to {@link Env#addReporter}.
|
||||
* @interface Reporter
|
||||
*/
|
||||
var reporter = new j$.ReportDispatcher([
|
||||
/**
|
||||
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
||||
* @function
|
||||
* @name Reporter#jasmineStarted
|
||||
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
|
||||
*/
|
||||
'jasmineStarted',
|
||||
/**
|
||||
* When the entire suite has finished execution `jasmineDone` is called
|
||||
* @function
|
||||
* @name Reporter#jasmineDone
|
||||
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
|
||||
*/
|
||||
'jasmineDone',
|
||||
/**
|
||||
* `suiteStarted` is invoked when a `describe` starts to run
|
||||
* @function
|
||||
* @name Reporter#suiteStarted
|
||||
* @param {SuiteResult} result Information about the individual {@link describe} being run
|
||||
*/
|
||||
'suiteStarted',
|
||||
/**
|
||||
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
|
||||
*
|
||||
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
|
||||
* @function
|
||||
* @name Reporter#suiteDone
|
||||
* @param {SuiteResult} result
|
||||
*/
|
||||
'suiteDone',
|
||||
/**
|
||||
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
|
||||
* @function
|
||||
* @name Reporter#specStarted
|
||||
* @param {SpecResult} result Information about the individual {@link it} being run
|
||||
*/
|
||||
'specStarted',
|
||||
/**
|
||||
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
|
||||
*
|
||||
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
|
||||
* @function
|
||||
* @name Reporter#specDone
|
||||
* @param {SpecResult} result
|
||||
*/
|
||||
'specDone'
|
||||
]);
|
||||
|
||||
@@ -258,6 +302,12 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
throw new Error('Invalid order: would cause a beforeAll or afterAll to be run multiple times');
|
||||
}
|
||||
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineStarted} event.
|
||||
* @typedef JasmineStartedInfo
|
||||
* @property {Int} totalSpecsDefined - The total number of specs defined in this suite.
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
*/
|
||||
reporter.jasmineStarted({
|
||||
totalSpecsDefined: totalSpecsDefined,
|
||||
order: order
|
||||
@@ -271,6 +321,12 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
currentlyExecutingSuites.pop();
|
||||
globalErrors.uninstall();
|
||||
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineDone} event.
|
||||
* @typedef JasmineDoneInfo
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
* @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
||||
*/
|
||||
reporter.jasmineDone({
|
||||
order: order,
|
||||
failedExpectations: topSuite.result.failedExpectations
|
||||
@@ -282,6 +338,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* Add a custom reporter to the Jasmine environment.
|
||||
* @name Env#addReporter
|
||||
* @function
|
||||
* @param {Reporter} reporterToAdd The reporter to be added.
|
||||
* @see custom_reporter
|
||||
*/
|
||||
this.addReporter = function(reporterToAdd) {
|
||||
|
||||
@@ -4,6 +4,15 @@ getJasmineRequireObj().buildExpectationResult = function() {
|
||||
var messageFormatter = options.messageFormatter || function() {},
|
||||
stackFormatter = options.stackFormatter || function() {};
|
||||
|
||||
/**
|
||||
* @typedef Expectation
|
||||
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
||||
* @property {String} message - The failure message for the expectation.
|
||||
* @property {String} stack - The stack trace for the failure if available.
|
||||
* @property {Boolean} passed - Whether the expectation passed or failed.
|
||||
* @property {Object} expected - If the expectation failed, what was the expected value.
|
||||
* @property {Object} actual - If the expectation failed, what actual value was produced.
|
||||
*/
|
||||
var result = {
|
||||
matcherName: options.matcherName,
|
||||
message: message(),
|
||||
|
||||
@@ -6,11 +6,10 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, use the global `jsApiReporter` to retrieve the instantiated object.
|
||||
*
|
||||
* @name jsApiReporter
|
||||
* @classdesc Reporter added by default in `boot.js` to record results for retrieval in javascript code.
|
||||
* @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.
|
||||
* @class
|
||||
* @hideconstructor
|
||||
*/
|
||||
function JsApiReporter(options) {
|
||||
var timer = options.timer || noopTimer,
|
||||
@@ -64,7 +63,7 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
* @function
|
||||
* @param {Number} index - The position in the suites list to start from.
|
||||
* @param {Number} length - Maximum number of suite results to return.
|
||||
* @return {Object[]}
|
||||
* @return {SuiteResult[]}
|
||||
*/
|
||||
this.suiteResults = function(index, length) {
|
||||
return suites.slice(index, index + length);
|
||||
@@ -79,7 +78,7 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
* Get all of the suites in a single object, with their `id` as the key.
|
||||
* @name jsApiReporter#suites
|
||||
* @function
|
||||
* @return {Object}
|
||||
* @return {Object} - Map of suite id to {@link SuiteResult}
|
||||
*/
|
||||
this.suites = function() {
|
||||
return suites_hash;
|
||||
@@ -99,7 +98,7 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
* @function
|
||||
* @param {Number} index - The position in the specs list to start from.
|
||||
* @param {Number} length - Maximum number of specs results to return.
|
||||
* @return {Object[]}
|
||||
* @return {SpecResult[]}
|
||||
*/
|
||||
this.specResults = function(index, length) {
|
||||
return specs.slice(index, index + length);
|
||||
@@ -109,7 +108,7 @@ getJasmineRequireObj().JsApiReporter = function() {
|
||||
* Get all spec results.
|
||||
* @name jsApiReporter#specs
|
||||
* @function
|
||||
* @return {Object[]}
|
||||
* @return {SpecResult[]}
|
||||
*/
|
||||
this.specs = function() {
|
||||
return specs;
|
||||
|
||||
@@ -40,6 +40,8 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.emitSet(value);
|
||||
} else if (j$.getType_(value) == '[object Map]') {
|
||||
this.emitMap(value);
|
||||
} else if (j$.isTypedArray_(value)) {
|
||||
this.emitTypedArray(value);
|
||||
} else if (value.toString && typeof value === 'object' && !j$.isArray_(value) && hasCustomToString(value)) {
|
||||
this.emitScalar(value.toString());
|
||||
} else if (j$.util.arrayContains(this.seen, value)) {
|
||||
@@ -210,6 +212,18 @@ getJasmineRequireObj().pp = function(j$) {
|
||||
this.append(' })');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.emitTypedArray = function(arr) {
|
||||
var constructorName = j$.fnNameFor(arr.constructor),
|
||||
limitedArray = Array.prototype.slice.call(arr, 0, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH),
|
||||
itemsString = Array.prototype.join.call(limitedArray, ', ');
|
||||
|
||||
if (limitedArray.length !== arr.length) {
|
||||
itemsString += ', ...';
|
||||
}
|
||||
|
||||
this.append(constructorName + ' [ ' + itemsString + ' ]');
|
||||
};
|
||||
|
||||
StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {
|
||||
this.append(property);
|
||||
this.append(': ');
|
||||
|
||||
@@ -18,6 +18,16 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
this.pend();
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef SpecResult
|
||||
* @property {Int} id - The unique id of this spec.
|
||||
* @property {String} description - The description passed to the {@link it} that created this spec.
|
||||
* @property {String} fullName - The full description including all ancestors of this spec.
|
||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
||||
* @property {Expectation[]} passedExpectations - The list of expectations that passed during execution of 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.
|
||||
*/
|
||||
this.result = {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
|
||||
@@ -15,6 +15,14 @@ getJasmineRequireObj().Suite = function(j$) {
|
||||
|
||||
this.children = [];
|
||||
|
||||
/**
|
||||
* @typedef SuiteResult
|
||||
* @property {Int} id - The unique id of this suite.
|
||||
* @property {String} description - The description text passed to the {@link describe} that made this suite.
|
||||
* @property {String} fullName - The full description including all ancestors of this suite.
|
||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
||||
* @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
|
||||
*/
|
||||
this.result = {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
|
||||
@@ -4,8 +4,9 @@ getJasmineRequireObj().ArrayContaining = function(j$) {
|
||||
}
|
||||
|
||||
ArrayContaining.prototype.asymmetricMatch = function(other, customTesters) {
|
||||
var className = Object.prototype.toString.call(this.sample);
|
||||
if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); }
|
||||
if (!j$.isArray_(this.sample)) {
|
||||
throw new Error('You must provide an array to arrayContaining, not ' + j$.pp(this.sample) + '.');
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.sample.length; i++) {
|
||||
var item = this.sample[i];
|
||||
|
||||
31
src/core/asymmetric_equality/ArrayWithExactContents.js
Normal file
31
src/core/asymmetric_equality/ArrayWithExactContents.js
Normal file
@@ -0,0 +1,31 @@
|
||||
getJasmineRequireObj().ArrayWithExactContents = function(j$) {
|
||||
|
||||
function ArrayWithExactContents(sample) {
|
||||
this.sample = sample;
|
||||
}
|
||||
|
||||
ArrayWithExactContents.prototype.asymmetricMatch = function(other, customTesters) {
|
||||
if (!j$.isArray_(this.sample)) {
|
||||
throw new Error('You must provide an array to arrayWithExactContents, not ' + j$.pp(this.sample) + '.');
|
||||
}
|
||||
|
||||
if (this.sample.length !== other.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.sample.length; i++) {
|
||||
var item = this.sample[i];
|
||||
if (!j$.matchersUtil.contains(other, item, customTesters)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
ArrayWithExactContents.prototype.jasmineToString = function() {
|
||||
return '<jasmine.arrayWithExactContents ' + j$.pp(this.sample) + '>';
|
||||
};
|
||||
|
||||
return ArrayWithExactContents;
|
||||
};
|
||||
@@ -63,6 +63,18 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return j$.isA_('AsyncFunction', value);
|
||||
};
|
||||
|
||||
j$.isTypedArray_ = function(value) {
|
||||
return j$.isA_('Float32Array', value) ||
|
||||
j$.isA_('Float64Array', value) ||
|
||||
j$.isA_('Int16Array', value) ||
|
||||
j$.isA_('Int32Array', value) ||
|
||||
j$.isA_('Int8Array', value) ||
|
||||
j$.isA_('Uint16Array', value) ||
|
||||
j$.isA_('Uint32Array', value) ||
|
||||
j$.isA_('Uint8Array', value) ||
|
||||
j$.isA_('Uint8ClampedArray', value);
|
||||
};
|
||||
|
||||
j$.isA_ = function(typeName, value) {
|
||||
return j$.getType_(value) === '[object ' + typeName + ']';
|
||||
};
|
||||
@@ -80,7 +92,9 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return func.name;
|
||||
}
|
||||
|
||||
var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/);
|
||||
var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/) ||
|
||||
func.toString().match(/^\s*\[object\s*(\w*)Constructor\]/);
|
||||
|
||||
return matches ? matches[1] : '<anonymous>';
|
||||
};
|
||||
|
||||
@@ -138,6 +152,17 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return new j$.ArrayContaining(sample);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
|
||||
* that will succeed if the actual value is an `Array` that contains all of the elements in the sample in any order.
|
||||
* @name jasmine.arrayWithExactContents
|
||||
* @function
|
||||
* @param {Array} sample
|
||||
*/
|
||||
j$.arrayWithExactContents = function(sample) {
|
||||
return new j$.ArrayWithExactContents(sample);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a bare {@link Spy} object. This won't be installed anywhere and will not have any implementation behind it.
|
||||
* @name jasmine.createSpy
|
||||
|
||||
@@ -66,13 +66,17 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
||||
|
||||
if (asymmetricA) {
|
||||
result = a.asymmetricMatch(b, customTesters);
|
||||
diffBuilder.record(a, b);
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (asymmetricB) {
|
||||
result = b.asymmetricMatch(a, customTesters);
|
||||
diffBuilder.record(a, b);
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -225,35 +229,84 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
||||
// Recursively compare objects and arrays.
|
||||
// Compare array lengths to determine if a deep comparison is necessary.
|
||||
if (className == '[object Array]') {
|
||||
size = a.length;
|
||||
if (size !== b.length) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
var aLength = a.length;
|
||||
var bLength = b.length;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
diffBuilder.withPath('length', function() {
|
||||
if (aLength !== bLength) {
|
||||
diffBuilder.record(aLength, bLength);
|
||||
result = false;
|
||||
}
|
||||
});
|
||||
|
||||
for (i = 0; i < aLength || i < bLength; i++) {
|
||||
diffBuilder.withPath(i, function() {
|
||||
result = eq(a[i], b[i], aStack, bStack, customTesters, diffBuilder) && result;
|
||||
result = eq(i < aLength ? a[i] : void 0, i < bLength ? b[i] : void 0, aStack, bStack, customTesters, diffBuilder) && result;
|
||||
});
|
||||
}
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
} else if (className == '[object Set]' || className == '[object Map]') {
|
||||
} else if (className == '[object Map]') {
|
||||
if (a.size != b.size) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
var iterA = a.entries(), iterB = b.entries();
|
||||
var valA, valB;
|
||||
do {
|
||||
valA = iterA.next();
|
||||
valB = iterB.next();
|
||||
if (!eq(valA.value, valB.value, aStack, bStack, customTesters, j$.NullDiffBuilder())) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
|
||||
// For both sets of keys, check they map to equal values in both maps
|
||||
var mapKeys = [a.keys(), b.keys()];
|
||||
var mapIter, mapKeyIt, mapKey;
|
||||
for (i = 0; result && i < mapKeys.length; i++) {
|
||||
mapIter = mapKeys[i];
|
||||
mapKeyIt = mapIter.next();
|
||||
while (result && !mapKeyIt.done) {
|
||||
mapKey = mapKeyIt.value;
|
||||
result = eq(a.get(mapKey), b.get(mapKey), aStack, bStack, customTesters, j$.NullDiffBuilder());
|
||||
mapKeyIt = mapIter.next();
|
||||
}
|
||||
} while (!valA.done && !valB.done);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
} else if (className == '[object Set]') {
|
||||
if (a.size != b.size) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
|
||||
// For both sets, check they are all contained in the other set
|
||||
var setPairs = [[a, b], [b, a]];
|
||||
var baseIter, baseValueIt, baseValue;
|
||||
var otherSet, otherIter, otherValueIt, otherValue, found;
|
||||
for (i = 0; result && i < setPairs.length; i++) {
|
||||
baseIter = setPairs[i][0].values();
|
||||
otherSet = setPairs[i][1];
|
||||
// For each value in the base set...
|
||||
baseValueIt = baseIter.next();
|
||||
while (result && !baseValueIt.done) {
|
||||
baseValue = baseValueIt.value;
|
||||
// ... test that it is present in the other set
|
||||
otherIter = otherSet.values();
|
||||
otherValueIt = otherIter.next();
|
||||
// Optimisation: start looking for value by object identity
|
||||
found = otherSet.has(baseValue);
|
||||
// If not found, compare by value equality
|
||||
while (!found && !otherValueIt.done) {
|
||||
otherValue = otherValueIt.value;
|
||||
found = eq(baseValue, otherValue, aStack, bStack, customTesters, j$.NullDiffBuilder());
|
||||
otherValueIt = otherIter.next();
|
||||
}
|
||||
result = result && found;
|
||||
baseValueIt = baseIter.next();
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
diffBuilder.record(a, b);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
||||
// Objects with different constructors are not equivalent, but `Object`s
|
||||
|
||||
20
src/core/matchers/nothing.js
Normal file
20
src/core/matchers/nothing.js
Normal file
@@ -0,0 +1,20 @@
|
||||
getJasmineRequireObj().nothing = function() {
|
||||
/**
|
||||
* {@link expect} nothing explicitly.
|
||||
* @function
|
||||
* @name matchers#nothing
|
||||
* @example
|
||||
* expect().nothing();
|
||||
*/
|
||||
function nothing() {
|
||||
return {
|
||||
compare: function() {
|
||||
return {
|
||||
pass: true
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return nothing;
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
|
||||
var availableMatchers = [
|
||||
'nothing',
|
||||
'toBe',
|
||||
'toBeCloseTo',
|
||||
'toBeDefined',
|
||||
|
||||
@@ -41,6 +41,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
j$.matchersUtil = jRequire.matchersUtil(j$);
|
||||
j$.ObjectContaining = jRequire.ObjectContaining(j$);
|
||||
j$.ArrayContaining = jRequire.ArrayContaining(j$);
|
||||
j$.ArrayWithExactContents = jRequire.ArrayWithExactContents(j$);
|
||||
j$.pp = jRequire.pp(j$);
|
||||
j$.QueueRunner = jRequire.QueueRunner(j$);
|
||||
j$.ReportDispatcher = jRequire.ReportDispatcher();
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
var jasmineInterface = {
|
||||
/**
|
||||
* Callback passed to parts of the Jasmine base interface.
|
||||
*
|
||||
* By default Jasmine assumes this function completes synchronously.
|
||||
* If you have code that you need to test asynchronously, you can declare that you receive a `done` callback, return a Promise, or use the `async` keyword if it is supported in your environment.
|
||||
* @callback implementationCallback
|
||||
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
|
||||
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a group of specs (often called a suite).
|
||||
*
|
||||
@@ -8,7 +18,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of the group
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites and specs
|
||||
*/
|
||||
describe: function(description, specDefinitions) {
|
||||
return env.describe(description, specDefinitions);
|
||||
@@ -22,7 +32,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of the group
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites and specs
|
||||
*/
|
||||
xdescribe: function(description, specDefinitions) {
|
||||
return env.xdescribe(description, specDefinitions);
|
||||
@@ -37,7 +47,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of the group
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs
|
||||
* @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites and specs
|
||||
*/
|
||||
fdescribe: function(description, specDefinitions) {
|
||||
return env.fdescribe(description, specDefinitions);
|
||||
@@ -51,7 +61,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of what this spec is checking
|
||||
* @param {Function} [testFunction] Function that contains the code of your test. If not provided the test will be `pending`.
|
||||
* @param {implementationCallback} [testFunction] Function that contains the code of your test. If not provided the test will be `pending`.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec.
|
||||
*/
|
||||
it: function() {
|
||||
@@ -66,7 +76,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of what this spec is checking.
|
||||
* @param {Function} [testFunction] Function that contains the code of your test. Will not be executed.
|
||||
* @param {implementationCallback} [testFunction] Function that contains the code of your test. Will not be executed.
|
||||
*/
|
||||
xit: function() {
|
||||
return env.xit.apply(env, arguments);
|
||||
@@ -80,7 +90,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {String} description Textual description of what this spec is checking.
|
||||
* @param {Function} testFunction Function that contains the code of your test.
|
||||
* @param {implementationCallback} testFunction Function that contains the code of your test.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec.
|
||||
*/
|
||||
fit: function() {
|
||||
@@ -92,7 +102,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @name beforeEach
|
||||
* @function
|
||||
* @global
|
||||
* @param {Function} [function] Function that contains the code to setup your specs.
|
||||
* @param {implementationCallback} [function] Function that contains the code to setup your specs.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeEach.
|
||||
*/
|
||||
beforeEach: function() {
|
||||
@@ -104,7 +114,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @name afterEach
|
||||
* @function
|
||||
* @global
|
||||
* @param {Function} [function] Function that contains the code to teardown your specs.
|
||||
* @param {implementationCallback} [function] Function that contains the code to teardown your specs.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterEach.
|
||||
*/
|
||||
afterEach: function() {
|
||||
@@ -118,7 +128,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @name beforeAll
|
||||
* @function
|
||||
* @global
|
||||
* @param {Function} [function] Function that contains the code to setup your specs.
|
||||
* @param {implementationCallback} [function] Function that contains the code to setup your specs.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeAll.
|
||||
*/
|
||||
beforeAll: function() {
|
||||
@@ -126,13 +136,13 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Run some shared teardown once before all of the specs in the {@link describe} are run.
|
||||
* Run some shared teardown once after all of the specs in the {@link describe} are run.
|
||||
*
|
||||
* _Note:_ Be careful, sharing the teardown from a afterAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail.
|
||||
* @name afterAll
|
||||
* @function
|
||||
* @global
|
||||
* @param {Function} [function] Function that contains the code to teardown your specs.
|
||||
* @param {implementationCallback} [function] Function that contains the code to teardown your specs.
|
||||
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterAll.
|
||||
*/
|
||||
afterAll: function() {
|
||||
|
||||
Reference in New Issue
Block a user