Merge branch 'pr/4052' into devel

Fixes #3824.  Fixes #4052.
This commit is contained in:
David Glasser
2015-04-14 23:36:20 -07:00
5 changed files with 168 additions and 8 deletions

View File

@@ -1,10 +1,12 @@
Package.describe({
summary: "Makes the application crawlable to web spiders",
version: "1.0.7"
version: "1.0.8"
});
Package.onUse(function (api) {
api.use('webapp', 'server');
api.use(['ddp'], 'client');
api.use(['callback-hook'], 'client');
api.use(['templating'], 'client');
api.use(['underscore'], ['client', 'server']);
@@ -20,5 +22,6 @@ Package.onUse(function (api) {
Package.onTest(function (api) {
api.use(['spiderable', 'tinytest']);
api.addFiles('spiderable_tests.js', 'server');
api.addFiles('spiderable_client_tests.js', 'client');
api.addFiles('spiderable_server_tests.js', 'server');
});

View File

@@ -10,12 +10,10 @@ var isReady = function () {
}
if (typeof Package === 'undefined'
|| Package.spiderable === undefined
|| Package.spiderable.Spiderable === undefined
|| !Package.spiderable.Spiderable._initialSubscriptionsStarted) {
|| Package.spiderable.Spiderable === undefined) {
return false;
}
Tracker.flush();
return DDP._allSubscriptionsReady();
return Package.spiderable.Spiderable.isReady();
});
};

View File

@@ -17,14 +17,50 @@
Spiderable._initialSubscriptionsStarted = false;
Spiderable._onReadyHook = new Hook({
debugPrintExceptions: "Spiderable.addReadyCondition callback"
});
// register a new onReady hook for validation
Spiderable.addReadyCondition = function (fn) {
return Spiderable._onReadyHook.register(fn);
};
//
// register default hooks
// top level code ready
Spiderable.addReadyCondition(function () {
// subs & top level code (startup) completed
return Spiderable._initialSubscriptionsStarted;
})
var startupCallbacksDone = function () {
Spiderable._initialSubscriptionsStarted = true;
};
// This extra indirection is how we get called last
var topLevelCodeDone = function () {
// We'd like to use Meteor.startup here I think, but docs/behaviour of that is wrong
Meteor._setImmediate(function () { startupCallbacksDone(); });
};
Meteor.startup(function () { topLevelCodeDone(); });
// all ddp subs ready
Spiderable.addReadyCondition(function () {
Tracker.flush();
return DDP._allSubscriptionsReady();
})
// run all hooks and return true if they all pass
Spiderable.isReady = function () {
var isReady = true;
Spiderable._onReadyHook.each(function (callback) {
if (callback()) {
return true; // next callback
} else {
isReady = false;
return false; // stop immediately
}
});
return isReady;
};

View File

@@ -0,0 +1,123 @@
Tinytest.add("spiderable - default hooks registered", function (test, expect) {
test.equal(
_.keys(Spiderable._onReadyHook.callbacks).length,
2
);
});
Tinytest.add("spiderable - is not ready while initial subscriptions aren't started", function (test, expect) {
var original = Spiderable._initialSubscriptionsStarted;
Spiderable._initialSubscriptionsStarted = false;
test.isFalse(Spiderable.isReady());
Spiderable._initialSubscriptionsStarted = original;
});
Tinytest.add("spiderable - is not ready while DDP Subscriptions aren't ready", function (test, expect) {
var original = DDP._allSubscriptionsReady;
Spiderable._initialSubscriptionsStarted = true;
DDP._allSubscriptionsReady = function () { return false; };
test.isFalse(Spiderable.isReady());
// restore original
DDP._allSubscriptionsReady = original;
});
Tinytest.add("spiderable - default hooks can ready", function (test, expect) {
var original = DDP._allSubscriptionsReady;
Spiderable._initialSubscriptionsStarted = true;
DDP._allSubscriptionsReady = function () { return true; };
test.isTrue(Spiderable.isReady());
// restore original
DDP._allSubscriptionsReady = original;
});
Tinytest.add("spiderable - is not ready with a custom hook", function (test, expect) {
var callbacks = {}
test.equal(
_.keys(Spiderable._onReadyHook.callbacks).length,
2
);
//clear all/default callbacks
_.each(Spiderable._onReadyHook.callbacks, function (value,key,list) {
callbacks[key] = value;
delete list[key];
});
test.equal(
_.keys(Spiderable._onReadyHook.callbacks).length,
0
);
// actually test not ready
Spiderable.addReadyCondition(function () { return false; });
test.isFalse(Spiderable.isReady());
// clear new callback
_.each(Spiderable._onReadyHook.callbacks, function (value,key,list) {
delete list[key];
});
test.equal(
_.keys(Spiderable._onReadyHook.callbacks).length,
0
);
// restore callbacks
_.each(callbacks, function (value,key,list) {
Spiderable._onReadyHook.callbacks[key] = value;
});
test.equal(
_.keys(Spiderable._onReadyHook.callbacks).length,
2
);
});
Tinytest.add("spiderable - is ready with a custom hook", function (test, expect) {
var callbacks = {}
test.equal(
_.keys(Spiderable._onReadyHook.callbacks).length,
2
);
//clear all callbacks
_.each(Spiderable._onReadyHook.callbacks, function (value,key,list) {
callbacks[key] = value;
delete list[key];
});
test.equal(
_.keys(Spiderable._onReadyHook.callbacks).length,
0
);
// actually test ready
Spiderable.addReadyCondition(function () { return true; });
test.isTrue(Spiderable.isReady());
// clear new callback
_.each(Spiderable._onReadyHook.callbacks, function (value,key,list) {
delete list[key];
});
test.equal(
_.keys(Spiderable._onReadyHook.callbacks).length,
0
);
// restore callbacks
_.each(callbacks, function (value,key,list) {
Spiderable._onReadyHook.callbacks[key] = value;
});
test.equal(
_.keys(Spiderable._onReadyHook.callbacks).length,
2
);
});