According to the GeoJSON specification [1]:
> * A linear ring is a closed LineString with four or more positions.
> * The first and last positions are equivalent, and they MUST contain
> identical values; their representation SHOULD also be identical.
> (...)
> * For type "Polygon", the "coordinates" member MUST be an array of
> linear ring coordinate arrays.
Note that, for simplicity, right now we aren't checking whether the
coordinates are defined counterclockwise for exterior rings and
clockwise for interior rings, which is what the specification expects.
[1] https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.6
We're reworking the format validation to correctly interpret feature
collection, feature, and geometry, according to RFC 7946 [1].
Since Leaflet interprets GeoJSON format, we're rendering the GeoJSON as
a layer instead of as a set of points. For that, we're normalizing the
GeoJSON to make sure it contains either a Feature or a
FeatureCollection. We're also adding the Leaflet images to the assets
path so the markers used for point geometries are rendered correctly.
Note we no longer allow a GeoJSON containing a geometry but not a
defined type. Since there might be invalid GeoJSON in existing Consul
Democracy databases, we're normalizing these existing geometry objects
to be part of a feature object.
We're also wrapping the outline points in a FeatureCollection object
because most of the large GIS systems eg ArcGIS, QGIS export geojson as
a complete FeatureCollection.
[1] https://datatracker.ietf.org/doc/html/rfc7946
Co-authored-by: Javi Martín <javim@elretirao.net>
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
Note that, since the button now generates a `form` tag, we need to
adjust the styles of this section.
As mentioned in commit 5311daadf, there are several reasons to use
buttons in these situations. And, as mentioned in the previous commits,
using buttons instead of links for actions requiring confirmation will
help us test for accessibility issues.
Note we're simplifying the `table .button` margin rules because the
`.button` class already defines `0` for all its margins except the
bottom margin. Otherwise, the margins defined by the `flex-with-gap`
mixin would be overwritten by the margins defined in the `table .button`
class.
We forgot to do so in commit f0ab7bcfc. We're still leaving one system
spec to test that these images are rendered when browsing the site.
We're also changing the existing component tests to check the `alt`
attribute, just like the remaining system test does.
Even after disabling the turbolinks previews in the previous commit
(which is still necessary, even with the changes in this commit), these
tests were still finishing before the "Go back" requests did. To
reproduce an issue caused by this behavior, run:
```
rspec spec/system/budgets/ballots_spec.rb:425 spec/system/users_auth_spec.rb:701 --seed 40358
```
Apparently, a `have_current_path` expectation isn't enough to check that
the request has finished and it only checks that the request to that
path has started or it's being processed.
Adding an additional expectation to check that the content of the page
has changed solves the issue.
When we create a budget heading through factories it's placed at Puerta del Sol,
Madrid. It seems reasonable that the `map_location` factory places the points near
there.
Before these changes sometimes the map center was placed in Madrid while map
locations were placed in Greenwich, therefore markers were not visible in the
map current pane.
This rule was added in rubocop-capybara 2.19.0. We were following it
about 85% of the time.
Now we won't have to check both have_css and have_selector when
searching the code.
Note we're excluding a few files:
* Configuration files that weren't generated by us
* Migration files that weren't generated by us
* The Gemfile, since it includes an important comment that must be on
the same line as the gem declaration
* The Budget::Stats class, since the heading statistics are a mess and
having shorter lines would require a lot of refactoring
For the HashAlignment rule, we're using the default `key` style (keys
are aligned and values aren't) instead of the `table` style (both keys
and values are aligned) because, even if we used both in the
application, we used the `key` style a lot more. Furthermore, the
`table` style looks strange in places where there are both very long and
very short keys and sometimes we weren't even consistent with the
`table` style, aligning some keys without aligning other keys.
Ideally we could align hashes to "either key or table", so developers
can decide whether keeping the symmetry of the code is worth it in a
case-per-case basis, but Rubocop doesn't allow this option.
We were using `map_location` in one place and
`location-map-remove-marker` in another one. We usually use dashes in
HTML class names, we don't say "location map" anywhere else.
We were rendering the whole sidebar again, which wasn't necessary since
most of it remains unchanged. This resulted in complicated code to pass
the necessary information to render the same map that was already
rendered. Furthermore, when users had been moving the map around or
zooming out, we were resetting the map to its default settings after
voting, which was potentially annoying.
This also fixes the wrong investments being displayed in the map after
voting; only the investments on the current page were displayed in this
case while the index displayed all of them.
We were getting a warning with Ruby 2.7 due to the change in the way
keyword arguments are handled in Ruby 3.0.
```
ruby/gems/2.7.0/gems/rspec-support-3.11.0/lib/rspec/support/with_keywords_when_needed.rb:18:
warning: Passing the keyword argument as the last hash parameter is
deprecated
```
As hinted by the warning, this code crashes with Ruby 3.0:
```
ArgumentError:
unknown keyword: :budget_id
```
I'm not sure why this is the case, though, since we were already
explicitely passing a hash first before passing the keyword parameters.
I guess there are some cases in this whole keyword VS hash parameters
incompatibility that I haven't completely understood.
When voting investment projects, the sidebar was rendered without the
`@heading_content_blocks` being set. That resulted in a 500 error when
the heading had content blocks.
By extracting the logic to a component, we make sure the heading content
blocks are properly set every time this code is rendered, no matter
which controller is rendering the view.
This rule was added in Rubocop 1.18.0, but we didn't add it back then.
Since we're applying it most of the time, we might as well be consistent
and apply it everywhere.
We were checking that the price of the investment isn't present on the
page. However, the text "200" could be present in either the title of
the budget or the title of the heading ("Heading 200"), for instance. So
now we're making sure we look for the text on the relevant part of the
page.
We were getting some failures because sometimes the titles which are
generated automatically (like "Budget Investment 200 title") contained
the price of the investment, and so, when testing the presence of the
price (200, in this case), the test was failing.
So we're adding a custom title to the investments we create during the
tests.
We were testing that the `calculate_winners` method does not take the
price into account; we can do the same in a model test. We already have
a different system test to check that the price isn't displayed in the
view.
The test was always passing because incompatible investments are only
shown after clicking on the "Show all" link. So now we're clicking the
link before checking the "incompatibles" table isn't shown.
I don't think "incompatibles" is a valid English word; for now, I'm
leaving it like this until a native English speaker reviews it.
While reviewing commit 7702b551e, I forgot to test whether selecting
text in the budget header or clicking its link worked properly.
The negative index (-5) meant it was impossible to select its text or
click on its link.
The good news is the pseudoelement with a negative index (-1) is
considered a child of the .budget-header element, so having a negative
index will cause the pseudoelement to be render behind the content of
the .budget-header element but in front of the background of the
.budget-header element.
This is exactly what we want.
Originally, we didn't have a z-index in the .budget-header element,
meaning the pseudoelement was rendered behind the background of the
.budget-header element, meaning both backgrounds were visible. This was
OK when the background was a plain color, but it wasn't when the
background was an image.
To stress the fact that the budget header is only affected when we use
an image, I'm also moving the code inside the `.with-background-image`
selector, although it would be interesting to check whether it's a good
idea to add `z-index: 0` to the `full-width-background` mixin.
We forgot to do so in commit 04605d5d5. Before that commit, we were
testing the links weren't displayed in the "informing" phase as opposed
to the "finished" phase. After that commit, they weren't displayed
anywhere since a <select> field was shown instead.
Since then, we've replaced the <select> field with the links generated
by the `Budgets::Investments::FiltersComponent`. We've already got tests
for these links.
We're going to make a change, and it's easier if we've already got a
component with tests so we don't have to write system tests to check
whether the map is rendered.
We were showing the header when there were no search terms but there
were advanced search filters, unlike what we do for debates and
proposals. Besides, we were already hiding the header when there were
search terms, so it makes sense to hide it when using the advanced
search too.
We're using the `@search_terms` and `@advanced_search_terms` instance
variables in order to be consistent with what we do in the debates and
proposals sections.
When using the advanced search in the debates and proposals sections, we
were not displaying the search term in the search results summary.
However, we were displaying it when using the advanced search in the
investments section.
Now we're doing the same thing everywhere.
Defining a behavior on hover means making it different for people using
a keyboard or a touchscreen (most of the population, nowadays).
In this case, we had an accessibility issue where the message wouldn't
disappear once it appeared. That meant that, after tabbing through all
the links and buttons in, for instance, the debates index, the page
would be filled with "participation not allowed" messages, and in order
to see the information about how many people have voted, reloading the
page was required.
For touchscreen users the behavior was similar to what we get on hover,
although we've found some inconsistencies when trying to support several
elements on the same page.
We think in proposals it makes sense to hide the "support" button when
users click on it, and the same applies to the buttonsto support and
vote investment projects. However, we aren't hiding the buttons to
agree/disagree with a debate in order to keep the information about the
current number of people agreeing and disagreeing visible.
Note we're removing some support spec methods because after these
changes the duplication isn't as obvious as it was in the past.