Need to loop through an array in rspec, test not running
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
Wale
Updated on June 09, 2022Comments
-
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 almost 11 yearsYes 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 almost 11 yearshey 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 almost 11 yearsThanks 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 almost 11 yearsAaron, 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 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 almost 11 yearsIn 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 almost 11 years@user2410627 you can go old school, by doing
p page
or maybe it'sp page.body
to look at the rendered HTML. -
Wale almost 11 yearsFound 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.