How to Use Before :All with Capybara

Can I use before :all with capybara?

Capybara resets session after each example run, so when you moved visit new_course_document_path(course) into before (:all) block, you had nothing to visit starting from a second example.

I would recommend to run only that tests you're working on. This could be achieved with a RSpec tag option or guard-rspec, and it'll save you a LOT of time.

Capybara and before(:all) in rspec

This is because the test data, including the capybara session data (such as logged-in state) and the model created by create(:idea) are wiped out between specs.

You want to go with before(:each) not :all, even though it is more time consuming.

Run block once before all capybara tests

I think you are overengineering the task. Since you are to run it once, just run it:

cb = lambda { puts 'I am run once' }
RSpec.configure do |config|
cb.call
end

How to wait in Capybara when using #all

If you are testing an app then this is relatively easy because you know the test data, so you can just do something like

expect(page).to have_css('table tr:first-child', text 'text first in order when sorted')

which would wait for the first row of the table to have the text that should appear first in the sort order once sorting has occurred.

If you are screen-scraping or testing an app where you somehow don't know the test data then it becomes more difficult. When you sort a column does anything change on the page other than the order of the rows? Is there a sort indicator, sorted column header highlight, etc? If so you may be able to wait for that, assuming it doesn't actually update until the columns are updated (if it updates as soon as it's clicked then this won't work, and is probably actually a bad UI since you can end up with data inconsistencies). For instance, if the column header gets a class of 'sorted' you could do something like

expect(page).to have_css('table th td.sorted', text: 'text of the column header you sorted by')

which would wait for the correct header to indicate it was sorted.

If there really are no changes to anything that indicates sorting is completed then you're out of luck and you've hit one of the very few cases where something like wait_for_ajax should be used.

Note: passing the :wait option wouldn't help you at all in this case. This is because it's the maximum amount of time that will be waited for matching elements to be found, and #all validly matches 0 elements - it would still return immediately (without any of the count options mentioned in another answer, which as you pointed out don't help you here anyway)

rails rspec before all vs before each

before(:all) runs the block one time before all of the examples are run.

before(:each) runs the block one time before each of your specs in the file

before(:all) sets the instance variables @admission, @project, @creative, @contest_entry one time before all of the it blocks are run.

However, :before(:each) resets the instance variables in the before block every time an it block is run.

Its a subtle distinction but important

again,

before(:all)
#before block is run
it { should belong_to(:owner).class_name('User') }
it { should belong_to(:project) }
it { should have_many(:entry_comments) }

it { should validate_presence_of(:owner) }
it { should validate_presence_of(:project) }
it { should validate_presence_of(:entry_no) }
it { should validate_presence_of(:title) }

before(:each)
# before block
it { should belong_to(:owner).class_name('User') }
# before block
it { should belong_to(:project) }
# before block
it { should have_many(:entry_comments) }
# before block

# before block
it { should validate_presence_of(:owner) }
# before block
it { should validate_presence_of(:project) }
# before block
it { should validate_presence_of(:entry_no) }
# before block
it { should validate_presence_of(:title) }

RSpec only first `it` block passes and Capybara or Selenium redirects page

before(:all) runs the block once before evaluating the 'it' blocks. This isn't going to work with a normal Capybara setup since Capybara resets the session after each test which includes a visit 'about:blank'. If you want to keep one expect per it then your initial visit needs to be in a before(:each) block.

That being said, sticking to one expect per test doesn't make a lot of sense in feature tests where you should be testing page behavior (visit page, fill in fields, click buttons, etc) and a given test is going to expect multiple things to happen. Your tests look they really belong as view tests and not feature tests.

Additionally, you should be using the have_title matcher rather than using eq with page.title



Related Topics



Leave a reply



Submit