I fixed an issue with RSpec helpers provided by the very useful YusekeIwaki/playwright-ruby-client gem.
Rather than diving into the technical issues here, I wanted to write this to document my process working through the fix. The technical details of the fix are in my PR.
A coworker of mine encountered this bug when expecting that an element gets removed from the page via expect(element).not_to be_visible
:
Failures:
1) Playwright::LocatorAssertions#to_be_visible should work eventually when negated
Failure/Error: @failure_message.gsub("expected to", "not expected to")
NoMethodError:
undefined method `gsub` for nil
# ./lib/playwright/test.rb:60 in `failure_message_when_negated`
....
and asked to pair on it with me.
The first step was to ensure that the issue was not on our end by confirming that the element we are expecting not to be visible does eventually get removed from the page, but initially is present.
After confirming the issue was with the gem, and given that it was a nil
error, I figured it might be an issue that we would be able to dive into the source code for and quickly fix.
So, we run bundle open playwright-ruby-client
and add debugger
statements in various code paths to see what the state of the @failure_message
variable was for the normal and negated matchers. i.e.
it "is not visible" do
expect(page.locator("span")).not_to be_visible
end
it "is visible" do
expect(page.locator("span")).to be_visible
end
I timeboxed this investigation to a few minutes and decided to look at the docs one more time to see if there were other ways to assert that an element is not visible.
I found that there was a hidden
matcher and a not_to_be_visible
matcher (as opposed to not_to be_visible
that uses RSpec negation logic) that worked for us.
Since the issue of testing the element's visibility was fixed, we ended the pairing session and I was determined to take a look at the fix on the playwright-ruby-client side on my own time.
I had a feeling that a working not_to_be_visible
matcher meant that getting not_to be_visible
to work would be possible if I could emulate not_to_be_visible
via RSpec negation of be_visible
. And that turned out to be the case!
Interestingly, the not_to_{matcher}
matchers were generated via metaprogramming so it wasn't as straightforward as I was expecting.
But, fortunately, toggling an is_not
parameter for expectations within the gem was all that was required to negate be_visible
correctly.
The crux, then, was using the RSpec matcher's #does_not_match?
method to provide the correct is_not
param.
I went through the docs of playwright-ruby-client to set up the dev environment locally and looked through existing tests to see if there were any I could adapt to show what I fixed.
Once I was happy with the code, I wrote the PR description and made the pull request. Four days later it was approved and merged.