Skip to content

Commit

Permalink
Excuse assert count expected error in Backbone and add support for ex…
Browse files Browse the repository at this point in the history
…cusing them qunit-extras.
  • Loading branch information
jdalton committed May 16, 2014
1 parent 5850400 commit cba8f81
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 22 deletions.
9 changes: 9 additions & 0 deletions test/backbone.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ <h1>Test</h1>
QUnit.config.asyncRetries = 10;
QUnit.config.hidepassed = true;

// excuse tests we intentionally fail or those with problems
QUnit.config.excused = {
'Backbone.Router': {
'#1695 - hashChange to pushState with search.': [
'Expected 1 assertions, but 0 were run'
]
}
};

// load Lo-Dash
if (!ui.isModularize) {
document.write('<script src="' + ui.buildPath + '"><\/script>');
Expand Down
93 changes: 71 additions & 22 deletions vendor/qunit-extras/qunit-extras.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@
/** Used as a horizontal rule in console output */
var hr = '----------------------------------------';

/** Used for native method references */
var arrayProto = Array.prototype;

/** Native method shortcut */
var unshift = Array.prototype.unshift;
var push = arrayProto.push,
unshift = arrayProto.unshift;

/** Used to match HTML entities */
var reEscapedHtml = /(&amp;|&lt;|&gt;|&quot;|&#39;)/g;
Expand Down Expand Up @@ -145,6 +149,25 @@
return htmlUnescapes[match];
}

/**
* Creates a function that provides `value` to the wrapper function as its
* first argument. Additional arguments provided to the function are appended
* to those provided to the wrapper function. The wrapper is executed with
* the `this` binding of the created function.
*
* @private
* @param {*} value The value to wrap.
* @param {Function} wrapper The wrapper function.
* @returns {Function} Returns the new function.
*/
function wrap(value, wrapper) {
return function() {
var args = [value];
push.apply(args, arguments);
return wrapper.apply(this, args);
};
}

/*--------------------------------------------------------------------------*/

/**
Expand Down Expand Up @@ -401,17 +424,17 @@

// add a callback to be triggered at the start of every test
QUnit.testStart(function(details) {
var excused = QUnit.config.excused || {},
var config = QUnit.config,
test = config.current;

var excused = config.excused || {},
excusedTests = excused[details.module],
excusedAsserts = excusedTests && excusedTests[details.name];

var test = QUnit.config.current,
finish = test.finish;

// allow async tests to retry
if (test.async && !test.retries) {
test.retries = 0;
test.finish = function() {
test.finish = wrap(test.finish, function(finish) {
var asserts = this.assertions,
config = QUnit.config,
index = -1,
Expand All @@ -436,7 +459,7 @@
}
}
finish.call(this);
};
});
}
// nothing to excuse
if (!excusedAsserts) {
Expand All @@ -450,28 +473,54 @@
return;
}
// excuse specific assertions
test.finish = function() {
test.finish = wrap(test.finish, function(finish) {
var asserts = this.assertions,
index = -1,
length = asserts.length;
config = QUnit.config,
expected = this.expected,
items = asserts.slice(),
length = items.length;

if (expected == null) {
expected = 1;
if (config.requireExpects) {
items.push('Expected number of assertions to be defined, but expect() was not called.');
} else if (!length) {
items.push('Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.');
}
} else if (expected != length) {
items.push('Expected ' + expected + ' assertions, but ' + length + ' were run');
}
var index = -1;
length = items.length;

while (++index < length) {
var assert = asserts[index],
message = unescape(result(reMessage.exec(assert.message), 1)),
died = result(reDied.exec(message), 0),
expected = unescape(result(reExpected.exec(assert.message), 1));

if ((message && contains(excusedAsserts, message)) ||
(died && contains(excusedAsserts, died)) ||
(expected && (
contains(excusedAsserts, expected) ||
contains(excusedAsserts, expected.replace(/\s+/g, ''))
var assert = items[index],
isStr = typeof assert == 'string',
message = assert.message;

var assertMessage = isStr ? assert : unescape(result(reMessage.exec(message), 1)),
assertValue = isStr ? assert : unescape(result(reExpected.exec(message), 1)),
assertDied = result(reDied.exec(message), 0);

if ((assertMessage && contains(excusedAsserts, assertMessage)) ||
(assertDied && contains(excusedAsserts, assertDied)) ||
(assertValue && (
contains(excusedAsserts, assertValue) ||
contains(excusedAsserts, assertValue.replace(/\s+/g, ''))
))) {
assert.result = true;
if (isStr) {
while (asserts.length < expected) {
asserts.push({ 'result': true });
}
asserts.length = expected;
}
else {
assert.result = true;
}
}
}
finish.call(this);
};
});
});

// replace poisoned `raises` method
Expand Down

1 comment on commit cba8f81

@jdalton
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.