Merge pull request #3850 from marpo60/port-my-aspects-to-backbone
Port my aspects to backbone
This commit is contained in:
commit
ab86423fe9
24 changed files with 443 additions and 139 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
26
app/assets/javascripts/app/collections/aspects.js
Normal file
26
app/assets/javascripts/app/collections/aspects.js
Normal file
|
|
@ -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");
|
||||
}
|
||||
})
|
||||
5
app/assets/javascripts/app/models/aspect.js
Normal file
5
app/assets/javascripts/app/models/aspect.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
app.models.Aspect = Backbone.Model.extend({
|
||||
toggleSelected: function(){
|
||||
this.set({'selected' : !this.get('selected')});
|
||||
}
|
||||
});
|
||||
27
app/assets/javascripts/app/models/stream_aspects.js
Normal file
27
app/assets/javascripts/app/models/stream_aspects.js
Normal file
|
|
@ -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))
|
||||
}
|
||||
});
|
||||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
28
app/assets/javascripts/app/views/aspect_view.js
Normal file
28
app/assets/javascripts/app/views/aspect_view.js
Normal file
|
|
@ -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
|
||||
})
|
||||
}
|
||||
});
|
||||
55
app/assets/javascripts/app/views/aspects_list_view.js
Normal file
55
app/assets/javascripts/app/views/aspects_list_view.js
Normal file
|
|
@ -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());
|
||||
}
|
||||
})
|
||||
|
|
@ -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 @@
|
|||
);
|
||||
}
|
||||
};
|
||||
})();
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
});
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
})();
|
||||
6
app/assets/templates/aspect_tpl.jst.hbs
Normal file
6
app/assets/templates/aspect_tpl.jst.hbs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<div class="edit">
|
||||
<a href="/aspects/{{id}}/edit" rel="facebox">
|
||||
<img alt="Pencil" src="{{imageUrl "icons/pencil.png"}}" title="{{t 'edit'}} {{name}}">
|
||||
</a>
|
||||
</div>
|
||||
<a class="aspect_selector name" data-guid="{{id}}" href="/aspects/query"> {{name}} </a>
|
||||
6
app/assets/templates/aspects-list_tpl.jst.hbs
Normal file
6
app/assets/templates/aspects-list_tpl.jst.hbs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<a class="toggle_selector" href="#">
|
||||
{{ t "aspect_navigation.select_all" }}
|
||||
</a>
|
||||
<li>
|
||||
<a class="new_aspect" href="/aspects/new" rel="facebox">{{ t "aspect_navigation.add_an_aspect" }}</a>
|
||||
</li>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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')}
|
||||
|
|
|
|||
|
|
@ -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?"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
94
spec/javascripts/app/collections/aspects_spec.js
Normal file
94
spec/javascripts/app/collections/aspects_spec.js
Normal file
|
|
@ -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"]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
15
spec/javascripts/app/models/aspect_spec.js
Normal file
15
spec/javascripts/app/models/aspect_spec.js
Normal file
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
42
spec/javascripts/app/views/aspect_view_spec.js
Normal file
42
spec/javascripts/app/views/aspect_view_spec.js
Normal file
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
61
spec/javascripts/app/views/aspects_list_view_spec.js
Normal file
61
spec/javascripts/app/views/aspects_list_view_spec.js
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
describe("app.views.AspectsList", function(){
|
||||
beforeEach(function(){
|
||||
setFixtures('<ul id="aspects_list"></ul>');
|
||||
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');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -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
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue