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.
We were always passing `officer.user` to this method, so we might as
well pass the officer (since the "officer" is in the name of the method)
and call `officer.user` inside the method.
We're also calling `login_through_form_as` in order to remove the
duplication between these two methods.
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.
This way it's more obvious what's going on.
Note that, in this case, the expectations were **not** true before
visiting the page, so we aren't fixing a flaky test.
We were doing it most of the time, but in some cases we were clicking
the "Sign out" link instead. These actions aren't the same, just like
using `login_as` is not the same as visiting the sign in page and
submitting the form.
Some of these tests failed sometimes because the user wasn't signed in
after using `login_as`. One possible cause could be that we weren't
adding an expectation after clicking the "Sign out" link.
So using `logout` adds consistency, simplifies the code, and might
reduce the chance of these tests failing in the future (although they
might still fail in the future because some of these tests check the
database after a `visit` call).
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
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.
Checking the database with methods like Activity.last does not test that
the record is present where it should be (first record of the table in
this case). In these tests there's only one record, though, so the order
doesn't matter that match.
However, calling methods like Activity.last generates a database query
after the process running the browser has been started, and this might
lead to inconsistent data.
JavaScript is used by about 98% of web users, so by testing without it
enabled, we're only testing that the application works for a very
reduced number of users.
We proceeded this way in the past because CONSUL started using Rails 4.2
and truncating the database between JavaScript tests with database
cleaner, which made these tests terribly slow.
When we upgraded to Rails 5.1 and introduced system tests, we started
using database transactions in JavaScript tests, making these tests much
faster. So now we can use JavaScript tests everywhere without critically
slowing down our test suite.