cant 'click' or 'fill_in' your elements?

8 views
Skip to first unread message

icarus.wings

unread,
Jun 8, 2010, 3:54:42 AM6/8/10
to gizmo - page-model testing
I have had some questions from people that have had a need to 'click'
on an element on their page.
It seems easy enough, because youre using capybara and their docs say
you can; right?
well, gizmo wants you to work with a bunch of Nokogiri elements, so
its not immediately obvious how to turn them into capybara elements so
you can do all the fun stuff.

lets say i have a method like this (taken from the gizmo examples):

def search_form
element_struct do |form|
form.container = @document.css("div.search")
form.element = container= form.container.css("form")
form.input = container.css("input[name=q]")
form.submit = container.css("input[alt=search]")
end
end

It just returns a gizmo element struct wich defines a search form on
my page and has accessors that return nokogiri nodes for each of the
elements in that form.

if i want to perform a search on the page that mixin belongs to, i
need to fill in the input field, and click the search button. so i
would probably define an action that looks like this.

define_action :search do |query|
fill_in search_form.input.attr('name').value, :with => query
click search_form.submit.attr('alt').value
end

I quite liked this approach until now, i have reused the elements
returned from the search_form struct so i have not repeated my
selectors and I have kept dry... kinda.
but I felt like there had to be an even better way.. Here i'm still
accessing the 'name' attribute and the 'alt' attribute (which can be
modified or removed in the future)
here is what i came up with today:

I defined a method to locate a capybara element, which was easy
because a nokogiri node can easily give me the xpath selector i can
use to find it.

def locate element
element = element.first if element.is_a?(Nokogiri::XML::NodeSet)
find(:xpath, element.path)
end

now i just have a normal capybara node, so I can do stuff like this:

define_action :search do |query|
locate(search_form.input).set(query)
locate(search_form.submit).click
end

I like that more, as it will not care if anything changes inside my
elements, i will always only have to change the page mixin in one
place, the selectors within my element_struct.
I can also do all kinds of things to make my code more reuseable (this
might not be the example that needs this refactoring, but in code that
might have a use for this, the actions could be much more generic)

define_action :click_submit do
locate(search_form.submit).click
end

define_action :enter_search_query do |query|
locate(search_form.input).set(query)
end

define_action :search do |query|
perform :enter_search_query, query
perform :click_submit
end

or

define_action :click do |element|
locate(button).click
end

or use from your step_definitions

on_page_with :search_form do |page|
page.perform :enter_search_query, query
page.perform :click, page.submit_button
end
Reply all
Reply to author
Forward
0 new messages