require 'rails_helper' require 'sessions_helper' feature 'Budget Investments' do let(:author) { create(:user, :level_two, username: 'Isabel') } let(:budget) { create(:budget, name: "Big Budget") } let(:other_budget) { create(:budget, name: "What a Budget!") } let(:group) { create(:budget_group, name: "Health", budget: budget) } let!(:heading) { create(:budget_heading, name: "More hospitals", price: 666666, group: group) } it_behaves_like "milestoneable", :budget_investment, "budget_investment_path" before do Setting['feature.allow_images'] = true end after do Setting['feature.allow_images'] = nil end context "Concerns" do it_behaves_like 'notifiable in-app', Budget::Investment it_behaves_like 'relationable', Budget::Investment end scenario 'Index' do investments = [create(:budget_investment, heading: heading), create(:budget_investment, heading: heading), create(:budget_investment, :feasible, heading: heading)] unfeasible_investment = create(:budget_investment, :unfeasible, heading: heading) visit budget_path(budget) click_link "Health" expect(page).to have_selector('#budget-investments .budget-investment', count: 3) investments.each do |investment| within('#budget-investments') do expect(page).to have_content investment.title expect(page).to have_css("a[href='#{budget_investment_path(budget_id: budget.id, id: investment.id)}']", text: investment.title) expect(page).not_to have_content(unfeasible_investment.title) end end end scenario 'Index view mode' do investments = [create(:budget_investment, heading: heading), create(:budget_investment, heading: heading), create(:budget_investment, heading: heading)] visit budget_path(budget) click_link 'Health' click_button 'View mode' click_link 'List' investments.each do |investment| within('#budget-investments') do expect(page).to have_link investment.title expect(page).not_to have_content(investment.description) end end click_button 'View mode' click_link 'Cards' investments.each do |investment| within('#budget-investments') do expect(page).to have_link investment.title expect(page).to have_content(investment.description) end end end scenario 'Index should show investment descriptive image only when is defined' do investment = create(:budget_investment, heading: heading) investment_with_image = create(:budget_investment, heading: heading) image = create(:image, imageable: investment_with_image) visit budget_investments_path(budget, heading_id: heading.id) within("#budget_investment_#{investment.id}") do expect(page).not_to have_css("div.with-image") end within("#budget_investment_#{investment_with_image.id}") do expect(page).to have_css("img[alt='#{investment_with_image.image.title}']") end end scenario 'Index should show a map if heading has coordinates defined', :js do create(:budget_investment, heading: heading) visit budget_investments_path(budget, heading_id: heading.id) within("#sidebar") do expect(page).to have_css(".map_location") end unlocated_heading = create(:budget_heading, name: "No Map", price: 500, group: group, longitude: nil, latitude: nil) create(:budget_investment, heading: unlocated_heading) visit budget_investments_path(budget, heading_id: unlocated_heading.id) within("#sidebar") do expect(page).not_to have_css(".map_location") end end context("Search") do scenario 'Search by text' do investment1 = create(:budget_investment, heading: heading, title: "Get Schwifty") investment2 = create(:budget_investment, heading: heading, title: "Schwifty Hello") investment3 = create(:budget_investment, heading: heading, title: "Do not show me") visit budget_investments_path(budget, heading_id: heading.id) within(".expanded #search_form") do fill_in "search", with: "Schwifty" click_button "Search" end within("#budget-investments") do expect(page).to have_css('.budget-investment', count: 2) expect(page).to have_content(investment1.title) expect(page).to have_content(investment2.title) expect(page).not_to have_content(investment3.title) end end context "Advanced search" do scenario "Search by text", :js do bdgt_invest1 = create(:budget_investment, heading: heading,title: "Get Schwifty") bdgt_invest2 = create(:budget_investment, heading: heading,title: "Schwifty Hello") bdgt_invest3 = create(:budget_investment, heading: heading,title: "Do not show me") visit budget_investments_path(budget) click_link "Advanced search" fill_in "Write the text", with: "Schwifty" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end context "Search by author type" do scenario "Public employee", :js do ana = create :user, official_level: 1 john = create :user, official_level: 2 bdgt_invest1 = create(:budget_investment, heading: heading, author: ana) bdgt_invest2 = create(:budget_investment, heading: heading, author: ana) bdgt_invest3 = create(:budget_investment, heading: heading, author: john) visit budget_investments_path(budget) click_link "Advanced search" select Setting['official_level_1_name'], from: "advanced_search_official_level" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end scenario "Municipal Organization", :js do ana = create :user, official_level: 2 john = create :user, official_level: 3 bdgt_invest1 = create(:budget_investment, heading: heading, author: ana) bdgt_invest2 = create(:budget_investment, heading: heading, author: ana) bdgt_invest3 = create(:budget_investment, heading: heading, author: john) visit budget_investments_path(budget) click_link "Advanced search" select Setting['official_level_2_name'], from: "advanced_search_official_level" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end scenario "General director", :js do ana = create :user, official_level: 3 john = create :user, official_level: 4 bdgt_invest1 = create(:budget_investment, heading: heading, author: ana) bdgt_invest2 = create(:budget_investment, heading: heading, author: ana) bdgt_invest3 = create(:budget_investment, heading: heading, author: john) visit budget_investments_path(budget) click_link "Advanced search" select Setting['official_level_3_name'], from: "advanced_search_official_level" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end scenario "City councillor", :js do ana = create :user, official_level: 4 john = create :user, official_level: 5 bdgt_invest1 = create(:budget_investment, heading: heading, author: ana) bdgt_invest2 = create(:budget_investment, heading: heading, author: ana) bdgt_invest3 = create(:budget_investment, heading: heading, author: john) visit budget_investments_path(budget) click_link "Advanced search" select Setting['official_level_4_name'], from: "advanced_search_official_level" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end scenario "Mayoress", :js do ana = create :user, official_level: 5 john = create :user, official_level: 4 bdgt_invest1 = create(:budget_investment, heading: heading, author: ana) bdgt_invest2 = create(:budget_investment, heading: heading, author: ana) bdgt_invest3 = create(:budget_investment, heading: heading, author: john) visit budget_investments_path(budget) click_link "Advanced search" select Setting['official_level_5_name'], from: "advanced_search_official_level" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end end context "Search by date" do context "Predefined date ranges" do scenario "Last day", :js do bdgt_invest1 = create(:budget_investment, heading: heading,created_at: 1.minute.ago) bdgt_invest2 = create(:budget_investment, heading: heading,created_at: 1.hour.ago) bdgt_invest3 = create(:budget_investment, heading: heading,created_at: 2.days.ago) visit budget_investments_path(budget) click_link "Advanced search" select "Last 24 hours", from: "js-advanced-search-date-min" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end scenario "Last week", :js do bdgt_invest1 = create(:budget_investment, heading: heading,created_at: 1.day.ago) bdgt_invest2 = create(:budget_investment, heading: heading,created_at: 5.days.ago) bdgt_invest3 = create(:budget_investment, heading: heading,created_at: 8.days.ago) visit budget_investments_path(budget) click_link "Advanced search" select "Last week", from: "js-advanced-search-date-min" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end scenario "Last month", :js do bdgt_invest1 = create(:budget_investment, heading: heading,created_at: 10.days.ago) bdgt_invest2 = create(:budget_investment, heading: heading,created_at: 20.days.ago) bdgt_invest3 = create(:budget_investment, heading: heading,created_at: 33.days.ago) visit budget_investments_path(budget) click_link "Advanced search" select "Last month", from: "js-advanced-search-date-min" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end scenario "Last year", :js do bdgt_invest1 = create(:budget_investment, heading: heading,created_at: 300.days.ago) bdgt_invest2 = create(:budget_investment, heading: heading,created_at: 350.days.ago) bdgt_invest3 = create(:budget_investment, heading: heading,created_at: 370.days.ago) visit budget_investments_path(budget) click_link "Advanced search" select "Last year", from: "js-advanced-search-date-min" click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end end scenario "Search by custom date range", :js do bdgt_invest1 = create(:budget_investment, heading: heading,created_at: 2.days.ago) bdgt_invest2 = create(:budget_investment, heading: heading,created_at: 3.days.ago) bdgt_invest3 = create(:budget_investment, heading: heading,created_at: 9.days.ago) visit budget_investments_path(budget) click_link "Advanced search" select "Customized", from: "js-advanced-search-date-min" fill_in "advanced_search_date_min", with: 7.days.ago fill_in "advanced_search_date_max", with: 1.day.ago click_button "Filter" expect(page).to have_content("There are 2 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).not_to have_content(bdgt_invest3.title) end end scenario "Search by custom invalid date range", :js do bdgt_invest1 = create(:budget_investment, heading: heading,created_at: 2.days.ago) bdgt_invest2 = create(:budget_investment, heading: heading,created_at: 3.days.ago) bdgt_invest3 = create(:budget_investment, heading: heading,created_at: 9.days.ago) visit budget_investments_path(budget) click_link "Advanced search" select "Customized", from: "js-advanced-search-date-min" fill_in "advanced_search_date_min", with: 4000.years.ago fill_in "advanced_search_date_max", with: "wrong date" click_button "Filter" expect(page).to have_content("There are 3 investments") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) expect(page).to have_content(bdgt_invest2.title) expect(page).to have_content(bdgt_invest3.title) end end scenario "Search by multiple filters", :js do ana = create :user, official_level: 1 john = create :user, official_level: 1 bdgt_invest1 = create(:budget_investment, heading: heading,title: "Get Schwifty", author: ana, created_at: 1.minute.ago) bdgt_invest2 = create(:budget_investment, heading: heading,title: "Hello Schwifty", author: john, created_at: 2.days.ago) bdgt_invest3 = create(:budget_investment, heading: heading,title: "Save the forest") visit budget_investments_path(budget) click_link "Advanced search" fill_in "Write the text", with: "Schwifty" select Setting['official_level_1_name'], from: "advanced_search_official_level" select "Last 24 hours", from: "js-advanced-search-date-min" click_button "Filter" expect(page).to have_content("There is 1 investment") within("#budget-investments") do expect(page).to have_content(bdgt_invest1.title) end end scenario "Maintain advanced search criteria", :js do visit budget_investments_path(budget) click_link "Advanced search" fill_in "Write the text", with: "Schwifty" select Setting['official_level_1_name'], from: "advanced_search_official_level" select "Last 24 hours", from: "js-advanced-search-date-min" click_button "Filter" expect(page).to have_content("investments cannot be found") within "#js-advanced-search" do expect(page).to have_selector("input[name='search'][value='Schwifty']") expect(page).to have_select('advanced_search[official_level]', selected: Setting['official_level_1_name']) expect(page).to have_select('advanced_search[date_min]', selected: 'Last 24 hours') end end scenario "Maintain custom date search criteria", :js do visit budget_investments_path(budget) click_link "Advanced search" select "Customized", from: "js-advanced-search-date-min" fill_in "advanced_search_date_min", with: 7.days.ago.strftime('%d/%m/%Y') fill_in "advanced_search_date_max", with: 1.day.ago.strftime('%d/%m/%Y') click_button "Filter" expect(page).to have_content("investments cannot be found") within "#js-advanced-search" do expect(page).to have_select('advanced_search[date_min]', selected: 'Customized') expect(page).to have_selector("input[name='advanced_search[date_min]'][value*='#{7.days.ago.strftime('%d/%m/%Y')}']") expect(page).to have_selector("input[name='advanced_search[date_max]'][value*='#{1.day.ago.strftime('%d/%m/%Y')}']") end end end end end context("Filters") do scenario 'by unfeasibility' do investment1 = create(:budget_investment, :unfeasible, heading: heading, valuation_finished: true) investment2 = create(:budget_investment, :feasible, heading: heading) investment3 = create(:budget_investment, heading: heading) investment4 = create(:budget_investment, :feasible, heading: heading) visit budget_investments_path(budget_id: budget.id, heading_id: heading.id, filter: "unfeasible") within("#budget-investments") do expect(page).to have_css('.budget-investment', count: 1) expect(page).to have_content(investment1.title) expect(page).not_to have_content(investment2.title) expect(page).not_to have_content(investment3.title) expect(page).not_to have_content(investment4.title) end end scenario "by unfeasibilty link for group with one heading" do budget.update(phase: :balloting) group = create(:budget_group, name: 'All City', budget: budget) heading = create(:budget_heading, name: "Madrid", group: group) visit budget_path(budget) click_link 'See unfeasible investments' click_link "All City" expected_path = budget_investments_path(budget, heading_id: heading.id, filter: "unfeasible") expect(page).to have_current_path(expected_path) end scenario "by unfeasibilty link for group with many headings" do budget.update(phase: :balloting) group = create(:budget_group, name: 'Districts', budget: budget) heading1 = create(:budget_heading, name: 'Carabanchel', group: group) heading2 = create(:budget_heading, name: 'Barajas', group: group) visit budget_path(budget) click_link 'See unfeasible investments' click_link 'Districts' click_link 'Carabanchel' expected_path = budget_investments_path(budget, heading_id: heading1.id, filter: "unfeasible") expect(page).to have_current_path(expected_path) end end context "Orders" do before { budget.update(phase: 'selecting') } scenario "Default order is random" do per_page = Kaminari.config.default_per_page (per_page + 100).times { create(:budget_investment) } visit budget_investments_path(budget, heading_id: heading.id) order = all(".budget-investment h3").collect {|i| i.text } visit budget_investments_path(budget, heading_id: heading.id) new_order = eq(all(".budget-investment h3").collect {|i| i.text }) expect(order).not_to eq(new_order) end scenario "Random order after another order" do per_page = Kaminari.config.default_per_page (per_page + 2).times { create(:budget_investment) } visit budget_investments_path(budget, heading_id: heading.id) click_link "highest rated" click_link "random" order = all(".budget-investment h3").collect {|i| i.text } visit budget_investments_path(budget, heading_id: heading.id) new_order = eq(all(".budget-investment h3").collect {|i| i.text }) expect(order).not_to eq(new_order) end scenario 'Random order maintained with pagination' do per_page = Kaminari.config.default_per_page (per_page + 2).times { create(:budget_investment, heading: heading) } visit budget_investments_path(budget, heading_id: heading.id) order = all(".budget-investment h3").collect {|i| i.text } click_link 'Next' expect(page).to have_content "You're on page 2" click_link 'Previous' expect(page).to have_content "You're on page 1" new_order = all(".budget-investment h3").collect {|i| i.text } expect(order).to eq(new_order) end scenario 'Random order maintained when going back from show' do 10.times { |i| create(:budget_investment, heading: heading) } visit budget_investments_path(budget, heading_id: heading.id) order = all(".budget-investment h3").collect {|i| i.text } click_link Budget::Investment.first.title click_link "Go back" new_order = all(".budget-investment h3").collect {|i| i.text } expect(order).to eq(new_order) end scenario "Investments are not repeated with random order" do 12.times { create(:budget_investment, heading: heading) } # 12 instead of per_page + 2 because in each page there are 10 (in this case), not 25 visit budget_investments_path(budget, order: 'random') first_page_investments = investments_order click_link 'Next' expect(page).to have_content "You're on page 2" second_page_investments = investments_order common_values = first_page_investments & second_page_investments expect(common_values.length).to eq(0) end scenario 'Proposals are ordered by confidence_score' do best_proposal = create(:budget_investment, heading: heading, title: 'Best proposal') best_proposal.update_column(:confidence_score, 10) worst_proposal = create(:budget_investment, heading: heading, title: 'Worst proposal') worst_proposal.update_column(:confidence_score, 2) medium_proposal = create(:budget_investment, heading: heading, title: 'Medium proposal') medium_proposal.update_column(:confidence_score, 5) visit budget_investments_path(budget, heading_id: heading.id) click_link 'highest rated' expect(page).to have_selector('a.is-active', text: 'highest rated') within '#budget-investments' do expect(best_proposal.title).to appear_before(medium_proposal.title) expect(medium_proposal.title).to appear_before(worst_proposal.title) end expect(current_url).to include('order=confidence_score') expect(current_url).to include('page=1') end scenario 'Each user has a different and consistent random budget investment order when random_seed is disctint' do (Kaminari.config.default_per_page * 1.3).to_i.times { create(:budget_investment, heading: heading) } in_browser(:one) do visit budget_investments_path(budget, heading: heading, random_seed: rand) @first_user_investments_order = investments_order end in_browser(:two) do visit budget_investments_path(budget, heading: heading, random_seed: rand) @second_user_investments_order = investments_order end expect(@first_user_investments_order).not_to eq(@second_user_investments_order) in_browser(:one) do click_link 'Next' expect(page).to have_content "You're on page 2" click_link 'Previous' expect(page).to have_content "You're on page 1" expect(investments_order).to eq(@first_user_investments_order) end in_browser(:two) do click_link 'Next' expect(page).to have_content "You're on page 2" click_link 'Previous' expect(page).to have_content "You're on page 1" expect(investments_order).to eq(@second_user_investments_order) end end scenario 'Each user has a equal and consistent budget investment order when the random_seed is equal' do (Kaminari.config.default_per_page * 1.3).to_i.times { create(:budget_investment, heading: heading) } in_browser(:one) do visit budget_investments_path(budget, heading: heading, random_seed: '1') @first_user_investments_order = investments_order end in_browser(:two) do visit budget_investments_path(budget, heading: heading, random_seed: '1') @second_user_investments_order = investments_order end expect(@first_user_investments_order).to eq(@second_user_investments_order) end scenario "Set votes for investments randomized with a seed" do voter = create(:user, :level_two) login_as(voter) 10.times { create(:budget_investment, heading: heading) } voted_investments = [] 10.times do investment = create(:budget_investment, heading: heading) create(:vote, votable: investment, voter: voter) voted_investments << investment end visit budget_investments_path(budget, heading_id: heading.id) voted_investments.each do |investment| if page.has_link?(investment.title) within("#budget_investment_#{investment.id}") do expect(page).to have_content "You have already supported this investment" end end end end scenario 'Order is random if budget is finished' do 10.times { create(:budget_investment) } budget.update(phase: 'finished') visit budget_investments_path(budget, heading_id: heading.id) order = all(".budget-investment h3").collect {|i| i.text } visit budget_investments_path(budget, heading_id: heading.id) new_order = eq(all(".budget-investment h3").collect {|i| i.text }) expect(order).not_to eq(new_order) end def investments_order all(".budget-investment h3").collect {|i| i.text } end end context 'Phase I - Accepting' do before { budget.update(phase: 'accepting') } scenario 'Create with invisible_captcha honeypot field' do login_as(author) visit new_budget_investment_path(budget_id: budget.id) select heading.name, from: 'budget_investment_heading_id' fill_in 'budget_investment_title', with: 'I am a bot' fill_in 'budget_investment_subtitle', with: 'This is the honeypot' fill_in 'budget_investment_description', with: 'This is the description' check 'budget_investment_terms_of_service' click_button 'Create Investment' expect(page.status_code).to eq(200) expect(page.html).to be_empty expect(page).to have_current_path(budget_investments_path(budget_id: budget.id)) end scenario 'Create budget investment too fast' do allow(InvisibleCaptcha).to receive(:timestamp_threshold).and_return(Float::INFINITY) login_as(author) visit new_budget_investment_path(budget_id: budget.id) select heading.name, from: 'budget_investment_heading_id' fill_in 'budget_investment_title', with: 'I am a bot' fill_in 'budget_investment_description', with: 'This is the description' check 'budget_investment_terms_of_service' click_button 'Create Investment' expect(page).to have_content 'Sorry, that was too quick! Please resubmit' expect(page).to have_current_path(new_budget_investment_path(budget_id: budget.id)) end scenario 'Create' do login_as(author) visit new_budget_investment_path(budget_id: budget.id) select heading.name, from: 'budget_investment_heading_id' fill_in 'budget_investment_title', with: 'Build a skyscraper' fill_in 'budget_investment_description', with: 'I want to live in a high tower over the clouds' fill_in 'budget_investment_location', with: 'City center' fill_in 'budget_investment_organization_name', with: 'T.I.A.' fill_in 'budget_investment_tag_list', with: 'Towers' check 'budget_investment_terms_of_service' click_button 'Create Investment' expect(page).to have_content 'Investment created successfully' expect(page).to have_content 'Build a skyscraper' expect(page).to have_content 'I want to live in a high tower over the clouds' expect(page).to have_content 'City center' expect(page).to have_content 'T.I.A.' expect(page).to have_content 'Towers' visit user_url(author, filter: :budget_investments) expect(page).to have_content '1 Investment' expect(page).to have_content 'Build a skyscraper' end scenario 'Errors on create' do login_as(author) visit new_budget_investment_path(budget_id: budget.id) click_button 'Create Investment' expect(page).to have_content error_message end context 'Suggest' do factory = :budget_investment scenario 'Show up to 5 suggestions', :js do login_as(author) %w(first second third fourth fifth sixth).each do |ordinal| create(factory, title: "#{ordinal.titleize} #{factory}, has search term", budget: budget) end create(factory, title: "This is the last #{factory}", budget: budget) visit new_budget_investment_path(budget) fill_in "budget_investment_title", with: "search" within("div#js-suggest") do expect(page).to have_content "You are seeing 5 of 6 investments containing the term 'search'" end end scenario 'No found suggestions', :js do login_as(author) %w(first second third fourth fifth sixth).each do |ordinal| create(factory, title: "#{ordinal.titleize} #{factory}, has search term", budget: budget) end visit new_budget_investment_path(budget) fill_in "budget_investment_title", with: "item" within('div#js-suggest') do expect(page).not_to have_content 'You are seeing' end end scenario "Don't show suggestions from a different budget", :js do login_as(author) %w(first second third fourth fifth sixth).each do |ordinal| create(factory, title: "#{ordinal.titleize} #{factory}, has search term", budget: budget) end visit new_budget_investment_path(other_budget) fill_in "budget_investment_title", with: "search" within('div#js-suggest') do expect(page).not_to have_content 'You are seeing' end end end scenario 'Ballot is not visible' do login_as(author) visit budget_investments_path(budget, heading_id: heading.id) expect(page).not_to have_link('Check my ballot') expect(page).not_to have_css('#progress_bar') within('#sidebar') do expect(page).not_to have_content('My ballot') end end scenario "Heading options are correctly ordered" do city_group = create(:budget_group, name: "Toda la ciudad", budget: budget) create(:budget_heading, name: "Toda la ciudad", price: 333333, group: city_group) create(:budget_heading, name: "More health professionals", price: 999999, group: group) login_as(author) visit new_budget_investment_path(budget_id: budget.id) select_options = find('#budget_investment_heading_id').all('option').collect(&:text) expect(select_options.first).to eq('') expect(select_options.second).to eq('Health: More health professionals') expect(select_options.third).to eq('Health: More hospitals') expect(select_options.fourth).to eq('Toda la ciudad') end end scenario "Show" do user = create(:user) login_as(user) investment = create(:budget_investment, heading: heading) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).to have_content(investment.title) expect(page).to have_content(investment.description) expect(page).to have_content(investment.author.name) expect(page).to have_content(investment.heading.name) within("#investment_code") do expect(page).to have_content(investment.id) end end context "Show Investment's price & cost explanation" do let(:investment) { create(:budget_investment, :selected_with_price, heading: heading) } context "When investment with price is selected" do scenario "Price & explanation is shown when Budget is on published prices phase" do Budget::Phase::PUBLISHED_PRICES_PHASES.each do |phase| budget.update(phase: phase) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).to have_content(investment.formatted_price) expect(page).to have_content(investment.price_explanation) expect(page).to have_link("See price explanation") if budget.finished? investment.update(winner: true) end visit budget_investments_path(budget) expect(page).to have_content(investment.formatted_price) end end scenario "Price & explanation isn't shown when Budget is not on published prices phase" do (Budget::Phase::PHASE_KINDS - Budget::Phase::PUBLISHED_PRICES_PHASES).each do |phase| budget.update(phase: phase) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).not_to have_content(investment.formatted_price) expect(page).not_to have_content(investment.price_explanation) expect(page).not_to have_link("See price explanation") visit budget_investments_path(budget) expect(page).not_to have_content(investment.formatted_price) end end end context "When investment with price is unselected" do background do investment.update(selected: false) end scenario "Price & explanation isn't shown for any Budget's phase" do Budget::Phase::PHASE_KINDS.each do |phase| budget.update(phase: phase) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).not_to have_content(investment.formatted_price) expect(page).not_to have_content(investment.price_explanation) expect(page).not_to have_link("See price explanation") visit budget_investments_path(budget) expect(page).not_to have_content(investment.formatted_price) end end end end scenario 'Can access the community' do Setting['feature.community'] = true investment = create(:budget_investment, heading: heading) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).to have_content "Access the community" Setting['feature.community'] = false end scenario 'Can not access the community' do Setting['feature.community'] = false investment = create(:budget_investment, heading: heading) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).not_to have_content "Access the community" end scenario "Don't display flaggable buttons" do investment = create(:budget_investment, heading: heading) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).not_to have_selector ".js-follow" end scenario "Show back link contains heading id" do investment = create(:budget_investment, heading: heading) visit budget_investment_path(budget, investment) expect(page).to have_link "Go back", href: budget_investments_path(budget, heading_id: investment.heading) end context "Show (feasible budget investment)" do let(:investment) do create(:budget_investment, :feasible, :finished, budget: budget, group: group, heading: heading, price: 16, price_explanation: 'Every wheel is 4 euros, so total is 16') end background do user = create(:user) login_as(user) end scenario "Budget in selecting phase" do budget.update(phase: "selecting") visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).not_to have_content("Unfeasibility explanation") expect(page).not_to have_content("Price explanation") expect(page).not_to have_content(investment.price_explanation) end end scenario "Show (unfeasible budget investment)" do user = create(:user) login_as(user) investment = create(:budget_investment, :unfeasible, :finished, budget: budget, group: group, heading: heading, unfeasibility_explanation: 'Local government is not competent in this matter') visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).to have_content("Unfeasibility explanation") expect(page).to have_content("Local government is not competent in this matter") expect(page).to have_content("This investment project has been marked as not feasible and will not go to balloting phase") end scenario "Show (selected budget investment)" do user = create(:user) login_as(user) investment = create(:budget_investment, :feasible, :finished, :selected, budget: budget, group: group, heading: heading) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).to have_content("This investment project has been selected for balloting phase") end scenario "Show (winner budget investment)" do user = create(:user) login_as(user) investment = create(:budget_investment, :feasible, :finished, :selected, :winner, budget: budget, group: group, heading: heading) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).to have_content("Winning investment project") end scenario "Show (not selected budget investment)" do budget.update(phase: 'balloting') user = create(:user) login_as(user) investment = create(:budget_investment, :feasible, :finished, budget: budget, group: group, heading: heading) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).to have_content("This investment project has not been selected for balloting phase") end scenario "Show title (no message)" do user = create(:user) login_as(user) investment = create(:budget_investment, :feasible, :finished, budget: budget, group: group, heading: heading) visit budget_investment_path(budget_id: budget.id, id: investment.id) within("aside") do expect(page).to have_content("Investment project") expect(page).to have_css(".label-budget-investment") end end scenario "Show (unfeasible budget investment with valuation not finished)" do user = create(:user) login_as(user) investment = create(:budget_investment, :unfeasible, valuation_finished: false, budget: budget, group: group, heading: heading, unfeasibility_explanation: 'Local government is not competent in this matter') visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).not_to have_content("Unfeasibility explanation") expect(page).not_to have_content("Local government is not competent in this matter") end scenario "Show (unfeasible budget investment with valuation not finished)" do user = create(:user) login_as(user) investment = create(:budget_investment, :unfeasible, valuation_finished: false, budget: budget, group: group, heading: heading, unfeasibility_explanation: 'Local government is not competent in this matter') visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).not_to have_content("Unfeasibility explanation") expect(page).not_to have_content("Local government is not competent in this matter") end scenario "Only winner investments are show when budget is finished" do 3.times { create(:budget_investment, heading: heading) } Budget::Investment.first.update(feasibility: 'feasible', selected: true, winner: true) Budget::Investment.second.update(feasibility: 'feasible', selected: true, winner: true) budget.update(phase: 'finished') visit budget_investments_path(budget, heading_id: heading.id) expect(page).to have_content("#{Budget::Investment.first.title}") expect(page).to have_content("#{Budget::Investment.second.title}") expect(page).not_to have_content("#{Budget::Investment.third.title}") end it_behaves_like "followable", "budget_investment", "budget_investment_path", { "budget_id": "budget_id", "id": "id" } it_behaves_like "imageable", "budget_investment", "budget_investment_path", { "budget_id": "budget_id", "id": "id" } it_behaves_like "nested imageable", "budget_investment", "new_budget_investment_path", { "budget_id": "budget_id" }, "imageable_fill_new_valid_budget_investment", "Create Investment", "Budget Investment created successfully." it_behaves_like "documentable", "budget_investment", "budget_investment_path", { "budget_id": "budget_id", "id": "id" } it_behaves_like "nested documentable", "user", "budget_investment", "new_budget_investment_path", { "budget_id": "budget_id" }, "documentable_fill_new_valid_budget_investment", "Create Investment", "Budget Investment created successfully." it_behaves_like "mappable", "budget_investment", "investment", "new_budget_investment_path", "", "budget_investment_path", { "budget_id": "budget_id" } context "Destroy" do scenario "Admin cannot destroy budget investments" do admin = create(:administrator) user = create(:user, :level_two) investment = create(:budget_investment, heading: heading, author: user) login_as(admin.user) visit user_path(user) within("#budget_investment_#{investment.id}") do expect(page).not_to have_link "Delete" end end scenario "Author can destroy while on the accepting phase" do user = create(:user, :level_two) sp1 = create(:budget_investment, heading: heading, price: 10000, author: user) login_as(user) visit user_path(user, tab: :budget_investments) within("#budget_investment_#{sp1.id}") do expect(page).to have_content(sp1.title) click_link('Delete') end visit user_path(user, tab: :budget_investments) end end context "Selecting Phase" do background do budget.update(phase: "selecting") end context "Popup alert to vote only in one heading per group" do scenario "When supporting in the first heading group", :js do carabanchel = create(:budget_heading, group: group) salamanca = create(:budget_heading, group: group) carabanchel_investment = create(:budget_investment, :selected, heading: carabanchel) salamanca_investment = create(:budget_investment, :selected, heading: salamanca) visit budget_investments_path(budget, heading_id: carabanchel.id) within("#budget_investment_#{carabanchel_investment.id}") do expect(page).to have_css(".in-favor a[data-confirm]") end end scenario "When already supported in the group", :js do carabanchel = create(:budget_heading, group: group) salamanca = create(:budget_heading, group: group) carabanchel_investment = create(:budget_investment, heading: carabanchel) salamanca_investment = create(:budget_investment, heading: salamanca) create(:vote, votable: carabanchel_investment, voter: author) login_as(author) visit budget_investments_path(budget, heading_id: carabanchel.id) within("#budget_investment_#{carabanchel_investment.id}") do expect(page).not_to have_css(".in-favor a[data-confirm]") end end scenario "When supporting in another group", :js do carabanchel = create(:budget_heading, group: group) another_heading = create(:budget_heading, group: create(:budget_group, budget: budget)) carabanchel_investment = create(:budget_investment, heading: carabanchel) another_group_investment = create(:budget_investment, heading: another_heading) create(:vote, votable: carabanchel_investment, voter: author) login_as(author) visit budget_investments_path(budget, heading_id: another_heading.id) within("#budget_investment_#{another_group_investment.id}") do expect(page).to have_css(".in-favor a[data-confirm]") end end end scenario "Sidebar in show should display support text" do investment = create(:budget_investment, budget: budget) visit budget_investment_path(budget, investment) within("aside") do expect(page).to have_content "Supports" end end end context "Evaluating Phase" do background do budget.update(phase: "valuating") end scenario "Sidebar in show should display support text and count" do investment = create(:budget_investment, :selected, budget: budget) create(:vote, votable: investment) visit budget_investment_path(budget, investment) within("aside") do expect(page).to have_content "Supports" expect(page).to have_content "1 support" end end scenario "Index should display support count" do investment = create(:budget_investment, budget: budget, heading: heading) create(:vote, votable: investment) visit budget_investments_path(budget, heading_id: heading.id) within("#budget_investment_#{investment.id}") do expect(page).to have_content "1 support" end end scenario "Show should display support text and count" do investment = create(:budget_investment, budget: budget, heading: heading) create(:vote, votable: investment) visit budget_investment_path(budget, investment) within("#budget_investment_#{investment.id}") do expect(page).to have_content "Supports" expect(page).to have_content "1 support" end end end context "Publishing prices phase" do background do budget.update(phase: "publishing_prices") end scenario "Heading index - should show only selected investments" do investment1 = create(:budget_investment, :selected, heading: heading, price: 10000) investment2 = create(:budget_investment, :selected, heading: heading, price: 15000) investment3 = create(:budget_investment, heading: heading, price: 30000) visit budget_investments_path(budget, heading: heading) within("#budget-investments") do expect(page).to have_content investment1.title expect(page).to have_content investment2.title expect(page).not_to have_content investment3.title end end end context "Balloting Phase" do background do budget.update(phase: "balloting") end scenario "Index" do user = create(:user, :level_two) sp1 = create(:budget_investment, :selected, heading: heading, price: 10000) sp2 = create(:budget_investment, :selected, heading: heading, price: 20000) login_as(user) visit root_path first(:link, "Participatory budgeting").click click_link "More hospitals €666,666" within("#budget_investment_#{sp1.id}") do expect(page).to have_content sp1.title expect(page).to have_content "€10,000" end within("#budget_investment_#{sp2.id}") do expect(page).to have_content sp2.title expect(page).to have_content "€20,000" end end scenario 'Order by cost (only when balloting)' do mid_investment = create(:budget_investment, :selected, heading: heading, title: 'Build a nice house', price: 1000) mid_investment.update_column(:confidence_score, 10) low_investment = create(:budget_investment, :selected, heading: heading, title: 'Build an ugly house', price: 1000) low_investment.update_column(:confidence_score, 5) high_investment = create(:budget_investment, :selected, heading: heading, title: 'Build a skyscraper', price: 20000) visit budget_investments_path(budget, heading_id: heading.id) click_link 'by price' expect(page).to have_selector('a.is-active', text: 'by price') within '#budget-investments' do expect(high_investment.title).to appear_before(mid_investment.title) expect(mid_investment.title).to appear_before(low_investment.title) end expect(current_url).to include('order=price') expect(current_url).to include('page=1') end scenario "Show" do user = create(:user, :level_two) sp1 = create(:budget_investment, :selected, heading: heading, price: 10000) login_as(user) visit budget_investments_path(budget, heading_id: heading.id) click_link sp1.title expect(page).to have_content "€10,000" end scenario "Sidebar in show should display vote text" do investment = create(:budget_investment, :selected, budget: budget) visit budget_investment_path(budget, investment) within("aside") do expect(page).to have_content "Votes" end end scenario "Confirm", :js do budget.update(phase: 'balloting') user = create(:user, :level_two) global_group = create(:budget_group, budget: budget, name: 'Global Group') global_heading = create(:budget_heading, group: global_group, name: 'Global Heading', latitude: -43.145412, longitude: 12.009423) carabanchel_heading = create(:budget_heading, group: group, name: "Carabanchel") new_york_heading = create(:budget_heading, group: group, name: "New York", latitude: -43.223412, longitude: 12.009423) sp1 = create(:budget_investment, :selected, price: 1, heading: global_heading) sp2 = create(:budget_investment, :selected, price: 10, heading: global_heading) sp3 = create(:budget_investment, :selected, price: 100, heading: global_heading) sp4 = create(:budget_investment, :selected, price: 1000, heading: carabanchel_heading) sp5 = create(:budget_investment, :selected, price: 10000, heading: carabanchel_heading) sp6 = create(:budget_investment, :selected, price: 100000, heading: new_york_heading) login_as(user) visit budget_path(budget) click_link "Global Group" # No need to click_link "Global Heading" because the link of a group with a single heading # points to the list of investments directly add_to_ballot(sp1) add_to_ballot(sp2) visit budget_path(budget) click_link "Health" click_link "Carabanchel" add_to_ballot(sp4) add_to_ballot(sp5) visit budget_ballot_path(budget) expect(page).to have_content "You can change your vote at any time until the close of this phase" within("#budget_group_#{global_group.id}") do expect(page).to have_content sp1.title expect(page).to have_content "€#{sp1.price}" expect(page).to have_content sp2.title expect(page).to have_content "€#{sp2.price}" expect(page).not_to have_content sp3.title expect(page).not_to have_content "€#{sp3.price}" end within("#budget_group_#{group.id}") do expect(page).to have_content sp4.title expect(page).to have_content "€1,000" expect(page).to have_content sp5.title expect(page).to have_content "€10,000" expect(page).not_to have_content sp6.title expect(page).not_to have_content "€100,000" end end scenario 'Ballot is visible' do login_as(author) visit budget_investments_path(budget, heading_id: heading.id) expect(page).to have_link('Check my ballot') expect(page).to have_css('#progress_bar') within('#sidebar') do expect(page).to have_content('My ballot') end end scenario 'Show unselected budget investments' do investment1 = create(:budget_investment, :unselected, :feasible, heading: heading, valuation_finished: true) investment2 = create(:budget_investment, :selected, :feasible, heading: heading, valuation_finished: true) investment3 = create(:budget_investment, :selected, :feasible, heading: heading, valuation_finished: true) investment4 = create(:budget_investment, :selected, :feasible, heading: heading, valuation_finished: true) visit budget_investments_path(budget_id: budget.id, heading_id: heading.id, filter: "unselected") within("#budget-investments") do expect(page).to have_css('.budget-investment', count: 1) expect(page).to have_content(investment1.title) expect(page).not_to have_content(investment2.title) expect(page).not_to have_content(investment3.title) expect(page).not_to have_content(investment4.title) end end scenario "Shows unselected link for group with one heading" do group = create(:budget_group, name: 'All City', budget: budget) heading = create(:budget_heading, name: "Madrid", group: group) visit budget_path(budget) click_link 'See investments not selected for balloting phase' click_link "All City" expected_path = budget_investments_path(budget, heading_id: heading.id, filter: "unselected") expect(page).to have_current_path(expected_path) end scenario "Shows unselected link for group with many headings" do group = create(:budget_group, name: 'Districts', budget: budget) heading1 = create(:budget_heading, name: 'Carabanchel', group: group) heading2 = create(:budget_heading, name: 'Barajas', group: group) visit budget_path(budget) click_link 'See investments not selected for balloting phase' click_link 'Districts' click_link 'Carabanchel' expected_path = budget_investments_path(budget, heading_id: heading1.id, filter: "unselected") expect(page).to have_current_path(expected_path) end scenario "Do not display vote button for unselected investments in index" do investment = create(:budget_investment, :unselected, heading: heading) visit budget_investments_path(budget_id: budget.id, heading_id: heading.id, filter: "unselected") expect(page).to have_content investment.title expect(page).not_to have_link("Vote") end scenario "Do not display vote button for unselected investments in show" do investment = create(:budget_investment, :unselected, heading: heading) visit budget_investment_path(budget, investment) expect(page).to have_content investment.title expect(page).not_to have_link("Vote") end feature "Reclassification" do scenario "Due to heading change" do user = create(:user, :level_two) investment = create(:budget_investment, :selected, heading: heading) heading2 = create(:budget_heading, group: group) ballot = create(:budget_ballot, user: user, budget: budget) ballot.investments << investment login_as(user) visit budget_ballot_path(budget) expect(page).to have_content("You have voted one investment") investment.heading = heading2 investment.save visit budget_ballot_path(budget) expect(page).to have_content("You have voted 0 investment") end scenario "Due to being unfeasible" do user = create(:user, :level_two) investment = create(:budget_investment, :selected, heading: heading) heading2 = create(:budget_heading, group: group) ballot = create(:budget_ballot, user: user, budget: budget) ballot.investments << investment login_as(user) visit budget_ballot_path(budget) expect(page).to have_content("You have voted one investment") investment.feasibility = "unfeasible" investment.unfeasibility_explanation = "too expensive" investment.save visit budget_ballot_path(budget) expect(page).to have_content("You have voted 0 investment") end end end scenario 'Flagging an investment as innapropriate', :js do user = create(:user) investment = create(:budget_investment, heading: heading) login_as(user) visit budget_investment_path(budget, investment) within "#budget_investment_#{investment.id}" do find("#flag-expand-investment-#{investment.id}").click find("#flag-investment-#{investment.id}").click expect(page).to have_css("#unflag-expand-investment-#{investment.id}") end expect(Flag.flagged?(user, investment)).to be end scenario 'Unflagging an investment', :js do user = create(:user) investment = create(:budget_investment, heading: heading) Flag.flag(user, investment) login_as(user) visit budget_investment_path(budget, investment) within "#budget_investment_#{investment.id}" do find("#unflag-expand-investment-#{investment.id}").click find("#unflag-investment-#{investment.id}").click expect(page).to have_css("#flag-expand-investment-#{investment.id}") end expect(Flag.flagged?(user, investment)).not_to be end scenario 'Flagging an investment updates the DOM properly', :js do user = create(:user) investment = create(:budget_investment, heading: heading) login_as(user) visit budget_investment_path(budget, investment) within "#budget_investment_#{investment.id}" do find("#flag-expand-investment-#{investment.id}").click find("#flag-investment-#{investment.id}").click expect(page).to have_css("#unflag-expand-investment-#{investment.id}") end expect(Flag.flagged?(user, investment)).to be within "#budget_investment_#{investment.id}" do find("#unflag-expand-investment-#{investment.id}").click find("#unflag-investment-#{investment.id}").click expect(page).to have_css("#flag-expand-investment-#{investment.id}") end expect(Flag.flagged?(user, investment)).not_to be end context 'sidebar map' do scenario "Display 6 investment's markers on sidebar map", :js do investment1 = create(:budget_investment, heading: heading) investment2 = create(:budget_investment, heading: heading) investment3 = create(:budget_investment, heading: heading) investment4 = create(:budget_investment, heading: heading) investment5 = create(:budget_investment, heading: heading) investment6 = create(:budget_investment, heading: heading) create(:map_location, longitude: 40.1231, latitude: -3.636, investment: investment1) create(:map_location, longitude: 40.1232, latitude: -3.635, investment: investment2) create(:map_location, longitude: 40.1233, latitude: -3.634, investment: investment3) create(:map_location, longitude: 40.1234, latitude: -3.633, investment: investment4) create(:map_location, longitude: 40.1235, latitude: -3.632, investment: investment5) create(:map_location, longitude: 40.1236, latitude: -3.631, investment: investment6) visit budget_investments_path(budget, heading_id: heading.id) within ".map_location" do expect(page).to have_css(".map-icon", count: 6, visible: false) end end scenario "Display 2 investment's markers on sidebar map", :js do investment1 = create(:budget_investment, heading: heading) investment2 = create(:budget_investment, heading: heading) create(:map_location, longitude: 40.1281, latitude: -3.656, investment: investment1) create(:map_location, longitude: 40.1292, latitude: -3.665, investment: investment2) visit budget_investments_path(budget, heading_id: heading.id) within ".map_location" do expect(page).to have_css(".map-icon", count: 2, visible: false) end end scenario "Display only investment's related to the current heading", :js do heading_2 = create(:budget_heading, name: "Madrid", group: group) investment1 = create(:budget_investment, heading: heading) investment2 = create(:budget_investment, heading: heading) investment3 = create(:budget_investment, heading: heading) investment4 = create(:budget_investment, heading: heading) investment5 = create(:budget_investment, heading: heading_2) investment6 = create(:budget_investment, heading: heading_2) create(:map_location, longitude: 40.1231, latitude: -3.636, investment: investment1) create(:map_location, longitude: 40.1232, latitude: -3.685, investment: investment2) create(:map_location, longitude: 40.1233, latitude: -3.664, investment: investment3) create(:map_location, longitude: 40.1234, latitude: -3.673, investment: investment4) create(:map_location, longitude: 40.1235, latitude: -3.672, investment: investment5) create(:map_location, longitude: 40.1236, latitude: -3.621, investment: investment6) visit budget_investments_path(budget, heading_id: heading.id) within ".map_location" do expect(page).to have_css(".map-icon", count: 4, visible: false) end end scenario "Do not display investment's, since they're all related to other heading", :js do heading_2 = create(:budget_heading, name: "Madrid", group: group) investment1 = create(:budget_investment, heading: heading_2) investment2 = create(:budget_investment, heading: heading_2) investment3 = create(:budget_investment, heading: heading_2) create(:map_location, longitude: 40.1255, latitude: -3.644, investment: investment1) create(:map_location, longitude: 40.1258, latitude: -3.637, investment: investment2) create(:map_location, longitude: 40.1251, latitude: -3.649, investment: investment3) visit budget_investments_path(budget, heading_id: heading.id) within ".map_location" do expect(page).to have_css(".map-icon", count: 0, visible: false) end end end end