diff --git a/Changelog.md b/Changelog.md index 6cbeeacc0..ccaa87b4e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ * Remove the hack for loading the entire lib folder with a proper solution. [#3809](https://github.com/diaspora/diaspora/issues/3750) * Update and refactor the default public view `public/default.html` [#3811](https://github.com/diaspora/diaspora/issues/3811) * Write unicorn stderr and stdout [#3785](https://github.com/diaspora/diaspora/pull/3785) +* Ported aspects to backbone [#3850](https://github.com/diaspora/diaspora/pull/3850) ## Features diff --git a/app/assets/javascripts/app/collections/aspects.js b/app/assets/javascripts/app/collections/aspects.js new file mode 100644 index 000000000..33c9cb56c --- /dev/null +++ b/app/assets/javascripts/app/collections/aspects.js @@ -0,0 +1,26 @@ +app.collections.Aspects = Backbone.Collection.extend({ + model: app.models.Aspect, + + selectedAspects: function(attribute){ + return _.pluck(_.filter(this.toJSON(), function(a){ + return a.selected; + }), attribute); + }, + + allSelected: function(){ + return this.length === _.filter(this.toJSON(), function(a){ return a.selected; }).length; + }, + + selectAll: function(){ + this.map(function(a){ a.set({ 'selected' : true })} ); + }, + + deselectAll: function(){ + this.map(function(a){ a.set({ 'selected' : false })} ); + }, + + toSentence: function(){ + var separator = Diaspora.I18n.t("comma") + ' '; + return this.selectedAspects('name').join(separator).replace(/,\s([^,]+)$/, ' ' + Diaspora.I18n.t("and") + ' $1') || Diaspora.I18n.t("my_aspects"); + } +}) diff --git a/app/assets/javascripts/app/models/aspect.js b/app/assets/javascripts/app/models/aspect.js new file mode 100644 index 000000000..8ae6dac71 --- /dev/null +++ b/app/assets/javascripts/app/models/aspect.js @@ -0,0 +1,5 @@ +app.models.Aspect = Backbone.Model.extend({ + toggleSelected: function(){ + this.set({'selected' : !this.get('selected')}); + } +}); diff --git a/app/assets/javascripts/app/models/stream_aspects.js b/app/assets/javascripts/app/models/stream_aspects.js new file mode 100644 index 000000000..f8536c65d --- /dev/null +++ b/app/assets/javascripts/app/models/stream_aspects.js @@ -0,0 +1,27 @@ +app.models.StreamAspects = app.models.Stream.extend({ + + url : function(){ + return _.any(this.items.models) ? this.timeFilteredPath() : this.basePath() + }, + + initialize : function(models, options){ + var collectionClass = options && options.collection || app.collections.Posts; + this.items = new collectionClass([], this.collectionOptions()); + this.aspects_ids = options.aspects_ids; + }, + + basePath : function(){ + return '/aspects'; + }, + + fetch: function() { + if(this.isFetching()){ return false } + var url = this.url(); + var ids = this.aspects_ids; + this.deferred = this.items.fetch({ + add : true, + url : url, + data : { 'a_ids': ids } + }).done(_.bind(this.triggerFetchedEvents, this)) + } +}); diff --git a/app/assets/javascripts/app/router.js b/app/assets/javascripts/app/router.js index 6fcd6c95b..f1aa32b95 100644 --- a/app/assets/javascripts/app/router.js +++ b/app/assets/javascripts/app/router.js @@ -11,8 +11,8 @@ app.Router = Backbone.Router.extend({ "stream": "stream", "participate": "stream", "explore": "stream", - "aspects": "stream", - "aspects:query": "stream", + "aspects": "aspects", + "aspects/stream": "aspects_stream", "commented": "stream", "liked": "stream", "mentions": "stream", @@ -74,13 +74,36 @@ app.Router = Backbone.Router.extend({ followedTagsView.setupAutoSuggest(); app.tagFollowings.add(preloads.tagFollowings); - + if(name) { var followedTagsAction = new app.views.TagFollowingAction( {tagText: name} ); $("#author_info").prepend(followedTagsAction.render().el) } + }, + + aspects : function(){ + app.aspects = new app.collections.Aspects(app.currentUser.get('aspects')); + var aspects_list = new app.views.AspectsList({ collection: app.aspects }); + aspects_list.render(); + this.aspects_stream(); + }, + + aspects_stream : function(){ + + var ids = app.aspects.selectedAspects('id'); + app.stream = new app.models.StreamAspects([], { aspects_ids: ids }); + app.stream.fetch(); + + app.page = new app.views.Stream({model : app.stream}); + app.publisher = app.publisher || new app.views.Publisher({collection : app.stream.items}); + app.publisher.updateAspectsSelector(ids); + + var streamFacesView = new app.views.StreamFaces({collection : app.stream.items}); + + $("#main_stream").html(app.page.render().el); + $('#selected_aspect_contacts .content').html(streamFacesView.render().el); } }); diff --git a/app/assets/javascripts/app/views/aspect_view.js b/app/assets/javascripts/app/views/aspect_view.js new file mode 100644 index 000000000..67d15429a --- /dev/null +++ b/app/assets/javascripts/app/views/aspect_view.js @@ -0,0 +1,28 @@ +app.views.Aspect = app.views.Base.extend({ + templateName: "aspect", + + tagName: "li", + + initialize: function(){ + if (this.model.get('selected')){ + this.$el.addClass('active'); + }; + }, + + events: { + 'click a.aspect_selector': 'toggleAspect' + }, + + toggleAspect: function(evt){ + if (evt) { evt.preventDefault(); }; + this.$el.toggleClass('active'); + this.model.toggleSelected(); + app.router.aspects_stream(); + }, + + presenter : function() { + return _.extend(this.defaultPresenter(), { + aspect : this.model + }) + } +}); diff --git a/app/assets/javascripts/app/views/aspects_list_view.js b/app/assets/javascripts/app/views/aspects_list_view.js new file mode 100644 index 000000000..468a79b8a --- /dev/null +++ b/app/assets/javascripts/app/views/aspects_list_view.js @@ -0,0 +1,55 @@ +app.views.AspectsList = app.views.Base.extend({ + templateName: 'aspects-list', + + el: '#aspects_list', + + events: { + 'click .toggle_selector' : 'toggleAll' + }, + + initialize: function(){ + this.collection.on('change', this.toggleSelector, this); + this.collection.on('change', this.updateStreamTitle, this); + }, + + postRenderTemplate: function() { + this.collection.each(this.appendAspect, this); + this.$('a[rel*=facebox]').facebox(); + this.updateStreamTitle(); + this.toggleSelector(); + }, + + appendAspect: function(aspect) { + $("#aspects_list > *:last").before(new app.views.Aspect({ + model: aspect, attributes: {'data-aspect_id': aspect.get('id')} + }).render().el); + }, + + toggleAll: function(evt){ + if (evt) { evt.preventDefault(); }; + + if (this.collection.allSelected()) { + this.collection.deselectAll(); + this.$('li:not(:last)').removeClass("active"); + } else { + this.collection.selectAll(); + this.$('li:not(:last)').addClass("active"); + } + + this.toggleSelector(); + app.router.aspects_stream(); + }, + + toggleSelector: function(){ + var selector = this.$('a.toggle_selector'); + if (this.collection.allSelected()) { + selector.text(Diaspora.I18n.t('aspect_navigation.deselect_all')); + } else { + selector.text(Diaspora.I18n.t('aspect_navigation.select_all')); + } + }, + + updateStreamTitle: function(){ + $('.stream_title').text(this.collection.toSentence()); + } +}) diff --git a/app/assets/javascripts/app/views/publisher/aspects_selector.js b/app/assets/javascripts/app/views/publisher/aspects_selector.js index ecb2c5764..d3b364265 100644 --- a/app/assets/javascripts/app/views/publisher/aspects_selector.js +++ b/app/assets/javascripts/app/views/publisher/aspects_selector.js @@ -21,16 +21,28 @@ } // update the selection summary - AspectsDropdown.updateNumber( - el.closest(".dropdown_list"), - null, - el.parent().find('li.selected').length, - '' - ); + this._updateAspectsNumber(el); this._updateSelectedAspectIds(); }, + updateAspectsSelector: function(ids){ + var el = this.$("ul.dropdown_list"); + this.$('.dropdown_list > li').each(function(){ + var el = $(this); + var aspectId = el.data('aspect_id'); + if (_.contains(ids, aspectId)) { + el.addClass('selected'); + } + else { + el.removeClass('selected'); + } + }); + + this._updateAspectsNumber(el); + this._updateSelectedAspectIds(); + }, + // take care of the form fields that will indicate the selected aspects _updateSelectedAspectIds: function() { var self = this; @@ -52,6 +64,15 @@ }); }, + _updateAspectsNumber: function(el){ + AspectsDropdown.updateNumber( + el.closest(".dropdown_list"), + null, + el.parent().find('li.selected').length, + '' + ); + }, + _addHiddenAspectInput: function(id) { var uid = _.uniqueId('aspect_ids_'); this.$('.content_creation form').append( @@ -59,4 +80,4 @@ ); } }; -})(); \ No newline at end of file +})(); diff --git a/app/assets/javascripts/pages/streams-aspects.js b/app/assets/javascripts/pages/streams-aspects.js deleted file mode 100644 index 6b85b63a2..000000000 --- a/app/assets/javascripts/pages/streams-aspects.js +++ /dev/null @@ -1,7 +0,0 @@ -Diaspora.Pages.StreamsAspects = function() { - var self = this; - - this.subscribe("page/ready", function(evt, document) { - self.aspectNavigation = self.instantiate("AspectNavigation", document.find("ul#aspect_nav")); - }); -}; diff --git a/app/assets/javascripts/widgets/aspect-navigation.js b/app/assets/javascripts/widgets/aspect-navigation.js deleted file mode 100644 index a6e9d095a..000000000 --- a/app/assets/javascripts/widgets/aspect-navigation.js +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (c) 2010, Diaspora Inc. This file is - * licensed under the Affero General Public License version 3 or later. See - * the COPYRIGHT file. - */ - -(function() { - Diaspora.Widgets.AspectNavigation = function() { - var self = this; - - this.subscribe("widget/ready", function(evt, aspectNavigation) { - $.extend(self, { - aspectNavigation: aspectNavigation, - aspectSelectors: aspectNavigation.find("a.aspect_selector[data-guid]"), - aspectLis: aspectNavigation.find("li[data-aspect_id]"), - toggleSelector: aspectNavigation.find("a.toggle_selector") - }); - - self.aspectSelectors.click(self.toggleAspect); - self.toggleSelector.click(self.toggleAll); - }); - - this.selectedAspects = function() { - return self.aspectNavigation.find("li.active[data-aspect_id]").map(function() { return $(this).data('aspect_id') }); - }; - - this.toggleAspect = function(evt) { - evt.preventDefault(); - - $(this).parent().toggleClass("active"); - self.perform(); - }; - - this.toggleAll = function(evt) { - evt.preventDefault(); - - if (self.allSelected()) { - self.aspectLis.removeClass("active"); - } else { - self.aspectLis.addClass("active"); - } - self.perform(); - }; - - this.perform = function() { - if (self.noneSelected()) { - // clear the posts - app.page.collection.reset(); - app.page.render(); - - // toggle the button - this.calculateToggleText(); - return; - } else { - window.location = self.generateURL(); // hella hax - } - }; - - this.calculateToggleText = function() { - if (self.allSelected()) { - self.toggleSelector.text(Diaspora.I18n.t('aspect_navigation.deselect_all')); - } else { - self.toggleSelector.text(Diaspora.I18n.t('aspect_navigation.select_all')); - } - }; - - this.generateURL = function() { - var baseURL = 'aspects'; - - // generate new url - baseURL = baseURL.replace('#',''); - baseURL += '?'; - - self.aspectLis.each(function() { - var aspectLi = $(this); - if (aspectLi.hasClass("active")) { - baseURL += "a_ids[]=" + aspectLi.data("aspect_id") + "&"; - } - }); - - if(!$("#publisher").hasClass("closed")) { - // open publisher - baseURL += "op=true"; - } else { - // slice last '&' - baseURL = baseURL.slice(0,baseURL.length-1); - } - return baseURL; - }; - - this.noneSelected = function() { - return self.aspectLis.filter(".active").length === 0; - } - - this.allSelected = function() { - return self.aspectLis.not(".active").length === 0; - } - }; -})(); diff --git a/app/assets/templates/aspect_tpl.jst.hbs b/app/assets/templates/aspect_tpl.jst.hbs new file mode 100644 index 000000000..5e51e1bed --- /dev/null +++ b/app/assets/templates/aspect_tpl.jst.hbs @@ -0,0 +1,6 @@ +
+ + Pencil + +
+ {{name}} diff --git a/app/assets/templates/aspects-list_tpl.jst.hbs b/app/assets/templates/aspects-list_tpl.jst.hbs new file mode 100644 index 000000000..493f259a4 --- /dev/null +++ b/app/assets/templates/aspects-list_tpl.jst.hbs @@ -0,0 +1,6 @@ + + {{ t "aspect_navigation.select_all" }} + +
  • + {{ t "aspect_navigation.add_an_aspect" }} +
  • diff --git a/app/controllers/streams_controller.rb b/app/controllers/streams_controller.rb index 4d6f2852c..a4e300823 100644 --- a/app/controllers/streams_controller.rb +++ b/app/controllers/streams_controller.rb @@ -21,7 +21,7 @@ class StreamsController < ApplicationController :json def aspects - aspect_ids = (session[:a_ids] ? session[:a_ids] : []) + aspect_ids = (session[:a_ids] || []) @stream = Stream::Aspect.new(current_user, aspect_ids, :max_time => max_time) stream_responder diff --git a/app/helpers/layout_helper.rb b/app/helpers/layout_helper.rb index 781fa5679..c226aff74 100644 --- a/app/helpers/layout_helper.rb +++ b/app/helpers/layout_helper.rb @@ -39,7 +39,8 @@ module LayoutHelper def set_current_user_in_javascript return unless user_signed_in? - user = UserPresenter.new(current_user).to_json + a_ids = session[:a_ids] || [] + user = UserPresenter.new(current_user, a_ids).to_json content_tag(:script) do <<-JS.html_safe window.current_user_attributes = #{user} diff --git a/app/presenters/user_presenter.rb b/app/presenters/user_presenter.rb index 018b57187..1874570c4 100644 --- a/app/presenters/user_presenter.rb +++ b/app/presenters/user_presenter.rb @@ -1,8 +1,9 @@ class UserPresenter - attr_accessor :user + attr_accessor :user, :aspects_ids - def initialize(user) - self.user = user + def initialize(user, aspects_ids) + self.user = user + self.aspects_ids = aspects_ids end def to_json(options = {}) @@ -27,7 +28,11 @@ class UserPresenter end def aspects - AspectPresenter.as_collection(user.aspects) + @aspects ||= begin + aspects = AspectPresenter.as_collection(user.aspects) + no_aspects = self.aspects_ids.empty? + aspects.each{ |a| a[:selected] = no_aspects || self.aspects_ids.include?(a[:id].to_s) } + end end def notifications_count diff --git a/app/views/aspects/_aspect_listings.haml b/app/views/aspects/_aspect_listings.haml index 41659509f..8e593df9d 100644 --- a/app/views/aspects/_aspect_listings.haml +++ b/app/views/aspects/_aspect_listings.haml @@ -4,19 +4,6 @@ %ul#aspect_nav.left_nav.sub %li.all_aspects - = link_to t('streams.aspects.title'), aspects_path, :class => 'home_selector' + = link_to t('streams.aspects.title'), aspects_path, :class => 'home_selector', :rel => 'backbone' - - if @stream.is_a?(Stream::Aspect) - %ul.sub_nav - - if defined?(stream) - %a.toggle_selector{:href => '#'} - = stream.for_all_aspects? ? t('.deselect_all') : t('.select_all') - - for aspect in all_aspects - %li{:data => {:aspect_id => aspect.id}, :class => ("active" if defined?(stream) && stream.aspect_ids.include?(aspect.id))} - .edit - = link_to image_tag("icons/pencil.png", :title => t('.edit_aspect', :name => aspect.name)), edit_aspect_path(aspect), :rel => "facebox" - %a.aspect_selector{:href => aspects_path("a_ids[]" => aspect.id), :class => "name", 'data-guid' => aspect.id} - = aspect - - %li - = link_to t('.add_an_aspect'), new_aspect_path, :class => "new_aspect", :rel => "facebox" + %ul#aspects_list.sub_nav diff --git a/app/views/aspects/_aspect_stream.haml b/app/views/aspects/_aspect_stream.haml index ca9263159..7b6121685 100644 --- a/app/views/aspects/_aspect_stream.haml +++ b/app/views/aspects/_aspect_stream.haml @@ -5,7 +5,7 @@ %h3#aspect_stream_header.stream_title = stream.title - = render 'shared/publisher', :selected_aspects => stream.aspects, :aspect_ids => stream.aspect_ids, :for_all_aspects => stream.for_all_aspects?, :aspect => stream.aspect += render 'shared/publisher', :selected_aspects => stream.aspects, :aspect_ids => stream.aspect_ids, :for_all_aspects => stream.for_all_aspects?, :aspect => stream.aspect = render 'aspects/no_posts_message' #gs-shim{:title => popover_with_close_html("3. #{t('.stay_updated')}"), 'data-content' => t('.stay_updated_explanation')} diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index 0811598d5..83e95433e 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -9,6 +9,9 @@ en: delete: "Delete" ignore: "Ignore" ignore_user: "Ignore this user?" + and: "and" + comma: "," + edit: "Edit" timeago: prefixAgo: "" prefixFromNow: "" @@ -28,6 +31,7 @@ en: my_activity: "My Activity" my_stream: "Stream" + my_aspects: "My Aspects" videos: watch: "Watch this video on <%= provider %>" @@ -64,6 +68,7 @@ en: select_all: "Select all" deselect_all: "Deselect all" no_aspects: "No aspects selected" + add_an_aspect: "+ Add an aspect" getting_started: hey: "Hey, <%= name %>!" no_tags: "Hey, you haven't followed any tags! Continue anyway?" diff --git a/features/oembed.feature b/features/oembed.feature index 3777c1fc3..9ae7a2b44 100644 --- a/features/oembed.feature +++ b/features/oembed.feature @@ -17,6 +17,7 @@ Feature: oembed When I fill in the following: | status_message_fake_text | http://youtube.com/watch?v=M3r2XDceM6A&format=json | And I press "Share" + And I wait for the ajax to finish And I follow "My Aspects" Then I should see a video player And I should see a ".oembed" within ".post-content" diff --git a/spec/javascripts/app/collections/aspects_spec.js b/spec/javascripts/app/collections/aspects_spec.js new file mode 100644 index 000000000..786cec3d6 --- /dev/null +++ b/spec/javascripts/app/collections/aspects_spec.js @@ -0,0 +1,94 @@ +describe("app.collections.Aspects", function(){ + beforeEach(function(){ + Diaspora.I18n.loadLocale({ + 'and' : "and", + 'comma' : ",", + 'my_aspects' : "My Aspects" + }); + var my_aspects = [{ name: 'Work', selected: true }, + { name: 'Friends', selected: false }, + { name: 'Acquaintances', selected: false }] + this.aspects = new app.collections.Aspects(my_aspects); + }); + + describe("#selectAll", function(){ + it("selects every aspect in the collection", function(){ + this.aspects.selectAll(); + this.aspects.each(function(aspect){ + expect(aspect.get('selected')).toBeTruthy(); + }); + }); + }); + + describe("#deselectAll", function(){ + it("deselects every aspect in the collection", function(){ + this.aspects.deselectAll(); + this.aspects.each(function(aspect){ + expect(aspect.get('selected')).toBeFalsy(); + }); + }); + }); + + describe("#allSelected", function(){ + it("returns true if every aspect is selected", function(){ + this.aspects.at(1).set('selected', true); + this.aspects.at(2).set('selected', true); + expect(this.aspects.allSelected()).toBeTruthy(); + }); + + it("returns false if at least one aspect is not selected", function(){ + expect(this.aspects.allSelected()).toBeFalsy(); + }); + }); + + describe("#toSentence", function(){ + describe('without aspects', function(){ + beforeEach(function(){ + this.aspects = new app.collections.Aspects({ name: 'Work', selected: false }) + spyOn(this.aspects, 'selectedAspects').andCallThrough(); + }); + + it("returns the name of the aspect", function(){ + expect(this.aspects.toSentence()).toEqual('My Aspects'); + expect(this.aspects.selectedAspects).toHaveBeenCalled(); + }); + }); + + describe("with one aspect", function(){ + beforeEach(function(){ + this.aspects = new app.collections.Aspects({ name: 'Work', selected: true }) + spyOn(this.aspects, 'selectedAspects').andCallThrough(); + }); + + it("returns the name of the aspect", function(){ + expect(this.aspects.toSentence()).toEqual('Work'); + expect(this.aspects.selectedAspects).toHaveBeenCalled(); + }); + }); + + describe("with three aspect", function(){ + it("returns the name of the selected aspect", function(){ + expect(this.aspects.toSentence()).toEqual('Work'); + }); + + it("returns the names of the two selected aspects", function(){ + this.aspects.at(1).set('selected', true); + expect(this.aspects.toSentence()).toEqual('Work and Friends'); + }); + + it("returns the names of the selected aspects in a comma-separated sentence", function(){ + this.aspects.at(1).set('selected', true); + this.aspects.at(2).set('selected', true); + expect(this.aspects.toSentence()).toEqual('Work, Friends and Acquaintances'); + }); + }); + }); + + describe("#selectedAspects", function(){ + describe("by name", function(){ + it("returns the names of the selected aspects", function(){ + expect(this.aspects.selectedAspects('name')).toEqual(["Work"]); + }); + }); + }); +}); diff --git a/spec/javascripts/app/models/aspect_spec.js b/spec/javascripts/app/models/aspect_spec.js new file mode 100644 index 000000000..72ab56047 --- /dev/null +++ b/spec/javascripts/app/models/aspect_spec.js @@ -0,0 +1,15 @@ +describe("app.models.Aspect", function(){ + describe("#toggleSelected", function(){ + it("should select the aspect", function(){ + this.aspect = new app.models.Aspect({ name: 'John Doe', selected: false }); + this.aspect.toggleSelected(); + expect(this.aspect.get("selected")).toBeTruthy(); + }); + + it("should deselect the aspect", function(){ + this.aspect = new app.models.Aspect({ name: 'John Doe', selected: true }); + this.aspect.toggleSelected(); + expect(this.aspect.get("selected")).toBeFalsy(); + }); + }); +}); diff --git a/spec/javascripts/app/views/aspect_view_spec.js b/spec/javascripts/app/views/aspect_view_spec.js new file mode 100644 index 000000000..cfdbb387d --- /dev/null +++ b/spec/javascripts/app/views/aspect_view_spec.js @@ -0,0 +1,42 @@ +describe("app.views.Aspect", function(){ + beforeEach(function(){ + this.aspect = new app.models.Aspect({ name: 'Acquaintances', selected: true }); + this.view = new app.views.Aspect({ model: this.aspect }); + }); + + describe("render", function(){ + beforeEach(function(){ + this.view.render(); + }); + + it('should show the aspect selected', function(){ + expect(this.view.$el.hasClass('active')).toBeTruthy(); + }); + + it('should show the name of the aspect', function(){ + expect(this.view.$('a.aspect_selector').text()).toMatch('Acquaintances'); + }); + + describe('selecting aspects', function(){ + beforeEach(function(){ + app.router = new app.Router(); + spyOn(app.router, 'aspects_stream'); + spyOn(this.view, 'toggleAspect').andCallThrough(); + this.view.delegateEvents(); + }); + + it('it should deselect the aspect', function(){ + this.view.$('a.aspect_selector').trigger('click'); + expect(this.view.toggleAspect).toHaveBeenCalled(); + expect(this.view.$el.hasClass('active')).toBeFalsy(); + expect(app.router.aspects_stream).toHaveBeenCalled(); + }); + + it('should call #toggleSelected on the model', function(){ + spyOn(this.aspect, 'toggleSelected'); + this.view.$('a.aspect_selector').trigger('click'); + expect(this.aspect.toggleSelected).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/spec/javascripts/app/views/aspects_list_view_spec.js b/spec/javascripts/app/views/aspects_list_view_spec.js new file mode 100644 index 000000000..27b5ed972 --- /dev/null +++ b/spec/javascripts/app/views/aspects_list_view_spec.js @@ -0,0 +1,61 @@ +describe("app.views.AspectsList", function(){ + beforeEach(function(){ + setFixtures(''); + Diaspora.I18n.loadLocale({ aspect_navigation : { + 'select_all' : 'Select all', + 'deselect_all' : 'Deselect all' + }}); + + var aspects = [{ name: 'Work', selected: true }, + { name: 'Friends', selected: false }, + { name: 'Acquaintances', selected: false }]; + this.aspects = new app.collections.Aspects(aspects); + this.view = new app.views.AspectsList({ collection: this.aspects }); + }); + + describe('rendering', function(){ + beforeEach(function(){ + this.view.render(); + }); + + it('should show the corresponding aspects selected', function(){ + expect(this.view.$('.active').length).toBe(1); + expect(this.view.$('.active > .aspect_selector').text()).toMatch('Work'); + }); + + it('should show all the aspects', function(){ + var aspect_selectors = this.view.$('.aspect_selector'); + expect(aspect_selectors.length).toBe(3) + expect(aspect_selectors[0].text).toMatch('Work'); + expect(aspect_selectors[1].text).toMatch('Friends'); + expect(aspect_selectors[2].text).toMatch('Acquaintances'); + }); + + it('should show \'Select all\' link', function(){ + expect(this.view.$('.toggle_selector').text()).toMatch('Select all'); + }); + + describe('selecting aspects', function(){ + context('selecting all aspects', function(){ + beforeEach(function(){ + app.router = new app.Router(); + spyOn(app.router, 'aspects_stream'); + spyOn(this.view, 'toggleAll').andCallThrough(); + spyOn(this.view, 'toggleSelector').andCallThrough(); + this.view.delegateEvents(); + this.view.$('.toggle_selector').click(); + }); + + it('should show all the aspects selected', function(){ + expect(this.view.toggleAll).toHaveBeenCalled(); + expect(this.view.$('li.active').length).toBe(3); + }); + + it('should show \'Deselect all\' link', function(){ + expect(this.view.toggleSelector).toHaveBeenCalled(); + expect(this.view.$('.toggle_selector').text()).toMatch('Deselect all'); + }); + }); + }); + }); +}); diff --git a/spec/presenters/user_presenter_spec.rb b/spec/presenters/user_presenter_spec.rb index 2f322b497..38720dcb3 100644 --- a/spec/presenters/user_presenter_spec.rb +++ b/spec/presenters/user_presenter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe UserPresenter do before do - @presenter = UserPresenter.new(bob) + @presenter = UserPresenter.new(bob, []) end describe '#to_json' do @@ -34,4 +34,4 @@ describe UserPresenter do @presenter.configured_services.should include("fakebook") end end -end \ No newline at end of file +end