Our original interface to vote in a poll had a few issues:
* Since there was no button to send the form, it wasn't clear that
selecting an option would automatically store it in the database.
* The interface was almost identical for single-choice questions and
multiple-choice questions, which made it hard to know which type of
question we were answering.
* Adding other type of questions, like open answers, was hard since we
would have to add a different submit button for each answer.
So we're now using radio buttons for single-choice questions and
checkboxes for multiple-choice questions, which are the native controls
designed for these purposes, and a button to send the whole form.
Since we don't have a database table for poll ballots like we have for
budget ballots, we're adding a new `Poll::WebVote` model to manage poll
ballots. We're using WebVote instead of Ballot or Vote because they
could be mistaken with other vote classes.
Note that browsers don't allow removing answers with radio buttons, so
once somebody has voted in a single-choice question, they can't remove
the vote unless they manually edit their HTML. This is the same behavior
we had before commit 7df0e9a96.
As mentioned in c2010f975, we're now adding the `ChangeByZero` rubocop
rule, since we've removed the test that used `and change`.
As mentioned in commits like a586ba806, a7664ad81, 006128da5, b41fbfa52
and c480cdd91, accessing the database after starting the browser with
the `visit` method sometimes results in database corruption and failing
tests on our CI due to the process running the test accessing the
database after the process running the browser has started.
In these cases, there's no need to check the database; we're already
checking the application behavior that shows that the voters have been
correctly created.
As mentioned in commits like a586ba806, a7664ad81, 006128da5, b41fbfa52
and c480cdd91, accessing the database after starting the browser with
the `visit` method sometimes results in database corruption and failing
tests on our CI due to the process running the test accessing the
database after the process running the browser has started.
For example, one of these tests has recently failed on our CI:
```
3) Users Create a level 3 user with email from scratch
Failure/Error: expect(user.reload).to be_confirmed
expected `#<User id: 2060, email: "pepe@gmail.com", created_at:
"2025-03-12 19:51:03.688867000 +0100", updated_...d_debates: true,
recommended_proposals: true, subscriptions_token: nil,
registering_from_web: false>.confirmed?` to be truthy, got false
```
IMHO this is also a bad practice for system tests, since these tests
should be checking what users experience.
So we're modifying the tests to check the results of users interaction
from the point of view of the users. For example, instead of checking
that a user is now level 3 verified in the database, we're checking that
the user interface states that the user is level 3 verified.
Note we're adding an offset when editing the map marker by clicking on
`map-location` with `.click(x: 30, y: 30)`. This way we make sure that
both the latitude and longitude change from the original values; we used
to clicking in the middle (no offset), which didn't change the longitude
and changed the latitude just by coincidence.
Also note we aren't changing tests with the `:no_js` tag, since these
tests don't run a real browser in a separate process. In the future, we
should also change most of these tests so they don't access the database
and they use a real browser.
By using the Rails `button_to` helper (which generates a form), and adapting the
response to `html` and `js` formats, the feature works with or without javascript
enabled.