Note we're using the in-favor HTML class instead of the in_favor class
so we're consistent with our conventions for HTML classes and because we
use the in-favor class in similar places.
Also note the styles of the legislation process annotations/comments
buttons is now similar to the styles in the other sections. Previously,
the colors didn't have enough contrast and there was a very strange
margin between the "thumbs up" icon and the number of people agreeing
(that margin wasn't present between the "thumbs down" icon and the
number of people disagreeing).
In the past, whenever we hid users, we also hid their comments.
However, we've now implemented an action to hide users without hiding
their comments. In this case, we still want to show the comment, but we
weren't doing so.
Note that in proposal notifications we're writing the call to
render the component in the same line as the <div class="reply">
definition in order to be able to use the `:empty` selector when the
component renders nothing. No browser matches whitespace with the
`:empty` selector, so we can't add newline characters inside the tag. A
more elegant solution would be extracting the proposal notification
actions to a component and only rendering it if the moderation actions
component is rendered.
It was a bit frustrating to click on one of the order elements or the
link to the next page and having to scroll down again until reaching the
comments.
We use order links in many places in the web. However, in the comments
section and the list of community topics, we were displaying a
`<select>` element, and changing the location when users select an
option.
This has several disadvantages.
First, and most important, it's terrible for keyboard users. `<select>`
fields allow using the arrow keys to navigate through their options, and
typing a letter will select the first option starting with that letter.
This will trigger the "change" event and so users will navigate through
a new page while they were probably just checking the available options
[1]. For these reasons, WCAG Success Criterion 3.2.2 [2] states:
> Changing the setting of any user interface component does not
> automatically cause a change of context unless the user has been
> advised of the behavior before using the component.
Second, the form didn't have a submit button. This might confuse screen
reader users, who might not know how that form is supposed to be
submitted.
Finally, dropdowns have usability issues of their own [3], particularly
on mobile phones [4]
The easiest solution is to use the same links we generally use to allow
users select an order, so using them here we make the user experience
more consistent. They offer one disadvantage, though; on small screens
and certain languages, these links might take too much space and not
look that great. This issue affects pretty much every place where we use
order or filter links, so we might revisit it in the future.
Note we're moving the links to order comments after the form to add a
new comment. In my opinion, having an element such as a form to add a
new comment between the element to select the desired order of the
comments and the comments themselves is a bit confusing.
[1] https://webaim.org/techniques/forms/controls#javascript
[2] https://www.w3.org/WAI/WCAG21/Understanding/on-input.html
[3] https://www.youtube.com/watch?v=CUkMCQR4TpY
[4] https://www.lukew.com/ff/entry.asp?1950
GitHub Actions is failing to finish sometimes. Usually that happens due
to concurrency issues when the process running the test accesses the
database after the process running the browser has started.
Since these files were the ones being tested the times we had this
issue, these are the ones we are fixing right now, although there are
probably other places where we might have this issue in the future.
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.
While running our test suite, we were getting an exception sometimes:
```
Proposal Notifications In-app notifications from the proposal's author Followers should receive a notification
Failure/Error: notification_for_user2 = Notification.find_by(user: user2)
ActiveRecord::StatementInvalid:
PG::ProtocolViolation: ERROR: bind message supplies 0 parameters, but prepared statement "" requires 2
: SELECT "notifications".* FROM "notifications" WHERE "notifications"."user_id" = $1 LIMIT $2
# ./spec/system/proposal_notifications_spec.rb:268
```
Sometimes we were getting a similar exception in a different test:
```
Commenting legislation questions Merged comment threads Reply on a multiple annotation thread and display it in the single annotation thread
And sometimes we were getting a different one:
Failure/Error: annotation.comments.roots.sort_by_most_voted.limit(Legislation::Annotation::COMMENTS_PAGE_SIZE).each do |comment|
ActionView::Template::Error:
PG::ProtocolViolation: ERROR: bind message supplies 0 parameters, but prepared statement "" requires 3
```
My best (wild) guess is these exceptions might take place because the
test is accessing the database and at the same time the browser
(chromedriver) process is accessing the database, with code like:
```
find(".icon-notification").click
notification_for_user2 = Notification.find_by(user: user2)
```
Or:
```
first(:css, ".annotator-hl").click
(...)
comment = annotation1.comments.first
click_link "Reply"
```
This behavior happened sometimes while using transactional fixtures and
a shared database connection with feature specs (before system specs
were introduced in Rails 5.1) when some queries were triggered from the
test after the browser process was started.
So we're avoiding the situation by writing the tests from the user's
point of view. This is just an attempt at fixing the issue; I don't know
whether these changes will fix it since I've only seen this exception on
Github Actions (never on my machine). Worst case scenario, we're still
improving the tests legibililty.
We were repeating the same code over and over (with a few variants) to
setup tests which require an administrator. We can use a tag and
simplify the code.
By default, Capybara only finds visible elements, so adding the
`visible: true` option is usually redundant.
We were using it sometimes to make it an obvious contrast with another
test using `visible: false`. However, from the user's perspective, we
don't care whether the element has been removed from the DOM or has been
hidden, so we can just test that the visible selector can't be found.
Besides, using `visible: false` means the test will also pass if the
element is present and visible. However, we want the test to fail if the
element is visible. That's why a couple of JavaScript-dependant tests
were passing even when JavaScript was disabled.
We weren't using `foundation()` in these cases, so after flagging a
debate or a comment, we had to reload the page before we could unflag
it.
We're also adding a test for the fix in commit ea85059d. This test shows
it's necessary to filter the elements with JavaSctipt using `first()` if
we want the same code to work with comments.
Co-Authored-By: taitus <sebastia.roig@gmail.com>
When a user replies to a comment whose responses was hidden at the
moment of reply form submission and although the reply were correctly
added to the DOM it was hidden because was added to a collapsed list.
This solution is about showing all responses of parent comment after adding
the new comment to the DOM so the user can see new reply into the screen.
(This is not applicable to root comments which cannot be collapsed)
Extract the needed portion of code to a new partial to be able to update
only the elements needed when a new comment is added keeping UI properly
updated.
We were using a <ul> tag for a single comment, where the first element
of the list was the comment itself and the second element was the list
of replies.
IMHO it makes more sense to have a list of all comments, where every
element is a comment and inside it there's a list of replies.
We're also rendering the list even if it has no children so it's easier
to add comments through JavaScript. Then we use the :empty CSS selector
to hide the list if it's empty. However, since ERB adds whitespace if we
structure our code the usual way and current browsers don't recognize
elements with whitespace as empty, we have to use the `tag` helper so no
whitespace is added.
Tests are also a bit easier to read, even though we need to use the
`text:` option to find links because otherwise the text in the hidden
`<span>` tags will cause `click_link` to miss the link we want to click.
Here's an explanation by one of Capybara's authors:
https://github.com/teamcapybara/capybara/issues/2347#issuecomment-626373440
We were calling initialize_modules after every ajax call only to apply the
application javascript to new elements added though ajax calls, this is not
always needed because some ajax calls do not add new elements to the user
interface so there is no new elements to initialize. This technique was working
fine in most cases but was causing different kind of problems at some pages where
some elements where being unnecessarily reinitiliazed causing the execution of the
element associated scripts as many times as the element was initialized. This fix
should relief a little bit of work to users browsers.
After this change we had to fix some pieces of javascript:
Regarding LegistationAnnotatable module, since we are not re-initializing Annotator
app we cannot destroy it so now we only need to insert the new annotation into annotator
interface to keep it properly updated.
Regarding Comments module, we do not need anymore the initialization check because this
code only will be fired once now we do not launch application initialization after ajax
calls. Also, when a new comment is created its added to the DOM through AJAX and include
some elements that needs javascript initialization to work. By using
"Delegated event handlers" [1] new comments will be initialized automatically when added.
[1] https://api.jquery.com/on/#direct-and-delegated-events