In the form of creating a new investment was hiding the name of the
group if it had only one heading, but could be confusing to users if
there are, for example, five different groups of one heading.
The solution:
- If the budget has one group and one heading, the heading selector is
hidden.
- If the budget has one group and more than one heading, the group name
is hidden.
- If the budget has more than one group, the group name appears
regardless of the number of headings.
- Allow to define a link (text and url) on budget form for render on the budget
header.
- Improve styles
Co-authored-by: Senén Rodero Rodríguez <senenrodero@gmail.com>
When users created a budget and made a typo, they could use the link to
go back to edit a budget. However, after doing so, they were out of the
budget creation process.
So we're now letting users go back to edit the budget, fix any mistakes
they might have made, and then continue to groups.
So now there's no need to edit each phase individually to enable/disable
them.
We aren't doing the same thing in the form to edit a budget because we
aren't sure about possible usability issues. On one hand, in some tables
we automatically update records when we mark a checkbox, so users might
expect that. On the other hand, having a checkbox in the middle of a
form which updates the database automatically is counter-intuitive,
particularly when right below that table there are other checkboxes
which don't update the database until the form is submitted.
So, either way, chances are users would think they've updated the phases
(or kept them intact) while the opposite would be true.
In the form within the wizard to create a budget that problem isn't that
important because there aren't any other fields in the form and it's
pretty intuitive that what users do will have no effect until they press
the "Finish" button.
Co-Authored-By: Julian Nicolas Herrero <microweb10@gmail.com>
Note we're keeping this section's original design (which had one button
to add a new group which after being pressed was replaced by a button to
cancel) but we aren't using Foundation's `data-toggle` because there
were a couple of usability and accessibility issues.
First, using `data-toggle` multiple times and applying it to multiple
elements led to the "cancel" button not being available after submitting
a form with errors. Fixing it made the code more complicated.
Second, the "Add new group" button always had the `aria-expanded`
attribute set to "true", so my screen reader was announcing the button
as expanded even when it wasn't. I didn't manage to fix it using
`data-toggle`.
Finally, after pressing either the "Add new group" and "Cancel" buttons,
the keyboard focus was lost since the elements disappeared.
So we're simplifying the HTML and adding some custom JavaScript to be
able to handle the focus and manually setting the `aria-expanded`
attribute.
Co-Authored-By: Javi Martín <javim@elretirao.net>
Co-Authored-By: Julian Herrero <microweb10@gmail.com>
We don't allow deleting a budget with associated investments. However,
we allow deleting a budget with associated administrators and valuators.
This results in a foreign key violation error:
PG::ForeignKeyViolation: ERROR: update or delete on table "budgets"
violates foreign key constraint "fk_rails_c847a52b1d" on table
"budget_administrators"
Using the `dependent: :destroy` option when defining the relationship,
we remove the association records when removing the budget.
As a bonus, we reduce the number of Rubocop offenses regarding the
`Rails/HasManyOrHasOneDependent` rule. Only 72 to go! :)
When configuring phases in a process, we were validating the start date
or the end date is present, the other date is present too.
However, in other parts of the application we were checking whether a
phase is enabled and then assumed its dates were present if the phase
was enabled. However, we weren't validating this behavior, so it was
possible to enable a phase and leaving its dates blank, causing the
application to crash.
So, as suggested by Alberto, we're changing the validation rule so
phase dates are mandatory when a phase is enabled.
With this rule, the old validation rules are not necessary. I've
considered leaving them in order to avoid database inconsistencies.
However, I realized records having a disabled phase with its start and
end dates have always been valid. This means applications checking for
the presence of these dates instead of checking whether the phase is
enabled have never worked properly.
We don't have to change the logic anywhere else because as mentioned we
were already checking phases are enabled before using their dates.
Before commit 28caabecd, it was clear which budgets were in draft mode
because their phase was "drafting".
Now the phase isn't "drafting" anymore, so we have to make it clear
somehow that the budget is a draft.
I'm using styles similar to the ones we added in commit 2f636eaf7 for
completed budgets but at the same time making them slightly different so
it's easy to differenciate completed and drafting budgets.
Particularly the line with `within "tr", text: "Finished budget" do` is
now easier to read.
This way we avoid a potential pitfall. Imagine that the factory which
creates a finished budget generated a budget with the name "COMPLETED
Budget 1". Then the test:
```
within "#budget_#{finished_budget.id}" do
expect(page).to have_content("COMPLETED")
end
```
Would pass even if we didn't add the text "COMPLETED" anywhere else,
because it would be included in the name of the budget.
The link to edit the process is already present before clicking the
"All" link, which meant the test failed sometimes because Capybara might
try to click on the "Edit" link at the same time the page is changing
due to the click on the "All" link".
Due to this issue, this test has failed at least one in our CI [1].
[1] https://github.com/consul/consul/runs/2324773853
We were checking content which was already present/absent before making
a certain request, so the expectations were not checking the request had
already finished. Our intention here is to check the page contents after
the request has finished.
We want to make sure the request is finished after clicking a button and
before visiting a different page, so we need to check the page has
changed.
Usually this shouldn't be a problem because most of our forms are sent
with regular HTTP requests instead of AJAX ones, so the `visit` method
wouldn't be called before the request is finished.
However, we're experiencing problems with certain version of
Chromedriver, and in general it's a good practice because we might send
forms using AJAX/Turbolinks in the future.
When we create a record like a debate or an event and we check the page
content, we want to make sure that today's date is present, since it's
the date where the record is supposed to have been created.
This way we avoid querying the database after the browser has been
started.
It's strange to create records without assigning them to a variable and
then query the database to fetch the very same records. Assigning them
to a variable makes the tests easier to understand.
Besides, this way we avoid querying the database after the browser has
started.
Users don't care about database content; they care about what they see
on the screen.
Writing tests this way we also avoid potencial database inconsistencies
due to accessing the database after starting the browser.
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.
System tests are about user experience, so instead of checking the slug
has been updated in the database, we check whether the page can be
accessed using the slug.
Note the budget group test is a bit different because the name of the
group isn't present in the budget group page.
We were checking the database, but users don't care about what's inside
the database; they care about what happens when they visit the page of a
record they've just restored.
This way we also avoid data inconsistency due to the process running the
test accessing the database after the process running the browser has
started.
These tests check what happens from the user's point of view. For
instance, we check that after disabling recommendations, they are not
shown. What happens in the database is not related to the user
experience.
Furthermore, checking the database after the browser has started is
proving to be a major source for inconsistent data in specs.
Changing the database after the process running the browser has started
is proving to be one of the reasons tests are failing sometimes, so
we're reducing the number of times were that happens. In this case, we
were changing a setting.
We were adding a `visit` in a `before` block but then we started the
search tests with another `visit`.
We also created records in the database in between, which increased the
risk of database inconsistency since the process running the browser had
already been started.
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.
Content like lowercase letters with `text-transform: uppercase` or
spaces after elements with `display: block` or "You're on page:" are not
seen that way by users with a browser supporting CSS.
So we're testing what most users actually experience.