diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss index e7e917be8..1ad457b87 100644 --- a/app/assets/stylesheets/layout.scss +++ b/app/assets/stylesheets/layout.scss @@ -18,7 +18,7 @@ // 16. Flags // 17. Activity // 18. Banners -// 19. Recommended Section Home +// 19. Recommendations // 20. Documents // 21. Related content // 22. Images @@ -2261,8 +2261,8 @@ table { } } -// 19. Recommended Section Home -// ---------------------------- +// 19. Recommendations +// ------------------- .section-recommended { background: #fafafa; @@ -2404,6 +2404,54 @@ table { } } +.recommended-index { + background: #fafafa; + border-bottom: 1px solid #eee; + margin-bottom: $line-height; + margin-top: rem-calc(-25); + padding: $line-height 0 $line-height / 2; + + @include breakpoint(medium) { + padding-top: 0; + } + + h2 { + font-size: $small-font-size; + text-transform: uppercase; + } + + h3 { + font-size: $base-font-size; + margin-bottom: 0; + } + + a { + + &:hover { + text-decoration: none; + } + } + + .recommendation { + background: #fff; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15); + display: block; + margin-bottom: $line-height / 4; + padding: $line-height / 2; + + &:hover { + box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.15); + } + } +} + +.hide-recommendations { + color: $text-light; + position: absolute; + right: 12px; + top: -18px; +} + // 20. Documents // ------------- diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb index fad581dc6..a82017f16 100644 --- a/app/controllers/account_controller.rb +++ b/app/controllers/account_controller.rb @@ -28,7 +28,7 @@ class AccountController < ApplicationController else [:username, :public_activity, :public_interests, :email_on_comment, :email_on_comment_reply, :email_on_direct_message, :email_digest, :newsletter, - :official_position_badge] + :official_position_badge, :recommended_debates, :recommended_proposals] end params.require(:account).permit(*attributes) end diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb index 09dfc940e..abcf79559 100644 --- a/app/controllers/debates_controller.rb +++ b/app/controllers/debates_controller.rb @@ -6,6 +6,7 @@ class DebatesController < ApplicationController before_action :parse_tag_filter, only: :index before_action :authenticate_user!, except: [:index, :show, :map] before_action :set_view, only: :index + before_action :debates_recommendations, only: :index, if: :current_user feature_flag :debates @@ -43,6 +44,14 @@ class DebatesController < ApplicationController redirect_to request.query_parameters.merge(action: :index) end + def disable_recommendations + if current_user.update(recommended_debates: false) + redirect_to debates_path, notice: t('debates.index.recommendations.actions.success') + else + redirect_to debates_path, error: t('debates.index.recommendations.actions.error') + end + end + private def debate_params @@ -57,4 +66,10 @@ class DebatesController < ApplicationController @view = (params[:view] == "minimal") ? "minimal" : "default" end + def debates_recommendations + if Setting['feature.user.recommendations_on_debates'] && current_user.recommended_debates + @recommended_debates = Debate.recommendations(current_user).sort_by_random.limit(3) + end + end + end diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index f43bc8ad9..798aeebf2 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -9,6 +9,7 @@ class ProposalsController < ApplicationController before_action :authenticate_user!, except: [:index, :show, :map, :summary] before_action :destroy_map_location_association, only: :update before_action :set_view, only: :index + before_action :proposals_recommendations, only: :index, if: :current_user feature_flag :proposals @@ -79,6 +80,14 @@ class ProposalsController < ApplicationController @tag_cloud = tag_cloud end + def disable_recommendations + if current_user.update(recommended_proposals: false) + redirect_to proposals_path, notice: t('proposals.index.recommendations.actions.success') + else + redirect_to proposals_path, error: t('proposals.index.recommendations.actions.error') + end + end + private def proposal_params @@ -144,4 +153,10 @@ class ProposalsController < ApplicationController end end + def proposals_recommendations + if Setting['feature.user.recommendations_on_proposals'] && current_user.recommended_proposals + @recommended_proposals = Proposal.recommendations(current_user).sort_by_random.limit(3) + end + end + end diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index 8f289f986..d8d716ec2 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -94,6 +94,8 @@ module Abilities can [:create], Topic can [:update, :destroy], Topic, author_id: user.id + + can :disable_recommendations, [Debate, Proposal] end end end diff --git a/app/models/debate.rb b/app/models/debate.rb index ec58b2e23..93ca5420f 100644 --- a/app/models/debate.rb +++ b/app/models/debate.rb @@ -151,7 +151,7 @@ class Debate < ActiveRecord::Base def self.debates_orders(user) orders = %w{hot_score confidence_score created_at relevance} - orders << "recommendations" if user.present? - orders + orders << "recommendations" if Setting['feature.user.recommendations_on_debates'] && user&.recommended_debates + return orders end end diff --git a/app/models/proposal.rb b/app/models/proposal.rb index 4393d0d51..f47584456 100644 --- a/app/models/proposal.rb +++ b/app/models/proposal.rb @@ -210,8 +210,8 @@ class Proposal < ActiveRecord::Base def self.proposals_orders(user) orders = %w{hot_score confidence_score created_at relevance archival_date} - orders << "recommendations" if user.present? - orders + orders << "recommendations" if Setting['feature.user.recommendations_on_proposals'] && user&.recommended_proposals + return orders end protected diff --git a/app/views/account/show.html.erb b/app/views/account/show.html.erb index 81b25e5e0..a0a782f2b 100644 --- a/app/views/account/show.html.erb +++ b/app/views/account/show.html.erb @@ -112,6 +112,32 @@ <% end %> + <% if feature?("user.recommendations") %> +

<%= t("account.show.recommendations") %>

+ + <% if feature?("user.recommendations_on_debates") %> +
+ <%= f.label :recommended_debates do %> + <%= f.check_box :recommended_debates, title: t("account.show.show_debates_recommendations"), label: false %> + + <%= t("account.show.show_debates_recommendations") %> + + <% end %> +
+ <% end %> + + <% if feature?("user.recommendations_on_proposals") %> +
+ <%= f.label :recommended_proposals do %> + <%= f.check_box :recommended_proposals, title: t("account.show.show_proposals_recommendations"), label: false %> + + <%= t("account.show.show_proposals_recommendations") %> + + <% end %> +
+ <% end %> + <% end %> + <%= f.submit t("account.show.save_changes_submit"), class: "button margin-top" %> diff --git a/app/views/debates/index.html.erb b/app/views/debates/index.html.erb index e5355b975..967864f04 100644 --- a/app/views/debates/index.html.erb +++ b/app/views/debates/index.html.erb @@ -35,6 +35,12 @@ <%= render "shared/section_header", i18n_namespace: "debates.index.section_header", image: "debates" %> <% end %> + <% if feature?('user.recommendations') && @recommended_debates.present? %> + <%= render "shared/recommended_index", recommended: @recommended_debates, + disable_recommendations_path: recommendations_disable_debates_path, + namespace: "debates" %> + <% end %> +
diff --git a/app/views/proposals/index.html.erb b/app/views/proposals/index.html.erb index 61d90a64c..25c294654 100644 --- a/app/views/proposals/index.html.erb +++ b/app/views/proposals/index.html.erb @@ -37,6 +37,12 @@ <%= render "shared/section_header", i18n_namespace: "proposals.index.section_header", image: "proposals" %> <% end %> + <% if feature?('user.recommendations') && @recommended_proposals.present? %> + <%= render "shared/recommended_index", recommended: @recommended_proposals, + disable_recommendations_path: recommendations_disable_proposals_path, + namespace: "proposals" %> + <% end %> +
diff --git a/app/views/shared/_recommended_index.html.erb b/app/views/shared/_recommended_index.html.erb new file mode 100644 index 000000000..e7c7d3835 --- /dev/null +++ b/app/views/shared/_recommended_index.html.erb @@ -0,0 +1,36 @@ + diff --git a/app/views/shared/_section_header.html.erb b/app/views/shared/_section_header.html.erb index 9408b663e..6ae7580ce 100644 --- a/app/views/shared/_section_header.html.erb +++ b/app/views/shared/_section_header.html.erb @@ -3,7 +3,9 @@
<%= image_tag "help/help_icon_#{image}.png", alt: t("#{i18n_namespace}.icon_alt"), class: "align-top" %>

<%= t("#{i18n_namespace}.title") %>

- <%= link_to t("#{i18n_namespace}.help"), "#section_help", class: "float-right" %> +
+ <%= link_to t("#{i18n_namespace}.help"), "#section_help" %> +
diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml index 406ca2dde..a3a451c2a 100644 --- a/config/locales/en/general.yml +++ b/config/locales/en/general.yml @@ -20,6 +20,9 @@ en: email_on_direct_message_label: Receive emails about direct messages email_digest_label: Receive a summary of proposal notifications official_position_badge_label: Show official position badge + recommendations: Recommendations + show_debates_recommendations: Show debates recommendations + show_proposals_recommendations: Show proposals recommendations title: My account user_permission_debates: Participate on debates user_permission_info: With your account you can... @@ -110,6 +113,10 @@ en: recommendations: without_results: There are not debates related to your interests without_interests: Follow proposals so we can give you recommendations + disable: "Debates recommendations will stop showing if you dismiss them. You can enable them again in 'My account' page" + actions: + success: "Recommendations for debates are now disabled for this account" + error: "An error has occured. Please go to 'Your account' page to manually disable recommendations for debates" search_form: button: Search placeholder: Search debates... @@ -361,6 +368,10 @@ en: recommendations: without_results: There are not proposals related to your interests without_interests: Follow proposals so we can give you recommendations + disable: "Proposals recommendations will stop showing if you dismiss them. You can enable them again in 'My account' page" + actions: + success: "Recommendations for proposals are now disabled for this account" + error: "An error has occured. Please go to 'Your account' page to manually disable recommendations for proposals" retired_proposals: Retired proposals retired_proposals_link: "Proposals retired by the author" retired_links: @@ -632,6 +643,10 @@ en: title: View mode cards: Cards list: List + recommended_index: + title: Recommendations + see_more: See more recommendations + hide: Hide recommendations social: blog: "%{org} Blog" facebook: "%{org} Facebook" diff --git a/config/locales/en/settings.yml b/config/locales/en/settings.yml index 938717187..1d2bb819a 100644 --- a/config/locales/en/settings.yml +++ b/config/locales/en/settings.yml @@ -43,6 +43,8 @@ en: user: recommendations: Recommendations skip_verification: Skip user verification + recommendations_on_debates: Recommendations on debates + recommendations_on_proposals: Recommendations on proposals community: Community on proposals and investments map: Proposals and budget investments geolocation allow_images: Allow upload and show images diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index d01f67422..69f49c18a 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -20,6 +20,9 @@ es: email_on_direct_message_label: Recibir emails con mensajes privados email_digest_label: Recibir resumen de notificaciones sobre propuestas official_position_badge_label: Mostrar etiqueta de tipo de usuario + recommendations: Recomendaciones + show_debates_recommendations: Mostrar recomendaciones en el listado de debates + show_proposals_recommendations: Mostrar recomendaciones en el listado de propuestas title: Mi cuenta user_permission_debates: Participar en debates user_permission_info: Con tu cuenta ya puedes... @@ -110,6 +113,10 @@ es: recommendations: without_results: No existen debates relacionados con tus intereses without_interests: Sigue propuestas para que podamos darte recomendaciones + disable: "Si ocultas las recomendaciones para debates, no se volverán a mostrar. Puedes volver a activarlas en 'Mi cuenta'" + actions: + success: "Las recomendaciones de debates han sido desactivadas" + error: "Ha ocurrido un error. Por favor dirígete al apartado 'Mi cuenta' para desactivar las recomendaciones manualmente" search_form: button: Buscar placeholder: Buscar debates... @@ -361,6 +368,10 @@ es: recommendations: without_results: No existen propuestas relacionadas con tus intereses without_interests: Sigue propuestas para que podamos darte recomendaciones + disable: "Si ocultas las recomendaciones para propuestas, no se volverán a mostrar. Puedes volver a activarlas en 'Mi cuenta'" + actions: + success: "Las recomendaciones de propuestas han sido desactivadas" + error: "Ha ocurrido un error. Por favor dirígete al apartado 'Mi cuenta' para desactivar las recomendaciones manualmente" retired_proposals: Propuestas retiradas retired_proposals_link: "Propuestas retiradas por sus autores" retired_links: @@ -631,6 +642,10 @@ es: title: Modo de vista cards: Tarjetas list: Lista + recommended_index: + title: Recomendaciones + see_more: Ver más recomendaciones + hide: Ocultar recomendaciones social: blog: "Blog de %{org}" facebook: "Facebook de %{org}" diff --git a/config/locales/es/settings.yml b/config/locales/es/settings.yml index 57dfaae50..90f785580 100644 --- a/config/locales/es/settings.yml +++ b/config/locales/es/settings.yml @@ -43,6 +43,8 @@ es: user: recommendations: Recomendaciones skip_verification: Omitir verificación de usuarios + recommendations_on_debates: Recomendaciones en debates + recommendations_on_proposals: Recomendaciones en propuestas community: Comunidad en propuestas y proyectos de gasto map: Geolocalización de propuestas y proyectos de gasto allow_images: Permitir subir y mostrar imágenes diff --git a/config/routes/debate.rb b/config/routes/debate.rb index 2345d150f..4167ed68c 100644 --- a/config/routes/debate.rb +++ b/config/routes/debate.rb @@ -10,5 +10,6 @@ resources :debates do collection do get :map get :suggest + put 'recommendations/disable', only: :index, controller: 'debates', action: :disable_recommendations end end diff --git a/config/routes/proposal.rb b/config/routes/proposal.rb index d3408ed29..b0736ec0e 100644 --- a/config/routes/proposal.rb +++ b/config/routes/proposal.rb @@ -13,5 +13,6 @@ resources :proposals do get :map get :suggest get :summary + put 'recommendations/disable', only: :index, controller: 'proposals', action: :disable_recommendations end end diff --git a/db/dev_seeds/settings.rb b/db/dev_seeds/settings.rb index 6c5d8862d..783781346 100644 --- a/db/dev_seeds/settings.rb +++ b/db/dev_seeds/settings.rb @@ -40,6 +40,8 @@ section "Creating Settings" do Setting.create(key: 'feature.signature_sheets', value: "true") Setting.create(key: 'feature.legislation', value: "true") Setting.create(key: 'feature.user.recommendations', value: "true") + Setting.create(key: 'feature.user.recommendations_on_debates', value: "true") + Setting.create(key: 'feature.user.recommendations_on_proposals', value: "true") Setting.create(key: 'feature.community', value: "true") Setting.create(key: 'feature.map', value: "true") Setting.create(key: 'feature.allow_images', value: "true") diff --git a/db/migrate/20180604124515_add_recommended_debates_setting_to_users.rb b/db/migrate/20180604124515_add_recommended_debates_setting_to_users.rb new file mode 100644 index 000000000..500f1f4fc --- /dev/null +++ b/db/migrate/20180604124515_add_recommended_debates_setting_to_users.rb @@ -0,0 +1,7 @@ +class AddRecommendedDebatesSettingToUsers < ActiveRecord::Migration + def change + change_table :users do |t| + t.boolean :recommended_debates, default: false + end + end +end diff --git a/db/migrate/20180604151014_add_recommended_proposals_setting_to_users.rb b/db/migrate/20180604151014_add_recommended_proposals_setting_to_users.rb new file mode 100644 index 000000000..53a59e210 --- /dev/null +++ b/db/migrate/20180604151014_add_recommended_proposals_setting_to_users.rb @@ -0,0 +1,7 @@ +class AddRecommendedProposalsSettingToUsers < ActiveRecord::Migration + def change + change_table :users do |t| + t.boolean :recommended_proposals, default: false + end + end +end diff --git a/db/migrate/20180711224810_enable_recommendations_by_default.rb b/db/migrate/20180711224810_enable_recommendations_by_default.rb new file mode 100644 index 000000000..ece94e1b8 --- /dev/null +++ b/db/migrate/20180711224810_enable_recommendations_by_default.rb @@ -0,0 +1,6 @@ +class EnableRecommendationsByDefault < ActiveRecord::Migration + def change + change_column_default :users, :recommended_debates, true + change_column_default :users, :recommended_proposals, true + end +end diff --git a/db/schema.rb b/db/schema.rb index 54794367d..5e9247806 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180519132610) do +ActiveRecord::Schema.define(version: 20180711224810) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1156,6 +1156,8 @@ ActiveRecord::Schema.define(version: 20180519132610) do t.integer "failed_email_digests_count", default: 0 t.text "former_users_data_log", default: "" t.boolean "public_interests", default: false + t.boolean "recommended_debates", default: true + t.boolean "recommended_proposals", default: true end add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree diff --git a/db/seeds.rb b/db/seeds.rb index 868dec2ad..e453495f2 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -82,6 +82,8 @@ Setting['feature.budgets'] = true Setting['feature.signature_sheets'] = true Setting['feature.legislation'] = true Setting['feature.user.recommendations'] = true +Setting['feature.user.recommendations_on_debates'] = true +Setting['feature.user.recommendations_on_proposals'] = true Setting['feature.community'] = true Setting['feature.map'] = nil Setting['feature.allow_images'] = true diff --git a/lib/tasks/settings.rake b/lib/tasks/settings.rake index d09d32527..17ddd9aa0 100644 --- a/lib/tasks/settings.rake +++ b/lib/tasks/settings.rake @@ -13,4 +13,11 @@ namespace :settings do Setting['feature.allow_attached_documents'] = true end + desc "Enable recommendations settings" + task enable_recommendations: :environment do + Setting['feature.user.recommendations'] = true + Setting['feature.user.recommendations_on_debates'] = true + Setting['feature.user.recommendations_on_proposals'] = true + end + end diff --git a/lib/tasks/users.rake b/lib/tasks/users.rake new file mode 100644 index 000000000..d447e727c --- /dev/null +++ b/lib/tasks/users.rake @@ -0,0 +1,10 @@ +namespace :users do + + desc "Enable recommendations for existing users" + task enable_recommendations: :environment do + User.find_each do |user| + user.update(recommended_debates: true, recommended_proposals: true) + end + end + +end diff --git a/spec/features/account_spec.rb b/spec/features/account_spec.rb index 2713815ae..a82f32495 100644 --- a/spec/features/account_spec.rb +++ b/spec/features/account_spec.rb @@ -174,4 +174,53 @@ feature 'Account' do expect(page).to have_content "Invalid login or password" end + + context 'Recommendations' do + + background do + Setting['feature.user.recommendations'] = true + Setting['feature.user.recommendations_on_debates'] = true + Setting['feature.user.recommendations_on_proposals'] = true + end + + after do + Setting['feature.user.recommendations'] = nil + Setting['feature.user.recommendations_on_debates'] = nil + Setting['feature.user.recommendations_on_proposals'] = nil + end + + scenario 'are enabled by default' do + visit account_path + + expect(page).to have_content('Recommendations') + expect(page).to have_content('Show debates recommendations') + expect(page).to have_content('Show proposals recommendations') + expect(find("#account_recommended_debates")).to be_checked + expect(find("#account_recommended_proposals")).to be_checked + end + + scenario "can be disabled through 'My account' page" do + visit account_path + + expect(page).to have_content('Recommendations') + expect(page).to have_content('Show debates recommendations') + expect(page).to have_content('Show proposals recommendations') + expect(find("#account_recommended_debates")).to be_checked + expect(find("#account_recommended_proposals")).to be_checked + + uncheck 'account_recommended_debates' + uncheck 'account_recommended_proposals' + + click_button 'Save changes' + + expect(find("#account_recommended_debates")).not_to be_checked + expect(find("#account_recommended_proposals")).not_to be_checked + + @user.reload + + expect(@user.recommended_debates).to be(false) + expect(@user.recommended_proposals).to be(false) + end + + end end diff --git a/spec/features/debates_spec.rb b/spec/features/debates_spec.rb index c4018ce76..447e47ca6 100644 --- a/spec/features/debates_spec.rb +++ b/spec/features/debates_spec.rb @@ -397,52 +397,70 @@ feature 'Debates' do context 'Recommendations' do - let!(:best_debate) { create(:debate, title: 'Best', cached_votes_total: 10, tag_list: "Sport") } - let!(:medium_debate) { create(:debate, title: 'Medium', cached_votes_total: 5, tag_list: "Sport") } - let!(:worst_debate) { create(:debate, title: 'Worst', cached_votes_total: 1, tag_list: "Sport") } + let!(:best_debate) { create(:debate, title: 'Best', cached_votes_total: 10, tag_list: 'Sport') } + let!(:medium_debate) { create(:debate, title: 'Medium', cached_votes_total: 5, tag_list: 'Sport') } + let!(:worst_debate) { create(:debate, title: 'Worst', cached_votes_total: 1, tag_list: 'Sport') } background do Setting['feature.user.recommendations'] = true + Setting['feature.user.recommendations_on_debates'] = true end after do Setting['feature.user.recommendations'] = nil + Setting['feature.user.recommendations_on_debates'] = nil end - scenario 'Debates can not ordered by recommendations when there is not an user logged', :js do + scenario "can't be sorted if there's no logged user" do visit debates_path - expect(page).not_to have_selector('a', text: 'recommendations') end - scenario 'Should display text when there are not recommendeds results', :js do - user = create(:user) - proposal = create(:proposal, tag_list: "Distinct_to_sport") + scenario 'are shown on index header when account setting is enabled' do + user = create(:user) + proposal = create(:proposal, tag_list: 'Sport') create(:follow, followable: proposal, user: user) + + login_as(user) + visit debates_path + + expect(page).to have_css('.recommendation', count: 3) + expect(page).to have_link 'Best' + expect(page).to have_link 'Medium' + expect(page).to have_link 'Worst' + expect(page).to have_link 'See more recommendations' + end + + scenario 'should display text when there are no results' do + user = create(:user) + proposal = create(:proposal, tag_list: 'Distinct_to_sport') + create(:follow, followable: proposal, user: user) + login_as(user) visit debates_path click_link 'recommendations' - expect(page).to have_content "There are not debates related to your interests" + expect(page).to have_content 'There are not debates related to your interests' end - scenario 'Should display text when user has not related interests', :js do + scenario 'should display text when user has no related interests' do user = create(:user) + login_as(user) visit debates_path click_link 'recommendations' - expect(page).to have_content "Follow proposals so we can give you recommendations" + expect(page).to have_content 'Follow proposals so we can give you recommendations' end - scenario 'Debates are ordered by recommendations when there is a user logged', :js do - proposal = create(:proposal, tag_list: "Sport") - user = create(:user) + scenario "can be sorted when there's a logged user" do + user = create(:user) + proposal = create(:proposal, tag_list: 'Sport') create(:follow, followable: proposal, user: user) - login_as(user) + login_as(user) visit debates_path click_link 'recommendations' @@ -457,6 +475,47 @@ feature 'Debates' do expect(current_url).to include('order=recommendations') expect(current_url).to include('page=1') end + + scenario 'are not shown if account setting is disabled' do + user = create(:user, recommended_debates: false) + proposal = create(:proposal, tag_list: 'Sport') + create(:follow, followable: proposal, user: user) + + login_as(user) + visit debates_path + + expect(page).not_to have_css('.recommendation', count: 3) + expect(page).not_to have_link('recommendations') + end + + scenario 'are automatically disabled when dismissed from index', :js do + user = create(:user) + proposal = create(:proposal, tag_list: 'Sport') + create(:follow, followable: proposal, user: user) + + login_as(user) + visit debates_path + + within("#recommendations") do + expect(page).to have_content('Best') + expect(page).to have_content('Worst') + expect(page).to have_content('Medium') + expect(page).to have_css('.recommendation', count: 3) + + accept_confirm { click_link 'Hide recommendations' } + end + + expect(page).not_to have_link('recommendations') + expect(page).not_to have_css('.recommendation', count: 3) + expect(page).to have_content('Recommendations for debates are now disabled for this account') + + user.reload + + visit account_path + + expect(find("#account_recommended_debates")).not_to be_checked + expect(user.recommended_debates).to be(false) + end end end @@ -866,10 +925,13 @@ feature 'Debates' do end end - scenario "Reorder by recommendations results maintaing search", :js do + scenario "Reorder by recommendations results maintaing search" do Setting['feature.user.recommendations'] = true - user = create(:user) + Setting['feature.user.recommendations_for_debates'] = true + + user = create(:user, recommended_debates: true) login_as(user) + debate1 = create(:debate, title: "Show you got", cached_votes_total: 10, tag_list: "Sport") debate2 = create(:debate, title: "Show what you got", cached_votes_total: 1, tag_list: "Sport") debate3 = create(:debate, title: "Do not display with same tag", cached_votes_total: 100, tag_list: "Sport") @@ -889,7 +951,9 @@ feature 'Debates' do expect(page).not_to have_content "Do not display with same tag" expect(page).not_to have_content "Do not display" end + Setting['feature.user.recommendations'] = nil + Setting['feature.user.recommendations_for_debates'] = nil end scenario 'After a search do not show featured debates' do diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb index ce5987532..d3d51a96b 100644 --- a/spec/features/proposals_spec.rb +++ b/spec/features/proposals_spec.rb @@ -721,52 +721,70 @@ feature 'Proposals' do context 'Recommendations' do - let!(:best_proposal) { create(:proposal, title: 'Best', cached_votes_up: 10, tag_list: "Sport") } - let!(:medium_proposal) { create(:proposal, title: 'Medium', cached_votes_up: 5, tag_list: "Sport") } - let!(:worst_proposal) { create(:proposal, title: 'Worst', cached_votes_up: 1, tag_list: "Sport") } + let!(:best_proposal) { create(:proposal, title: 'Best', cached_votes_up: 10, tag_list: 'Sport') } + let!(:medium_proposal) { create(:proposal, title: 'Medium', cached_votes_up: 5, tag_list: 'Sport') } + let!(:worst_proposal) { create(:proposal, title: 'Worst', cached_votes_up: 1, tag_list: 'Sport') } before do Setting['feature.user.recommendations'] = true + Setting['feature.user.recommendations_on_proposals'] = true end after do Setting['feature.user.recommendations'] = nil + Setting['feature.user.recommendations_on_proposals'] = nil end - scenario 'Proposals can not ordered by recommendations when there is not an user logged', :js do + scenario "can't be sorted if there's no logged user" do visit proposals_path - expect(page).not_to have_selector('a', text: 'recommendations') end - scenario 'Should display text when there are not recommendeds results', :js do - user = create(:user) - proposal = create(:proposal, tag_list: "Distinct_to_sport") + scenario 'are shown on index header when account setting is enabled' do + user = create(:user) + proposal = create(:proposal, tag_list: 'Sport') create(:follow, followable: proposal, user: user) + + login_as(user) + visit proposals_path + + expect(page).to have_css('.recommendation', count: 3) + expect(page).to have_link 'Best' + expect(page).to have_link 'Medium' + expect(page).to have_link 'Worst' + expect(page).to have_link 'See more recommendations' + end + + scenario 'should display text when there are no results' do + user = create(:user) + proposal = create(:proposal, tag_list: 'Distinct_to_sport') + create(:follow, followable: proposal, user: user) + login_as(user) visit proposals_path click_link 'recommendations' - expect(page).to have_content "There are not proposals related to your interests" + expect(page).to have_content 'There are not proposals related to your interests' end - scenario 'Should display text when user has not related interests', :js do + scenario 'should display text when user has no related interests' do user = create(:user) + login_as(user) visit proposals_path click_link 'recommendations' - expect(page).to have_content "Follow proposals so we can give you recommendations" + expect(page).to have_content 'Follow proposals so we can give you recommendations' end - scenario 'Proposals are ordered by recommendations when there is an user logged', :js do - user = create(:user) - proposal = create(:proposal, tag_list: "Sport") + scenario "can be sorted when there's a logged user" do + user = create(:user) + proposal = create(:proposal, tag_list: 'Sport') create(:follow, followable: proposal, user: user) - login_as(user) + login_as(user) visit proposals_path click_link 'recommendations' @@ -781,6 +799,47 @@ feature 'Proposals' do expect(current_url).to include('order=recommendations') expect(current_url).to include('page=1') end + + scenario 'are not shown if account setting is disabled' do + user = create(:user, recommended_proposals: false) + proposal = create(:proposal, tag_list: 'Sport') + create(:follow, followable: proposal, user: user) + + login_as(user) + visit proposals_path + + expect(page).not_to have_css('.recommendation', count: 3) + expect(page).not_to have_link('recommendations') + end + + scenario 'are automatically disabled when dismissed from index', :js do + user = create(:user) + proposal = create(:proposal, tag_list: 'Sport') + create(:follow, followable: proposal, user: user) + + login_as(user) + visit proposals_path + + within("#recommendations") do + expect(page).to have_content('Best') + expect(page).to have_content('Worst') + expect(page).to have_content('Medium') + expect(page).to have_css('.recommendation', count: 3) + + accept_confirm { click_link 'Hide recommendations' } + end + + expect(page).not_to have_link('recommendations') + expect(page).not_to have_css('.recommendation', count: 3) + expect(page).to have_content('Recommendations for proposals are now disabled for this account') + + user.reload + + visit account_path + + expect(find("#account_recommended_proposals")).not_to be_checked + expect(user.recommended_proposals).to be(false) + end end end @@ -1317,10 +1376,13 @@ feature 'Proposals' do end end - scenario "Reorder by recommendations results maintaing search", :js do + scenario "Reorder by recommendations results maintaing search" do Setting['feature.user.recommendations'] = true - user = create(:user) + Setting['feature.user.recommendations_for_proposals'] = true + + user = create(:user, recommended_proposals: true) login_as(user) + proposal1 = create(:proposal, title: "Show you got", cached_votes_up: 10, tag_list: "Sport") proposal2 = create(:proposal, title: "Show what you got", cached_votes_up: 1, tag_list: "Sport") proposal3 = create(:proposal, title: "Do not display with same tag", cached_votes_up: 100, tag_list: "Sport") @@ -1340,7 +1402,9 @@ feature 'Proposals' do expect(page).not_to have_content "Do not display with same tag" expect(page).not_to have_content "Do not display" end + Setting['feature.user.recommendations'] = nil + Setting['feature.user.recommendations_for_proposals'] = nil end scenario 'After a search do not show featured proposals' do diff --git a/spec/models/abilities/common_spec.rb b/spec/models/abilities/common_spec.rb index f559eba99..93ffa9a48 100644 --- a/spec/models/abilities/common_spec.rb +++ b/spec/models/abilities/common_spec.rb @@ -299,4 +299,10 @@ describe Abilities::Common do it { should_not be_able_to(:answer, incoming_poll_question_from_other_geozone) } end end + + describe "#disable_recommendations" do + it { should be_able_to(:disable_recommendations, Debate) } + it { should be_able_to(:disable_recommendations, Proposal) } + end + end