-
- <%= t("welcome.proposal.title") %>
- <%= t("welcome.proposal.description") %>
-
+
+
+
+
<%= t("welcome.debates.title") %>
+
<%= t("welcome.debates.description") %>
+
+
+
<%= t("welcome.proposal.title") %>
+
<%= t("welcome.proposal.description") %>
+
+
+
<%= t("welcome.decide.title") %>
+
<%= t("welcome.decide.description") %>
+
+
+
<%= t("welcome.do.title") %>
+
<%= t("welcome.do.description") %>
+
-
-
-
- <%= t("welcome.decide.title") %>
- <%= t("welcome.decide.description") %>
-
-
-
-
- <%= t("welcome.do.title") %>
- <%= t("welcome.do.description") %>
-
-
-
<% end %>
diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml
index 290e1a278..67d8eef2c 100644
--- a/config/locales/en/general.yml
+++ b/config/locales/en/general.yml
@@ -109,6 +109,10 @@ en:
hot_score: most active
most_commented: most commented
relevance: relevance
+ recommendations: recommendations
+ recommendations:
+ without_results: There are not debates related to your interests
+ without_interests: Follow proposals so we can give you recommendations
search_form:
button: Search
placeholder: Search debates...
@@ -348,6 +352,10 @@ en:
most_commented: most commented
relevance: relevance
archival_date: Archived
+ recommendations: recommendations
+ recommendations:
+ without_results: There are not proposals related to your interests
+ without_interests: Follow proposals so we can give you recommendations
retired_proposals: Retired proposals
retired_proposals_link: "Proposals retired by the author"
retired_links:
@@ -473,6 +481,7 @@ en:
help_text_1: "Voting takes place when a citizen proposal supports reaches 1% of the census with voting rights. Voting can also include questions that the City Council ask to the citizens decision."
help_text_2: "To participate in the next vote you have to sign up on %{org} and verify your account. All registered voters in the city over 16 years old can vote. The results of all votes are binding on the government."
show:
+ already_voted_in_booth: "You have already participated in a booth for this poll."
dates_title: "Participation dates"
cant_answer_not_logged_in: "You must %{signin} or %{signup} to participate."
signin: Sign in
@@ -753,6 +762,16 @@ en:
proposal:
description: Open space for citizen proposals about the kind of city we want to live in.
title: You propose
+ recommended:
+ title: Recommendations that may interest you
+ debates:
+ title: Recommended debates
+ btn_text_link: All recommended debates
+ proposals:
+ title: Recommended proposals
+ btn_text_link: All recommended proposals
+ budget_investments:
+ title: Recommended investments
verification:
i_dont_have_an_account: I don't have an account
i_have_an_account: I already have an account
diff --git a/config/locales/en/settings.yml b/config/locales/en/settings.yml
index eaf610f4d..44e767a6e 100644
--- a/config/locales/en/settings.yml
+++ b/config/locales/en/settings.yml
@@ -39,6 +39,8 @@ en:
spending_proposal_features:
voting_allowed: Voting on investment projects
legislation: Legislation
+ user:
+ recommendations: Recommendeds
community: Community on proposals and investments
map: Proposals and budget investments geolocation
map_latitude: Latitude
diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml
index 722c0dabb..aaa59a900 100644
--- a/config/locales/es/general.yml
+++ b/config/locales/es/general.yml
@@ -109,6 +109,10 @@ es:
hot_score: Más activos hoy
most_commented: Más comentados
relevance: Más relevantes
+ recommendations: Recomendaciones
+ recommendations:
+ without_results: No existen debates relacionados con tus intereses
+ without_interests: Sigue propuestas para que podamos darte recomendaciones
search_form:
button: Buscar
placeholder: Buscar debates...
@@ -348,6 +352,10 @@ es:
most_commented: Más comentadas
relevance: Más relevantes
archival_date: Archivadas
+ recommendations: Recomendaciones
+ recommendations:
+ without_results: No existen propuestas relacionadas con tus intereses
+ without_interests: Sigue propuestas para que podamos darte recomendaciones
retired_proposals: Propuestas retiradas
retired_proposals_link: "Propuestas retiradas por sus autores"
retired_links:
@@ -394,7 +402,7 @@ es:
proposal:
created: "¡Has creado una propuesta!"
share:
- guide: "Compártela para que la gente empieze a apoyarla."
+ guide: "Compártela para que la gente empiece a apoyarla."
edit: "Antes de que se publique podrás modificar el texto a tu gusto."
view_proposal: "Ahora no, ir a mi propuesta"
improve_info: "Mejora tu campaña y consigue más apoyos"
@@ -473,6 +481,7 @@ es:
help_text_1: "Las votaciones se convocan cuando una propuesta ciudadana alcanza el 1% de apoyos del censo con derecho a voto. En las votaciones también se pueden incluir cuestiones que el Ayuntamiento somete a decisión directa de la ciudadanía."
help_text_2: "Para participar en la próxima votación tienes que registrarte en %{org} y verificar tu cuenta. Pueden votar todas las personas empadronadas en la ciudad mayores de 16 años. Los resultados de todas las votaciones serán vinculantes para el gobierno."
show:
+ already_voted_in_booth: "Ya has participado en esta votación en una urna."
dates_title: "Fechas de participación"
cant_answer_not_logged_in: "Necesitas %{signin} o %{signup} para participar."
signin: iniciar sesión
@@ -753,6 +762,16 @@ es:
proposal:
description: Espacio abierto para propuestas ciudadanas sobre el tipo de ciudad en el que queremos vivir.
title: Propones
+ recommended:
+ title: Recomendaciones que te pueden interesar
+ debates:
+ title: Debates recomendados
+ btn_text_link: Todos los debates recomendados
+ proposals:
+ title: Propuestas recomendadas
+ btn_text_link: Todas las propuestas recomendadas
+ budget_investments:
+ title: Presupuestos recomendados
verification:
i_dont_have_an_account: No tengo cuenta, quiero crear una y verificarla
i_have_an_account: Ya tengo una cuenta que quiero verificar
diff --git a/config/locales/es/settings.yml b/config/locales/es/settings.yml
index b23c6e688..fcf2eb1db 100644
--- a/config/locales/es/settings.yml
+++ b/config/locales/es/settings.yml
@@ -39,6 +39,8 @@ es:
spending_proposal_features:
voting_allowed: Votaciones sobre propuestas de inversión
legislation: Legislación
+ user:
+ recommendations: Recomendaciones
community: Comunidad en propuestas y proyectos de inversión
map: Geolocalización de propuestas y proyectos de inversión
map_latitude: Latitud
diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb
index fcd86c44a..b151a45cf 100644
--- a/db/dev_seeds.rb
+++ b/db/dev_seeds.rb
@@ -36,6 +36,7 @@ Setting.create(key: 'feature.facebook_login', value: "true")
Setting.create(key: 'feature.google_login', value: "true")
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.community', value: "true")
Setting.create(key: 'feature.map', value: "true")
Setting.create(key: 'per_page_code_head', value: "")
diff --git a/db/migrate/20171002121658_add_origin_to_poll_voters.rb b/db/migrate/20171002121658_add_origin_to_poll_voters.rb
new file mode 100644
index 000000000..845c1b774
--- /dev/null
+++ b/db/migrate/20171002121658_add_origin_to_poll_voters.rb
@@ -0,0 +1,5 @@
+class AddOriginToPollVoters < ActiveRecord::Migration
+ def change
+ add_column :poll_voters, :origin, :string
+ end
+end
diff --git a/db/migrate/20171002122312_create_poll_recount.rb b/db/migrate/20171002122312_create_poll_recount.rb
new file mode 100644
index 000000000..807f1c84e
--- /dev/null
+++ b/db/migrate/20171002122312_create_poll_recount.rb
@@ -0,0 +1,24 @@
+class CreatePollRecount < ActiveRecord::Migration
+ def change
+ create_table :poll_recounts do |t|
+ t.integer :author_id
+ t.string :origin
+ t.date :date
+ t.integer :booth_assignment_id
+ t.integer :officer_assignment_id
+ t.text :officer_assignment_id_log, default: ""
+ t.text :author_id_log, default: ""
+ t.integer :white_amount
+ t.text :white_amount_log, default: ""
+ t.integer :null_amount
+ t.text :null_amount_log, default: ""
+ t.integer :total_amount
+ t.text :total_amount_log, default: ""
+ end
+
+ add_index :poll_recounts, :booth_assignment_id
+ add_index :poll_recounts, :officer_assignment_id
+ add_foreign_key :poll_recounts, :poll_booth_assignments, column: :booth_assignment_id
+ add_foreign_key :poll_recounts, :poll_officer_assignments, column: :officer_assignment_id
+ end
+end
diff --git a/db/migrate/20171002191347_add_default_to_recount_amounts.rb b/db/migrate/20171002191347_add_default_to_recount_amounts.rb
new file mode 100644
index 000000000..b90e86aae
--- /dev/null
+++ b/db/migrate/20171002191347_add_default_to_recount_amounts.rb
@@ -0,0 +1,7 @@
+class AddDefaultToRecountAmounts < ActiveRecord::Migration
+ def change
+ change_column_default :poll_recounts, :white_amount, 0
+ change_column_default :poll_recounts, :null_amount, 0
+ change_column_default :poll_recounts, :total_amount, 0
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index f6ff7447d..5c5b99d11 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: 20171002103314) do
+ActiveRecord::Schema.define(version: 20171002191347) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -690,6 +690,25 @@ ActiveRecord::Schema.define(version: 20171002103314) do
add_index "poll_questions", ["proposal_id"], name: "index_poll_questions_on_proposal_id", using: :btree
add_index "poll_questions", ["tsv"], name: "index_poll_questions_on_tsv", using: :gin
+ create_table "poll_recounts", force: :cascade do |t|
+ t.integer "author_id"
+ t.string "origin"
+ t.date "date"
+ t.integer "booth_assignment_id"
+ t.integer "officer_assignment_id"
+ t.text "officer_assignment_id_log", default: ""
+ t.text "author_id_log", default: ""
+ t.integer "white_amount", default: 0
+ t.text "white_amount_log", default: ""
+ t.integer "null_amount", default: 0
+ t.text "null_amount_log", default: ""
+ t.integer "total_amount", default: 0
+ t.text "total_amount_log", default: ""
+ end
+
+ add_index "poll_recounts", ["booth_assignment_id"], name: "index_poll_recounts_on_booth_assignment_id", using: :btree
+ add_index "poll_recounts", ["officer_assignment_id"], name: "index_poll_recounts_on_officer_assignment_id", using: :btree
+
create_table "poll_shifts", force: :cascade do |t|
t.integer "booth_id"
t.integer "officer_id"
@@ -734,6 +753,7 @@ ActiveRecord::Schema.define(version: 20171002103314) do
t.integer "answer_id"
t.integer "officer_assignment_id"
t.integer "user_id"
+ t.string "origin"
end
add_index "poll_voters", ["booth_assignment_id"], name: "index_poll_voters_on_booth_assignment_id", using: :btree
@@ -1127,6 +1147,8 @@ ActiveRecord::Schema.define(version: 20171002103314) do
add_foreign_key "poll_questions", "polls"
add_foreign_key "poll_questions", "proposals"
add_foreign_key "poll_questions", "users", column: "author_id"
+ add_foreign_key "poll_recounts", "poll_booth_assignments", column: "booth_assignment_id"
+ add_foreign_key "poll_recounts", "poll_officer_assignments", column: "officer_assignment_id"
add_foreign_key "poll_voters", "polls"
add_foreign_key "poll_white_results", "poll_booth_assignments", column: "booth_assignment_id"
add_foreign_key "poll_white_results", "poll_officer_assignments", column: "officer_assignment_id"
diff --git a/db/seeds.rb b/db/seeds.rb
index ee444bd91..fcfa6340c 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -79,6 +79,7 @@ Setting['feature.public_stats'] = true
Setting['feature.budgets'] = true
Setting['feature.signature_sheets'] = true
Setting['feature.legislation'] = true
+Setting['feature.user.recommendations'] = true
Setting['feature.community'] = true
Setting['feature.map'] = nil
diff --git a/spec/factories.rb b/spec/factories.rb
index b0a287aea..c21c35b4e 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -52,6 +52,12 @@ FactoryGirl.define do
trait :verified do
verified_at Time.current
end
+
+ trait :in_census do
+ document_number "12345678Z"
+ document_type "1"
+ verified_at Time.current
+ end
end
factory :identity do
@@ -525,6 +531,7 @@ FactoryGirl.define do
factory :poll_voter, class: 'Poll::Voter' do
poll
association :user, :level_two
+ origin "web"
trait :from_booth do
association :booth_assignment, factory: :poll_booth_assignment
@@ -569,6 +576,11 @@ FactoryGirl.define do
origin { 'web' }
end
+ factory :poll_recount, class: 'Poll::Recount' do
+ association :author, factory: :user
+ origin { 'web' }
+ end
+
factory :officing_residence, class: 'Officing::Residence' do
user
association :officer, factory: :poll_officer
diff --git a/spec/features/admin/poll/polls_spec.rb b/spec/features/admin/poll/polls_spec.rb
index 6eb64f6e1..8d30dc5eb 100644
--- a/spec/features/admin/poll/polls_spec.rb
+++ b/spec/features/admin/poll/polls_spec.rb
@@ -249,18 +249,18 @@ feature 'Admin polls' do
booth_assignment_final_recounted = create(:poll_booth_assignment, poll: poll)
3.times do |i|
- create(:poll_total_result,
+ create(:poll_recount,
booth_assignment: booth_assignment,
date: poll.starts_at + i.days,
- amount: 21)
+ total_amount: 21)
end
2.times { create(:poll_voter, booth_assignment: booth_assignment_final_recounted) }
- create(:poll_total_result,
+ create(:poll_recount,
booth_assignment: booth_assignment_final_recounted,
date: poll.ends_at,
- amount: 55555)
+ total_amount: 55555)
visit admin_poll_path(poll)
@@ -318,12 +318,10 @@ feature 'Admin polls' do
answer: 'Tomorrow',
amount: 5)
end
- create(:poll_white_result,
+ create(:poll_recount,
booth_assignment: booth_assignment_1,
- amount: 21)
- create(:poll_null_result,
- booth_assignment: booth_assignment_3,
- amount: 44)
+ white_amount: 21,
+ null_amount: 44)
visit admin_poll_path(poll)
diff --git a/spec/features/admin_spec.rb b/spec/features/admin_spec.rb
index 9ea2c2390..f2374f183 100644
--- a/spec/features/admin_spec.rb
+++ b/spec/features/admin_spec.rb
@@ -12,7 +12,7 @@ feature 'Admin' do
visit admin_root_path
expect(current_path).not_to eq(admin_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -22,7 +22,7 @@ feature 'Admin' do
visit admin_root_path
expect(current_path).not_to eq(admin_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -32,7 +32,7 @@ feature 'Admin' do
visit admin_root_path
expect(current_path).not_to eq(admin_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -42,7 +42,7 @@ feature 'Admin' do
visit admin_root_path
expect(current_path).not_to eq(admin_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -52,7 +52,7 @@ feature 'Admin' do
visit admin_root_path
expect(current_path).not_to eq(admin_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
diff --git a/spec/features/debates_spec.rb b/spec/features/debates_spec.rb
index 61210df6e..3d7c6acf8 100644
--- a/spec/features/debates_spec.rb
+++ b/spec/features/debates_spec.rb
@@ -219,7 +219,7 @@ feature 'Debates' do
visit edit_debate_path(debate)
expect(current_path).not_to eq(edit_debate_path(debate))
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to carry out the action 'edit' on debate."
end
@@ -234,7 +234,7 @@ feature 'Debates' do
visit edit_debate_path(debate)
expect(current_path).not_to eq(edit_debate_path(debate))
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content 'You do not have permission to'
end
@@ -351,6 +351,69 @@ feature 'Debates' do
expect(current_url).to include('order=created_at')
expect(current_url).to include('page=1')
end
+
+ context 'Recommendations' do
+
+ background do
+ Setting['feature.user.recommendations'] = true
+ create(:debate, title: 'Best', cached_votes_total: 10, tag_list: "Sport")
+ create(:debate, title: 'Medium', cached_votes_total: 5, tag_list: "Sport")
+ create(:debate, title: 'Worst', cached_votes_total: 1, tag_list: "Sport")
+ end
+
+ after do
+ Setting['feature.user.recommendations'] = nil
+ end
+
+ scenario 'Debates can not ordered by recommendations when there is not an user logged', :js 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")
+ 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"
+ end
+
+ scenario 'Should display text when user has not related interests', :js 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"
+ end
+
+ scenario 'Debates are ordered by recommendations when there is a user logged', :js do
+ proposal = create(:proposal, tag_list: "Sport" )
+ user = create(:user)
+ create(:follow, followable: proposal, user: user)
+ login_as(user)
+
+ visit debates_path
+
+ click_link 'recommendations'
+
+ expect(page).to have_selector('a.active', text: 'recommendations')
+
+ within '#debates' do
+ expect('Best').to appear_before('Medium')
+ expect('Medium').to appear_before('Worst')
+ end
+
+ expect(current_url).to include('order=recommendations')
+ expect(current_url).to include('page=1')
+ end
+ end
end
context "Search" do
@@ -759,6 +822,32 @@ feature 'Debates' do
end
end
+ scenario "Reorder by recommendations results maintaing search", :js do
+ Setting['feature.user.recommendations'] = true
+ user = create(:user)
+ 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")
+ debate4 = create(:debate, title: "Do not display", cached_votes_total: 1)
+ proposal1 = create(:proposal, tag_list: "Sport")
+ create(:follow, followable: proposal1, user: user)
+
+ visit debates_path
+ fill_in "search", with: "Show you got"
+ click_button "Search"
+ click_link 'recommendations'
+ expect(page).to have_selector("a.active", text: "recommendations")
+
+ within("#debates") do
+ expect(all(".debate")[0].text).to match "Show you got"
+ expect(all(".debate")[1].text).to match "Show what you got"
+ expect(page).to_not have_content "Do not display with same tag"
+ expect(page).to_not have_content "Do not display"
+ end
+ Setting['feature.user.recommendations'] = nil
+ end
+
scenario 'After a search do not show featured debates' do
featured_debates = create_featured_debates
debate = create(:debate, title: "Abcdefghi")
diff --git a/spec/features/home_spec.rb b/spec/features/home_spec.rb
index 4deed36bb..cb5349814 100644
--- a/spec/features/home_spec.rb
+++ b/spec/features/home_spec.rb
@@ -3,20 +3,138 @@ require 'rails_helper'
feature "Home" do
feature "For not logged users" do
+
scenario 'Welcome message' do
visit root_path
expect(page).to have_content "Love the city, and it will become a city you love"
end
+
+ scenario 'Not display recommended section' do
+ debate = create(:debate)
+
+ visit root_path
+
+ expect(page).not_to have_content "Recommendations that may interest you"
+ end
+
end
feature "For signed in users" do
- scenario 'Redirect to proposals' do
- login_as(create(:user))
- visit root_path
- expect(current_path).to eq proposals_path
+ feature "Recommended" do
+
+ background do
+ Setting['feature.user.recommendations'] = true
+ user = create(:user)
+ proposal = create(:proposal, tag_list: "Sport" )
+ create(:follow, followable: proposal, user: user)
+ login_as(user)
+ end
+
+ after do
+ Setting['feature.user.recommendations'] = nil
+ end
+
+ scenario 'Display recommended section' do
+ debate = create(:debate, tag_list: "Sport")
+ visit root_path
+ expect(page).to have_content "Recommendations that may interest you"
+ end
+
+ scenario 'Display recommended section when feature flag recommended is active' do
+ debate = create(:debate, tag_list: "Sport")
+ visit root_path
+ expect(page).to have_content "Recommendations that may interest you"
+ end
+
+ scenario 'Not display recommended section when feature flag recommended is not active' do
+ debate = create(:debate, tag_list: "Sport")
+ Setting['feature.user.recommendations'] = false
+
+ visit root_path
+
+ expect(page).not_to have_content "Recommendations that may interest you"
+ end
+
+ scenario 'Display debates' do
+ debate = create(:debate, tag_list: "Sport")
+
+ visit root_path
+
+ expect(page).to have_content debate.title
+ expect(page).to have_content debate.description
+ end
+
+ scenario 'Display all recommended debates link' do
+ debate = create(:debate, tag_list: "Sport")
+ visit root_path
+ expect(page).to have_link("All recommended debates", href: debates_path(order: "recommendations"))
+ end
+
+ scenario 'Display proposal' do
+ proposal = create(:proposal, tag_list: "Sport")
+
+ visit root_path
+
+ expect(page).to have_content proposal.title
+ expect(page).to have_content proposal.description
+ end
+
+ scenario 'Display all recommended proposals link' do
+ debate = create(:proposal, tag_list: "Sport")
+ visit root_path
+ expect(page).to have_link("All recommended proposals", href: proposals_path(order: "recommendations"))
+ end
+
+ scenario 'Display orbit carrousel' do
+ create_list(:debate, 3, tag_list: "Sport")
+
+ visit root_path
+
+ expect(page).to have_selector('li[data-slide="0"]')
+ expect(page).to have_selector('li[data-slide="1"]', visible: false)
+ expect(page).to have_selector('li[data-slide="2"]', visible: false)
+ end
+
+ scenario 'Display recommended show when click on carousel' do
+ debate = create(:debate, tag_list: "Sport")
+
+ visit root_path
+ click_on debate.title
+
+ expect(current_path).to eq debate_path(debate)
+ end
+
+ scenario 'Do not display recommended section when there are not debates and proposals' do
+ visit root_path
+ expect(page).not_to have_content "Recommendations that may interest you"
+ end
+
+ feature 'Carousel size' do
+
+ scenario 'Display debates centered when there are no proposals' do
+ debate = create(:debate, tag_list: "Sport")
+ visit root_path
+ expect(page).to have_selector('.medium-centered.large-centered')
+ end
+
+ scenario 'Correct display debates and proposals' do
+ proposal = create(:proposal, tag_list: "Sport")
+ debates = create(:debate, tag_list: "Sport")
+
+ visit root_path
+
+ expect(page).to have_selector('.debates.medium-offset-2.large-offset-2')
+ expect(page).not_to have_selector('.proposals.medium-offset-2.large-offset-2')
+ expect(page).not_to have_selector('.debates.end')
+ expect(page).to have_selector('.proposals.end')
+ expect(page).not_to have_selector('.medium-centered.large-centered')
+ end
+
+ end
end
+
end
feature 'IE alert' do
diff --git a/spec/features/moderation_spec.rb b/spec/features/moderation_spec.rb
index fedcb105d..ad4042425 100644
--- a/spec/features/moderation_spec.rb
+++ b/spec/features/moderation_spec.rb
@@ -11,7 +11,7 @@ feature 'Moderation' do
visit moderation_root_path
expect(current_path).not_to eq(moderation_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -25,7 +25,7 @@ feature 'Moderation' do
visit moderation_root_path
expect(current_path).not_to eq(moderation_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -39,7 +39,7 @@ feature 'Moderation' do
visit moderation_root_path
expect(current_path).not_to eq(moderation_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -53,7 +53,7 @@ feature 'Moderation' do
visit moderation_root_path
expect(current_path).not_to eq(moderation_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb
index 7b044e18a..9925b0d56 100644
--- a/spec/features/notifications_spec.rb
+++ b/spec/features/notifications_spec.rb
@@ -15,16 +15,7 @@ feature "Notifications" do
let(:legislation_annotation) { create(:legislation_annotation, author: author) }
scenario "User commented on my debate", :js do
- login_as user
- visit debate_path debate
-
- fill_in "comment-body-debate_#{debate.id}", with: "I commented on your debate"
- click_button "Publish comment"
- within "#comments" do
- expect(page).to have_content "I commented on your debate"
- end
-
- logout
+ create(:notification, notifiable: debate, user: author)
login_as author
visit root_path
@@ -37,17 +28,7 @@ feature "Notifications" do
end
scenario "User commented on my legislation question", :js do
- verified_user = create(:user, :level_two)
- login_as verified_user
- visit legislation_process_question_path legislation_question.process, legislation_question
-
- fill_in "comment-body-legislation_question_#{legislation_question.id}", with: "I answered your question"
- click_button "Publish answer"
- within "#comments" do
- expect(page).to have_content "I answered your question"
- end
-
- logout
+ create(:notification, notifiable: legislation_question, user: administrator)
login_as administrator
visit root_path
@@ -82,6 +63,7 @@ feature "Notifications" do
logout
login_as author
visit root_path
+ visit root_path
find(".icon-notification").click
@@ -107,8 +89,10 @@ feature "Notifications" do
end
logout
+
login_as author
visit root_path
+ visit root_path
find(".icon-notification").click
@@ -137,6 +121,7 @@ feature "Notifications" do
login_as author
visit root_path
+ visit root_path
find(".icon-notification").click
@@ -208,6 +193,7 @@ feature "Notifications" do
logout
login_as user1
visit root_path
+ visit root_path
find(".icon-notification").click
@@ -219,6 +205,7 @@ feature "Notifications" do
logout
login_as user2
visit root_path
+ visit root_path
find(".icon-notification").click
@@ -230,6 +217,7 @@ feature "Notifications" do
logout
login_as user3
visit root_path
+ visit root_path
find(".icon-no-notification").click
diff --git a/spec/features/officing/results_spec.rb b/spec/features/officing/results_spec.rb
index 835903ab9..f7e1ad8ef 100644
--- a/spec/features/officing/results_spec.rb
+++ b/spec/features/officing/results_spec.rb
@@ -127,21 +127,13 @@ feature 'Officing Results' do
date: @poll.ends_at,
question: @question_1,
amount: 33)
- white_result = create(:poll_white_result,
+ poll_recount = create(:poll_recount,
officer_assignment: @officer_assignment,
booth_assignment: @officer_assignment.booth_assignment,
date: @poll.ends_at,
- amount: 21)
- null_result = create(:poll_null_result,
- officer_assignment: @officer_assignment,
- booth_assignment: @officer_assignment.booth_assignment,
- date: @poll.ends_at,
- amount: 44)
- total_result = create(:poll_total_result,
- officer_assignment: @officer_assignment,
- booth_assignment: @officer_assignment.booth_assignment,
- date: @poll.ends_at,
- amount: 66)
+ white_amount: 21,
+ null_amount: 44,
+ total_amount: 66)
visit officing_poll_results_path(@poll,
date: I18n.l(@poll.ends_at.to_date),
diff --git a/spec/features/officing_spec.rb b/spec/features/officing_spec.rb
index d4cb416a1..aff3eac4e 100644
--- a/spec/features/officing_spec.rb
+++ b/spec/features/officing_spec.rb
@@ -11,7 +11,7 @@ feature 'Poll Officing' do
visit officing_root_path
expect(current_path).not_to eq(officing_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -24,7 +24,7 @@ feature 'Poll Officing' do
visit officing_root_path
expect(current_path).not_to eq(officing_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -37,7 +37,7 @@ feature 'Poll Officing' do
visit officing_root_path
expect(current_path).not_to eq(officing_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -50,7 +50,7 @@ feature 'Poll Officing' do
visit officing_root_path
expect(current_path).not_to eq(officing_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
diff --git a/spec/features/polls/polls_spec.rb b/spec/features/polls/polls_spec.rb
index 047c71146..8a90fb4a8 100644
--- a/spec/features/polls/polls_spec.rb
+++ b/spec/features/polls/polls_spec.rb
@@ -184,6 +184,7 @@ feature 'Polls' do
poll.geozones << geozone
create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
user = create(:user, :level_two, geozone: geozone)
+
login_as user
visit poll_path(poll)
@@ -193,5 +194,25 @@ feature 'Polls' do
expect(page).to have_link('Chewbacca')
end
+ scenario 'Level 2 users changing answer', :js do
+ poll.update(geozone_restricted: true)
+ poll.geozones << geozone
+ create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca')
+ user = create(:user, :level_two, geozone: geozone)
+
+ login_as user
+ visit poll_path(poll)
+
+ click_link 'Han Solo'
+
+ expect(page).to_not have_link('Han Solo')
+ expect(page).to have_link('Chewbacca')
+
+ click_link 'Chewbacca'
+
+ expect(page).to_not have_link('Chewbacca')
+ expect(page).to have_link('Han Solo')
+ end
+
end
end
diff --git a/spec/features/polls/voter_spec.rb b/spec/features/polls/voter_spec.rb
new file mode 100644
index 000000000..08bc6f963
--- /dev/null
+++ b/spec/features/polls/voter_spec.rb
@@ -0,0 +1,94 @@
+require 'rails_helper'
+
+feature "Voter" do
+
+ context "Origin" do
+
+ scenario "Voting via web", :js do
+ poll = create(:poll)
+ question = create(:poll_question, poll: poll, valid_answers: 'Yes, No')
+ user = create(:user, :level_two)
+
+ login_as user
+ visit question_path(question)
+
+ click_link 'Answer this question'
+ click_link 'Yes'
+
+ expect(page).to_not have_link('Yes')
+ expect(Poll::Voter.count).to eq(1)
+ expect(Poll::Voter.first.origin).to eq("web")
+ end
+
+ scenario "Voting in booth", :js do
+ user = create(:user, :in_census)
+ create(:geozone, :in_census)
+
+ poll = create(:poll)
+ officer = create(:poll_officer)
+
+ ba = create(:poll_booth_assignment, poll: poll)
+ create(:poll_officer_assignment, officer: officer, booth_assignment: ba)
+
+ login_through_form_as_officer(officer.user)
+
+ visit new_officing_residence_path
+ officing_verify_residence
+
+ expect(page).to have_content poll.name
+
+ first(:button, "Confirm vote").click
+ expect(page).to have_content "Vote introduced!"
+
+ expect(Poll::Voter.count).to eq(1)
+ expect(Poll::Voter.first.origin).to eq("booth")
+ end
+
+ context "Trying to vote the same poll in booth and web" do
+
+ let(:poll) { create(:poll) }
+ let(:question) { create(:poll_question, poll: poll, valid_answers: 'Yes, No') }
+ let!(:user) { create(:user, :in_census) }
+
+ let(:officer) { create(:poll_officer) }
+ let(:ba) { create(:poll_booth_assignment, poll: poll) }
+ let!(:oa) { create(:poll_officer_assignment, officer: officer, booth_assignment: ba) }
+
+ scenario "Trying to vote in web and then in booth", :js do
+ login_as user
+ vote_for_poll_via_web
+
+ click_link "Sign out"
+
+ login_through_form_as_officer(officer.user)
+
+ visit new_officing_residence_path
+ officing_verify_residence
+
+ expect(page).to have_content poll.name
+ expect(page).to_not have_button "Confirm vote"
+ expect(page).to have_content "Has already participated in this poll"
+ end
+
+ scenario "Trying to vote in booth and then in web", :js do
+ login_through_form_as_officer(officer.user)
+
+ vote_for_poll_via_booth
+
+ visit root_path
+ click_link "Sign out"
+
+ login_as user
+ visit question_path(question)
+
+ click_link 'Answer this question'
+
+ expect(page).to_not have_link('Yes')
+ expect(page).to have_content "You have already participated in a booth for this poll."
+ expect(Poll::Voter.count).to eq(1)
+ end
+ end
+
+ end
+
+end
\ No newline at end of file
diff --git a/spec/features/proposal_notifications_spec.rb b/spec/features/proposal_notifications_spec.rb
index 4756a1903..1e93f7e13 100644
--- a/spec/features/proposal_notifications_spec.rb
+++ b/spec/features/proposal_notifications_spec.rb
@@ -189,7 +189,7 @@ feature 'Proposal Notifications' do
login_as(user)
visit new_proposal_notification_path(proposal_id: proposal.id)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content("You do not have permission to carry out the action")
end
diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb
index f0e50c7eb..81f7fb998 100644
--- a/spec/features/proposals_spec.rb
+++ b/spec/features/proposals_spec.rb
@@ -556,7 +556,7 @@ feature 'Proposals' do
visit edit_proposal_path(proposal)
expect(current_path).not_to eq(edit_proposal_path(proposal))
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content 'You do not have permission'
end
@@ -571,7 +571,7 @@ feature 'Proposals' do
visit edit_proposal_path(proposal)
expect(current_path).not_to eq(edit_proposal_path(proposal))
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content 'You do not have permission'
Setting["max_votes_for_proposal_edit"] = 1000
end
@@ -663,6 +663,69 @@ feature 'Proposals' do
expect(current_url).to include('order=created_at')
expect(current_url).to include('page=1')
end
+
+ context 'Recommendations' do
+
+ before do
+ Setting['feature.user.recommendations'] = true
+ create(:proposal, title: 'Best', cached_votes_up: 10, tag_list: "Sport")
+ create(:proposal, title: 'Medium', cached_votes_up: 5, tag_list: "Sport")
+ create(:proposal, title: 'Worst', cached_votes_up: 1, tag_list: "Sport")
+ end
+
+ after do
+ Setting['feature.user.recommendations'] = nil
+ end
+
+ scenario 'Proposals can not ordered by recommendations when there is not an user logged', :js 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")
+ 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"
+ end
+
+ scenario 'Should display text when user has not related interests', :js 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"
+ end
+
+ scenario 'Proposals are ordered by recommendations when there is an user logged', :js do
+ user = create(:user)
+ proposal = create(:proposal, tag_list: "Sport")
+ create(:follow, followable: proposal, user: user)
+ login_as(user)
+
+ visit proposals_path
+
+ click_link 'recommendations'
+
+ expect(page).to have_selector('a.active', text: 'recommendations')
+
+ within '#proposals-list' do
+ expect('Best').to appear_before('Medium')
+ expect('Medium').to appear_before('Worst')
+ end
+
+ expect(current_url).to include('order=recommendations')
+ expect(current_url).to include('page=1')
+ end
+ end
end
feature 'Archived proposals' do
@@ -1198,6 +1261,32 @@ feature 'Proposals' do
end
end
+ scenario "Reorder by recommendations results maintaing search", :js do
+ Setting['feature.user.recommendations'] = true
+ user = create(:user)
+ 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")
+ proposal4 = create(:proposal, title: "Do not display", cached_votes_up: 1)
+ proposal5 = create(:proposal, tag_list: "Sport")
+ create(:follow, followable: proposal5, user: user)
+
+ visit proposals_path
+ fill_in "search", with: "Show you got"
+ click_button "Search"
+ click_link 'recommendations'
+ expect(page).to have_selector("a.active", text: "recommendations")
+
+ within("#proposals") do
+ expect(all(".proposal")[0].text).to match "Show you got"
+ expect(all(".proposal")[1].text).to match "Show what you got"
+ expect(page).to_not have_content "Do not display with same tag"
+ expect(page).to_not have_content "Do not display"
+ end
+ Setting['feature.user.recommendations'] = nil
+ end
+
scenario 'After a search do not show featured proposals' do
featured_proposals = create_featured_proposals
proposal = create(:proposal, title: "Abcdefghi")
diff --git a/spec/features/valuation_spec.rb b/spec/features/valuation_spec.rb
index 5b6cc961c..9e74d9341 100644
--- a/spec/features/valuation_spec.rb
+++ b/spec/features/valuation_spec.rb
@@ -21,7 +21,7 @@ feature 'Valuation' do
visit valuation_root_path
expect(current_path).not_to eq(valuation_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -34,7 +34,7 @@ feature 'Valuation' do
visit valuation_root_path
expect(current_path).not_to eq(valuation_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -47,7 +47,7 @@ feature 'Valuation' do
visit valuation_root_path
expect(current_path).not_to eq(valuation_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
@@ -60,7 +60,7 @@ feature 'Valuation' do
visit valuation_root_path
expect(current_path).not_to eq(valuation_root_path)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
expect(page).to have_content "You do not have permission to access this page"
end
diff --git a/spec/features/welcome_spec.rb b/spec/features/welcome_spec.rb
index ce06befcc..245a9923e 100644
--- a/spec/features/welcome_spec.rb
+++ b/spec/features/welcome_spec.rb
@@ -33,7 +33,7 @@ feature "Welcome screen" do
login_through_form_as(user)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
end
scenario 'is not shown to organizations' do
@@ -41,7 +41,7 @@ feature "Welcome screen" do
login_through_form_as(organization.user)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
end
scenario 'it is not shown to level-2 users' do
@@ -49,7 +49,7 @@ feature "Welcome screen" do
login_through_form_as(user)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
end
scenario 'it is not shown to level-3 users' do
@@ -57,7 +57,7 @@ feature "Welcome screen" do
login_through_form_as(user)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
end
scenario 'is not shown to administrators' do
@@ -65,7 +65,7 @@ feature "Welcome screen" do
login_through_form_as(administrator.user)
- expect(current_path).to eq(proposals_path)
+ expect(current_path).to eq(root_path)
end
end
diff --git a/spec/models/abilities/administrator_spec.rb b/spec/models/abilities/administrator_spec.rb
index 5a6c4b734..0934c7cfe 100644
--- a/spec/models/abilities/administrator_spec.rb
+++ b/spec/models/abilities/administrator_spec.rb
@@ -72,6 +72,7 @@ describe "Abilities::Administrator" do
it { should be_able_to(:create, Budget) }
it { should be_able_to(:update, Budget) }
+ it { should be_able_to(:read_results, Budget) }
it { should be_able_to(:create, Budget::ValuatorAssignment) }
diff --git a/spec/models/abilities/everyone_spec.rb b/spec/models/abilities/everyone_spec.rb
index fcfff4e42..21568c999 100644
--- a/spec/models/abilities/everyone_spec.rb
+++ b/spec/models/abilities/everyone_spec.rb
@@ -8,6 +8,9 @@ describe "Abilities::Everyone" do
let(:debate) { create(:debate) }
let(:proposal) { create(:proposal) }
+ let(:reviewing_ballot_budget) { create(:budget, phase: 'reviewing_ballots') }
+ let(:finished_budget) { create(:budget, phase: 'finished') }
+
it { should be_able_to(:index, Debate) }
it { should be_able_to(:show, debate) }
it { should_not be_able_to(:edit, Debate) }
@@ -28,4 +31,7 @@ describe "Abilities::Everyone" do
it { should_not be_able_to(:create, SpendingProposal) }
it { should be_able_to(:index, Budget) }
-end
\ No newline at end of file
+
+ it { should be_able_to(:read_results, finished_budget) }
+ it { should_not be_able_to(:read_results, reviewing_ballot_budget) }
+end
diff --git a/spec/models/debate_spec.rb b/spec/models/debate_spec.rb
index 5ab801cd0..64dbf729f 100644
--- a/spec/models/debate_spec.rb
+++ b/spec/models/debate_spec.rb
@@ -714,4 +714,53 @@ describe Debate do
end
end
+ describe "#recommendations" do
+
+ let(:user) { create(:user) }
+
+ it "Should not return any debates when user has not interests" do
+ create(:debate)
+
+ expect(Debate.recommendations(user).size).to eq 0
+ end
+
+ it "Should return debates ordered by cached_votes_total" do
+ debate1 = create(:debate, cached_votes_total: 1, tag_list: "Sport" )
+ debate2 = create(:debate, cached_votes_total: 5, tag_list: "Sport" )
+ debate3 = create(:debate, cached_votes_total: 10, tag_list: "Sport" )
+ proposal = create(:proposal, tag_list: "Sport" )
+ create(:follow, followable: proposal, user: user)
+
+ result = Debate.recommendations(user).sort_by_recommendations
+
+ expect(result.first).to eq debate3
+ expect(result.second).to eq debate2
+ expect(result.third).to eq debate1
+ end
+
+ it "Should return debates related with user interests" do
+ debate1 = create(:debate, tag_list: "Sport")
+ debate2 = create(:debate, tag_list: "Politics")
+ proposal1 = create(:proposal, tag_list: "Sport")
+ create(:follow, followable: proposal1, user: user)
+
+ result = Debate.recommendations(user)
+
+ expect(result.size).to eq 1
+ expect(result).to eq [debate1]
+ end
+
+ it "Should not return debates when user is the author" do
+ debate1 = create(:debate, author: user, tag_list: "Sport")
+ debate2 = create(:debate, tag_list: "Sport")
+ proposal = create(:proposal, tag_list: "Sport" )
+ create(:follow, followable: proposal, user: user)
+
+ result = Debate.recommendations(user)
+
+ expect(result.size).to eq 1
+ expect(result).to eq [debate2]
+ end
+
+ end
end
diff --git a/spec/models/poll/answer_spec.rb b/spec/models/poll/answer_spec.rb
index 10ccafbb6..d66cdc18c 100644
--- a/spec/models/poll/answer_spec.rb
+++ b/spec/models/poll/answer_spec.rb
@@ -3,28 +3,71 @@ require 'rails_helper'
describe Poll::Answer do
describe "validations" do
- it "validates that the answers are included in the Poll::Question's list" do
- q = create(:poll_question, valid_answers: 'One, Two, Three')
- expect(build(:poll_answer, question: q, answer: 'One')).to be_valid
- expect(build(:poll_answer, question: q, answer: 'Two')).to be_valid
- expect(build(:poll_answer, question: q, answer: 'Three')).to be_valid
- expect(build(:poll_answer, question: q, answer: 'Four')).to_not be_valid
+ let(:answer) { build(:poll_answer) }
+
+ it "should be valid" do
+ expect(answer).to be_valid
+ end
+
+ it "should not be valid wihout a question" do
+ answer.question = nil
+ expect(answer).to_not be_valid
+ end
+
+ it "should not be valid without an author" do
+ answer.author = nil
+ expect(answer).to_not be_valid
+ end
+
+ it "should not be valid without an answer" do
+ answer.answer = nil
+ expect(answer).to_not be_valid
+ end
+
+ it "should be valid for answers included in the Poll::Question's list" do
+ question = create(:poll_question, valid_answers: 'One, Two, Three')
+ expect(build(:poll_answer, question: question, answer: 'One')).to be_valid
+ expect(build(:poll_answer, question: question, answer: 'Two')).to be_valid
+ expect(build(:poll_answer, question: question, answer: 'Three')).to be_valid
+
+ expect(build(:poll_answer, question: question, answer: 'Four')).to_not be_valid
end
end
describe "#record_voter_participation" do
+
+ let(:author) { create(:user, :level_two) }
+ let(:poll) { create(:poll) }
+ let(:question) { create(:poll_question, poll: poll, valid_answers: "Yes, No") }
+
it "creates a poll_voter with user and poll data" do
- answer = create(:poll_answer)
+ answer = create(:poll_answer, question: question, author: author, answer: "Yes")
expect(answer.poll.voters).to be_blank
answer.record_voter_participation
- expect(answer.poll.reload.voters.size).to eq(1)
- voter = answer.poll.voters.first
+ expect(poll.reload.voters.size).to eq(1)
+ voter = poll.voters.first
expect(voter.document_number).to eq(answer.author.document_number)
expect(voter.poll_id).to eq(answer.poll.id)
end
+
+ it "updates a poll_voter with user and poll data" do
+ answer = create(:poll_answer, question: question, author: author, answer: "Yes")
+ answer.record_voter_participation
+
+ expect(poll.reload.voters.size).to eq(1)
+
+ answer = create(:poll_answer, question: question, author: author, answer: "No")
+ answer.record_voter_participation
+
+ expect(poll.reload.voters.size).to eq(1)
+
+ voter = poll.voters.first
+ expect(voter.document_number).to eq(answer.author.document_number)
+ expect(voter.poll_id).to eq(answer.poll.id)
+ end
end
end
diff --git a/spec/models/poll/poll_spec.rb b/spec/models/poll/poll_spec.rb
index ac0cc44ea..5083d7439 100644
--- a/spec/models/poll/poll_spec.rb
+++ b/spec/models/poll/poll_spec.rb
@@ -138,4 +138,33 @@ describe :poll do
end
end
end
+
+ describe "#voted_in_booth?" do
+
+ it "returns true if the user has already voted in booth" do
+ user = create(:user, :level_two)
+ poll = create(:poll)
+
+ create(:poll_voter, poll: poll, user: user, origin: "booth")
+
+ expect(poll.voted_in_booth?(user)).to be
+ end
+
+ it "returns false if the user has not already voted in a booth" do
+ user = create(:user, :level_two)
+ poll = create(:poll)
+
+ expect(poll.voted_in_booth?(user)).to_not be
+ end
+
+ it "returns false if the user has voted in web" do
+ user = create(:user, :level_two)
+ poll = create(:poll)
+
+ create(:poll_voter, poll: poll, user: user, origin: "web")
+
+ expect(poll.voted_in_booth?(user)).to_not be
+ end
+
+ end
end
diff --git a/spec/models/poll/recount_spec.rb b/spec/models/poll/recount_spec.rb
new file mode 100644
index 000000000..2a5ed16a7
--- /dev/null
+++ b/spec/models/poll/recount_spec.rb
@@ -0,0 +1,104 @@
+require 'rails_helper'
+
+describe Poll::Recount do
+
+ describe "logging changes" do
+ let(:author) { create(:user) }
+ let(:officer_assignment) { create(:poll_officer_assignment) }
+ let(:poll_recount) { create(:poll_recount, author: author, officer_assignment: officer_assignment) }
+
+ it "should update white_amount_log if white_amount changes" do
+ poll_recount.white_amount = 33
+
+ expect(poll_recount.white_amount_log).to eq("")
+
+ poll_recount.white_amount = 33
+ poll_recount.save
+ poll_recount.white_amount = 32
+ poll_recount.save
+ poll_recount.white_amount = 34
+ poll_recount.save
+
+ expect(poll_recount.white_amount_log).to eq(":0:33:32")
+ end
+
+ it "should update null_amount_log if null_amount changes" do
+ poll_recount.null_amount = 33
+
+ expect(poll_recount.null_amount_log).to eq("")
+
+ poll_recount.null_amount = 33
+ poll_recount.save
+ poll_recount.null_amount = 32
+ poll_recount.save
+ poll_recount.null_amount = 34
+ poll_recount.save
+
+ expect(poll_recount.null_amount_log).to eq(":0:33:32")
+ end
+
+ it "should update total_amount_log if total_amount changes" do
+ poll_recount.total_amount = 33
+
+ expect(poll_recount.total_amount_log).to eq("")
+
+ poll_recount.total_amount = 33
+ poll_recount.save
+ poll_recount.total_amount = 32
+ poll_recount.save
+ poll_recount.total_amount = 34
+ poll_recount.save
+
+ expect(poll_recount.total_amount_log).to eq(":0:33:32")
+ end
+
+ it "should update officer_assignment_id_log if amount changes" do
+ poll_recount.white_amount = 33
+
+ expect(poll_recount.white_amount_log).to eq("")
+ expect(poll_recount.officer_assignment_id_log).to eq("")
+
+ poll_recount.white_amount = 33
+ poll_recount.officer_assignment = create(:poll_officer_assignment, id: 101)
+ poll_recount.save
+
+ poll_recount.white_amount = 32
+ poll_recount.officer_assignment = create(:poll_officer_assignment, id: 102)
+ poll_recount.save
+
+ poll_recount.white_amount = 34
+ poll_recount.officer_assignment = create(:poll_officer_assignment, id: 103)
+ poll_recount.save
+
+ expect(poll_recount.white_amount_log).to eq(":0:33:32")
+ expect(poll_recount.officer_assignment_id_log).to eq(":#{officer_assignment.id}:101:102")
+ end
+
+ it "should update author_id if amount changes" do
+ poll_recount.white_amount = 33
+
+ expect(poll_recount.white_amount_log).to eq("")
+ expect(poll_recount.author_id_log).to eq("")
+
+ first_author = create(:poll_officer).user
+ second_author = create(:poll_officer).user
+ third_author = create(:poll_officer).user
+
+ poll_recount.white_amount = 33
+ poll_recount.author_id = first_author.id
+ poll_recount.save!
+
+ poll_recount.white_amount = 32
+ poll_recount.author_id = second_author.id
+ poll_recount.save!
+
+ poll_recount.white_amount = 34
+ poll_recount.author_id = third_author.id
+ poll_recount.save!
+
+ expect(poll_recount.white_amount_log).to eq(":0:33:32")
+ expect(poll_recount.author_id_log).to eq(":#{author.id}:#{first_author.id}:#{second_author.id}")
+ end
+ end
+
+end
diff --git a/spec/models/poll/voter_spec.rb b/spec/models/poll/voter_spec.rb
index c1c248550..f306248dc 100644
--- a/spec/models/poll/voter_spec.rb
+++ b/spec/models/poll/voter_spec.rb
@@ -83,6 +83,64 @@ describe :voter do
expect(voter.errors.messages[:document_number]).to eq(["User has already voted"])
end
+ context "origin" do
+
+ it "should not be valid without an origin" do
+ voter.origin = nil
+ expect(voter).to_not be_valid
+ end
+
+ it "should not be valid without a valid origin" do
+ voter.origin = "invalid_origin"
+ expect(voter).to_not be_valid
+ end
+
+ it "should be valid with a booth origin" do
+ voter.origin = "booth"
+ expect(voter).to be_valid
+ end
+
+ it "should be valid with a web origin" do
+ voter.origin = "web"
+ expect(voter).to be_valid
+ end
+
+ end
+
+ end
+
+ describe "scopes" do
+
+ describe "#web" do
+ it "returns voters with a web origin" do
+ voter1 = create(:poll_voter, origin: "web")
+ voter2 = create(:poll_voter, origin: "web")
+ voter3 = create(:poll_voter, origin: "booth")
+
+ web_voters = Poll::Voter.web
+
+ expect(web_voters.count).to eq(2)
+ expect(web_voters).to include(voter1)
+ expect(web_voters).to include(voter2)
+ expect(web_voters).to_not include(voter3)
+ end
+ end
+
+ describe "#booth" do
+ it "returns voters with a booth origin" do
+ voter1 = create(:poll_voter, origin: "booth")
+ voter2 = create(:poll_voter, origin: "booth")
+ voter3 = create(:poll_voter, origin: "web")
+
+ booth_voters = Poll::Voter.booth
+
+ expect(booth_voters.count).to eq(2)
+ expect(booth_voters).to include(voter1)
+ expect(booth_voters).to include(voter2)
+ expect(booth_voters).to_not include(voter3)
+ end
+ end
+
end
describe "save" do
diff --git a/spec/models/proposal_spec.rb b/spec/models/proposal_spec.rb
index 83c19edde..588bd4057 100644
--- a/spec/models/proposal_spec.rb
+++ b/spec/models/proposal_spec.rb
@@ -891,4 +891,63 @@ describe Proposal do
end
end
+
+ describe "#recommendations" do
+
+ let(:user) { create(:user) }
+
+ it "Should not return any proposals when user has not interests" do
+ create(:proposal)
+
+ expect(Proposal.recommendations(user).size).to eq 0
+ end
+
+ it "Should return proposals ordered by cached_votes_up" do
+ proposal1 = create(:proposal, cached_votes_up: 1, tag_list: "Sport" )
+ proposal2 = create(:proposal, cached_votes_up: 5, tag_list: "Sport" )
+ proposal3 = create(:proposal, cached_votes_up: 10, tag_list: "Sport" )
+ proposal4 = create(:proposal, tag_list: "Sport" )
+ create(:follow, followable: proposal4, user: user)
+
+ result = Proposal.recommendations(user).sort_by_recommendations
+
+ expect(result.first).to eq proposal3
+ expect(result.second).to eq proposal2
+ expect(result.third).to eq proposal1
+ end
+
+ it "Should return proposals related with user interests" do
+ proposal1 = create(:proposal, tag_list: "Sport")
+ proposal2 = create(:proposal, tag_list: "Sport")
+ proposal3 = create(:proposal, tag_list: "Politics")
+ create(:follow, followable: proposal1, user: user)
+
+ result = Proposal.recommendations(user)
+
+ expect(result.size).to eq 1
+ expect(result).to eq [proposal2]
+ end
+
+ it "Should not return proposals when user is follower" do
+ proposal1 = create(:proposal, tag_list: "Sport")
+ create(:follow, followable: proposal1, user: user)
+
+ result = Proposal.recommendations(user)
+
+ expect(result.size).to eq 0
+ end
+
+ it "Should not return proposals when user is the author" do
+ proposal1 = create(:proposal, author: user, tag_list: "Sport")
+ proposal2 = create(:proposal, tag_list: "Sport")
+ proposal3 = create(:proposal, tag_list: "Sport")
+ create(:follow, followable: proposal3, user: user)
+
+ result = Proposal.recommendations(user)
+
+ expect(result.size).to eq 1
+ expect(result).to eq [proposal2]
+ end
+
+ end
end
diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb
index 8b8470293..97f05294c 100644
--- a/spec/support/common_actions.rb
+++ b/spec/support/common_actions.rb
@@ -24,6 +24,17 @@ module CommonActions
click_button 'Enter'
end
+ def login_through_form_as_officer(user)
+ visit root_path
+ click_link 'Sign in'
+
+ fill_in 'user_login', with: user.email
+ fill_in 'user_password', with: user.password
+
+ click_button 'Enter'
+ visit new_officing_residence_path
+ end
+
def login_as_authenticated_manager
expected_response = {login: login, user_key: user_key, date: date}.with_indifferent_access
login, user_key, date = "JJB042", "31415926", Time.current.strftime("%Y%m%d%H%M%S")
@@ -287,4 +298,26 @@ module CommonActions
end
end
+ def vote_for_poll_via_web
+ visit question_path(question)
+
+ click_link 'Answer this question'
+ click_link 'Yes'
+
+ expect(page).to_not have_link('Yes')
+ expect(Poll::Voter.count).to eq(1)
+ end
+
+ def vote_for_poll_via_booth
+ visit new_officing_residence_path
+ officing_verify_residence
+
+ expect(page).to have_content poll.name
+
+ first(:button, "Confirm vote").click
+ expect(page).to have_content "Vote introduced!"
+
+ expect(Poll::Voter.count).to eq(1)
+ end
+
end
diff --git a/spec/views/welcome/index.html.erb_spec.rb b/spec/views/welcome/index.html.erb_spec.rb
new file mode 100644
index 000000000..d8738f42b
--- /dev/null
+++ b/spec/views/welcome/index.html.erb_spec.rb
@@ -0,0 +1,43 @@
+require "rails_helper"
+
+RSpec.describe "welcome/index" do
+
+ it 'Display images on orbit carrousel when we have defined image_default' do
+ debate = create(:debate)
+
+ render template: "welcome/_recommended_carousel.html.erb",
+ locals: { key: "debates",
+ recommendeds: [debate],
+ image_field: nil,
+ image_version: nil,
+ image_default: "https://dummyimage.com/600x400/000/fff",
+ carousel_size: "medium-6 large-6 medium-centered large-centered",
+ btn_text_link: t("welcome.recommended.debates.btn_text_link"),
+ btn_path_link: debates_path(order: "recommendations")}
+
+ within 'li[data-slide="0"] .card' do
+ expect(page).to have_selector("img")
+ end
+
+ end
+
+ it 'Not display images on orbit carrousel when we have not defined image_default' do
+ debate = create(:debate)
+
+ render template: "welcome/_recommended_carousel.html.erb",
+ locals: { key: "debates",
+ recommendeds: [debate],
+ image_field: nil,
+ image_version: nil,
+ image_default: nil,
+ carousel_size: "medium-6 large-6 medium-centered large-centered",
+ btn_text_link: t("welcome.recommended.debates.btn_text_link"),
+ btn_path_link: debates_path(order: "recommendations")}
+
+ within 'li[data-slide="0"] .card' do
+ expect(page).not_to have_selector("img")
+ end
+
+ end
+
+end