From ff84ee0485fd4e3e36d59f86633113f266ba3510 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 25 Aug 2014 19:22:23 +0200 Subject: [PATCH] Small style changes, add tests --- Changelog.md | 3 +- app/assets/javascripts/app/router.js | 2 +- .../javascripts/app/views/contacts_view.js | 28 +-- app/assets/javascripts/contact-list.js | 28 --- app/assets/javascripts/jasmine-load-all.js | 1 + app/assets/stylesheets/aspects.css.scss | 2 +- app/assets/stylesheets/contacts.css.scss | 18 +- app/assets/stylesheets/people.css.scss | 4 +- app/controllers/aspects_controller.rb | 1 + app/controllers/contacts_controller.rb | 53 +++-- app/helpers/contacts_helper.rb | 8 +- app/views/contacts/_aspect_listings.haml | 2 +- app/views/contacts/_contact.html.haml | 2 +- app/views/contacts/_header.html.haml | 2 +- app/views/contacts/index.html.haml | 9 +- config/locales/diaspora/en.yml | 3 +- config/locales/javascript/javascript.en.yml | 3 +- config/routes.rb | 4 +- features/desktop/contacts.feature | 8 +- features/desktop/manages_aspects.feature | 33 +-- .../desktop/stops_following_users.feature | 5 +- features/step_definitions/aspects_steps.rb | 12 +- spec/controllers/aspects_controller_spec.rb | 49 +--- spec/controllers/contacts_controller_spec.rb | 19 +- .../jasmine_fixtures/contacts_spec.rb | 4 +- .../app/views/contacts_view_spec.js | 215 ++++++++++++++++++ spec/javascripts/contact-list-spec.js | 19 -- spec/javascripts/search-spec.js | 1 - 28 files changed, 323 insertions(+), 215 deletions(-) create mode 100644 spec/javascripts/app/views/contacts_view_spec.js delete mode 100644 spec/javascripts/contact-list-spec.js diff --git a/Changelog.md b/Changelog.md index c5414fd08..7edd18e74 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Diaspora::Application.config.secret_key_base = '*************...' The default for including jQuery from a CDN has changed. If you want to continue to include it from a CDN, please explicitly set the `jquery_cdn` setting to `true` in diaspora.yml. ## Refactor +* Redesign contacts page [#5153](https://github.com/diaspora/diaspora/pull/5153) ## Bug fixes * orca cannot see 'Add Contact' button [#5158](https://github.com/diaspora/diaspora/pull/5158) @@ -105,7 +106,7 @@ Read more in [#4249](https://github.com/diaspora/diaspora/pull/4249) and [#4883] * Reorder and reword items on user settings page [#4912](https://github.com/diaspora/diaspora/pull/4912) * SPV: Improve padding and interaction counts [#4426](https://github.com/diaspora/diaspora/pull/4426) * Remove auto 'mark as read' for notifications [#4810](https://github.com/diaspora/diaspora/pull/4810) -* Improve set read/unread in notifications dropdown [#4869](https://github.com/diaspora/diaspora/pull/4869) +* Improve set read/unread in notifications dropdown [#4869](https://github.com/diaspora/diaspora/pull/4869) * Refactor publisher: trigger events for certain actions, introduce 'disabled' state [#4932](https://github.com/diaspora/diaspora/pull/4932) ## Bug fixes diff --git a/app/assets/javascripts/app/router.js b/app/assets/javascripts/app/router.js index 717c4e1ba..76b9895d5 100644 --- a/app/assets/javascripts/app/router.js +++ b/app/assets/javascripts/app/router.js @@ -24,7 +24,7 @@ app.Router = Backbone.Router.extend({ "people/:id": "stream", "u/:name": "stream" }, - + initialize: function() { // To support encoded linefeeds (%0A) we need to specify // our own internal router.route call with the correct regexp. diff --git a/app/assets/javascripts/app/views/contacts_view.js b/app/assets/javascripts/app/views/contacts_view.js index 770e03ab5..7ddd9fdf4 100644 --- a/app/assets/javascripts/app/views/contacts_view.js +++ b/app/assets/javascripts/app/views/contacts_view.js @@ -52,23 +52,24 @@ app.views.Contacts = Backbone.View.extend({ addContactToAspect: function(e){ var contact = $(e.currentTarget); var aspect_membership = new app.models.AspectMembership({ - 'person_id': contact.data('person_id'), - 'aspect_id': contact.data('aspect_id') + 'person_id': contact.attr('data-person_id'), + 'aspect_id': contact.attr('data-aspect_id') }); - aspect_membership.save({ + aspect_membership.save({},{ success: function(model,response){ contact.attr('data-membership_id',model.id) .tooltip('destroy') .removeAttr('data-original-title') - .removeClass("contact_add-to_aspect").removeClass("circled-plus") - .addClass("contact_remove-from_aspect").addClass("circled-cross") - .attr('title', Diaspora.I18n.t('contacts.add_contact')) + .removeClass("contact_add-to-aspect").removeClass("circled-plus") + .addClass("contact_remove-from-aspect").addClass("circled-cross") + .attr('title', Diaspora.I18n.t('contacts.remove_contact')) .tooltip() - .closest('.stream_element').removeClass('not_in_aspect'); + .closest('.stream_element').addClass('in_aspect'); }, error: function(model,response){ - alert("SAVE ERROR " + JSON.stringify(model)); + var msg = Diaspora.I18n.t('contacts.error_add', { 'name':contact.closest('.stream_element').find('.name').text() }); + Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg }); } }); }, @@ -76,7 +77,7 @@ app.views.Contacts = Backbone.View.extend({ removeContactFromAspect: function(e){ var contact = $(e.currentTarget); var aspect_membership = new app.models.AspectMembership({ - 'id': contact.data('membership_id') + 'id': contact.attr('data-membership_id') }); aspect_membership.destroy({ @@ -84,14 +85,15 @@ app.views.Contacts = Backbone.View.extend({ contact.removeAttr('data-membership_id') .tooltip('destroy') .removeAttr('data-original-title') - .removeClass("contact_remove-from_aspect").removeClass("circled-cross") - .addClass("contact_add-to_aspect").addClass("circled-plus") + .removeClass("contact_remove-from-aspect").removeClass("circled-cross") + .addClass("contact_add-to-aspect").addClass("circled-plus") .attr('title', Diaspora.I18n.t('contacts.add_contact')) .tooltip() - .closest('.stream_element').addClass('not_in_aspect'); + .closest('.stream_element').removeClass('in_aspect'); }, error: function(model,response){ - alert("DESTROY ERROR " + JSON.stringify(model)); + var msg = Diaspora.I18n.t('contacts.error_remove', { 'name':contact.closest('.stream_element').find('.name').text() }); + Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg }); } }); }, diff --git a/app/assets/javascripts/contact-list.js b/app/assets/javascripts/contact-list.js index e4caeabd6..f8ee17374 100644 --- a/app/assets/javascripts/contact-list.js +++ b/app/assets/javascripts/contact-list.js @@ -1,8 +1,3 @@ -/* Copyright (c) 2010-2011, Diaspora Inc. This file is - * licensed under the Affero General Public License version 3 or later. See - * the COPYRIGHT file. - */ - var List = { runDelayedSearch: function( searchTerm ) { $.getJSON('/people/refresh_search', @@ -23,27 +18,4 @@ var List = { startSearchDelay: function (theSearch) { setTimeout( "List.runDelayedSearch('" + theSearch + "')", 10000); } - }; - -$(document).ready(function() { - $('.added').bind('ajax:loading', function() { - var $this = $(this); - - $this.addClass('disabled'); - $this.fadeTo(200,0.4); - }); - - $('.added').bind('hover', - function() { - var $this = $(this) - $this.addClass("remove"); - $this.children("img").attr("src","/images/icons/monotone_close_exit_delete.png"); - }, - - function() { - var $this = $(this) - $this.removeClass("remove"); - $this.children("img").attr("src","/images/icons/monotone_check_yes.png"); - }); -}); diff --git a/app/assets/javascripts/jasmine-load-all.js b/app/assets/javascripts/jasmine-load-all.js index 7395aba77..5872aee01 100644 --- a/app/assets/javascripts/jasmine-load-all.js +++ b/app/assets/javascripts/jasmine-load-all.js @@ -7,4 +7,5 @@ //= require mobile //= require profile //= require people +//= require contact-list //= require sinon diff --git a/app/assets/stylesheets/aspects.css.scss b/app/assets/stylesheets/aspects.css.scss index a6603be88..1b9cf7da9 100644 --- a/app/assets/stylesheets/aspects.css.scss +++ b/app/assets/stylesheets/aspects.css.scss @@ -1,5 +1,5 @@ .aspect_dropdown { - + li { .status_indicator { width: 19px; diff --git a/app/assets/stylesheets/contacts.css.scss b/app/assets/stylesheets/contacts.css.scss index 5c565b355..fe872dd27 100644 --- a/app/assets/stylesheets/contacts.css.scss +++ b/app/assets/stylesheets/contacts.css.scss @@ -1,14 +1,14 @@ #contacts_container { #people_stream.contacts { - .header { + .header { border-bottom: 1px solid $border-grey; margin-top: 10px; min-height: 53px; #change_aspect_name { cursor: pointer; } - #aspect_name_form { + #aspect_name_form { display: none; form { margin: 0px; } - input { + input { margin-bottom: 0px; margin-top: 10px; } @@ -17,8 +17,9 @@ #contact_list_search { margin: 6px 30px 0 0; width: 150px; + &:focus { width: 250px; } } - & > a, #aspect_controls > a { + & > a, #aspect_controls > a { text-decoration: none; margin-right: 25px; } @@ -41,10 +42,13 @@ color: lighten($black,75%); &:hover { color: $black; } } - - &.not_in_aspect { background-color: $background-grey; } + &.in_aspect { + border-left: 3px solid $green; + background-color: lighten($green,35%); + } + &:not(.in_aspect) { border-left: 3px solid $white; } } - + .no_contacts { text-align: center; margin-top: 50px; diff --git a/app/assets/stylesheets/people.css.scss b/app/assets/stylesheets/people.css.scss index 0c0c67783..c217dcca4 100644 --- a/app/assets/stylesheets/people.css.scss +++ b/app/assets/stylesheets/people.css.scss @@ -20,9 +20,9 @@ height: 50px; } .btn-group.aspect_membership_dropdown { margin: 12px 0; } - .thats_you { + .thats_you { line-height: 50px; - margin-right: 20px; + margin-right: 10px; } .info { font-size: 11px; } } diff --git a/app/controllers/aspects_controller.rb b/app/controllers/aspects_controller.rb index becffae3b..13988f814 100644 --- a/app/controllers/aspects_controller.rb +++ b/app/controllers/aspects_controller.rb @@ -87,6 +87,7 @@ class AspectsController < ApplicationController @aspect.contacts_visible = true end @aspect.save + render :nothing => true end private diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb index ad8b76013..462bc1692 100644 --- a/app/controllers/contacts_controller.rb +++ b/app/controllers/contacts_controller.rb @@ -34,29 +34,40 @@ class ContactsController < ApplicationController private def set_up_contacts - c = Contact.arel_table - @contacts = case params[:set] - when "only_sharing" - current_user.contacts.only_sharing.to_a.sort_by { |c| c.person.name } - when "all" - current_user.contacts.to_a.sort_by { |c| c.person.name } - else - if params[:a_id] - @aspect = current_user.aspects.find(params[:a_id]) - @contacts_in_aspect = @aspect.contacts.includes(:aspect_memberships, :person => :profile).to_a.sort_by { |c| c.person.name } - if @contacts_in_aspect.empty? - @contacts_not_in_aspect = current_user.contacts.includes(:aspect_memberships, :person => :profile).to_a.sort_by { |c| c.person.name } - else - @contacts_not_in_aspect = current_user.contacts.where(c[:id].not_in(@contacts_in_aspect.map(&:id))).includes(:aspect_memberships, :person => :profile).to_a.sort_by { |c| c.person.name } - end - @contacts_in_aspect + @contacts_not_in_aspect - else - current_user.contacts.receiving.to_a.sort_by { |c| c.person.name } - end - end + type = params[:set].presence + type ||= "by_aspect" if params[:a_id].present? + type ||= "receiving" + + @contacts = contacts_by_type(type) @contacts_size = @contacts.length end - + + def contacts_by_type(type) + contacts = case type + when "all" + [current_user.contacts] + when "only_sharing" + [current_user.contacts.only_sharing] + when "receiving" + [current_user.contacts.receiving] + when "by_aspect" + @aspect = current_user.aspects.find(params[:a_id]) + @contacts_in_aspect = @aspect.contacts + @contacts_not_in_aspect = current_user.contacts.where.not(contacts: {id: @contacts_in_aspect.pluck(:id) }) + [@contacts_in_aspect, @contacts_not_in_aspect].map {|relation| + relation.includes(:aspect_memberships) + } + else + raise ArgumentError, "unknown type #{type}" + end + + contacts.map {|relation| + relation.includes(:person => :profile).to_a.tap {|contacts| + contacts.sort_by! {|contact| contact.person.name } + } + }.inject(:+) + end + def set_up_contacts_mobile @contacts = case params[:set] when "only_sharing" diff --git a/app/helpers/contacts_helper.rb b/app/helpers/contacts_helper.rb index a197bb4e8..0dd9d4bd2 100644 --- a/app/helpers/contacts_helper.rb +++ b/app/helpers/contacts_helper.rb @@ -4,9 +4,9 @@ module ContactsHelper if membership content_tag(:i, nil, :class => 'entypo circled-cross contact_remove-from-aspect', - :title => t('contacts.index.remove_person_from_aspect', :person_name => contact.person_first_name, :aspect_name => @aspect.name), + :title => t('contacts.index.remove_contact'), 'data-aspect_id' => @aspect.id, - 'data-person_id' => contact.person_id, + 'data-person_id' => contact.person_id, 'data-membership_id' => membership.id ) elsif @aspect.nil? @@ -16,7 +16,7 @@ module ContactsHelper :current_user => current_user } else content_tag(:i, nil, :class => 'entypo circled-plus contact_add-to-aspect', - :title => t('people.person.add_contact'), + :title => t('contacts.index.add_contact'), 'data-aspect_id' => @aspect.id, 'data-person_id' => contact.person_id ) end @@ -26,7 +26,7 @@ module ContactsHelper suggested_limit = 16 conv_opts = { class: "conversation_button", rel: "facebox"} conv_opts[:title] = t('.many_people_are_you_sure', suggested_limit: suggested_limit) if contacts_size > suggested_limit - + link_to new_conversation_path(aspect_id: aspect.id, name: aspect.name), conv_opts do content_tag(:i, nil, :class => 'entypo mail contacts-header-icon', :title => t('contacts.index.start_a_conversation')) end diff --git a/app/views/contacts/_aspect_listings.haml b/app/views/contacts/_aspect_listings.haml index 413ac2b4b..a9b9be9b8 100644 --- a/app/views/contacts/_aspect_listings.haml +++ b/app/views/contacts/_aspect_listings.haml @@ -11,7 +11,7 @@ = t('contacts.index.my_contacts') .badge.badge-default.pull-right = my_contacts_count - + - all_aspects.each do |aspect| %li.aspect{:data => {:aspect_id => aspect.id}, :class => ("active" if params["a_id"].to_i == aspect.id)} %a{:href => contacts_path(:a_id => aspect.id)} diff --git a/app/views/contacts/_contact.html.haml b/app/views/contacts/_contact.html.haml index ed484a85d..3e6aeb8a4 100644 --- a/app/views/contacts/_contact.html.haml +++ b/app/views/contacts/_contact.html.haml @@ -1,5 +1,5 @@ - membership = contact.aspect_memberships.where(:aspect_id => @aspect.id).first unless @aspect.nil? -.media.stream_element{:id => contact.person_id, :class => ("not_in_aspect" unless membership)} +.media.stream_element{:id => contact.person_id, :class => ("in_aspect" if membership)} .pull-right = contact_aspect_dropdown(contact) .media-object.pull-left diff --git a/app/views/contacts/_header.html.haml b/app/views/contacts/_header.html.haml index bedae3a8d..e51c36957 100644 --- a/app/views/contacts/_header.html.haml +++ b/app/views/contacts/_header.html.haml @@ -10,7 +10,7 @@ -else %i.entypo.lock.contacts-header-icon{:title => t('aspects.edit.aspect_list_is_not_visible')} - = link_to @aspect, method: "delete", data: { confirm: t('aspects.edit.confirm_remove_aspect') }, class: 'delete' do + = link_to @aspect, method: "delete", data: { confirm: t('aspects.edit.confirm_remove_aspect') }, class: 'delete', id: 'delete_aspect' do %i.entypo.trash.contacts-header-icon{:title => t('delete')} .pull-right = search_field_tag :contact_search, "", id: "contact_list_search", placeholder: t('contacts.index.user_search') diff --git a/app/views/contacts/index.html.haml b/app/views/contacts/index.html.haml index d833e9118..d2a6b7743 100644 --- a/app/views/contacts/index.html.haml +++ b/app/views/contacts/index.html.haml @@ -21,10 +21,5 @@ %h3 = t('.no_contacts') %p - - if @aspect - != t('.no_contacts_message_with_aspect', - :community_spotlight => link_to(t('.community_spotlight'), community_spotlight_path), - :add_to_aspect_link => link_to(t('.add_to_aspect_link', :name => @aspect.name), edit_aspect_path(@aspect), :rel => "facebox")) - - else - != t('.no_contacts_message', - :community_spotlight => link_to(t('.community_spotlight'), community_spotlight_path)) + != t('.no_contacts_message', + :community_spotlight => link_to(t('.community_spotlight'), community_spotlight_path)) diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 6aab979c4..cbd2ed9c1 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -343,7 +343,8 @@ en: my_contacts: "My Contacts" all_contacts: "All Contacts" only_sharing_with_me: "Only sharing with me" - remove_person_from_aspect: "Remove %{person_name} from \"%{aspect_name}\"" + add_contact: "Add contact" + remove_contact: "Remove contact" many_people_are_you_sure: "Are you sure you want to start a private conversation with more than %{suggested_limit} contacts? Posting to this aspect may be a better way to contact them." user_search: "User Search" spotlight: diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index dd25785d1..a977d733f 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -43,7 +43,8 @@ en: aspect_list_is_visible: "Contacts in this aspect are able to see each other." aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other." remove_contact: "Remove contact" - + error_add: "Couldn't add <%= name %> to the aspect :(" + error_remove: "Couldn't remove <%= name %> from the aspect :(" my_activity: "My Activity" my_stream: "Stream" diff --git a/config/routes.rb b/config/routes.rb index 558c8de7b..e32770a80 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -84,7 +84,7 @@ Diaspora::Application.routes.draw do get :read_all end end - + resources :tags, :only => [:index] @@ -221,7 +221,7 @@ Diaspora::Application.routes.draw do #Statistics get :statistics, controller: :statistics - + # Terms if AppConfig.settings.terms.enable? get 'terms' => 'terms#index' diff --git a/features/desktop/contacts.feature b/features/desktop/contacts.feature index 9e59a9c93..33639826e 100644 --- a/features/desktop/contacts.feature +++ b/features/desktop/contacts.feature @@ -16,7 +16,7 @@ Feature: show contacts And I press the first "a" within ".section.contact_pictures" Then I should see "Alice Smith" - Scenario: see contacts of a visible aspect list + Scenario: see contacts of a visible aspect list When I am on "bob@bob.bob"'s page And I add the person to my "Unicorns" aspect And I sign out @@ -25,14 +25,12 @@ Feature: show contacts And I press the first "a" within ".section.contact_pictures" Then I should see "Bob Jones" - Scenario: don't see contacts of an invisible aspect list + Scenario: don't see contacts of an invisible aspect list When I am on "bob@bob.bob"'s page And I add the person to my "Unicorns" aspect And I am on the contacts page And I follow "Unicorns" - And I follow "Manage" - And I press the first "a.contact_visibility_link" in the modal window - And I press "Done" in the modal window + And I press the first "a#contacts_visibility_toggle" And I sign out And I sign in as "alice@alice.alice" diff --git a/features/desktop/manages_aspects.feature b/features/desktop/manages_aspects.feature index 9c285844e..360709474 100644 --- a/features/desktop/manages_aspects.feature +++ b/features/desktop/manages_aspects.feature @@ -25,55 +25,42 @@ Feature: User manages contacts And I have an aspect called "People" When I am on the contacts page And I follow "People" - And I follow "add contacts to People" - And I press "Delete" in the modal window + And I click on selector "#delete_aspect" And I confirm the alert Then I should be on the contacts page - And I should not see "People" within "#aspects_list" + And I should not see "People" within "#aspect_nav" Scenario: deleting an aspect from homepage Given I am signed in And I have an aspect called "People" When I am on the aspects page And I click on "People" aspect edit icon - And I follow "Delete" within "#aspect_controls" + And I click on selector "#delete_aspect" And I confirm the alert Then I should be on the contacts page - And I should not see "People" within "#aspects_list" + And I should not see "People" within "#aspect_nav" - Scenario: Editing the aspect memberships of a contact from the aspect edit facebox + Scenario: Editing the aspect memberships of a contact from the contacts page Given I am signed in And I have 2 contacts And I have an aspect called "Cat People" When I am on the contacts page And I follow "Cat People" - And I follow "add contacts to Cat People" - And I check the first contact list button + And I add the first person to the aspect Then I should have 1 contact in "Cat People" - When I uncheck the first contact list button + When I remove the first person from the aspect Then I should have 0 contacts in "Cat People" - + Scenario: Renaming an aspect Given I am signed in And I have an aspect called "Cat People" When I am on the contacts page And I follow "Cat People" - And I follow "Manage" within "#aspect_controls" - And I follow "rename" + And I click on selector "#change_aspect_name" And I fill in "aspect_name" with "Unicorn People" And I press "update" - Then I should see "Unicorn People" within "#aspect_name_title" - - Scenario: infinite scroll on contacts index - Given I am signed in - And I resize my window to 800x600 - And I have 30 contacts - And I am on the contacts page - Then I should see 25 contacts - - When I scroll down - Then I should see 30 contacts + Then I should see "Unicorn People" within "#aspect_name" Scenario: clicking on the contacts link in the header with zero contacts directs a user to the featured users page Given I am signed in diff --git a/features/desktop/stops_following_users.feature b/features/desktop/stops_following_users.feature index 30a5b97af..b2a066324 100644 --- a/features/desktop/stops_following_users.feature +++ b/features/desktop/stops_following_users.feature @@ -27,14 +27,13 @@ Feature: Unfollowing Then I should not see "is sharing with you." - Scenario: stop following someone while on the aspect edit page + Scenario: stop following someone while on the contacts page When I go to the home page And I go to the contacts page And I follow "Besties" - And I follow "Manage" - And I press the first ".added" within "#facebox .contact_list ul > li:first-child" + And I remove the first person from the aspect When I follow "My Contacts" Then I should have 0 contacts in "Besties" diff --git a/features/step_definitions/aspects_steps.rb b/features/step_definitions/aspects_steps.rb index 83539e80f..f1e53a852 100644 --- a/features/step_definitions/aspects_steps.rb +++ b/features/step_definitions/aspects_steps.rb @@ -41,17 +41,17 @@ When /^I select "([^"]*)" aspect as well$/ do |aspect_name| step %Q(I should see "#{aspect_name}" aspect selected) end -When /^I check the first contact list button$/ do - find(".contact_list .btn", match: :first).tap do |button| +When /^I add the first person to the aspect$/ do + find(".contact_add-to-aspect", match: :first).tap do |button| button.click - button.parent.should have_css ".added" + button.parent.should have_css ".contact_remove-from-aspect" end end -When /^I uncheck the first contact list button$/ do - find(".contact_list .btn", match: :first).tap do |button| +When /^I remove the first person from the aspect$/ do + find(".contact_remove-from-aspect", match: :first).tap do |button| button.click - button.parent.should have_css ".add" + button.parent.should have_css ".contact_add-to-aspect" sleep 1 # The expectation above should wait for the request to finsh, but that doesn't work for some reason end end diff --git a/spec/controllers/aspects_controller_spec.rb b/spec/controllers/aspects_controller_spec.rb index 86adf5895..c8369f94b 100644 --- a/spec/controllers/aspects_controller_spec.rb +++ b/spec/controllers/aspects_controller_spec.rb @@ -112,57 +112,12 @@ describe AspectsController do end end - describe '#edit' do - before do - eve.profile.first_name = eve.profile.last_name = nil - eve.profile.save - eve.save - - @zed = FactoryGirl.create(:user_with_aspect, :username => "zed") - @zed.profile.first_name = "zed" - @zed.profile.save - @zed.save - @katz = FactoryGirl.create(:user_with_aspect, :username => "katz") - @katz.profile.first_name = "katz" - @katz.profile.save - @katz.save - - connect_users(alice, @alices_aspect_2, eve, eve.aspects.first) - connect_users(alice, @alices_aspect_2, @zed, @zed.aspects.first) - connect_users(alice, @alices_aspect_1, @katz, @katz.aspects.first) - end - - it 'renders' do - get :edit, :id => @alices_aspect_1.id - response.should be_success - end - - it 'assigns the contacts in alphabetical order with people in aspects first' do - get :edit, :id => @alices_aspect_2.id - assigns[:contacts].map(&:id).should == [alice.contact_for(eve.person), alice.contact_for(@zed.person), alice.contact_for(bob.person), alice.contact_for(@katz.person)].map(&:id) - end - - it 'assigns all the contacts if noone is there' do - alices_aspect_3 = alice.aspects.create(:name => "aspect 3") - - get :edit, :id => alices_aspect_3.id - assigns[:contacts].map(&:id).should == [alice.contact_for(bob.person), alice.contact_for(eve.person), alice.contact_for(@katz.person), alice.contact_for(@zed.person)].map(&:id) - end - - it 'eager loads the aspect memberships for all the contacts' do - get :edit, :id => @alices_aspect_2.id - assigns[:contacts].each do |c| - c.aspect_memberships.loaded?.should be_true - end - end - end - describe "#toggle_contact_visibility" do it 'sets contacts visible' do @alices_aspect_1.contacts_visible = false @alices_aspect_1.save - xhr :get, :toggle_contact_visibility, :format => 'js', :aspect_id => @alices_aspect_1.id + xhr :get, :toggle_contact_visibility, :aspect_id => @alices_aspect_1.id @alices_aspect_1.reload.contacts_visible.should be_true end @@ -170,7 +125,7 @@ describe AspectsController do @alices_aspect_1.contacts_visible = true @alices_aspect_1.save - xhr :get, :toggle_contact_visibility, :format => 'js', :aspect_id => @alices_aspect_1.id + xhr :get, :toggle_contact_visibility, :aspect_id => @alices_aspect_1.id @alices_aspect_1.reload.contacts_visible.should be_false end end diff --git a/spec/controllers/contacts_controller_spec.rb b/spec/controllers/contacts_controller_spec.rb index 91be1c5dc..de2380e70 100644 --- a/spec/controllers/contacts_controller_spec.rb +++ b/spec/controllers/contacts_controller_spec.rb @@ -10,23 +10,6 @@ describe ContactsController do @controller.stub(:current_user).and_return(bob) end - describe '#sharing' do - it "succeeds" do - get :sharing - response.should be_success - end - - it 'eager loads the aspects' do - get :sharing - assigns[:contacts].first.aspect_memberships.loaded?.should be_true - end - - it "assigns only the people sharing with you with 'share_with' flag" do - get :sharing, :id => 'share_with' - assigns[:contacts].to_set.should == bob.contacts.sharing.to_set - end - end - describe '#index' do context 'format mobile' do it "succeeds" do @@ -51,7 +34,7 @@ describe ContactsController do contact = bob.contacts.first contact.update_attributes(:sharing => false) - get :index, :set => "mine" + get :index contacts = assigns(:contacts) contacts.to_set.should == bob.contacts.receiving.to_set end diff --git a/spec/controllers/jasmine_fixtures/contacts_spec.rb b/spec/controllers/jasmine_fixtures/contacts_spec.rb index d2a5321de..e672dec41 100644 --- a/spec/controllers/jasmine_fixtures/contacts_spec.rb +++ b/spec/controllers/jasmine_fixtures/contacts_spec.rb @@ -7,11 +7,13 @@ require 'spec_helper' describe ContactsController do describe '#index' do before do + @aspect = bob.aspects.create(:name => "another aspect") + bob.share_with alice.person, @aspect sign_in :user, bob end it "generates a jasmine fixture", :fixture => true do - get :index + get :index, :a_id => @aspect.id save_fixture(html_for("body"), "aspects_manage") end end diff --git a/spec/javascripts/app/views/contacts_view_spec.js b/spec/javascripts/app/views/contacts_view_spec.js new file mode 100644 index 000000000..d9236c0d7 --- /dev/null +++ b/spec/javascripts/app/views/contacts_view_spec.js @@ -0,0 +1,215 @@ +describe("app.views.Contacts", function(){ + beforeEach(function() { + spec.loadFixture("aspects_manage"); + this.view = new app.views.Contacts(); + Diaspora.I18n.load({ + contacts: { + add_contact: "Add contact", + aspect_list_is_visible: "Contacts in this aspect are able to see each other.", + aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other.", + remove_contact: "Remove contact", + error_add: "Couldn't add <%= name %> to the aspect :(", + error_remove: "Couldn't remove <%= name %> from the aspect :(" + } + }); + }); + + context('toggle contacts visibility', function() { + beforeEach(function() { + this.visibility_toggle = $("#contacts_visibility_toggle"); + this.lock_icon = $("#contacts_visibility_toggle .entypo"); + }); + + it('updates the title for the tooltip', function() { + expect(this.lock_icon.attr('data-original-title')).toBe( + Diaspora.I18n.t("contacts.aspect_list_is_visible") + ); + + this.visibility_toggle.trigger('click'); + + expect(this.lock_icon.attr('data-original-title')).toBe( + Diaspora.I18n.t("contacts.aspect_list_is_not_visible") + ); + }); + + it('toggles the lock icon', function() { + expect(this.lock_icon.hasClass('lock-open')).toBeTruethy; + expect(this.lock_icon.hasClass('lock')).toBeFalsy; + + this.visibility_toggle.trigger('click'); + + expect(this.lock_icon.hasClass('lock')).toBeTruethy; + expect(this.lock_icon.hasClass('lock-open')).toBeFalsy; + }); + }); + + context('show aspect name form', function() { + beforeEach(function() { + this.button = $('#change_aspect_name'); + }); + + it('shows the form', function() { + expect($('#aspect_name_form').css('display')).toBe('none'); + this.button.trigger('click'); + expect($('#aspect_name_form').css('display')).not.toBe('none'); + }); + + it('hides the aspect name', function() { + expect($('.header > h3').css('display')).not.toBe('none'); + this.button.trigger('click'); + expect($('.header > h3').css('display')).toBe('none'); + }); + }); + + context('add contact to aspect', function() { + beforeEach(function() { + this.contact = $('#people_stream .stream_element').last(); + this.button = this.contact.find('.contact_add-to-aspect'); + this.person_id = this.button.attr('data-person_id'); + this.aspect_id = this.button.attr('data-aspect_id'); + }); + + it('sends a correct ajax request', function() { + jasmine.Ajax.install(); + $('.contact_add-to-aspect',this.contact).trigger('click'); + var obj = $.parseJSON(jasmine.Ajax.requests.mostRecent().params); + expect(obj.person_id).toBe(this.person_id); + expect(obj.aspect_id).toBe(this.aspect_id); + }); + + it('adds a membership id to the contact', function() { + jasmine.Ajax.install(); + $('.contact_add-to-aspect',this.contact).trigger('click'); + jasmine.Ajax.requests.mostRecent().response({ + status: 200, // success + responseText: '{ "id": 42 }' + }); + expect(this.button.attr('data-membership_id')).toBe('42'); + }); + + it('displays a flash message on errors', function(){ + jasmine.Ajax.install(); + $('.contact_add-to-aspect',this.contact).trigger('click'); + jasmine.Ajax.requests.mostRecent().response({ + status: 400, // fail + }); + expect($('[id^="flash"]')).toBeErrorFlashMessage( + Diaspora.I18n.t( + 'contacts.error_add', + {name: this.contact.find('.name').text()} + ) + ); + }); + + it('changes the appearance of the contact', function() { + expect(this.button.hasClass('contact_add-to-aspect')).toBeTruethy; + expect(this.button.hasClass('circled-cross')).toBeTruethy; + expect(this.contact.hasClass('in_aspect')).toBeTruethy; + expect(this.button.hasClass('contact_remove-from-aspect')).toBeFalsy; + expect(this.button.hasClass('circled-plus')).toBeFalsy; + expect(this.button.attr('data-original-title')).toBe( + Diaspora.I18n.t('contacts.add_contact') + ); + jasmine.Ajax.install(); + $('.contact_add-to-aspect',this.contact).trigger('click'); + jasmine.Ajax.requests.mostRecent().response({ + status: 200, // success + responseText: '{ "id": 42 }' + }); + expect(this.button.hasClass('contact_add-to-aspect')).toBeFalsy; + expect(this.button.hasClass('circled-cross')).toBeFalsy; + expect(this.contact.hasClass('in_aspect')).toBeFalsy; + expect(this.button.hasClass('contact_remove-from-aspect')).toBeTruethy; + expect(this.button.hasClass('circled-plus')).toBeTruethy; + expect(this.button.attr('data-original-title')).toBe( + Diaspora.I18n.t('contacts.remove_contact') + ); + }); + }); + + context('remove contact from aspect', function() { + beforeEach(function() { + this.contact = $('#people_stream .stream_element').first(); + this.button = this.contact.find('.contact_remove-from-aspect'); + this.person_id = this.button.attr('data-person_id'); + this.aspect_id = this.button.attr('data-aspect_id'); + this.membership_id = this.button.attr('data-membership_id'); + + }); + + it('sends a correct ajax request', function() { + jasmine.Ajax.install(); + $('.contact_remove-from-aspect',this.contact).trigger('click'); + expect(jasmine.Ajax.requests.mostRecent().url).toBe( + "/aspect_memberships/"+this.membership_id + ); + }); + + it('removes the membership id from the contact', function() { + jasmine.Ajax.install(); + $('.contact_remove-from-aspect',this.contact).trigger('click'); + jasmine.Ajax.requests.mostRecent().response({ + status: 200, // success + responseText: '{}' + }); + expect(this.button.attr('data-membership_id')).toBe(undefined); + }); + + it('displays a flash message on errors', function(){ + jasmine.Ajax.install(); + $('.contact_remove-from-aspect',this.contact).trigger('click'); + jasmine.Ajax.requests.mostRecent().response({ + status: 400, // fail + }); + expect($('[id^="flash"]')).toBeErrorFlashMessage( + Diaspora.I18n.t( + 'contacts.error_remove', + {name: this.contact.find('.name').text()} + ) + ); + }); + + it('changes the appearance of the contact', function() { + expect(this.button.hasClass('contact_add-to-aspect')).toBeFalsy; + expect(this.button.hasClass('circled-cross')).toBeFalsy; + expect(this.contact.hasClass('in_aspect')).toBeFalsy; + expect(this.button.hasClass('contact_remove-from-aspect')).toBeTruethy; + expect(this.button.hasClass('circled-plus')).toBeTruethy; + expect(this.button.attr('data-original-title')).toBe( + Diaspora.I18n.t('contacts.remove_contact') + ); + + jasmine.Ajax.install(); + $('.contact_remove-from-aspect',this.contact).trigger('click'); + jasmine.Ajax.requests.mostRecent().response({ + status: 200, // success + responseText: '{}' + }); + + expect(this.button.hasClass('contact_add-to-aspect')).toBeTruethy; + expect(this.button.hasClass('circled-cross')).toBeTruethy; + expect(this.contact.hasClass('in_aspect')).toBeTruethy; + expect(this.button.hasClass('contact_remove-from-aspect')).toBeFalsy; + expect(this.button.hasClass('circled-plus')).toBeFalsy; + expect(this.button.attr('data-original-title')).toBe( + Diaspora.I18n.t('contacts.add_contact') + ); + }); + }); + + context('search contact list', function() { + beforeEach(function() { + this.searchinput = $('#contact_list_search'); + this.username = $('.stream_element .name').first().text(); + }); + + it('filters the contact list by name', function() { + expect($('.stream_element').length).toBeGreaterThan(1); + this.searchinput.val(this.username); + this.searchinput.trigger('keyup'); + expect($('.stream_element:visible').length).toBe(1); + expect($('.stream_element:visible .name').first().text()).toBe(this.username); + }); + }); + +}); diff --git a/spec/javascripts/contact-list-spec.js b/spec/javascripts/contact-list-spec.js deleted file mode 100644 index 6bafe6653..000000000 --- a/spec/javascripts/contact-list-spec.js +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (c) 2010-2011, Diaspora Inc. This file is -* licensed under the Affero General Public License version 3 or later. See -* the COPYRIGHT file. -*/ - -describe("Contact List", function() { - describe("disconnectUser", function() { - it("does an ajax call to person delete with the passed in id", function(){ - var id = '3'; - spyOn($,'ajax'); - List.disconnectUser(id); - expect($.ajax).toHaveBeenCalled(); - var option_hash = $.ajax.calls.mostRecent().args[0]; - expect(option_hash.url).toEqual("/contacts/" + id); - expect(option_hash.type).toEqual("DELETE"); - expect(option_hash.success).toBeDefined(); - }); - }); -}); diff --git a/spec/javascripts/search-spec.js b/spec/javascripts/search-spec.js index f1c41d0ba..99f018dbf 100644 --- a/spec/javascripts/search-spec.js +++ b/spec/javascripts/search-spec.js @@ -7,7 +7,6 @@ describe("List", function() { describe("runDelayedSearch", function() { beforeEach( function(){ spec.loadFixture('empty_people_search'); - List.initialize(); }); it('inserts contact html', function(){