Files
grecia/spec/shared/system/mappable.rb
Javi Martín f638e50174 Wait for suggestions to finish loading in tests
Sometimes tests were hanging indefinitely. Debugging shows that in some
cases it's due to submitting a form before the AJAX request to get
proposals, debates or investments suggestions is finished, since having
an AJAX and a non-AJAX request at the same time when running the test
sometimes leads to unexpected results.

In our case, we were having many timeouts in Github Actions in the
branches where we use both ActiveStorage and Paperclip to store files
(based on pull request 4598). I can reproduce it in those branches
running the following test ("Should show new image after successful
creation with one uploaded file"), although only when my laptop isn't
plugged (!!):

```
rspec './spec/system/proposals_spec.rb[1:33:1:14]'
```

Since we didn't have a proper way to know the AJAX request had finished,
we're adding a `suggest-success` class to the element showing the
suggestions when that happens. Then in the tests we can look for that
class after filling in the title of a proposal, debate or investments.
Just for clarity's sake, we're also adding the `suggest-loading` class
when the suggestions are loading.

In order not to have expectations everywhere about the suggestions,
we're extracting methods to fill in those titles in the tests. Note we
aren't using these methods in the "edit" actions (suggestions are not
showing when editing) or in tests with the `no_js` tag (since
suggestions only work with JavaScript).
2021-09-22 18:29:23 +02:00

353 lines
11 KiB
Ruby

shared_examples "mappable" do |mappable_factory_name, mappable_association_name, mappable_new_path, mappable_edit_path, mappable_show_path, mappable_path_arguments, management: false|
let!(:user) { create(:user, :level_two) }
let!(:arguments) { {} }
let!(:mappable) { create(mappable_factory_name.to_s.to_sym) }
let!(:map_location) { create(:map_location, "#{mappable_factory_name}_map_location".to_sym, "#{mappable_association_name}": mappable) }
let(:management) { management }
before do
Setting["feature.map"] = true
end
describe "At #{mappable_new_path}" do
before { set_arguments(arguments, mappable, mappable_path_arguments) }
scenario "Should not show marker by default on create #{mappable_factory_name}" do
do_login_for user
visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form")
within ".map_location" do
expect(page).not_to have_css(".map-icon")
end
end
scenario "Should show marker on create #{mappable_factory_name} when click on map" do
do_login_for user
visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form")
find("#new_map_location").click
within ".map_location" do
expect(page).to have_css(".map-icon")
end
end
scenario "Should create #{mappable_factory_name} with map" do
do_login_for user
visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form")
find("#new_map_location").click
send("submit_#{mappable_factory_name}_form")
within ".map_location" do
expect(page).to have_css(".map-icon")
end
end
scenario "Can not display map on #{mappable_factory_name} when not fill marker on map" do
do_login_for user
visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form")
expect(page).to have_css ".map_location"
send("submit_#{mappable_factory_name}_form")
expect(page).not_to have_css(".map_location")
end
scenario "Can not display map on #{mappable_factory_name} when feature.map is disabled" do
Setting["feature.map"] = false
do_login_for user
visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form")
expect(page).not_to have_css ".map_location"
send("submit_#{mappable_factory_name}_form")
expect(page).not_to have_css(".map_location")
end
describe "When restoring the page from browser history" do
before { Setting["org_name"] = "CONSUL" }
scenario "map should not be duplicated" do
do_login_for user
visit send(mappable_new_path, arguments)
if management
click_link "Select user"
expect(page).to have_content "User management"
else
click_link "Help"
expect(page).to have_content "CONSUL is a platform for citizen participation"
end
go_back
within ".map_location" do
expect(page).to have_css(".leaflet-map-pane", count: 1)
end
end
scenario "keeps marker and zoom defined by the user" do
do_login_for user
visit send(mappable_new_path, arguments)
within ".map_location" do
expect(page).not_to have_css(".map-icon")
end
expect(page.execute_script("return App.Map.maps[0].getZoom();")).to eq(10)
map_zoom_in
find("#new_map_location").click
within ".map_location" do
expect(page).to have_css(".map-icon")
end
if management
click_link "Select user"
expect(page).to have_content "User management"
else
click_link "Help"
expect(page).to have_content "CONSUL is a platform for citizen participation"
end
go_back
within ".map_location" do
expect(page).to have_css(".map-icon")
expect(page.execute_script("return App.Map.maps[0].getZoom();")).to eq(11)
end
end
scenario "shows marker at map center" do
do_login_for user
visit send(mappable_new_path, arguments)
within ".map_location" do
expect(page).not_to have_css(".map-icon")
end
place_map_at(-68.592487, -62.391357)
find("#new_map_location").click
within ".map_location" do
expect(page).to have_css(".map-icon")
end
if management
click_link "Select user"
expect(page).to have_content "User management"
else
click_link "Help"
expect(page).to have_content "CONSUL is a platform for citizen participation"
end
go_back
within ".map_location" do
expect(page).to have_css(".map-icon")
end
end
end
scenario "Skip map" do
do_login_for user
visit send(mappable_new_path, arguments)
send("fill_in_#{mappable_factory_name}_form")
send("submit_#{mappable_factory_name}_form")
expect(page).not_to have_content "Map location can't be blank"
end
end
describe "At #{mappable_edit_path}" do
before { skip } if mappable_edit_path.blank?
scenario "Should edit map on #{mappable_factory_name} and contain default values" do
do_login_for mappable.author
visit send(mappable_edit_path, id: mappable.id)
expect(page).to have_content "Navigate the map to the location and place the marker."
validate_latitude_longitude(mappable_factory_name)
end
scenario "Should edit default values from map on #{mappable_factory_name} edit page" do
do_login_for mappable.author
visit send(mappable_edit_path, id: mappable.id)
find(".map_location").click
click_on("Save changes")
mappable.reload
expect(page).to have_css(".map_location")
expect(page).not_to have_selector(".map_location[data-marker-latitude='#{map_location.latitude}']")
expect(page).to have_selector(".map_location[data-marker-latitude='#{mappable.map_location.latitude}']")
end
scenario "Should edit mappable on #{mappable_factory_name} without change map" do
do_login_for mappable.author
visit send(mappable_edit_path, id: mappable.id)
fill_in "#{mappable_factory_name.camelize} title", with: "New title"
click_on("Save changes")
mappable.reload
expect(page).to have_css(".map_location")
expect(page).to have_selector(".map_location[data-marker-latitude='#{map_location.latitude}']")
expect(page).to have_selector(".map_location[data-marker-latitude='#{mappable.map_location.latitude}']")
end
scenario "Can not display map on #{mappable_factory_name} edit when remove map marker" do
do_login_for mappable.author
visit send(mappable_edit_path, id: mappable.id)
click_link "Remove map marker"
click_on "Save changes"
expect(page).not_to have_css(".map_location")
end
scenario "Can not display map on #{mappable_factory_name} edit when feature.map is disabled" do
Setting["feature.map"] = false
do_login_for mappable.author
visit send(mappable_edit_path, id: mappable.id)
fill_in "#{mappable_factory_name.camelize} title", with: "New title"
click_on("Save changes")
expect(page).not_to have_css(".map_location")
end
scenario "No errors on update" do
skip ""
do_login_for mappable.author
visit send(mappable_edit_path, id: mappable.id)
click_link "Remove map marker"
click_on "Save changes"
expect(page).not_to have_content "Map location can't be blank"
end
scenario "No need to skip map on update" do
do_login_for mappable.author
visit send(mappable_edit_path, id: mappable.id)
click_link "Remove map marker"
click_on "Save changes"
expect(page).not_to have_content "Map location can't be blank"
end
end
describe "At #{mappable_show_path}" do
before do
set_arguments(arguments, mappable, mappable_path_arguments)
end
scenario "Should display map and marker on #{mappable_factory_name} show page" do
arguments[:id] = mappable.id
do_login_for(user) if management
visit send(mappable_show_path, arguments)
within ".map_location" do
expect(page).to have_css(".map-icon")
end
end
scenario "Should not display map on #{mappable_factory_name} show when marker is not defined" do
mappable_without_map = create(mappable_factory_name.to_s.to_sym)
set_arguments(arguments, mappable_without_map, mappable_path_arguments)
arguments[:id] = mappable_without_map.id
do_login_for(user) if management
visit send(mappable_show_path, arguments)
expect(page).not_to have_css(".map_location")
end
scenario "Should not display map on #{mappable_factory_name} show page when feature.map is disable" do
Setting["feature.map"] = false
arguments[:id] = mappable.id
do_login_for(user) if management
visit send(mappable_show_path, arguments)
expect(page).not_to have_css(".map_location")
end
end
end
def do_login_for(user)
common_do_login_for(user, management: management)
end
def fill_in_proposal_form
fill_in_new_proposal_title with: "Help refugees"
fill_in "Proposal summary", with: "In summary, what we want is..."
end
def submit_proposal_form
check :proposal_terms_of_service
click_button "Create proposal"
if page.has_content?("Not now, go to my proposal")
click_link "Not now, go to my proposal"
end
end
def validate_latitude_longitude(mappable_factory_name)
expect(find("##{mappable_factory_name}_map_location_attributes_latitude", visible: false).value).to eq "51.48"
expect(find("##{mappable_factory_name}_map_location_attributes_longitude", visible: false).value).to eq "0.0"
expect(mappable.map_location.latitude).to eq 51.48
expect(mappable.map_location.longitude).to eq 0.0
end
def fill_in_budget_investment_form
fill_in_new_investment_title with: "Budget investment title"
fill_in_ckeditor "Description", with: "Budget investment description"
check :budget_investment_terms_of_service
end
def submit_budget_investment_form
check :budget_investment_terms_of_service
click_button "Create Investment"
end
def set_arguments(arguments, mappable, mappable_path_arguments)
mappable_path_arguments&.each do |argument_name, path_to_value|
arguments.merge!("#{argument_name}": mappable.send(path_to_value))
end
end
def map_zoom_in
initial_zoom = page.execute_script("return App.Map.maps[0].getZoom();")
find(".leaflet-control-zoom-in").click
until page.execute_script("return App.Map.maps[0].getZoom() === #{initial_zoom + 1};") do
sleep 0.01
end
end
def place_map_at(latitude, longitude)
page.execute_script("App.Map.maps[0].setView(new L.LatLng(#{latitude}, #{longitude}))")
until page.execute_script("return App.Map.maps[0].getCenter().lat === #{latitude};") do
sleep 0.01
end
end