Need to loop through an array in rspec, test not running

12,922

Solution 1

You can't have your test nested that way due to RSpec being a DSL. RSpec reads the example spec files first, before running the tests. So it hits the Blog.all before any of the tests are run. This also means that there is no population of the database. So unless there was leftover state from a previous test run Blog.all will return [].

Trying to create the objects in a before will not work either with the way the test is written in your question. Again, this is due to Blog.all being executed at parse time, while before is executed at test time.

In order to achieve what you want, you will probably need to break the "only test one thing" rule and nest the Blog.all inside the it block:

it "list the first five posts" do
  Blog.all(limit:5).each do |blog|
    expect(page).to have_selector('ul.accordmobile li#blog ul li a',
                                  text: blog.title,
                                  href: blog_path(blog.id))
  end
end

Solution 2

important! for hoping loop, to run you should have 5 or more than 5 blogs.

than do

may be this should be re-factored as

  Blog.limit(5).each do |blog|    
      it { should have_selector('ul.accordmobile li#blog ul li a', text: blog.title, href: blog_path(blog.id)) }
            end
Share:
12,922
Wale
Author by

Wale

Updated on June 09, 2022

Comments

  • Wale
    Wale almost 2 years

    I have a test that needs to loop through 5 elements in an array then verify that all the elements are displayed as list items on the page. I have the code below, it's the last test with the comment '#get the first 5 blog posts'. When I run the tests, this test is not seen, because only 4 tests are getting executed. If I move the 'it {} ' statement outside the array code blog, the test becomes visible. How do I properly write this test so it can loop correctly?

    require 'spec_helper'
    require 'requests/shared'
    
    describe "Header" do
    
        let (:title) { "my title" }
    
        subject { page }
    
        before { visit root_path }
    
        describe "Home" do
            it { should have_selector('title', text: title) }
            it { should have_selector('header') }
            it { should have_link 'Home', href: root_path}
    
    
            describe "Blog link exist" do
                    it { should have_link 'Blog'}
            end
    
            describe "Blog list elements" do
    
                #get the first 5 blog posts
                Blog.all(limit:5).each do |blog|    
                    it { should have_selector('ul.accordmobile li#blog ul li a', text: blog.title, href: blog_path(blog.id)) }
                end
            end 
    end
    

    end

  • Wale
    Wale almost 11 years
    Yes I have more than 5 blog entries in the db. I tried the code you proposed, the 'it' block is still not visible.
  • Sachin Singh
    Sachin Singh almost 11 years
    hey tests are tun on test database not on development database, i cannot see any creation of blog objects here, so create them with factory or fixtures.
  • Wale
    Wale almost 11 years
    Thanks for pointing this out. I have now refactored the test to create a blog entry 6 times. In the UI I am displaying only the first 5 entries. However the test is actually able to find 6 li items and it's passing. I don't understand why there is a mismatch in the test environment. How can I load the UI that the test env sees? Thanks a lot.
  • Wale
    Wale almost 11 years
    Aaron, thanks for your help. Your suggestions works. This raises another issue though. In the test I am creating 6 blog elements, but in the UI I am displaying only 5. When I loop over the 6 blog elements in the test, they are all found, however only 5 should be found! Any thoughts on why there is a mismatch in the elements the test is seeing?
  • Aaron K
    Aaron K almost 11 years
    @user2410627 Sounds like a bug in the code. That's why we have tests. :-D Do you see all six when you load the actual page with more than 5 blog elements in the DB?
  • Wale
    Wale almost 11 years
    In my development environment this looks fine. I have not been able to load what the test environment sees. I added launchy gem, required it in spec_helper.rb, called save_and_open_page but I got errors about that method not being found.
  • Aaron K
    Aaron K almost 11 years
    @user2410627 you can go old school, by doing p page or maybe it's p page.body to look at the rendered HTML.
  • Wale
    Wale almost 11 years
    Found the issue, for some reason the href I gave to have_selector was not matching. Since the blogs I created had the same title, the resulting xpath was not unique enough so it just matched anchor elements as many times as the loop ran. The blog.id in href was supposed to match unique blogs, but have_selector was using the only css and the text. I made the titles unique to resolve this, maybe have_selector cannot match on text + href?. Either way thanks a lot for all your help, I spent too many hours trying to solve this.