How to make Capybara check for visibility after some JS has run?
I think that the find
statement here is the one with the implicit wait, so Capybara will wait until the element is on the page, but won't wait for it to become visible.
Here, you would want Capybara to wait for the visible element to appear, which should be achievable by specifying the visible
option:
expect(page).to have_selector('#blah', visible: true)
I haven't tried it, but the ignore_hidden_elements
configuration option might be useful here as well, if you wanted find
to always wait for visible elements.
how to test window.status variable
With Capybara when you want to get access to the values of JS things you use evaluate_script
. In this case that would mean
evaluate_script('window.status')
If you want to wait for that be some value you could wrap it in a loop (possibly with a timeout), or if you just want to verify it is a specific value right now
expect(evaluate_script('window.status')).to eq 'ready_to_print'
Capybara: How to check that an element has content among many similar elements?
Apparently you can select elements with a given text:
page.should have_selector('h2', text: /#{headline}/i)
Note: I used a regular expression to make the text search case insensitive.
Capybara synchronize with has_no_css?
The have_no_css
matcher already waits for the element to disappear. The problem seems to be using it within a synchronize
block. The synchronize
method only re-runs for certain exceptions, which does not include RSpec::Expectations::ExpectationNotMetError
.
Removing the synchronize
seems to do what you want - ie forces a wait until the element disappears. In other words, just do:
page.should have_no_css('#ajax_indicator', :visible => true)
Working Example
Here is a page, say "wait.htm", that I think reproduces your problem. It has a link that when clicked, waits 6 seconds and then hides the indicator element.
<html>
<head>
<title>wait test</title>
<script type="text/javascript" charset="utf-8">
function setTimeoutDisplay(id, display, timeout) {
setTimeout(function() {
document.getElementById(id).style.display = display;
}, timeout);
}
</script>
</head>
<body>
<div id="ajax_indicator" style="display:block;">indicator</div>
<a id="hide_foo" href="#" onclick="setTimeoutDisplay('ajax_indicator', 'none', 6000);">hide indicator</a>
</body>
</html>
The following spec shows that by using the page.should have_no_css
without manually calling synchronize
, Capybara is already forcing a wait. When waiting only 2 seconds, the spec fails since the element does not disappear. When waiting 10 seconds, the spec passes since the element has time to disappear.
require 'capybara/rspec'
Capybara.run_server = false
Capybara.current_driver = :selenium
Capybara.app_host = 'file:///C:/test/wait.htm'
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = [:should, :expect]
end
end
RSpec.describe "#have_no_css", :js => true, :type => :feature do
it 'raise exception when element does not disappear in time' do
Capybara.default_wait_time = 2
visit('')
click_link('hide indicator')
page.should have_no_css('#ajax_indicator', :visible => true)
end
it 'passes when element disappears in time' do
Capybara.default_wait_time = 10
visit('')
click_link('hide indicator')
page.should have_no_css('#ajax_indicator', :visible => true)
end
end
Rails4/Capybara - use the value of the test window width/dimensions inside a test
You shouldn't be using driver specific methods for any of this (any time you're using Capybara.current_session.driver. you're probably doing something wrong). Rather you should be using Capybara's window api - http://www.rubydoc.info/gems/capybara/Capybara/Window
To get the size of the current window
Capybara.current_session.current_window.size
To set the size of the current window
Capybara.current_session.current_window.resize_to(width, height)
Link doesn't hide after some time capybara
There are a number of things wrong with your approach to testing this. The reason your attempt is failing is because using_wait_time just sets the amount of time Capybaras matchers will wait for their expectations to become true, it doesn't actually make the program wait. Therefore expect(page).to have_no_css('.comment-edit')
will wait up to the time your using_wait_time
specifies, rechecking the page every 50 milliseconds or so for the content, but it never reloads the page and doesn't wait before the loading the page. For your approach to work you would need to sleep before visiting the page
it 'hides the edit symbol due 5 minutes after comment was created' do
sleep 5.minutes
visit category_theme_path(category, theme)
save_and_open_page
expect(page).to have_no_css('.comment-edit')
end
however this is a terrible idea since your tests will become ridiculously slow.
Rather than that approach you could be generating your test comment already "old" (as pascal betz suggests), using something like FactoryGirl and specifying a created_at that is more than 5 minutes ago.
FactoryGirl.create(:comment, created_at: 5.minutes.ago)
or if you want to continue creating your comment through the interface then include something like the Timecop gem and you can do
Timecop.travel(5.minutes.from_now) do
visit category_theme_path(category, theme)
save_and_open_page
expect(page).to have_no_css('.comment-edit')
end
which will move the clock 5 minutes forward before visiting the page, and then reset it back to normal once the block if finished.
Additionally, your editable?
method is comparing in the wrong direction and should be
def editable?
self.created_at > (Time.now - 5.minute)
end
Then the view should be
- if comment.editable?
= link_to 'Edit', edit_category_theme_comment_path(@category, @theme, comment)
Related Topics
Rails Email Error - 530-5.5.1 Authentication Required
How to Use Ruby Regexp to Substitute String with a "Callback Function"-Like Manipulation
Will Uuid as Primary Key in Postgresql Give Bad Index Performance
Can Someone Explain Ruby's Use of Pipe Characters in a Block
Are There Good Reasons for 'Private' to Work the Way It Does in Ruby
Rails Fields_For Form Not Showing Up, Nested Form
Why Does Ruby Open-Uri's Open Return a Stringio in My Unit Test, But a Fileio in My Controller
Convert Non-Ascii Chars from Ascii-8Bit to Utf-8
What Is the Expected Syntax for Checking Exception Messages in Minitest's Assert_Raises/Must_Raise
Rails with Paypal Permissions and Paypal Express Checkout
Optimization for Finding Perfect-Square Algorithm
Remove Substring from the String
Sort Array Returned by Activerecord by Date (Or Any Other Column)
Setting Up the Logger in Rails 3
Ruby 1.9, Force_Encoding, But Check