Skip to content
This repository has been archived by the owner on Aug 16, 2020. It is now read-only.

Commit

Permalink
Added printResolved() to support promises
Browse files Browse the repository at this point in the history
  • Loading branch information
ianb committed Apr 12, 2013
1 parent 5c3a85a commit 1bc8e9e
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 12 deletions.
61 changes: 61 additions & 0 deletions doctest.js
Expand Up @@ -673,6 +673,7 @@ Runner.prototype = {
var globs = {
write: this.write.bind(this),
writeln: this.writeln.bind(this),
printResolved: this.printResolved.bind(this),
wait: this.wait.bind(this),
Abort: this.Abort.bind(this),
repr: repr,
Expand Down Expand Up @@ -727,6 +728,65 @@ Runner.prototype = {
this.write('\n');
},

printResolved: function () {
// We used finished to signal that nothing should be printed, even when
// waiting is 0, as there are more arguments still to collect:
var finished = false;
var waiting = 0;
var fullValues = [];
var args = Array.prototype.slice.call(arguments);

// This function is called as each promise is resolved, to see if it
// was the last promise:
var check = (function (dec) {
waiting -= dec;
if (waiting || ! finished) {
return;
}
var flattened = [];
fullValues.forEach(function (items) {
items.forEach(function (item) {
flattened.push(item);
});
});
this.writeln.apply(this, flattened);
}).bind(this);

args.forEach(function (value, index) {
if (value.then) {
// It's a promise
waiting++;
value.then(
(function () {
var values = Array.prototype.slice.call(arguments);
if (! values.length) {
values.push("(resolved)");
}
fullValues[index] = values;
check(1);
}).bind(this),
(function () {
var errs = Array.prototype.slice.call(arguments);
if (! errs.length) {
errs.push("(error)");
}
errs = ["Error:"].concat(errs);
fullValues[index] = errs;
check(1);
}).bind(this));
} else {
fullValues[index] = [value];
}
}, this);
finished = true;
if (waiting) {
this.wait(function () {
return ! waiting;
});
}
check(0);
},

wait: function (conditionOrTime, hardTimeout) {
// FIXME: should support a timeout even with a condition
if (conditionOrTime === undefined ||
Expand Down Expand Up @@ -811,6 +871,7 @@ Runner.prototype = {
if (typeof window != 'undefined') {
window.write = undefined;
window.writeln = undefined;
window.printResolved = undefined;
window.print = undefined;
window.wait = undefined;
window.onerror = undefined;
Expand Down
49 changes: 37 additions & 12 deletions examples/examples.html
Expand Up @@ -116,27 +116,52 @@ <h3>Web Service/XML</h3>
What we do for JSON, we can also do for XML; in this case
it's just fetching a static XML Atom document.

<pre class="doctest">
$ $.ajax({
> url: './.resources/example.xml',
> dataType: 'xml',
> success: function (doc) {
> gdoc = doc;
> writeln(repr(doc));
> },
> error: Spy('error')
> });
$ wait(0.5);
<pre class="test">
$.ajax({
url: './.resources/example.xml',
dataType: 'xml',
success: function (doc) {
gdoc = doc;
writeln(repr(doc));
},
error: Spy('error')
});
wait(0.5);
/* =>
&lt;feed xmlns="http://www.w3.org/2005/Atom">
&lt;title>Example Feed&lt;/title>
...
&lt;/feed>
*/

</pre>

</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<h3>Deferred/Promise</h3>

<div class="test">

You can also
print <a href="http://api.jquery.com/category/deferred-object/">jquery.Deferred</a>
(promise) objects once they've resolved, using
the <code>printResolved()</code> function. This also implicitly
calls <code>wait()</code> with the condition that all the promises
be resolved. Both errors and resolved values are printed.

<pre class="test">
var def1 = $.Deferred();
var def2 = $.Deferred();
def1.resolve("Value 1!", "Value2!");
setTimeout(function () {
def2.reject("sucka");
}, 500);
printResolved("def1", def1, "def2", def2);
// => def1 Value 1! Value2! def2 Error: sucka
</pre>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<!-- FOOTER --></div>

Expand Down
29 changes: 29 additions & 0 deletions reference.html
Expand Up @@ -218,6 +218,35 @@ <h4 id="console"><code>console.log()</code></h3>

<p>All the methods on console should work, like <code>console.warn()</code>. The underlying normal console function is called, but in addition on a test-by-test basis these are collected and displayed.</p>

<h4 id="printResolved"><code>printResolved()</code> for Deferred and Promises</h4>

<p>There's special support for the jQuery <a href="http://api.jquery.com/category/deferred-object/">Deferred</a> object, and generally <a href="http://wiki.commonjs.org/wiki/Promises/A">Promises/A</a>.</p>

<p>This support is through the <code>printResolved()</code> function, which is basically equivalent to <code>print()</code> except any promise arguments will be waited on to resolve (proper resolution or an error). You can use it like this:</p>

<pre class="test">
var def = $.Deferred();
setTimeout(function () {
def.resolve("Resolved!");
});
printResolved(def);
// => Resolved!
</pre>

<p>Errors are printed out with <code>Error:</code> before the value, and multiple arguments are printed out with spaces between them, or a placeholder if there's no arguments. For instance:</p>

<pre class="test">
var def = $.Deferred();
def.reject({code: 1}, "a message");
printResolved(def);
// => Error: {code: 1} a message
// Or you might not have any value at all:
def = $.Deferred();
def.resolve();
printResolved(def);
// => (resolved)
</pre>

<h3 id="matching">Output matching</h3>

<p>The <em>expected</em> output is compared with the output you actually <em>got</em> (received).</p>
Expand Down

0 comments on commit 1bc8e9e

Please sign in to comment.