Add `attributes` as a name to the v4 blacklist for DSL definitions
kouno opened this issue · comments
Environment
- Ubuntu
- SitePrism v3.6
- Using RSpec and Cucumber
Issue
When defining a new class inheriting from SitePrism::Page which defines a :attributes
section, the default helper have_attributes
from RSpec gets overwritten.
Steps to reproduce
Here is a RSpec test to showcase the issue:
RSpec.describe "have_attributes" do
let(:struct) { Struct.new(:a, :b, :c) }
it "checks that the object has the listed attributes" do
expect(struct.new(1, 2, 3)).to have_attributes(a: 1, b: 2, c: 3)
end
end
RSpec.describe "a Page implementing an attributes section" do
let(:struct) { Struct.new(:a, :b, :c) }
context "when it is defined" do
let!(:page) do
Class.new(SitePrism::Page) do
section :attributes, '.foo' do
element :unused_element, '.btn'
end
end
end
it "breaks `have_attributes`" do
expect(struct.new(1, 2, 3)).to have_attributes(a: 1, b: 2, c: 3)
end
end
context "after it has been defined once" do
it "breaks `have_attributes`" do
expect(struct.new(1, 2, 3)).to have_attributes(a: 1, b: 2, c: 3)
end
end
end
The matcher for have_attributes should be: https://relishapp.com/rspec/rspec-expectations/v/3-9/docs/built-in-matchers/have-attributes-matcher.
From what I saw in the docs and in the code, SitePrism::RSpecMatchers
seems to define new have_*
matchers. Is this still necessary since RSpec already have the have_xxx
matcher?
This is an intractable problem and solved by your load order being incorrect.
the RSpec defined matchers allow us to use our metaprogrammed matchers inside RSpecs metaprogrammed assertion logic.
I would look at your stack and see if you can isolate your logic. Or failing that control your load order more succinctly. You are encountering the same issue as anyone else would when overwriting any protected method name
@luke-hill First, thanks for coming back on this and taking the time to look into this! :)
However, I don't think this is a loading issue.
SitePrism can override the default RSpec matcher for have_attributes
which breaks tests that have nothing to do with SitePrism. Once the class is loaded, and the matcher setup, it is not possible to go back to the previous behaviour.
I'm not sure why SitePrism defines its own matchers at all since I would expect the have_
default matchers to just work as expected in the current implementation. SitePrism defines has_
methods on the page object and should already plug nicely with RSpec.
Maybe I'm just missing a piece here on why these are necessary... Do you know why that would be?
I'm not going to lie, that area has changed a lot recently. So if you're having problems, I need you to perhaps dig a bit deeper into it as I don't have time at the moment.
If memory serves me right, this was to allow us to do complex matching. and also to add a negative matcher (Which is needed to be custom, as it deviates from RSpecs default ! behaviour).
It seems as though what you're proposing is to remove the positive matcher. Now if this has no adverse effects, and you can reconcile the unit tests / feature tests (I'm aware we have 2 failing ones on old firefox). Then I'm not against some changes being made.
I hope that helps. I'll leave this open for some discussion if needed.
If memory serves me right, this was to allow us to do complex matching. and also to add a negative matcher (Which is needed to be custom, as it deviates from RSpecs default ! behaviour).
Are you speaking of the have_no_*
matchers? I know that Capybara has the right behaviour when using negations but I probably would need to crosscheck how that is implemented and if it would work as expected with SitePrism.
Any thoughts on this @kouno
At the moment I'm spending a lot of time tackling some internal tech debt around capybara restrictions. Once that is finished I need to cut a stable v1 of the all_there gem. So that's gonna keep me tied up for a while.
@luke-hill I don't think there is much urgency to fix this bug yet so feel free to leave on the side for now.
I'll make a PR when I'm ready and have gotten cucumber tests running locally.
So re-reading this now we have 2 avenues.
- Add attributes to the blacklist (We are creating one), that will be released in v4. I personally think it's a very weird name for a section.
- Somehow Scope the RSpec matchers. I don't believe this is possible, so #1 looks like the only solution. For v3 we can add a deprecator in. I would probably make it passive (As I plan on cutting v4 soon). So it would be soft-deprecated in v3, and hard deprecated in v4.
I do plan on committing a bit more time to work on this where time allows. I'm also pushing a bit on the funding route now, as I've seen how it can help from other avenues.
@kouno Having spent some time off recently, I've come back to this. I think the best thing is add this to the blacklist. Which whilst masking the issue I think is probably the best one. As it'll also allow us to be stricter with other names we don't want in the blacklist (Such as special characters e.t.c.)