Files
grecia/spec/system/budgets/ballots_spec.rb
Javi Martín 64bb42b288 Add missing expectation in hide money test
All the expectations checked after the `click_link "Check my votes"`
action were already true before clicking the link, meaning the test
could finish before the request did.

It's possible that this request caused a test run 8274, job 2 [1], since
a multitenancy test failed and a possible cause could have been
simultaneous requests to both a tenant subdomain and the application's
main domain. The failure was:

```
1) Multitenancy PostgreSQL extensions work for tenants
     Failure/Error: expect(page).to have_content "Proposal created
successfully."
       expected to find text "Proposal created successfully." in
       "Language: \n
       \nEnglish\nDeutsch\nEspañol\nFrançais\nNederlands\nPortuguês
       brasileiro\n中文\n       Notifications\nMy content\nMy account\nSign
       out\nDebates\nYou are in\nProposals\nVoting\nCollaborative
       legislation\nParticipatory budgeting\nSDG\nHelp\nProposals\nCreate new
       proposal\nHow do citizen proposals work?\nRecommendations for creating a
       proposal\nDo not use capital letters for the proposal title or for whole
       sentences. On the internet, this is considered shouting. And nobody
       likes being shouted at.\nAny proposal or comment suggesting illegal
       action will be deleted, as well as those intending to sabotage the
       debate spaces. Anything else is allowed.\nEnjoy this space and the
       voices that fill it. It belongs to you too.\n×\n1 error prevented this
       Proposal from being saved.\nPlease check the marked fields to know how
       to correct them:\nREQUIRED FIELDS\nProposal title\nProposal
       summary\n(maximum 200 characters)\ntsvector for María the
       Martian\nProposal text\n    Format\n    ◢\n  If you are human, ignore
       this field\nOPTIONAL FIELDS\nExternal video URL\nYou may add a link to
       YouTube or Vimeo\nDescriptive image\nYou can upload one image of
       following content types: jpg, up to 1 MB.\nAdd image\nDocuments\nYou can
       upload up to a maximum of 3 documents of following content types: pdf,
       up to 3 MB per file.\nAdd new document\nTags\nTag this proposal. You can
       choose from proposed categories or add your own\nCategories\n\nFull name
       of the person submitting the proposal\n(individually or as
       representative of a collective; will not be displayed publically)\ncan't
       be blank, is too short (minimum is 6 characters)\nSustainable
       Development Goals and Targets\nYou can choose one or several SDGs
       aligned with your citizen proposal\nGoals and Targets\nYou can introduce
       the code of a specific goal/target or a text to find one. For more
       information visit the SDG help page.\nI agree to the Privacy Policy and
       the Terms and conditions of use\nOpen government\nThis portal uses the
       CONSUL DEMOCRACY application which is open-source
       software.\nParticipation\nDecide how to shape the city you want to live
       in.\nCONSUL DEMOCRACY, 2024 Privacy Policy Terms and conditions of use
       Accessibility"
```

Note the `can't be blank, is too short` reference to the responsible
name, which is only checked when user verification is not skipped. In
this test, the `mars` tenant skips the verification while the default
tenant does not. The mentioned possibility of simultaneous requests
might have caused the issue.

[1] https://github.com/consuldemocracy/consuldemocracy/actions/runs/11747689680/job/32730131655
2024-11-11 15:53:43 +01:00

720 lines
26 KiB
Ruby

require "rails_helper"
require "sessions_helper"
describe "Ballots" do
let(:user) { create(:user, :level_two) }
let!(:budget) { create(:budget, :balloting) }
let!(:states) { create(:budget_group, budget: budget, name: "States") }
let!(:california) { create(:budget_heading, group: states, name: "California", price: 1000) }
let!(:new_york) { create(:budget_heading, group: states, name: "New York", price: 1000000) }
context "Load" do
let(:user) do
create(:user, :level_two, ballot_lines: [create(:budget_investment, :selected, heading: california)])
end
before do
budget.update!(slug: "budget_slug")
login_as(user)
end
scenario "finds ballot using budget slug" do
visit budget_ballot_path("budget_slug")
expect(page).to have_content("You have voted one investment")
end
end
context "Lines Load" do
before do
create(:budget_investment, :selected, heading: california, title: "More rain")
budget.update!(slug: "budget_slug")
login_as(user)
end
scenario "finds ballot lines using budget slug" do
visit budget_investments_path("budget_slug", states, california)
add_to_ballot("More rain")
within("#sidebar") { expect(page).to have_content "More rain" }
end
end
context "Voting" do
before { login_as(user) }
let!(:city) { create(:budget_group, budget: budget, name: "City") }
let!(:districts) { create(:budget_group, budget: budget, name: "Districts") }
context "Group and Heading Navigation" do
scenario "Headings" do
create(:budget_heading, group: city, name: "Investments Type1")
create(:budget_heading, group: city, name: "Investments Type2")
create(:budget_heading, group: districts, name: "District 1")
create(:budget_heading, group: districts, name: "District 2")
visit budget_path(budget)
within("#groups_and_headings") do
expect(page).to have_link "Investments Type1"
expect(page).to have_link "Investments Type2"
expect(page).to have_link "District 1"
expect(page).to have_link "District 2"
end
end
scenario "Investments" do
create(:budget_heading, group: city, name: "Under the city")
create(:budget_heading, group: city, name: "Above the city") do |heading|
create(:budget_investment, :selected, heading: heading, title: "Solar panels")
create(:budget_investment, :selected, heading: heading, title: "Observatory")
end
create(:budget_heading, group: districts, name: "District 1") do |heading|
create(:budget_investment, :selected, heading: heading, title: "New park")
create(:budget_investment, :selected, heading: heading, title: "Zero-emission zone")
end
create(:budget_heading, group: districts, name: "District 2") do |heading|
create(:budget_investment, :selected, heading: heading, title: "Climbing wall")
end
visit budget_path(budget)
click_link "Above the city"
expect(page).to have_css(".budget-investment", count: 2)
expect(page).to have_content "Solar panels"
expect(page).to have_content "Observatory"
visit budget_path(budget)
click_link "District 1"
expect(page).to have_css(".budget-investment", count: 2)
expect(page).to have_content "New park"
expect(page).to have_content "Zero-emission zone"
visit budget_path(budget)
click_link "District 2"
expect(page).to have_css(".budget-investment", count: 1)
expect(page).to have_content "Climbing wall"
end
end
context "Adding and Removing Investments" do
scenario "Add a investment" do
create(:budget_investment, :selected, heading: new_york, price: 10000, title: "Bring back King Kong")
create(:budget_investment, :selected, heading: new_york, price: 20000, title: "Paint cabs black")
visit budget_investments_path(budget, heading_id: new_york)
add_to_ballot("Bring back King Kong")
expect(page).to have_css("#total_amount", text: "€10,000")
expect(page).to have_css("#amount_available", text: "€990,000")
within("#sidebar") do
expect(page).to have_content "Bring back King Kong"
expect(page).to have_content "€10,000"
expect(page).to have_link "Check my votes"
end
add_to_ballot("Paint cabs black")
expect(page).to have_css("#total_amount", text: "€30,000")
expect(page).to have_css("#amount_available", text: "€970,000")
within("#sidebar") do
expect(page).to have_content "Paint cabs black"
expect(page).to have_content "€20,000"
expect(page).to have_link "Check my votes"
end
end
scenario "Removing a investment" do
investment = create(:budget_investment, :selected, heading: new_york, price: 10000, balloters: [user])
visit budget_investments_path(budget, heading_id: new_york)
expect(page).to have_content investment.title
expect(page).to have_css("#total_amount", text: "€10,000")
expect(page).to have_css("#amount_available", text: "€990,000")
within("#sidebar") do
expect(page).to have_content investment.title
expect(page).to have_content "€10,000"
expect(page).to have_link "Check my votes"
end
within("#budget_investment_#{investment.id}") do
click_button "Remove vote"
end
expect(page).to have_css("#total_amount", text: "€0")
expect(page).to have_css("#amount_available", text: "€1,000,000")
within("#sidebar") do
expect(page).not_to have_content investment.title
expect(page).not_to have_content "€10,000"
expect(page).to have_link "Check my votes"
end
end
scenario "map and content block shoud be visible before and after" do
stub_const("#{Budgets::InvestmentsController}::PER_PAGE", 1)
create(
:budget_investment, :selected, :with_map_location,
heading: new_york,
price: 10000,
title: "More bridges",
)
create(
:budget_investment, :selected, :with_map_location,
heading: new_york,
price: 5000,
title: "Less bridges"
)
create(:heading_content_block, heading: new_york, body: "<li>New Block</li>")
new_york.update!(allow_custom_content: true)
visit budget_investments_path(budget, heading_id: new_york, order: :price)
within("#sidebar") do
expect(page).to have_content "OpenStreetMap"
expect(page).to have_content "New Block"
expect(page).to have_css ".map-icon", visible: :all, count: 2
end
add_to_ballot("More bridges")
within("#sidebar") do
expect(page).to have_content "More bridges"
expect(page).to have_content "OpenStreetMap"
expect(page).to have_content "New Block"
expect(page).to have_css ".map-icon", visible: :all, count: 2
end
within(".budget-investment", text: "More bridges") do
click_button "Remove vote"
end
within("#sidebar") do
expect(page).not_to have_content "More bridges"
expect(page).to have_content "OpenStreetMap"
expect(page).to have_content "New Block"
expect(page).to have_css ".map-icon", visible: :all, count: 2
end
end
end
#Break up or simplify with helpers
context "Balloting in multiple headings" do
scenario "Independent progress bar for headings" do
city_heading = create(:budget_heading, group: city, name: "All city", price: 10000000)
district_heading1 = create(:budget_heading, group: districts, name: "District 1", price: 1000000)
district_heading2 = create(:budget_heading, group: districts, name: "District 2", price: 2000000)
create(:budget_investment, :selected, heading: city_heading, price: 10000, title: "Cheap")
create(:budget_investment, :selected, heading: district_heading1, price: 20000, title: "Average")
create(:budget_investment, :selected, heading: district_heading2, price: 30000, title: "Expensive")
visit budget_investments_path(budget, heading_id: city_heading)
add_to_ballot("Cheap")
expect(page).to have_css("#total_amount", text: "€10,000")
expect(page).to have_css("#amount_available", text: "€9,990,000")
within("#sidebar") do
expect(page).to have_content "Cheap"
expect(page).to have_content "€10,000"
end
visit budget_investments_path(budget, heading_id: district_heading1)
expect(page).to have_css("#total_amount", text: "€0")
expect(page).to have_css("#amount_available", text: "€1,000,000")
add_to_ballot("Average")
expect(page).to have_css("#total_amount", text: "€20,000")
expect(page).to have_css("#amount_available", text: "€980,000")
within("#sidebar") do
expect(page).to have_content "Average"
expect(page).to have_content "€20,000"
expect(page).not_to have_content "Cheap"
expect(page).not_to have_content "€10,000"
end
visit budget_investments_path(budget, heading_id: city_heading)
expect(page).to have_css("#total_amount", text: "€10,000")
expect(page).to have_css("#amount_available", text: "€9,990,000")
within("#sidebar") do
expect(page).to have_content "Cheap"
expect(page).to have_content "€10,000"
expect(page).not_to have_content "Average"
expect(page).not_to have_content "€20,000"
end
visit budget_investments_path(budget, heading_id: district_heading2)
expect(page).to have_content("You have active votes in another heading: District 1")
end
end
scenario "Display progress bar after first vote" do
create(:budget_investment, :selected, heading: new_york, price: 10000, title: "Park expansion")
visit budget_investments_path(budget, heading_id: new_york.id)
add_to_ballot("Park expansion")
within("#progress_bar") do
expect(page).to have_css("#total_amount", text: "€10,000")
end
end
end
context "Groups" do
before { login_as(user) }
scenario "Select my heading" do
create(:budget_investment, :selected, heading: california, title: "Green beach")
visit budget_investments_path(budget, heading_id: california)
add_to_ballot("Green beach")
visit budget_group_path(budget, states)
expect(page).to have_content "California"
expect(page).to have_css("#budget_heading_#{california.id}.is-active")
end
scenario "Change my heading" do
create(:budget_investment, :selected, heading: california, title: "Early ShakeAlert", balloters: [user])
create(:budget_investment, :selected, heading: new_york, title: "Avengers Tower")
visit budget_investments_path(budget, heading_id: california.id)
within(".budget-investment", text: "Early ShakeAlert") do
click_button "Remove vote"
expect(page).to have_button "Vote"
end
visit budget_investments_path(budget, heading_id: new_york.id)
add_to_ballot("Avengers Tower")
visit budget_group_path(budget, states)
expect(page).to have_css("#budget_heading_#{new_york.id}.is-active")
expect(page).not_to have_css("#budget_heading_#{california.id}.is-active")
end
scenario "View another heading" do
create(:budget_investment, :selected, heading: california, balloters: [user])
visit budget_investments_path(budget, heading_id: new_york.id)
expect(page).not_to have_css "#progressbar"
expect(page).to have_content "You have active votes in another heading: California"
expect(page).to have_link california.name,
href: budget_investments_path(budget, heading_id: california.id)
end
end
context "Showing the ballot" do
scenario "Displaying the correct group, heading, count & amount" do
group1 = create(:budget_group, budget: budget)
group2 = create(:budget_group, budget: budget)
create(:budget_heading, name: "District A", group: group1, price: 100)
heading1 = create(:budget_heading, name: "District 1", group: group1, price: 100)
heading2 = create(:budget_heading, name: "District 2", group: group2, price: 50)
create(:budget_heading, name: "District Z", group: group1, price: 100)
investment1 = create(:budget_investment, :selected, price: 10, heading: heading1)
investment2 = create(:budget_investment, :selected, price: 10, heading: heading1)
investment3 = create(:budget_investment, :selected, price: 5, heading: heading2)
investment4 = create(:budget_investment, :selected, price: 5, heading: heading2)
investment5 = create(:budget_investment, :selected, price: 5, heading: heading2)
user = create(:user, :level_two,
ballot_lines: [investment1, investment2, investment3, investment4, investment5])
login_as(user)
visit budget_ballot_path(budget)
expect(page).to have_content("You have voted 5 investments")
within("#budget_group_#{group1.id}") do
expect(page).to have_content "#{group1.name} - #{heading1.name}"
expect(page).to have_content "Amount spent €20"
expect(page).to have_link "Still available to you €80", href: budget_group_path(budget, group1)
end
within("#budget_group_#{group2.id}") do
expect(page).to have_content "#{group2.name} - #{heading2.name}"
expect(page).to have_content "Amount spent €15"
expect(page).to have_content "Still available to you €35"
end
end
end
scenario "Removing investments from ballot" do
investment = create(:budget_investment, :selected, price: 10, heading: new_york)
user = create(:user, :level_two, ballot_lines: [investment])
login_as(user)
visit budget_ballot_path(budget)
expect(page).to have_content("You have voted one investment")
within("#budget_investment_#{investment.id}") do
click_link "Remove vote"
end
expect(page).to have_current_path(budget_ballot_path(budget))
expect(page).to have_content("You have voted 0 investments")
end
scenario "Removing investments from ballot (sidebar)" do
investment1 = create(:budget_investment, :selected, price: 10000, heading: new_york)
investment2 = create(:budget_investment, :selected, price: 20000, heading: new_york)
user = create(:user, :level_two, ballot_lines: [investment1, investment2])
login_as(user)
visit budget_investments_path(budget, heading_id: new_york.id)
expect(page).to have_css("#total_amount", text: "€30,000")
expect(page).to have_css("#amount_available", text: "€970,000")
within("#sidebar") do
expect(page).to have_content investment1.title
expect(page).to have_content "€10,000"
expect(page).to have_content investment2.title
expect(page).to have_content "€20,000"
end
within("#sidebar #budget_investment_#{investment1.id}_sidebar") do
click_link "Remove vote"
end
expect(page).to have_css("#total_amount", text: "€20,000")
expect(page).to have_css("#amount_available", text: "€980,000")
within("#sidebar") do
expect(page).not_to have_content investment1.title
expect(page).not_to have_content "€10,000"
expect(page).to have_content investment2.title
expect(page).to have_content "€20,000"
end
end
describe "Back link" do
scenario "after adding and removing an investment from the ballot" do
create(:budget_investment, :selected, heading: new_york, price: 10, title: "Sully monument")
login_as(user)
visit budget_investments_path(budget, heading_id: new_york.id)
add_to_ballot("Sully monument")
within(".budget-heading") do
click_link "Check my votes"
end
expect(page).to have_content("You have voted one investment")
within(".ballot-list li", text: "Sully monument") do
click_link "Remove vote"
end
expect(page).to have_content("You have voted 0 investments")
click_link "Go back"
expect(page).to have_current_path(budget_investments_path(budget, heading_id: new_york.id))
expect(page).to have_link "Check my votes"
end
scenario "before adding any investments" do
login_as(user)
visit budget_investments_path(budget, heading_id: new_york.id)
within(".budget-heading") do
click_link "Check my votes"
end
expect(page).to have_content("You have voted 0 investments")
click_link "Go back"
expect(page).to have_current_path(budget_investments_path(budget, heading_id: new_york.id))
expect(page).to have_link "Check my votes"
end
end
context "Permissions" do
scenario "User not logged in" do
investment = create(:budget_investment, :selected, heading: new_york)
visit budget_investments_path(budget, heading_id: new_york.id)
within("#budget_investment_#{investment.id}") do
click_button "Vote"
expect(page).to have_content "You must sign in or sign up to continue."
expect(page).not_to have_button "Vote", disabled: :all
end
end
scenario "User not verified" do
unverified_user = create(:user)
investment = create(:budget_investment, :selected, heading: new_york)
login_as(unverified_user)
visit budget_investments_path(budget, heading_id: new_york.id)
within("#budget_investment_#{investment.id}") do
click_button "Vote"
expect(page).to have_content "Only verified users can vote on investments"
expect(page).not_to have_button "Vote", disabled: :all
end
end
scenario "User is organization" do
org = create(:organization)
investment = create(:budget_investment, :selected, heading: new_york)
login_as(org.user)
visit budget_investments_path(budget, heading_id: new_york.id)
within("#budget_investment_#{investment.id}") do
click_button "Vote"
expect(page).to have_content "Organization"
expect(page).not_to have_button "Vote", disabled: :all
end
end
scenario "Unselected investments" do
investment = create(:budget_investment, heading: new_york, title: "WTF asdfasfd")
login_as(user)
visit budget_investments_path(budget, heading_id: new_york)
expect(page).not_to have_css("#budget_investment_#{investment.id}")
end
scenario "Investments with feasibility undecided are not shown" do
investment = create(:budget_investment, :undecided, heading: new_york)
login_as(user)
visit budget_investments_path(budget, heading_id: new_york)
within("#budget-investments") do
expect(page).not_to have_css("div.ballot")
expect(page).not_to have_css("#budget_investment_#{investment.id}")
end
end
scenario "Different district" do
bi1 = create(:budget_investment, :selected, heading: california)
bi2 = create(:budget_investment, :selected, heading: new_york)
user = create(:user, :level_two, ballot_lines: [bi1])
login_as(user)
visit budget_investments_path(budget, heading: new_york)
within("#budget_investment_#{bi2.id}") do
click_button "Vote"
expect(page).to have_content("already voted a different heading")
expect(page).not_to have_button "Vote", disabled: :all
end
end
scenario "Insufficient funds (on page load)" do
bi1 = create(:budget_investment, :selected, heading: california, price: 600)
bi2 = create(:budget_investment, :selected, heading: california, price: 500)
user = create(:user, :level_two, ballot_lines: [bi1])
login_as(user)
visit budget_investments_path(budget, heading_id: california.id)
within("#budget_investment_#{bi2.id}") do
click_button "Vote"
expect(page).to have_content("You have already assigned the available budget")
expect(page).not_to have_button "Vote", disabled: :all
end
end
scenario "Insufficient funds (added after create)" do
create(:budget_investment, :selected, heading: california, price: 600, title: "Build replicants")
create(:budget_investment, :selected, heading: california, price: 500, title: "Build terminators")
login_as(user)
visit budget_investments_path(budget, heading_id: california.id)
add_to_ballot("Build replicants")
within(".budget-investment", text: "Build terminators") do
click_button "Vote"
expect(page).to have_content("You have already assigned the available budget")
expect(page).not_to have_button "Vote", disabled: :all
end
end
scenario "Insufficient funds (removed after destroy)" do
bi1 = create(:budget_investment, :selected, heading: california, price: 600)
bi2 = create(:budget_investment, :selected, heading: california, price: 500)
user = create(:user, :level_two, ballot_lines: [bi1])
login_as(user)
visit budget_investments_path(budget, heading_id: california.id)
within("#budget_investment_#{bi2.id}") do
click_button "Vote"
expect(page).to have_content("You have already assigned the available budget")
expect(page).not_to have_button "Vote", disabled: :all
expect(page).not_to have_button "Remove vote"
end
within("#budget_investment_#{bi1.id}") do
click_button "Remove vote"
expect(page).to have_button "Vote"
end
within("#budget_investment_#{bi2.id}") do
click_button "Vote"
expect(page).not_to have_content("You have already assigned the available budget")
expect(page).to have_button "Remove vote"
end
end
scenario "Insufficient funds (removed after destroying from sidebar)" do
bi1 = create(:budget_investment, :selected, heading: california, price: 600)
bi2 = create(:budget_investment, :selected, heading: california, price: 500)
user = create(:user, :level_two, ballot_lines: [bi1])
login_as(user)
visit budget_investments_path(budget, heading_id: california.id)
within("#budget_investment_#{bi2.id}") do
click_button "Vote"
expect(page).to have_content("You have already assigned the available budget")
expect(page).not_to have_button "Vote", disabled: :all
end
within("#budget_investment_#{bi1.id}_sidebar") do
click_link "Remove vote"
end
expect(page).not_to have_css "#budget_investment_#{bi1.id}_sidebar"
within("#budget_investment_#{bi2.id}") do
click_button "Vote"
expect(page).not_to have_content("You have already assigned the available budget")
expect(page).to have_button "Remove vote"
end
end
scenario "Edge case voting a non-elegible investment" do
investment1 = create(:budget_investment, :selected, heading: new_york, price: 10000)
admin_user = create(:administrator).user
login_as user
visit budget_investments_path(budget, heading_id: new_york)
expect(page).to have_button "Vote"
in_browser(:admin) do
login_as admin_user
visit edit_admin_budget_group_heading_path(budget, states, new_york)
fill_in "Money amount", with: 10
click_button "Save heading"
expect(page).to have_content "Heading updated successfully"
within "tr", text: "New York" do
expect(page).to have_css "td", exact_text: "€10"
end
end
within("#budget_investment_#{investment1.id}") do
click_button "Vote"
expect(page).to have_css ".participation-not-allowed", visible: :hidden
expect(page).not_to have_content "Remove"
click_button "Vote"
expect(page).to have_css ".participation-not-allowed"
expect(page).not_to have_button "Vote", disabled: :all
end
end
scenario "Balloting is disabled when budget isn't in the balotting phase" do
budget.update!(phase: "accepting")
bi1 = create(:budget_investment, :selected, heading: california, price: 600)
login_as(user)
visit budget_investments_path(budget, heading_id: california.id)
within("#budget_investment_#{bi1.id}") do
expect(page).not_to have_css("div.ballot")
end
end
end
context "Hide money" do
scenario "Do not show prices on sidebar or ballot show" do
budget_hide_money = create(:budget, :balloting, :approval, :hide_money)
group_no_price = create(:budget_group, budget: budget_hide_money)
heading_no_price = create(:budget_heading, group: group_no_price, max_ballot_lines: 2)
investment_1 = create(:budget_investment, :selected, heading: heading_no_price, price: 3000)
investment_2 = create(:budget_investment, :selected, heading: heading_no_price, price: 4000)
user = create(:user, :level_two, ballot_lines: [investment_1, investment_2])
login_as(user)
visit budget_investments_path(budget_hide_money, heading_id: heading_no_price.id)
expect(page).not_to have_content "Your ballot"
within("#sidebar") do
expect(page).to have_content investment_1.title
expect(page).to have_content investment_2.title
expect(page).not_to have_content investment_1.price
expect(page).not_to have_content investment_2.price
expect(page).not_to have_content ""
click_link "Check my votes"
end
expect(page).to have_content "Your ballot"
expect(page).to have_content investment_1.title
expect(page).to have_content investment_2.title
expect(page).not_to have_content investment_1.price
expect(page).not_to have_content investment_2.price
expect(page).not_to have_content ""
end
end
end