After upgrading to Turbolinks 5, redirects are followed on AJAX
requests, so we were accidentally redirecting the user after they mark
an investment as visible to valuators.
There was already a system spec failing due to this issue ("Admin budget
investments Mark as visible to valuators Keeps the valuation tags");
however, it only failed in some cases, so we're adding additional tests.
Ideally we would write a system test to check what happens when users
click on the checkbox. However, from the user's point of view, nothing
happens when they do so, and so testing it is hard. There's a usability
issue here (no feedback is provided to the user indicating the
investment is actually updated when they click on the checkbox and so
they might look for a button to send the form), which also results in a
feature which is difficult to test.
So we're writing two tests instead: one checking the controller does not
redirect when using a JSON request, and one checking the form submits a
JSON request.
I've chosen JSON over AJAX because usually requests to the update action
come from the edit form, and we might change the edit form to send an
AJAX request (and, in this case, Turbolinks would handle the redirect as
mentioned above).
Another option would be to send an AJAX request to a different action,
like it's done for the toggle selection action. I don't have a strong
preference for either option, so I'm leaving it the way it was. At some
point we should change the user interface, though; right now in the same
row there are two actions doing basically the same thing (toggling
valuator visibility and toggling selection) but with very different user
interfaces (one is a checkbox and the other one a link changing its
style depending on the state), resulting in a confusing interface.
We were getting a deprecation message in Rails 5.2:
> The success? predicate is deprecated and will be removed in Rails 6.0.
> Please use successful? as provided by Rack::Response::Helpers.
We were getting a deprecation message in Rails 5.2:
The missing? predicate is deprecated and will be removed in Rails 6.0.
Please use not_found? as provided by Rack::Response::Helpers
The method `available_locales` in
`RemoteTranslations::Microsoft::AvailableLocales` needs to execute a
request to an external server in order to work, meaning it will fail if
the machine its executed on doesn't have an internet connection.
So we're stubbing the method in the tests using it.
Legislation::Proposal is not Globalize model but use CommentableActions and try
detect remote translations. Add new condition to discard Non Globalize models.
This fix is necessary since the following commit was included: c1f3a4ad.
In theory it's possible to add a `host` parameter to a URL, and we could
end up redirecting to that host if we just redirect using query
parameters.
Generating the path using `url_for` with `only_path` solves the issue.
Note in the tests I'm using the `get` method because the `patch` method
wouldn't send query parameters. This doesn't mean the action can be
accessed through GET requests, since controller tests don't check route
verbs. Using feature specs doesn't seem to work because `controller` and
`host` parameters are filtered automatically in feature specs.
Also note I'm not testing every hidden/moderation controller because
they basically use the same code.
These actions are never called with query parameters in our application,
so there's no need to use these parameters in a redirect.
Note in the test I'm using the `get` method because the `patch` method
wouldn't send query parameters. This doesn't mean the action can be
accessed through GET requests, since controller tests don't check route
verbs.
This method is ambiguous. Sometimes we use it to set invalid data in
tests (which can usually be done with `update_column`), and other times
we use it instead of `update!`.
I'm removing it because, even if sometimes it could make sense to use
it, it's too similar to `update_attributes` (which is an alias for
`update` and runs validations), making it confusing.
However, there's one case where we're still using it: in the
ActsAsParanoidAliases module, we need to invoke the callbacks, which
`update_column` skips, but tests related to translations fail if we use
`update!`. The reason for this is the tests check what happens if we
restore a record without restoring its translations. But that will make
the record invalid, since there's a validation rule checking it has at
least one translation.
I'm not blacklisting any other method which skips validations because we
know they skip validations and use them anyway (hopefully with care).
We were very inconsistent regarding these rules.
Personally I prefer no empty lines around blocks, clases, etc... as
recommended by the Ruby style guide [1], and they're the default values
in rubocop, so those are the settings I'm applying.
The exception is the `private` access modifier, since we were leaving
empty lines around it most of the time. That's the default rubocop rule
as well. Personally I don't have a strong preference about this one.
[1] https://rubystyle.guide/#empty-lines-around-bodies
These variables can be considered a block, and so removing them doesn't
make the test much harder to undestand.
Sometimes these variables formed the setup, sometimes they formed an
isolated part of the setup, and sometimes they were the part of the test
that made the test different from other tests.
Assigning a variable to each budget we declare results in useless
assignments. We could just delete the three useless assignments and
leave the fourth one, but I find the code easier to read if we use the
name of the budgets to differenciate between them. This way we also keep
the code vertically aligned.
The instance variable was being evaluated to `nil`, and the budget was
automatically created by the `set_denormalized_ids` method in the budget
investment class.
Settings are stored in the database, and so any changes to the settings
done during the tests are automatically rolled back between one test and
the next one.
There were also a few places where we weren't using an `after` block but
changing the setting at the end of the test.
- Create RemoteTranslations Controller to receive resources without
translations and create RemoteTranslation instances when theirs
translations are not enqueued.
- Create remote_translation_enqueued? class method on RemoteTranslation
model to check if exists same remote translations without errors
pending to translate.
- Create concern to reuse the logic of detection of non-existent
translations in Controllers.
- Add detect_remote_translation method:
* This method will be called from controllers to recover resources
without translation.
* Receive arrays of resources.
* Return an array with hashes of remote_translations values for
every resources that have not translations.
* This array will be the param that will be sent from view to
RemoteTranslationController for create remote translations instances.
Also fix broken spec after removing translatable attributes from
strong_parameters definition. Now we need to send these attributes
as nested translations attributes.
Use activerecord.yml title attribute label so form helper could load it
from default location.
DEPRECATION WARNING: Using positional arguments in functional tests
has been deprecated, in favor of keyword arguments, and will be
removed in Rails 5.1.
Deprecated style:
get :show, { id: 1 }, nil, { notice: "Flash message" }
New keyword style:
get :show, params: { id: 1 }, flash: { notice: "Flash message" }
When requesting files like `/hackattempt.js`, the pages controller was
responding with 404 status code.
However, since the request was considered a JavaScript request (because
of the `.js` extension), the response was also considered to be a
JavaScript one, and since the request wasn't an AJAX request, our
protection from forgery was preventing a potential security issue by
raising an InvalidCrossOriginRequest exception.
By setting HTML as content type, we correctly respond with a 404 status
code.
More info:
https://die-antwort.eu/techblog/2018-08-avoid-invalid-cross-origin-request-with-catch-all-route/
We were raising a `CanCan::AcessDenied` and were getting a 500 Internal
Server Error.
I've chosen to do the same thing we do in the ApplicationController.
There are other options to handle this request, like redirecting to the
login page or returning a 401 Unauthorized HTTP status.
Metrics/LineLength: Line is too long.
RSpec/InstanceVariable: Use let instead of an instance variable.
Layout/TrailingBlankLines: Final newline missing.
Style/StringLiterals: Prefer double-quoted strings.