Commit Graph

357 Commits

Author SHA1 Message Date
Javi Martín
f93c85bd2e Don't check the database during system tests
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.

IMHO this is also a bad practice for system tests, since these tests
should be checking what users experience.

So, just like we did a few commits ago with tests that reloaded records,
we're modifying the tests to check the results of user interactions from
the point of view of the users.

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.

Finally, note that one of the tests we're changing in the shared
`notifiable_in_app` file did not check the database content, but we're
also changing it for consistency.
2025-04-01 14:53:27 +02:00
Javi Martín
f15991dd3e Simplify tests replying to a comment
We were using the `reply_to` method in some places, but not in others.
2025-04-01 14:53:26 +02:00
Javi Martín
1b8a079727 Don't reload records in system tests
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.
2025-04-01 14:53:26 +02:00
Javi Martín
533d2198ee Use refresh instead of visiting the current page
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.
2025-03-26 16:27:08 +01:00
Javi Martín
368cf47adf Group tests to delete a document together
This way the tests are slightly faster, and we avoid a possible flaky
spec since in one test we were checking that a certain text was not
present, which didn't guarantee that the request to delete the document
had finished.
2025-03-26 16:27:08 +01:00
Javi Martín
a39201e408 Add missing expectations in mappable tests
After clicking the "Save changes" button, we were sometimes checking
expectations that were already true before clicking the button, so it
was possible that the request generated by that button didn't finish
before the test did.

So now we're checking that the button is no longer present, which is
only true after the request has finished.
2025-03-26 16:27:08 +01:00
taitus
3877479b69 Extract proposal edit from shared nested imageable specs to system specs 2024-11-26 18:10:26 +01:00
Javi Martín
2fb8abe83f Use a button to delete documents
While testing for accessibility issues (in a development branch), we're
removing Turbolinks and monkey-patching the behavior of the `click_link`
method to check the page for accessibility issues after each request.
However, we were getting false positives when clicking links that act
like buttons.

So, for the reasons mentioned in commit 5311daadf, we're replacing the
link to delete a document with a button.
2024-11-07 15:18:37 +01:00
Javi Martín
3e44eeaee0 Directly select language in remotely translatable tests
The test "request a translation of an already translated text" was
failing sometimes on our CI since August 29, maybe due to a change in
GitHub Actions since the test had been passing for a year and a half and
we didn't change any code around that time (we were updating the
documentation). While the root cause is unknown, debugging shows that
sometimes (usually the first time this test is executed on our CI, and
only the first time, since running it 600 tests in a row also resulted
in only one failure) the request done by clicking on "Traducir página"
is done with a user session where the locale is in English.

This doesn't make much sense, since both user sessions are already in
Spanish (and we had either explicit or implicit expectations to confirm
that), and debugging shows that the session is indeed in Spanish during
the previous request.

In any case, we're solving it by never using English during the test,
since it wasn't necessary; it was only done that way because all the
tests on this file used the language selector to get to the Spanish
pages. We're simplifying some of the other tests the same way.

The test failure was:

```
Failure/Error: expect(page).to have_content "Se han solicitado
correctamente las traducciones"
expected to find text "Se han solicitado correctamente las traducciones"
in
"Idioma: \n
\nEnglish\nDeutsch\nEspañol\nFrançais\nNederlands\nPortuguês
brasileiro\n中文\n
Entrar\nRegistrarse\nDebates\nPropuestas\nVotaciones\nLegislación
colaborativa\nPresupuestos participativos\nODS\nAyuda\n×\nTranslations
have been correctly requested.\nPropuestas más activas\nAhora mismo no
hay propuestas\nDebates más activos\nndfrrqufrp\nVer todos los
debates\nProcesos abiertos\nAhora mismo no hay procesos
abiertos\nGobierno abierto\nEste portal usa la aplicación CONSUL
DEMOCRACY que es software de código abierto.\nParticipación\nDecide cómo
debe ser la ciudad que quieres.\nCONSUL DEMOCRACY, 2024 Política de
privacidad Condiciones de uso Accesibilidad"
```

Note that most of the text is in Spanish (as expected) but the flash
message itself is in English.
2024-09-24 16:54:02 +02:00
Javi Martín
314019bee7 Remove database expectations in remotely translatable tests
In the past, having this kind of expectations after the process running
the browser has started has resulted in flaky issues with the database
connection.

In one case, we're removing the test because there are controller tests
covering the same scenario and a system test checking what happens from
the user perspective.

In the other case, we're replacing the expectations with expectations
from the user's point of view.
2024-09-24 16:54:02 +02:00
Javi Martín
3ab9fb1d27 Simplify similar remotely translatable tests
We were using the same setup in these tests, and we were only changing
the expectations or adding an extra step.

Note we're also using `refresh` to simplify the code and because we were
using `select "Español", from: "Idioma:"` when that language was already
selected.
2024-09-24 16:54:02 +02:00
Javi Martín
95dc70acee Remove parentheses in remove translatable expectations
So it's consistent with both the rest of the file and what we usually
do.
2024-09-24 16:53:53 +02:00
Javi Martín
d636f1fe75 Add missing expectations in remotely translatable tests
After changing the language, we were checking that certain content isn't
there.

However, the content wasn't there before changing the language either,
so the test will pass even if the request to change the language hasn't
finished.

Although this is probably OK because we aren't changing the language
using an AJAX request, and so Capybara will correctly wait until the
request is finished before finishing the test, confirming that the page
has changed after a request is something we try to do in every test.
2024-09-24 16:53:45 +02:00
Javi Martín
38b38d1fcc Rename Poll::Question::Answer to Poll::Question::Option
Having a class named `Poll::Question::Answer` and another class named
`Poll::Answer` was so confusing that no developer working on the project
has ever been capable of remembering which is which for more than a few
seconds.

Furthermore, we're planning to add open answers to polls, and we might
add a reference from the `poll_answers` table to the
`poll_question_answers` table to property differentiate between open
answers and closed answers. Having yet another thing named answer would
be more than what our brains can handle (we know it because we did this
once in a prototype).

So we're renaming `Poll::Question::Answer` to `Poll::Question::Option`.
Hopefully that'll make it easier to remember. The name is also (more or
less) consistent with the `Legislation::QuestionOption` class, which is
similar.

We aren't changing the table or columns names for now in order to avoid
possible issues when upgrading (old code running with the new database
tables/columns after running the migrations but before deployment has
finished, for instance). We might do it in the future.

I've tried not to change the internationalization keys either so
existing translations would still be valid. However, since we have to
change the keys in `activerecord.yml` so methods like
`human_attribute_name` keep working, I'm also changing them in places
where similar keys were used (like `poll_question_answer` or
`poll/question/answer`).

Note that it isn't clear whether we should use `option` or
`question_option` in some cases. In order to keep things simple, we're
using `option` where we were using `answer` and `question_option` where
we were using `question_answer`.

Also note we're adding tests for the admin menu component, since at
first I forgot to change the `answers` reference there and all tests
passed.
2024-06-13 19:13:01 +02:00
Javi Martín
5e7b5ccfd3 Add and apply Capybara/ClickLinkOrButtonStyle rule
This rule was added in rubocop-capybara 2.19.0. We were following it
most of the time.
2023-11-08 14:18:16 +01:00
Javi Martín
0cec581ec0 Add and apply Capybara/RSpec/HaveSelector rule
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.
2023-11-08 14:18:16 +01:00
Javi Martín
cdc5e05d48 Open PDF files in the same tab/window
Quoting usability experts Jakob Nielsen and Anna Kaley [1]:

> [Opening PDF files in new tabs] is problematic, because it assumes
> users will always do the exact same things with certain file formats,
> which isn’t always the case.

There are many examples of this situation. For example, some people
(myself included) configure their browser so it downloads PDF files
instead of opening them in the browser. In this situation, a new tab is
opened, a blank page is displayed, the file is downloaded, and then
either the tab is closed or the blank page needs to be manually closed.
The end result is really annoying.

Other situations include people who use a mobile phone browser, where
navigating through tabs is generally much harder than doing so on a
desktop browser.

But IMHO the most important point is: every browser already provides a
way to open "regular" links in a new tab, so people can choose what to
do, but if we decide to open the link in a new tab, we take control away
from them, and people who'd like to open the link in the same tab might
feel frustrated.

In these cases, the links either say "download" or include the word
"PDF", so people know in advance that they're going to download/open a
PDF file, and so we're giving them information and, by removing the
`target` attribute, we're giving them control over their browser so they
can choose what's convenient for them.

[1] https://www.nngroup.com/articles/new-browser-windows-and-tabs
2023-10-23 18:16:14 +02:00
Javi Martín
7c6134fdee Unify the way we display document information
We were displaying documents in five places, and in five different ways.
Sometimes with the metadata in parenthesis after the title, sometimes
with the metadata below the title, sometimes without metadata, sometimes
with an icon in front of the document, and sometimes with a separate
link to download the file.

So we're now displaying the same thing everywhere. Not sure whether this
is the best solution, but at least it's consistent.

We aren't unifying the way we display a list of documents, though, since
different sections look pretty different and I'm not sure whether the
same style would look well everywhere.

Note that we're renaming the `document` HTML class in the documents
table to `document-row` so the styles for the `document` class don't
apply here.
2023-10-23 18:15:54 +02:00
Javi Martín
5f0a7f4bbc Group show document tests together
While in unit tests it's great to have different tests for different
expectations, system tests are slow, and so it's better to have just one
test for all the expectations related to the same actions.
2023-10-23 15:49:01 +02:00
Javi Martín
a8bd5eb192 Rename document/image fields HTML classes
Using the `document` or `documents` classes meant styles defined for the
public list of documents conflict with these ones.

So now we're using HTML classes that match the name of the Ruby
component classes, as we usually do.
2023-10-23 15:49:01 +02:00
Javi Martín
9a1dd9992a Don't depend on the "Help" link in tests
In order to leave the page using turbolinks and then going back, we were
clicking on the "Help" page link, but this link doesn't have to be
available on every Consul Democracy installation.

So we're using the link to the homepage instead.
2023-09-13 23:32:25 +02:00
Javi Martín
6e9df3be5a Upgrade to Rails 6.1
Note that `Capybara.app_host` now returns `nil` by default and that
breaks tests using `lvh.me` or our custom `app_host` method, so we're
setting `Capybara.app_host` to the value it had in earlier versions of
Rails. I also haven't found a way to remove the code to set the
integration session host in relationable tests which I mentioned in
commit ffc14e499.

Also note that we now filter more parameters, and that they match
regular expressions, so filtering `:passw` means we're filtering
`passwd`, `password`, ...
2023-09-11 23:40:37 +02:00
Javi Martín
ea913f9332 Use Capybara methods to find/click/check links
We applied the Capybara/SpecificMatcher in commit f52a86b46.  However,
this rule doesn't convert methods finding <a> tags to methods finding
links because <a> tags only count as links when they've got the `href`
attribute. For instance, in the `xss_spec.rb` file we check what happens
when clicking on an anchor tag because we're testing that the `href`
attribute has been removed and so we can't use `click_link`.

So, basically, we can't enable a rule to automatically detect when we're
using `have_css` instead of `have_link`, but we should still do it
because `have_link` adds an extra check which affects accessibility
since it makes sure the tag has the `href` attribute and so it's
recognizable as a link by screen readers.
2023-09-11 14:10:41 +02:00
Javi Martín
8e276e2891 Add FactoryBot/ConsistentParenthesesStyle rule
This rule was added in rubocop-rspec 2.14.0. We were already applying it
most of the time.
2023-09-06 19:00:56 +02:00
Javi Martín
f79a21f071 Add and apply RSpec/BeEq rubocop rule
This rule was added in rubocop-rspec 2.9.0. Once again, we were applying
it about 50% of the time.
2023-09-06 19:00:56 +02:00
Javi Martín
a1439d0790 Apply Layout/LineLength rubocop rule
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
2023-08-30 14:46:35 +02:00
Javi Martín
3fe292dfe2 Move relationable expectations to controller tests
Having expectations related to database operations in system tests after
the process running the browser has started might result in exceptions
while running our test suite.
2023-08-30 14:46:35 +02:00
Javi Martín
8898c30f55 Rename AvailableLocales.available_locales method
I'm not sure whether we should rename the class instead. I'm renaming
the method because renaming the class would require more changes.
2023-08-30 14:46:35 +02:00
Javi Martín
025f3ad210 Simplify variable names in remote translations tests 2023-08-30 14:46:35 +02:00
Javi Martín
03fa5fc8d6 Simplify long test titles 2023-08-30 14:46:35 +02:00
Javi Martín
5b6de96241 Add and apply MultilineMethodCallIndentation rule 2023-08-18 14:56:16 +02:00
Javi Martín
8b13daad95 Add and apply rules for multi-line hashes
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.
2023-08-18 14:56:16 +02:00
Javi Martín
09c63e354c Add and apply Layout/DotPosition rule
Since IRB has improved its support for multiline, the main argument
towars using a trailing dot no longer affects most people.

It still affects me, though, since I use Pry :), but I agree
leading dots are more readable, so I'm enabling the rule anyway.
2023-08-18 14:56:16 +02:00
Javi Martín
8b14522bf5 Use a button instead of a link to remove a marker
Using a button for interactive elements is better, as explained in
commit 5311daadf.

Since buttons with "type=button" do nothing by default, we no longer
need to call `preventDefault()` when clicking it.
2023-05-04 15:32:33 +02:00
Javi Martín
a145fdb8a8 Make map location HTML class names consistent
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.
2023-05-04 15:32:33 +02:00
Javi Martín
2b9f9ed557 Fix crash translating an already translated text
The page was crashing when at least part of the content of the page had
been translated between the request showing the remote translations
button and the moment people pressed the button.
2023-02-16 17:52:17 +01:00
Javi Martín
3fe65bafd1 Use keyword arguments in mappable specs
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.
2023-01-26 17:19:15 +01:00
Javi Martín
efc46fe6c8 Add Performance/StringIdentifierArgument rule
It was added in rubocop-performance 1.13.0. We were already applying it
in most places.

We aren't adding it for performance reasons but in order to make the
code more consistent.
2023-01-11 16:05:20 +01:00
Javi Martín
adfb141d1b Simplify URL validation in related content
We were using `Setting["url"]` to verify the content belonged to the
application URL, but we can use `root_url` instead.

Note that means we need to include the port when filling in forms in the
tests, since in tests URL helpers like `polymorphic_url` don't include
the port, but a port is automatically added when actually making the
request.
2022-10-02 16:54:06 +02:00
Javi Martín
ffc14e499a Upgrade to Rails 6.0
All the code in the `bin/` and the `config/` folders has been generated
running `rake app:update`. The only exception is the code in
`config/application.rb` where we've excluded the engines that Rails 6.0
has added, since we don't use them.

There are a few changes in Active Storage which aren't compatible with
the code we were using until now.

Since the method to assign an attachment in ActiveStorage has changed
and is incompatible with the hack we used to allow assigning `nil`
attachments, and since ActiveStorage now supports assigning `nil`
attachments, we're removing the mentioned hack. This makes the
HasAttachment module redundant, so we're removing it.

Another change in ActiveStorage is files are no longer saved before
saving the `ActiveStorage::Attachment` record. This means we need to
manually upload the file when using direct uploads. We also have to
change the width and height validations we used for images; however,
doing so results in very complex code, and we currently have to write
that code for both images and site customization images.

So, for now, we're just uploading the file before checking its
dimensions. Not ideal, though. We might use active_storage_validations
in the future to fix this issue (when they support a proc/lambda, as
mentioned in commit 600f5c35e).

We also need to update a couple of tests due to a small change in
response headers. Now the content disposition returns something like:

```
attachment; filename="budget_investments.csv"; filename*=UTF-8''budget_investments.csv
```

So we're updating regular expression we use to check the filename.

Finally, Rails 6.0.1 changed the way the host is set in integration
tests [1] and so both `Capybara.app_host` and `Capybara.default_host`
were ignored when generating URLs in the relationable examples. The only
way I've found to make it work is to explicitely assign the host to the
integration session. Rails 6.1 will change this setup again, so maybe
then we can remove this hack.

[1] https://github.com/rails/rails/pull/36283/commits/fe00711e9
2022-08-24 14:33:02 +02:00
Javi Martín
2d693328dc Simplify checking map longitude and latitude
We were doing a `mappable.map_location` call in an `expect` which might
result in a database queries. Doing database queries in a test after the
process running the browser has started might result in exceptions while
running our test suite.
2022-06-02 19:25:14 +02:00
Javi Martín
4318b371b0 Add expectations after submit in attachments specs
There were cases where we clicked the button to submit the form and
immediately we visited a different page.

In the past, we've had similar code produce PG::ProtocolViolation errors
in similar situations. Since we've had these errors a few times in the
nested imageable specs, there's a chance they're related to the absence
of the expectation.

Although I'm not even remotely sure this will fix these issues, at least
we now follow the convention of making expectations after every request.

Note we're changing both the nested imageable and nested documentable
specs. Only the nested imageable would need to be changed because it's
the one where there's a `visit` inside the
`imageable_redirected_to_resource_show_or_navigate_to` method. I'm
changing both for consistency.
2022-06-02 19:20:40 +02:00
Javi Martín
b68aa67b1d Remove unnecessary "pending" comment
The test is already working with poll question answers (which are the
only ones using `has_many_images`) as well.
2022-04-07 15:34:10 +02:00
Javi Martín
e637bce3d8 Fix error messages for question answer images
Since we were creating a new answer in the form, we weren't getting the
errors associated to the answer the administrator was trying to create,
and so we were skipping the test.

Using the answer which contains the information about validation errors
fixes the issue and so we don't have to skip the tests.
2022-04-07 15:34:10 +02:00
Javi Martín
e49c32638d Use if instead of skip to skip tests
This way the tests won't appear as "pending" when running the test
suite, and so we get rid of a lot of noise in the test results. There
doesn't seem to be a way to call `skip` without the test being marked as
"pending".

Note that in the globalizable tests we need to build a factory before
deciding whether an atribute is required or not (particularly for the
milestone factory, since milestone attributes are required depending on
the presence of other attributes). This isn't possible before we're
inside the test, so we can't add an `if:` condition to the test. So
we're adding the condition inside the test instead. A minor
inconvenience of this method is the test still runs even when the
condition is `false`.
2022-04-07 15:34:10 +02:00
Javi Martín
d5867db2cf Remove unnecessary condition to skip tag list test
This file only has tests related to tags; if the model doesn't have
tags, we simply wouldn't include `it_behaves_as` in their tests instead
of including it and then skipping it.
2022-04-07 15:34:09 +02:00
Javi Martín
42b8729cd8 Remove duplicate map test
We were skipping the test, but there's an identical test right below it.
2022-04-07 15:34:09 +02:00
Senén Rodero Rodríguez
c086308b6f Call new common actions modules methods explicitly 2022-04-06 16:06:44 +02:00
Senén Rodero Rodríguez
46537cb708 Move nested_imageable helper methods to a new common actions module 2022-04-06 11:15:23 +02:00
Senén Rodero Rodríguez
071311be00 Move nested_documentable helper methods to a new common actions module 2022-04-06 11:15:23 +02:00