tinytest/run now returns immediatedly; sends a 'complete' record when finished

Otherwise the DDP call to tinytest/run was blocking client test execution,
in particular Accounts DDP calls won't run concurrently with another DDP call,
even if the first DDP call calls unblock.
This commit is contained in:
Justin SB
2014-07-14 13:42:50 -07:00
parent 57465b00c2
commit 2ac9da43f9
2 changed files with 32 additions and 21 deletions

View File

@@ -20,6 +20,8 @@ Tinytest._runTestsEverywhere = function (onReport, onComplete, pathPrefix) {
maybeDone();
}, pathPrefix);
var handle;
Meteor.connection.registerStore(Meteor._ServerTestResultsCollection, {
update: function (msg) {
// We only should call _runTestsEverywhere once per client-page-load, so
@@ -28,25 +30,33 @@ Tinytest._runTestsEverywhere = function (onReport, onComplete, pathPrefix) {
return;
// This will only work for added & changed messages.
// hope that is all you get.
_.each(msg.fields, function (report) {
_.each(msg.fields, function (report, key) {
// Skip the 'complete' report (deal with it last)
if (key === 'complete') {
return;
}
_.each(report.events, function (event) {
delete event.cookie; // can't debug a server test on the client..
});
report.server = true;
onReport(report);
});
// Now that we've processed all the other messages,
// check if we have the 'complete' message
if (_.has(msg.fields, 'complete')) {
remoteComplete = true;
handle.stop();
Meteor.call('tinytest/clearResults', runId);
maybeDone();
}
}
});
var handle = Meteor.subscribe(Meteor._ServerTestResultsSubscription, runId);
handle = Meteor.subscribe(Meteor._ServerTestResultsSubscription, runId);
Meteor.call('tinytest/run', runId, pathPrefix, function (error, result) {
if (error)
// XXX better report error
throw new Error("Test server returned an error");
remoteComplete = true;
handle.stop();
Meteor.call('tinytest/clearResults', runId);
maybeDone();
});
};

View File

@@ -27,13 +27,18 @@ Meteor.methods({
check(pathPrefix, Match.Optional([String]));
this.unblock();
// XXX using private API === lame
var path = Npm.require('path');
var Future = Npm.require(path.join('fibers', 'future'));
var future = new Future;
reportsForRun[runId] = {};
var addReport = function (key, report) {
var fields = {};
fields[key] = report;
_.each(handlesForRun[runId], function (handle) {
handle.changed(Meteor._ServerTestResultsCollection, runId, fields);
});
// Save for future subscriptions.
reportsForRun[runId][key] = report;
};
var onReport = function (report) {
if (! Fiber.current) {
Meteor._debug("Trying to report a test not in a fiber! "+
@@ -41,22 +46,18 @@ Meteor.methods({
console.trace();
}
var dummyKey = Random.id();
var fields = {};
fields[dummyKey] = report;
_.each(handlesForRun[runId], function (handle) {
handle.changed(Meteor._ServerTestResultsCollection, runId, fields);
});
// Save for future subscriptions.
reportsForRun[runId][dummyKey] = report;
addReport(dummyKey, report);
};
var onComplete = function() {
future['return']();
// We send an object for current and future compatibility,
// though we could get away with just sending { complete: true }
var report = { done: true };
var key = 'complete';
addReport(key, report);
};
Tinytest._runTests(onReport, onComplete, pathPrefix);
future.wait();
},
'tinytest/clearResults': function (runId) {
check(runId, String);