From 385b2fbde21929d010bfe82461b2e4d92fcdc1db Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Fri, 26 Jul 2013 17:09:54 -0400 Subject: [PATCH] Some tests for the user stream --- .../javascripts/discourse/models/user.js | 34 ++++------ .../discourse/models/user_stream.js | 64 +++++++++++++------ .../discourse/routes/user_routes.js | 6 +- test/javascripts/models/user_stream_test.js | 29 +++++++++ test/javascripts/models/user_test.js | 19 ++++++ 5 files changed, 110 insertions(+), 42 deletions(-) create mode 100644 test/javascripts/models/user_stream_test.js create mode 100644 test/javascripts/models/user_test.js diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js index cf1a9e72b20..65570c0f56f 100644 --- a/app/assets/javascripts/discourse/models/user.js +++ b/app/assets/javascripts/discourse/models/user.js @@ -8,6 +8,16 @@ **/ Discourse.User = Discourse.Model.extend({ + /** + The user's stream + + @property stream + @type {Discourse.UserStream} + **/ + stream: function() { + return Discourse.UserStream.create({ user: this }); + }.property(), + /** Is this user a member of staff? @@ -32,9 +42,9 @@ Discourse.User = Discourse.Model.extend({ @property avatarSmall @type {String} **/ - avatarSmall: (function() { + avatarSmall: function() { return Discourse.Utilities.avatarUrl(this.get('username'), 'small', this.get('avatar_template')); - }).property('username'), + }.property('username'), searchContext: function() { return ({ type: 'user', id: this.get('username_lower'), user: this }); @@ -269,26 +279,6 @@ Discourse.User = Discourse.Model.extend({ user.setProperties(json.user); return user; }); - }, - - findStream: function(filter) { - - // When filtering for replies, include mentions and quotes too - if (filter === Discourse.UserAction.TYPES.replies) { - filter = [Discourse.UserAction.TYPES.replies, - Discourse.UserAction.TYPES.mentions, - Discourse.UserAction.TYPES.quotes].join(","); - } - - var stream = Discourse.UserStream.create({ - itemsLoaded: 0, - content: [], - filter: filter, - user: this - }); - - stream.findItems(); - return stream; } }); diff --git a/app/assets/javascripts/discourse/models/user_stream.js b/app/assets/javascripts/discourse/models/user_stream.js index 0b9edfe4195..d75869d2808 100644 --- a/app/assets/javascripts/discourse/models/user_stream.js +++ b/app/assets/javascripts/discourse/models/user_stream.js @@ -7,38 +7,64 @@ @module Discourse **/ Discourse.UserStream = Discourse.Model.extend({ + loaded: false, - filterChanged: function() { - this.setProperties({ - content: Em.A(), - itemsLoaded: 0 - }); - this.findItems(); - }.observes('filter'), + init: function() { + this.setProperties({ itemsLoaded: 0, content: [] }); + }, + + filterParam: function() { + var filter = this.get('filter'); + if (filter === Discourse.UserAction.TYPES.replies) { + return [Discourse.UserAction.TYPES.replies, + Discourse.UserAction.TYPES.mentions, + Discourse.UserAction.TYPES.quotes].join(","); + } + return filter; + }.property('filter'), + + baseUrl: Discourse.computed.url('itemsLoaded', 'user.username_lower', '/user_actions.json?offset=%@&username=%@'), + + filterBy: function(filter) { + if (this.get('loaded') && (this.get('filter') === filter)) { return Ember.RSVP.resolve(); } + this.set('filter', filter); + return this.findItems(); + }, findItems: function() { var userStream = this; - if(this.get("loading")) { return Ember.RSVP.reject(); } - this.set("loading",true); + if(this.get('loading')) { return Ember.RSVP.reject(); } - var url = Discourse.getURL("/user_actions.json?offset=") + this.get('itemsLoaded') + "&username=" + (this.get('user.username_lower')); - if (this.get('filter')) { - url += "&filter=" + (this.get('filter')); + this.setProperties({ + loading: true, + itemsLoaded: 0, + content: [] + }); + + var url = this.get('baseUrl'); + if (this.get('filterParam')) { + url += "&filter=" + this.get('filterParam'); } - var stream = this; + var loadingFinished = function() { + userStream.set('loading', false); + }; + return Discourse.ajax(url, {cache: 'false'}).then( function(result) { - userStream.set("loading",false); if (result && result.user_actions) { var copy = Em.A(); - _.each(result.user_actions,function(action) { + result.user_actions.forEach(function(action) { copy.pushObject(Discourse.UserAction.create(action)); }); - copy = Discourse.UserAction.collapseStream(copy); - stream.get('content').pushObjects(copy); - stream.set('itemsLoaded', stream.get('itemsLoaded') + result.user_actions.length); + + userStream.get('content').pushObjects(Discourse.UserAction.collapseStream(copy)); + userStream.setProperties({ + loaded: true, + itemsLoaded: userStream.get('itemsLoaded') + result.user_actions.length + }); } - }, function(){ userStream.set("loading", false); }); + loadingFinished(); + }, loadingFinished); } }); diff --git a/app/assets/javascripts/discourse/routes/user_routes.js b/app/assets/javascripts/discourse/routes/user_routes.js index f5a98b1fb8b..9cc42293444 100644 --- a/app/assets/javascripts/discourse/routes/user_routes.js +++ b/app/assets/javascripts/discourse/routes/user_routes.js @@ -135,7 +135,11 @@ Discourse.UserIndexRoute = Discourse.UserActivityRoute.extend({ **/ Discourse.UserActivityStreamRoute = Discourse.Route.extend({ model: function() { - return this.modelFor('user').findStream(this.get('userActionType')); + return this.modelFor('user').get('stream'); + }, + + afterModel: function() { + return this.modelFor('user').get('stream').filterBy(this.get('userActionType')); }, renderTemplate: function() { diff --git a/test/javascripts/models/user_stream_test.js b/test/javascripts/models/user_stream_test.js new file mode 100644 index 00000000000..643160cb1f8 --- /dev/null +++ b/test/javascripts/models/user_stream_test.js @@ -0,0 +1,29 @@ +module("Discourse.User"); + +test('basics', function(){ + var user = Discourse.User.create({id: 1, username: 'eviltrout'}); + var stream = user.get('stream'); + present(stream, "a user has a stream by default"); + equal(stream.get('user'), user, "the stream points back to the user"); + + equal(stream.get('itemsLoaded'), 0, "no items are loaded by default"); + blank(stream.get('content'), "no content by default"); + blank(stream.get('filter'), "no filter by default"); + + ok(!stream.get('loaded'), "the stream is not loaded by default"); +}); + + +test('filterParam', function() { + var user = Discourse.User.create({id: 1, username: 'eviltrout'}); + var stream = user.get('stream'); + + blank(stream.get('filterParam'), "it's blank by default"); + + stream.set('filter', Discourse.UserAction.TYPES.likes_given); + equal(stream.get('filterParam'), Discourse.UserAction.TYPES.likes_given); + + stream.set('filter', Discourse.UserAction.TYPES.replies); + equal(stream.get('filterParam'), '6,7,9'); + +}); diff --git a/test/javascripts/models/user_test.js b/test/javascripts/models/user_test.js new file mode 100644 index 00000000000..04d490bee4e --- /dev/null +++ b/test/javascripts/models/user_test.js @@ -0,0 +1,19 @@ +module("Discourse.User"); + +test('staff', function(){ + var user = Discourse.User.create({id: 1, username: 'eviltrout'}); + + ok(!user.get('staff'), "user is not staff"); + + user.toggleProperty('moderator'); + ok(user.get('staff'), "moderators are staff"); + + user.setProperties({moderator: false, admin: true}); + ok(user.get('staff'), "admins are staff"); +}); + +test('searchContext', function() { + var user = Discourse.User.create({id: 1, username: 'EvilTrout'}); + + deepEqual(user.get('searchContext'), {type: 'user', id: 'eviltrout', user: user}, "has a search context"); +}); \ No newline at end of file