Reputation: 18843
Let's suppose you want to submit a form to create a post, wait for it to be created, fetch the post from database and check if the image from the post is being displayed on the next page:
visit url
fill_in the_form
click_on 'Create'
post = Post.first
img = page.find '.post .image'
assert_equal post.file.thumb.url, URI(img[:src]).path
But this way, post
will be nil
more often than not. Since when you fetch it from database, it might not have been created yet. How do I make sure next page is loaded?
Upvotes: 3
Views: 5007
Reputation: 18843
Unfortunately, you don't want to wait for page reload. Since, for instance, now post appears after page reload. In a while it might appear without full page reload. If you do, explain your circumstances, please.
I say unfortunately since if we ignore what was said above, if we really need to wait for page reload for some reason, the idea from the old answer is better than any other I've seen in the internets.
So, what you care is that post has appeared on the page. Which brings us to the following code:
test 'create post' do
visit url
fill_in the_form
click_on 'Create'
assert_selector '.post'
post = Post.first
img = page.find '.post .image'
assert_equal post.file.thumb.url, URI(img[:src]).path
end
old answer
Inspired by these great article, link and comment. According to one of capybara
's authors, this is the only legitimate use case for wait_until
he's heard of in Capybara. Asserting on model objects, that is.
def wait_until
Timeout.timeout(Capybara.default_max_wait_time) do
sleep(0.1) until value = yield
value
end
end
def wait_for_page_reload
id = find('html').native.ref
yield
wait_until { find('html').native.ref != id }
end
test 'create post' do
visit url
fill_in the_form
wait_for_page_load do
click_on 'Create'
end
post = Post.first
img = page.find '.post .image'
assert_equal post.file.thumb.url, URI(img[:src]).path
end
This is a bit hacky. But it works. It waits until html
element's internal id changes.
Upvotes: -1
Reputation: 49870
find
will wait up to Capybara.default_max_wait_time
seconds for a matching element to appear on the screen. Therefore, to do what you're asking, check for content you expect to be on the next page before loading the item from the DB
visit url
fill_in the_form
click_on 'Create'
img = page.find '.post .image'
post = Post.first
assert_equal post.file.thumb.url, URI(img[:src]).path
If done in this order the page.find
will wait for the element to appear on the page which guarantees the Post has already been saved so you can then load it.
Upvotes: 3