Why Does Adding "Sleep 1" in an After Hook Cause This Rspec/Capybara Test to Pass

Why does adding sleep 1 in an after hook cause this Rspec/Capybara test to pass?

I suspect that it's possible in your application for the comment to disappear from the page (which is the last thing you're asserting) before it's deleted from the database. That means that the test can clean up before the deletion happens. If this is the case you can fix it by waiting for the actual deletion to happen at the end of the test. I have this method around (a reimplementation of a method that was removed from Capybara 2 but is still sometimes necessary)

def wait_until(delay = 1)
seconds_waited = 0
while ! yield && seconds_waited < Capybara.default_wait_time
sleep delay
seconds_waited += 1
end
raise "Waited for #{Capybara.default_wait_time} seconds but condition did not become true" unless yield
end

so I can do

wait_until { Comment.count == 0 }

in tests.

Another approach is to add Rack middleware that blocks requests made after the test ends. This approach is described in detail here: http://www.salsify.com/blog/tearing-capybara-ajax-tests I saw it do a very good job of addressing data leakage in a good-sized suite of RSpec feature specs.

Why is this capybara test failing when running programmatically, but passing when done manually?

When you say "fails to click", I'm assuming you don't mean you're getting an error from the page.find("svg", class: "fa-times").click(wait: 5) but rather that the line is proceeding just fine and your expect(page).to have_css(".fa-bars") is what's actually failing.

Given that, your description tells me that Capybara is actually clicking just fine, but it's happening before the menu is ready to interpret the click as meaning to close. When you add a binding.pry you're giving the menu time to finish opening. The thing you need to understand about passing the wait parameter is that it sets the maximum amount of time Capybara will wait for the element to exist. If the element exists before that time Capybara will move on, so setting wait: 10 when wait: 5 didn't error on that line will make no difference (condition was met already - allowing it to wait longer is meaningless). You can confirm this by just putting a sleep(2) before the find/click line to delay the find and click long enough for the menu to open before the click happens to close it. The proper fix for your tests is to either disable animation in your testing environment (so the menu opens instantly) or add an extra expectation for some state of the menu that indicates it is actually fully open and ready to receive a click that closes it.

Record Deletion testing failure using Capybara with Selenium

First, best practices is to have all of your scenarios be independent so they can be run in any order. You have opted to ignore best practices here and made scenarios order dependent - hopefully you have a really good reason for doing that.

As for the sleep being necessary, that is (as your surmised) because browser actions occur asynchronously which means that accepting the confirm returns as soon as the confirm is accepted. It will then take a little time for the deletion request to be processed by your server and the Post.count will be checked before the deletion has actually occurred. To fix that you should be checking for whatever visual change indicates the deletion has occurred. In your case that looks to be the text "Post was successfully destroyed.", so move that inside the Post.count expectation in order to synchronize your test with the application.

expect{
within 'table' do
accept_confirm do
find_link(class: 'tester').click
end
end

expect(page).to have_content("Post was successfully destroyed.")
}.to change {Post.count}.by(-1)

Why Capypara + Rspect tests still pass even though I delete application.js file?

Try with

rake assets:clobber

This will remove compiled assets and clean them.

Why would binding.pry cause Rspec Selenium test to fail?

When testing apps with JS capable drivers the app is run in a different thread than the tests. This means when you add binding.pry to the controller code, it gets paused but the test thread may continue on, finishes/fails the test and then database cleaner is run to clean up your objects. If you're relatively quick in your pry session you'll find your objects ( within the sleep(5) timeframe ) - otherwise they may be cleaned up and gone. Also it's telling you the error is occurring in an after hook, but you don't show any after hooks, only before, in your code???

Note: using sleep() in a test with Capybara is generally frowned upon since it means your tests will take longer than necessary. Instead you should be checking a visual change on the page that indicates the action has completed - something like

expect(page).to have_text('Order updated') 

or

expect(page).to have_current_path('/success')

etc. depending on exactly what your app does or how it shows that the update was successful

Capybara test doesn't pass with database cleaner, must be run twice without database_cleaner to pass

There is no visit shown in the test, which means you've visited the page before the questions are created and therefore the info expected is not shown on the page. The data would exist from the first run on the second run if you don't clear the DB which explains why it passes second time around. You should always visit the page after creating the test data.

Additionally as I mentioned in the comments you probably want to fix (remove if using Rails 5.1+) your DatabaseCleaner config and the use of trigger is a really bad idea in tests since it can do things a user never could.



Related Topics



Leave a reply



Submit