Custom matchers for request specs

Hi all, I’m trying to create a custom matcher that will visit a given
path and check it’s authenticated.
Here’s what I have so far (using rspec-rails and capybara):

matcher :require_authentication do
match do |path|
visit path
#page.current_path.should == sign_in_path
page.current_path.should == ‘/sign_in’
end
end

The above version works, but when using the commented out line I get:

NameError:
undefined local variable or method `sign_in_path’ for
#RSpec::Matchers::Matcher:0xbbd68ec

sign_in_path is one of the routes in my application and works fine
inside a describe/it block.
I don’t understand why the matcher recognises visit() but not
sign_in_path.

any ideas?

On 4 Feb 2011, at 09:30, Alan B wrote:

end
sign_in_path.
I’m surprised either of them do. This DSL is just a factory method for a
matcher class. Unless that matcher class includes Capybara and the Rails
routing methods module (can’t remember the name off-hand) you won’t have
access to either of these methods in the matcher. Look at the non-DSL
way to create a matcher and this will make more sense.

Also, you need to return true / false from #match, rather than using an
assertion.

cheers,
Matt

[email protected]
07974 430184

On Feb 8, 2011, at 4:14 AM, Matt W. wrote:

#page.current_path.should == sign_in_path
sign_in_path is one of the routes in my application and works fine
inside a describe/it block.
I don’t understand why the matcher recognises visit() but not
sign_in_path.

I’m surprised either of them do.

Actually, I’m not, but that’s because I know something that you don’t
know (because I wrote it and it’s not well documented):

A matcher created using the Matcher DSL is provided access to the example it is running in. When it receives method_missing, it asks the example if _it_ will respond to the message and, if so, sends it to the example.

<educated_guess guarantees=“none”>
If visit() is defined in the scope of the example using “def visit”,
then example.respond_to?(:visit) would return true, so the matcher would
send visit() to the example.

If, however, sign_in_path() is handled with method_missing(), but
respond_to?() is not also overridden to return true for
respond_to?(:sign_in_path), then the matcher would call super from
method_missing, raising the NameError.

You can test this theory out by putting the following in the same
example before the matcher:

self.should respond_to(:visit)
self.should respond_to(:sign_in_path)

If my guess is correct, the former will pass, but the latter will fail.
If they both pass, then I’m not sure about the explanation.
</educated_guess>

HTH,
David


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Cheers,
David