Commit Graph

5915 Commits

Author SHA1 Message Date
taitus
1e6901ec34 Add render method to notification item component 2024-11-06 11:07:00 +01:00
CoslaJohn
424cedc0c8 Restrict access to admin functions by IP
There are many possible ways to implement this feature:

* Adding a custom middleware
* Using rack-attack with a blocklist
* Using routes constraints

We're choosing to use a controller concern with a redirect because it's
what we do to handle unauthorized cancancan exceptions.
2024-10-30 15:59:50 +01:00
Javi Martín
07202fea10 Add and apply Style/RedundantBegin rubocop rule
We're about to add code which might fall into the `RedundantBegin`
category, so we're adding the rule in order to prevent that.
2024-10-30 15:57:44 +01:00
Javi Martín
9f38ed6bae Extract method to stub secrets in tests 2024-10-30 14:50:41 +01:00
Javi Martín
3931b43b87 Move omniauth form partial to a component
This way we simplify the view a little bit and replace some slow system
tests with faster component tests.
2024-10-28 21:23:56 +01:00
Javi Martín
fc5103881d Use a switch to toggle visibility to valuators
Using a checkbox wasn't very intuitive because checkboxes are
checked/unchecked when clicked on even if there's an error in the
request. Usually, when checkboxes appear on a form, they don't send any
information to the server unless we click a button to send the form.

So we're using a switch instead of a checkbox, like we did to
enable/disable phases in commit 46d8bc4f0.

Note that, since we've got two switches that match the default
`dom_id(record) .toggle-switch` selector, we need to find a way to
differentiate them. We're adding the `form_class` option for that.

Also note that we're now using a separate action and removing the
JavaScript in the `update` action which assumed that AJAX requests to
this action were always related to updating the `visible_to_valuators`
attribute.
2024-10-28 13:41:55 +01:00
Javi Martín
76b0971b4a Simplify mark as visible to valuators tests
We were performing 3 requests in order to refresh the page and check the
content was still there. We can use `refresh` instead.

We're also reusing the `investment1` variable in every test, instead of
redifining it in one of them.
2024-10-28 13:41:55 +01:00
Javi Martín
00d7299e9e Extract component for visible to valuators toggling 2024-10-28 13:41:55 +01:00
Javi Martín
958c13061f Fix duplicate HTML visible to valuator IDs 2024-10-28 13:41:55 +01:00
Javi Martín
173b1bb07c Make it possible to select investments without JavaScript 2024-10-28 13:41:55 +01:00
Javi Martín
54a48d63e1 Use separate actions to select/deselect investments
This is consistent to what we usually do. Also, we're applying the same
criteria mentioned in commit 72704d776:

> We're also making these actions idempotent, so sending many requests
> to the same action will get the same result, which wasn't the case
> with the `toggle` action. Although it's a low probability case, the
> `toggle` action could result in [selecting an investment] when trying
> to [deselect] it if someone else has [deselected it] it between the
> time the page loaded and the time the admin clicked on the
> "[Selected]" button.
2024-10-28 13:41:50 +01:00
Javi Martín
463112c2ea Use a switch to toggle investment selection
Just like it happened with proposals, the button to select/deselect an
investment wasn't very intuitive; for example, it wasn't obvious that
pressing a button saying "selected" would deselect the investment.

So we're using a switch control, like we do to enable/disable features
since commit fabe97e50.

Note that we're making the text of the switch smaller than in other
places because the text in the investments table it is also smaller
(we're using `font-size: inherit` for that purpose). That made the
button look weird because we were using rems instead of ems for the
width of the button, so we're adjusting that as well.

Also note we're changing the width of the switch to `6em` instead of
`6.25em` (which would be 100px if 1em is 16px). We're doing so because
we used 100 for the minimum width because it's a round number, so
now we're using another round number.
2024-10-28 13:40:27 +01:00
Javi Martín
1b46afc95c Check different content in select investments test
Since we were checking something that was already there, if the form
were submitted using an AJAX request (which is the default with Turbo,
although we don't use it yet), there would be a chance that the request
didn't finish before the test does, leading to potential failures in the
next test.

This way we're also checking that the "Filter" button actually does
something when selecting the "Selected" filter.
2024-10-28 13:39:49 +01:00
Javi Martín
9e5566cee4 Use a button to toggle investment selection
As mentioned in commit 5311daadf, using buttons for non-GET requests has
several advantages over using links.
2024-10-28 13:39:49 +01:00
Javi Martín
cf0d8258ed Use abilities to allow toggling investment selection
We were checking it in the view, meaning that it was possible to toggle
the selection by sending a custom request even when the investment
wasn't feasible.
2024-10-28 13:39:49 +01:00
Javi Martín
fde24870bc Extract component for investment toggle selection
This way it'll be easier to refactor it.
2024-10-28 13:31:34 +01:00
Javi Martín
b9c3e75930 Fix duplicate HTML IDs in investments selection
Since this cell is shown once per row, there were multiple rows with the
same HTML ID on the page.
2024-10-25 17:24:32 +02:00
Javi Martín
bb42809168 Move investment partial to a component
This way we'll be able to simplify it a little bit.

Note that the original partial didn't include the whole row and only
the cells. Since, most of the time, we include the whole row in
partials, we're slightly modifying the component.
2024-10-25 17:19:42 +02:00
Javi Martín
2acaa14705 Make it possible to select proposals without JavaScript
This way, when JavaScript hasn't loaded (for whatever reason),
administrators can still use this functionality.
2024-10-25 17:12:47 +02:00
Javi Martín
fec44c146c Use a switch to toggle proposal selection
The button to select/deselect a proposal wasn't very intuitive; for
example, it wasn't obvious that pressing a button saying "selected"
would deselect the proposal.

So we're using a switch control, like we do to enable/disable features
since commit fabe97e50.
2024-10-25 17:12:44 +02:00
Javi Martín
b127bd2f51 Use a button to toggle proposal selection
As mentioned in commit 5311daadf, using buttons for non-GET requests has
several advantages over using links.
2024-10-25 17:10:14 +02:00
Javi Martín
9da582cb91 Wait for suggestions in multitenancy and document tests
In commit f638e5017 we introduced some methods to avoid race conditions
in tests that created debates, proposals or investments.

However, since we don't have a way to effectively make sure we use these
methods in new code, we forgot to do so when adding tests in commits
c483c6036 and 84b88c0ec.

So we're using them now.

There's a chance that this is what was causing multitenancy tests to
fail sometimes; if we don't wait for the request to get the suggestions
to finish, the application might still be dealing with this request when
we make another request to a different subdomain, or when the test has
finished and the tenant has already been deleted.

On my machine, the test "Creating content in one tenant doesn't affect
other tenants" failed about 5% of the time without these changes, and I
haven't been able to reproduce this failure after applying them. Having
said that, it's possible that this is a coincidence and that this test
will fail for a different reason in the future (like `login_as` not
working properly with subdomains).
2024-10-23 21:04:06 +02:00
Javi Martín
27a4dc1471 Check page content in ballots specs
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.
2024-10-15 15:55:15 +02:00
taitus
93189d3ecd Allow use embedded_video_component in legislation proposals
Since the PR "Do not use third-party cookies in embedded videos #5548", the logic from
"embed_videos_helper" was extracted to the "embedded_video_component" and the
"videoable" model concern.

However, during this refactor, the "regex" method, which uses record.class:: to handle
video embeds, was left inaccessible for Legislation Proposals.

This commit fixes the issue by including the concern in the Legislation Proposal model.
2024-10-14 15:24:29 +02:00
Javi Martín
e2d9d0f2b4 Fix default dashboard actions factories
We had a trait called `:admin_request` for actions that are requests to
administrators, but the default factories were also requests to
administrators.

The tests checking that the "Request" button is not present, which
shouldn't pass with the wrong default factories, were passing by
coincidence. The issue was that we weren't checking whether that the
request had finished before checking that the "Request" button wasn't
present. That meant that we were checking that the "Request" button
wasn't there right at the moment we pressed the link, before the request
was finished.

So we're now checking that the request is finished before checking that
the button isn't there.

On the other hand, the tests checking for the "Request resource" link
being present were checking a behavior that's no longer there since
commit 9d85b3935, when we changed the conditions affecting that link.
2024-10-11 15:05:24 +02:00
Sebastia
4382861cd5 Merge pull request #5717 from consuldemocracy/dependabot/bundler/rubocop-rspec-3.1.0
Bump rubocop-rspec from 3.0.3 to 3.1.0
2024-10-10 09:23:41 +02:00
taitus
9300fe5a58 Add an apply RSpec/StringAsInstanceDoubleConstant rubocop rule
This rule was added in 3.1.0. Applying it allows you to start defining a way of doing
this in the project, helping to maintain consistency.
2024-10-08 18:43:07 +02:00
Javi Martín
af0911a8d2 Fix warning in hidden proposals spec
We were checking the proposal video URL, but its value was `nil` since
commit bedcb5bca2. This resulted in a warning:

```
Checking for expected text of nil is confusing and/or pointless since it
will always match. Please specify a string or regexp instead.
spec/system/admin/hidden_proposals_spec.rb:14
```
2024-10-07 16:37:13 +02:00
Javi Martín
5f80a75161 Limit GraphQL queries complexity once again
We accidentally removed the code for maximum complexity in commit
c984e666f. As mentioned in the documentation:

> The main risk factor is multiple collections of resources being
> requested in the same query.

We reject these requests by limiting the complexity.

The `max_complexity` option depends on the page size being set. Without
it, we get an error:

```
Can't calculate complexity for User.public_debates, no `first:`,
`last:`, `max_page_size` or `default_max_page_size`
```

So we're also adding a default max page size.

Note that the documentation mentioned that the default page size was 25.
However, before commit c984e666f, we were using a page size of 50 in
some cases. We're going with the one mentioned in the documentation
since we don't fully understand the old code.
2024-09-30 12:06:42 +02:00
Javi Martín
90bb7484a5 Add max_depth limit to GraphQL queries once again
We accidentally removed this code in commit c984e666f. As mentioned in
our GraphQL documentation, limiting the depth of the queries helps
against DoS attacks.
2024-09-30 11:52:39 +02:00
Javi Martín
b01364d26b Make sure we only return public records in the API
When returning a collection of records in the API, we were making sure
we only returned public ones. However, when returning individual
records, we were not checking that.

In practice, this wasn't a big issue, since most `public_for_api`
methods return all records, but it could affect Consul Democracy
installations which might have customized their `public_for_api` method.
The only exception was the `budget` method, since it was returning
budgets that were still in drafting.
2024-09-30 11:35:15 +02:00
Javi Martín
ba558b1490 Reorganize graphql specs
Back in commit c984e666f, we reorganized the code related to the GraphQL
API, but we didn't reorganize the tests.

So we're doing it now, since we're going to fix a potential issue and
add some tests for it.
2024-09-30 11:35:15 +02:00
Javi Martín
b1b963f90a Fix public_for_api association tests
These tests were always passing because they were stubbing the response
of the same method they were testing. For example, we were testing the
result of `Comment.public_for_api` and stubbing it at the same time.

So we're now stubbing the result of the associations; for example, in
order to test `Comment.public_for_api`, we're stubbing the response of
`Debate.public_for_api`. Now the tests fail if, for instance, the
implementation of `Comment.public_for_api` returns all comments.
2024-09-30 11:35:15 +02:00
cyrillefr
18323a36c3 Add new GraphQL type for milestones
- added the milestone type to be displayed with investments
- the corresponding spec
2024-09-30 11:14:01 +02:00
cyrillefr
5ec6337d47 Add new GraphQL types for budget investments
- added 2 new types
- modified the models to get data through graphQL
- modified the corresponding spec
- also testing that hidden comments do not show up
- modified comments specs bc now it returns comments on budget
  investments
2024-09-30 11:14:01 +02: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
ec0bcd4277 Use a more realistic size for small window tests
The resolution of most devices is at least 640 pixels in at least one of
their dimensions. Since we need the width to be smaller than 640 pixels,
having a height of 479px wasn't realistic.

Doing so caused the tests checking the sticky "support proposal" tests
to fail because on 480px-high devices the sticky message covers the
whole screen.

This is a usability issue, but since I'm not sure how many people use
such a small window when browsing the web, for now I'm simply changing
the tests.

We're changing the width to 320px since it's the width required by the
Web Content Accessibility Guidelines 2.2. Quoting these guidelines [1]:

> Content can be presented without loss of information or functionality,
> and without requiring scrolling in two dimensions for:

> * Vertical scrolling content at a width equivalent to 320 CSS pixels;
> * Horizontal scrolling content at a height equivalent to 256 CSS
>   pixels.

Note that, using a height of 256px, the sticky message would make the
application unusable, though. IMHO we'll have to get rid of the sticky
message sooner or later.
2024-09-17 15:09:21 +02:00
Javi Martín
bedcb5bca2 Don't include videos in proposal factories
Since August 29, probably due to a change in the browser used by GitHub
Actions (since branches whose code we didn't change were suddenly
affected that day), many tests related to proposals are failing on
GitHub Actions. Although every time the test suite is run different
tests fail, on each run at least half a dozen tests fail.

Most tests have one thing in common: they click on an element on the
`proposals#show` page, and the click isn't done correctly.

One possible explanation is that the video included on the page causes
the page to scroll at the exact same time that Capybara is clicking on a
link, which results in a misclick.

I haven't been able to reproduce the issue on my machine, so I'm not
sure whether giving the video element a fixed height using CSS (so the
page doesn't scroll when the iframe is loaded) could solve the issue.
But, after using proposals without videos in the tests (except the tests
testing the videos themselves), all these tests are passing in the test
suite.

So, for now, we're simply removing the videos in the proposal factories.

Note this issue wasn't caused by the "no cookie" changes done in commit
ee64efe659, since running the tests in Cosul Democracy 2.1.1 (which
didn't contain those changes) also fails on GitHub Actions.
2024-09-17 15:09:17 +02:00
Javi Martín
00c97ad587 Split polls date range validation
It was a bit strange to leave the end date blank and have a message
associated with the start date, so we're using presence validations
instead.

For the range validation, we're using the comparison validator included
in Rails 7.0.
2024-07-22 18:35:35 +02:00
Javi Martín
a56e1bf3cf Simplify strategy to insert records in tests
Since Rails 7.0, the `insert` method automatically generates timestamps.
2024-07-22 17:50:40 +02:00
Javi Martín
5dbd2ede14 Delete duplicate records in different languages 2024-06-27 15:22:02 +02:00
Javi Martín
58f88d6805 Add task to add option_id to existing answers
Note: to avoid confusion, "answer" will mean a row in the poll_answers
table and "choice" will mean whatever is in the "answer" column of that
table (I'm applying the same convention in the code of the task).

In order make this task perform reasonably on installations with
millions of votes, we're using `update_all` to update all the answers
with the same choice at once. In order to do that, we first need to
check the existing choices and what are the possible option_ids for
those choices.

Note that, in order for this task to work, we need to remote the
duplicate answers first. Otherwise, we will run into a RecordNotUnique
exception when trying to add the same option_id to two duplicate
answers.

So we're making this task depend on the one that removes duplicate
answers. That means we no longer need to specify the task to remove
duplicate answers in the release tasks; it will automatically be
executed when running the task to add an option_id.
2024-06-27 15:05:56 +02:00
Javi Martín
d2ec73e92c Add task to delete duplicate poll answers 2024-06-26 20:20:24 +02:00
Javi Martín
81abbd5021 Remove unused block variable in poll ABC factory 2024-06-26 20:20:24 +02:00
Javi Martín
5033691666 Avoid duplicate records in poll answers
Until now, we've stored the text of the answer somebody replied to. The
idea was to handle the scenarios where the user voters for an option but
then that option is deleted and restored, or the texts of the options
are accidentally edited and so the option "Yes" is now "Now" and vice
versa.

However, since commit 3a6e99cb8, options can no longer be edited once
the poll starts, so there's no risk of the option changing once somebody
has voted.

This means we can now store the ID of the option that has been voted.
That'll also help us deal with a bug introduced int 673ec075e, since
answers in different locales are not counted as the same answer. Note we
aren't dealing with this bug right now.

We're still keeping (and storing) the answer as well. There are two
reasons for that.

First, we might add an "open answer" type of questions in the future and
use this column for it.

Second, we've still got logic depending on the answer, and we need to be
careful when changing it because there are existing installations where
the answer is present but the option_id is not.

Note that we're using `dependent: nullify`. The reasoning is that, since
we're storing both the option_id and the answer text, we can still use
the answer text when removing the option. In practice, this won't matter
much, though, since we've got a validation rule that makes it impossible
to destroy options once the poll has started.

Also note we're still allowing duplicate records when the option is nil.
We need to do that until we've removed every duplicate record in the
database.
2024-06-26 20:20:24 +02:00
Javi Martín
9fbd7eec8f Remove obsolete routes for poll questions
The routes for poll questions were accidentally deleted in commit
5bb831e959 when deleting the `:show` action, and restored in commit
9871503c5e. However, the deleted code was:

```
resources :questions, only: [:show], controller: 'polls/questions' (...)
```

While the restored code was:

```
resources :questions, controller: 'polls/questions' (...)
```

Meaning we forgot to add the `only: []` option when restoring the
routes.

We also forgot to remove the `before_action` code when deleting the
`:show` action, so we're removing it now.
2024-06-26 20:20:24 +02:00