-
Notifications
You must be signed in to change notification settings - Fork 3
Capybara UI Best Practices
Suggestions for success and happiness in the Capybara-UI world.
Widgets can grow fat with custom methods and sub widgets, which leads to more complex code.
# an overly complex widget
list :todo_items, '.todo-items', do
widget :todo_item, '.todo-item'
def find_item(text)
root.items.detect { |item| item.text == text }
end
end
def select_item(text)
widget(:todo_items).find_item(text).click
end
This example has an additional drawback, in that if you are adding items to the list via javascript, your find_item
method will not wait for the new item to appear.
As a general rule, if you're implementing an element finder in Capybara-UI, reach for a Proc instead.
We can improve this example by focusing instead on the list items, resulting in less code and a widget that waits to find any asynchronously added list items.
# a better widget
widget :todo_item, -> (text) ['.todo-item', text: text]
def select_item(text)
click :todo_item, text
end
Our new widget also works nicely with see
in RSpec.
expect(roles.user).to see :todo_item, 'Buy Milk'
Role methods allow you to define clear steps your role may take, and act as a form of documentation for how the code works. They can also help you DRY up repetitive code.
Consider this example in RSpec.
feature 'when a user creates a new todo item' do
let(:user) { roles.user }
scenario 'with valid information, the item appears in the list' do
visit new_items_path
user.widget(:new_todo_item_form).submit_with(item_name: 'Buy Milk')
expect(user.widget?(:todo_item, 'Buy Milk')).to eq(true)
end
end
Now let's look at that example when we use role methods named after our business logic.
# much better
feature 'when a user creates a new todo item' do
let(:user) { roles.user }
scenario 'with valid information, the item appears in the list' do
user.view_new_item_page
user.create_item('Buy Milk')
expect(user).to see :todo_item, 'Buy Milk'
end
end