0

I'm new to ruby/rails and doing a turorial I was wondering how I could solve my little problem...

I have a describe "with valid information" which tests what should or should not happen when the user signs in with valid info. In this procedure, I want to be able to verify that some links exists on the new page. In the tuto, there are only 2 links so we do it like that:

it { should have_link('Profile', href: user_path(user)) }
it { should have_link('Sign out', href: signout_path) }

But what if we have let's say 10 links? I think it would be easier to have a helper no? But I can't figure out how to write it. This is what I came with...

 lol = Hash[ 'Profile'  => 'user_path(user)',
             'Sign out' => 'signin_path']
 it { should have_list_of_links(lol) }

then in a $PROJECT/spec/support/utilities.rb file, I define the new *have_list_of_links* function:

RSpec::Matchers.define :have_list_of_links do |lol|
  match do |page|
    lol.each_pair do |label, link| 
                page.should have_link(label, href: link) 
    end
  end
end

I know it's not the right way to do it but I can't figure out how to do it...

Thanks.

jon
  • 910
  • 3
  • 12
  • 34
  • what do you mean by **I know it's not the right way to do** by looking at the code it should work and do what you expect. Do you get any errors? Only side effect I can see is that all links will be run in a single example and that might not be good for documentation. – Kocur4d Mar 20 '13 at 02:52
  • actually I don't know if it's the right way to do it, that's more what I wanted to say... – jon Mar 20 '13 at 08:56
  • I have an error message, I'll just have to wait until end of working day to copy/paste it here. I'm not sure though if I understand the side effect you mention. Would you not recommend that way of implementing the tests? But anyway, at the end my goal here is only to practice some lines of code not written in the tuto. – jon Mar 20 '13 at 09:03

1 Answers1

1

There is two small problems I can see here. First use let syntax to define memoized variables inside rspec. Second drop the parentheses around *_path helpers when you build your hash.

So insted:

lol = Hash[ 'Profile'  => 'user_path(user)',
            'Sign out' => 'signin_path']

have:

let(:lol) { Hash[ 'Profile'  => user_path(user),
                  'Sign out' => signin_path] }

Your description block could be:

describe "with valid information" do
  let(:lol) { Hash[ 'Profile'  => user_path(user),
                    'Sign out' => signin_path] }

  it { should have_list_of_links(lol) }
end

As of a side effect I'll show you small example. Given you have matcher defined in $PROJECT/spec/support/utilities.rb file, application routes etc... are set up correctly and you have links in your view.

describe "Users pages" do
  before { visit root_path }
  let(:values) { Hash['Index' => users_path, 
                      'Sign out' => signout_path, 
                      'Sign in' => signin_path] }

  subject { page }

  describe "with valid informations" do
    it { should have_list_of_links(values) }
  end
end  

running rspec:

> rspec
.

Finished in 0.00267 seconds
1 example, 0 failures

Randomized with seed 67346

running rspec -f documentation

>rspec -f documentation
Users pages
  with valid informations
    should have link "Sign in"

Finished in 0.00049 seconds
1 example, 0 failures

Randomized with seed 53331

This is not clear and misleading, specially the documentation switch. Its a common practice to run a rspec -f documentation on new application You just put your hands on(if they use rspec ofc). To better understands what is going on.

If you instead have:

describe "Users pages" do
  before { visit root_path }

  subject { page }

  describe "with valid informations" do
    it { should have_link('Index', href: users_path) }
    it { should have_link('Sign out', href: signout_path) }
    it { should have_link('Sign in', href: signout_path) }
  end
end  

running rspec:

>rspec
...

Finished in 0.0097 seconds
3 examples, 0 failures

Randomized with seed 53347

running rspec -f documentation

>rspec -f documentation
Users pages
  with valid informations
    should have link "Index"
    should have link "Sign out"
    should have link "Sign in"

Finished in 0.00542 seconds
3 examples, 0 failures

Randomized with seed 40120

I personally like second case(more verbose one). Its value increasing when number of test are growing and test structures are getting more complicated. You can simply run rspec -f documentation to learn how to use application without even going to user manual/tutorial.

Kocur4d
  • 6,701
  • 8
  • 35
  • 53
  • super, thanks for the crash course! I will test your solution this evening and share the results. One more question: is RSpec and behaviour driven programming really that used in web companies or is it more an ideal way to do it? – jon Mar 20 '13 at 13:49
  • Good companies test, bad companies don't test. What they are testing with (RSpec/Minitest/other frameworks) is just a personal taste. If I would say **Rspec and BDD** is "The BEST" and you should use it over **UnitTest and TDD** half of the people reading this question would crucify me and other half would buy me a drink:) Bottom line is - it doesn't really matter whit what you test. Just test:). – Kocur4d Mar 20 '13 at 14:14
  • ok, thanks again for the info, my stuff is now working. I also found a quite similar post http://stackoverflow.com/questions/11916962/how-to-keep-rspec-tests-dry-with-lots-of-have-link?rq=1 which exposes view slightly different. I guess I need to continue trying some "experiments" and I'll surely be back here in a few. ciao – jon Mar 20 '13 at 22:06