Make Meteor.user() reactive on user-loaded state. Fix #380.

This commit is contained in:
David Glasser
2012-10-09 11:18:03 -07:00
parent ae46f89bc2
commit dffed84155
3 changed files with 51 additions and 2 deletions

View File

@@ -12,11 +12,12 @@
return currentUserSubscriptionData && currentUserSubscriptionData.loaded;
};
// This calls userId and userLoaded, both of which are reactive.
Meteor.user = function () {
var userId = Meteor.userId();
if (!userId)
return null;
if (currentUserSubscriptionData && currentUserSubscriptionData.loaded)
if (Meteor.userLoaded())
return Meteor.users.findOne(userId);
// Not yet loaded: return a minimal object.
return {_id: userId};

View File

@@ -14,7 +14,7 @@ Package.on_use(function(api) {
});
Package.on_test(function(api) {
api.use(['accounts-password', 'tinytest', 'test-helpers']);
api.use(['accounts-password', 'tinytest', 'test-helpers', 'deps']);
api.add_files('passwords_tests_setup.js', 'server');
api.add_files('passwords_tests.js', ['client', 'server']);
api.add_files('email_tests_setup.js', 'server');

View File

@@ -63,6 +63,54 @@ if (Meteor.isClient) (function () {
loggedInAs(username, test, expect));
},
logoutStep,
// This next step tests reactive contexts which are reactive on
// Meteor.user() without explicitly calling Meteor.userLoaded() --- we want
// to make sure that user loading finishing invalidates them too.
function (test, expect) {
// Set up a reactive context that only refreshes when Meteor.user() is
// invalidated.
var user;
var handle1 = Meteor._autorun(function () {
user = Meteor.user();
});
// At the beginning, we're not logged in.
test.equal(user, null);
// This will get called once a second context (which does explicitly call
// Meteor.userLoaded()) tells us we are ready.
var callWhenLoaded = expect(function () {
Meteor.flush();
// ... and this means that the first context did refresh and give us
// data.
test.isTrue(user.emails);
handle1.stop();
});
var waitForLoaded = expect(function () {
Meteor._autorun(function(handle2) {
if (!Meteor.userLoaded()) return;
handle2.stop();
callWhenLoaded();
});
});
Meteor.loginWithPassword(username, password, expect(function (error) {
test.equal(error, undefined);
test.notEqual(Meteor.userId(), null);
// Since userId has changed, the first autorun has been invalidated, so
// flush will re-run it and user will become not null. In the *CURRENT
// IMPLEMENTATION*, we will have just called _makeClientLoggedIn which
// just started a new meteor.currentUser subscription. There is no way
// that it is complete yet because we haven't gotten back to the event
// loop to actually get the data, so user.emails hasn't been populated
// yet. (That said, if we redo how userLoaded is implemented to not
// involve unsub/sub, it's possible that this test may become flaky by
// the test.isFalse failing.)
Meteor.flush();
test.notEqual(user, null);
test.isFalse(user.emails);
waitForLoaded();
}));
},
logoutStep,
function (test, expect) {
Meteor.loginWithPassword({username: username}, password,
loggedInAs(username, test, expect));