This one is a bit different than our usual scenario, since we create
three annotations and we only use two of them in the specs (because we
visit the path to that annotation). So there are probably better options
than the combination of `let!` and `before` I've chosen.
Having two questions, each of them with two comments, made the code hard
to follow.
Grouping the comments inside the block creating the questions makes it
easier to know which comment belongs to which question, even if the code
is still not 100% readable.
We also remove instance variables, which by the way used the same
variable name for two different things.
We couldn't declare them inside the block because they would be
considered local variables and its value would be lost when the block
was finished. So we were using instance variables instead.
However, with instance variables we don't get any warnings when we
misspell their names. We can avoid them by declaring the local variables
before the block starts.
I haven't found an elegant way to remove them, but since they were the
only three variables left out of 383 we used to have, I can live with
this low percentage of inelegant solutions.
We had four headings, some of them had investments, and some of them
didn't, and it was very hard to scan the code and check which investment
belongs to which heading.
Grouping the investments inside the block creating the heading makes
that task much easier, even if the code is still not 100% readable.
We also avoid unused variables which were there to keep the code
vertically algined.
There's a very common pattern in our test, where the setup only has two
lines:
variable = create(:something)
unused_variable = create(:something_else, something: variable)
In this case, since there's a blank line below these ones and then we'll
get to the body of the test, and the second variable is going to be
created based on the first variable, we can remove the useless
assignment and the readability is still OK.
Another option we almost unanimously discarded was:
variable = create(:something)
_unused_variable = create(:something_else, something: variable)
We don't use it anywhere else, either.
One more option we considered but found a bit too much for simple tests:
variable = create(:something) do |something|
create(:something_else, something: variable)
end
Then of course we could move the setup to `let` and `before` blocks, but
the tests could get over-structured really quickly.
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.
The test was hard to follow, and splitting the test in three it's easier
to read and doesn't create unused variables anymore. On the minus side,
now there's one extra request during the tests.
We were creating records with a title we manually set, so to be
consistent with the rest of the code, in the test we check the title is
present using a string literal.
This way we can also remove useless assignments while keeping the code
vertically aligned.
This way we write the tests from the user's point of view: users can see
(for example) a proposal with the title "Make everything awesome", but
they don't see a proposal with a certain ID.
There are probably dozens, if not hundreds, of places where we could
write tests this way. However, it's very hard to filter which ones are
safe to edit, since not many of them have an HTML class we can use in
the tests, and adding a class might generate conflicts with CSS styles.
So, for now, I'm only changing the ones allowing us to cleanly remove
useless assignements while maintaining the code vertically aligned.
Note we usually cannot make it simple because officer assignments are
usually assigned to both a poll and a booth, and on a certain date.
However, in the few cases where the booth nor the date don't matter, we
can make the code a bit easier to read.
While in theory we wouldn't need to use the `transient` nor the
`after(:create)` because there's already a `has_many :through`
association with followers, Factory Bot / ActiveRecord don't
automatically associate the followable, resulting in an invalid record
exception.
These factories were only used in one place and they even declared ID
attributes. Using the comment factory with the `commentable` attribute
does the same thing.
The `create_proposal_notification` method won't create a new
notification when a proposal has no supporters, so in the test
`notification3` was actually the same as `notification2`, related to
`proposal2`.
The attribute made sense before we changed it in commit ba1a6b4c. Since
then, all milestones have the same date, so the attribute doesn't affect
the test at all.
The valuation comment doesn't show up in the comment show action because
it's not a child of the parent comment. With a regular comment, the test
passes as well.
However, if we make the valuation comment a child of the parent comment,
it shows up both in the index and show actions. That's because the
method `root_descendants` in the `CommentTree` class doesn't filter
valuation comments. I'm not sure whether it's a bug or the intended
behaviour.
The group is automatically assigned when we assign the heading. The
budget isn't needed either, except for a special case related to the
reason to be rejected.
These tests are only checking which proposals are not included in the
recommendations, so we don't need to sort the included ones, just like
we don't use the cached votes up attribute in the tests preceeding these
ones.