diff --git a/lib/webcat/dsl.rb b/lib/webcat/dsl.rb index 0ad3f6cf..bdeca099 100644 --- a/lib/webcat/dsl.rb +++ b/lib/webcat/dsl.rb @@ -36,7 +36,7 @@ module Webcat SESSION_METHODS = [ :visit, :body, :click_link, :click_button, :fill_in, :choose, - :check, :uncheck, :attach_file, :select, :has_content? + :check, :uncheck, :attach_file, :select, :has_content?, :within ] SESSION_METHODS.each do |method| class_eval <<-RUBY, __FILE__, __LINE__+1 diff --git a/lib/webcat/session.rb b/lib/webcat/session.rb index d67c4ba2..1fd605fa 100644 --- a/lib/webcat/session.rb +++ b/lib/webcat/session.rb @@ -60,11 +60,25 @@ class Webcat::Session end def has_content?(content) - driver.find("//*[contains(child::text(),'#{content}')]").size > 0 + find("//*[contains(child::text(),'#{content}')]").size > 0 + end + + def within(scope) + scopes.push(scope) + yield + scopes.pop end private + def current_scope + scopes.join('') + end + + def scopes + @scopes ||= [] + end + def find_link(locator) find_element("//a[@id='#{locator}']", %{//a[text()="#{locator}"]}, %{//a[@title="#{locator}"]}) end @@ -96,7 +110,7 @@ private def find_field_by_id(locator, *kinds) kinds.each do |kind| path = FIELDS_PATHS[kind] - element = driver.find(path.call(locator)).first + element = find(path.call(locator)).first return element if element end return nil @@ -104,7 +118,7 @@ private def find_field_by_label(locator, *kinds) kinds.each do |kind| - label = driver.find("//label[text()='#{locator}']").first + label = find("//label[text()='#{locator}']").first if label element = find_field_by_id(label[:for], kind) return element if element @@ -115,10 +129,15 @@ private def find_element(*locators) locators.each do |locator| - element = driver.find(locator).first + element = find(locator).first return element if element end raise Webcat::ElementNotFound, "element not found" end + def find(locator) + locator = current_scope.to_s + locator + driver.find(locator) + end + end diff --git a/spec/session_spec.rb b/spec/session_spec.rb index b556bffd..3eebb034 100644 --- a/spec/session_spec.rb +++ b/spec/session_spec.rb @@ -324,6 +324,56 @@ shared_examples_for "session" do end end + + describe '#within' do + before do + @session.visit('/with_scope') + end + + context "with click_link" do + it "should click links in the given scope" do + @session.within("//li[contains(.,'With Simple HTML')]") do + @session.click_link('Go') + end + @session.body.should include('

Bar

') + end + + context "with nested scopes" do + it "should respect the inner scope" do + @session.within("//div[@id='for_bar']") do + @session.within("//li[contains(.,'Bar')]") do + @session.click_link('Go') + end + end + @session.body.should include('Another World') + end + + it "should respect the outer scope" do + @session.within("//div[@id='another_foo']") do + @session.within("//li[contains(.,'With Simple HTML')]") do + @session.click_link('Go') + end + end + @session.body.should include('Hello world') + end + end + end + + context "with forms" do + it "should fill in a field and click a button" do + @session.within("//li[contains(.,'Bar')]") do + @session.click_button('Go') + end + extract_results(@session)['first_name'].should == 'Peter' + @session.visit('/with_scope') + @session.within("//li[contains(.,'Bar')]") do + @session.fill_in('First Name', :with => 'Dagobert') + @session.click_button('Go') + end + extract_results(@session)['first_name'].should == 'Dagobert' + end + end + end end describe Webcat::Session do diff --git a/spec/test_app.rb b/spec/test_app.rb index 00adfc5a..7b249adc 100644 --- a/spec/test_app.rb +++ b/spec/test_app.rb @@ -16,15 +16,19 @@ class TestApp < Sinatra::Base get '/with_html' do erb :with_html end - + get '/with_js' do erb :with_js end - + get '/with_simple_html' do erb :with_simple_html end + get '/with_scope' do + erb :with_scope + end + get '/form' do erb :form end diff --git a/spec/views/with_scope.erb b/spec/views/with_scope.erb new file mode 100644 index 00000000..4d18b80c --- /dev/null +++ b/spec/views/with_scope.erb @@ -0,0 +1,36 @@ +

This page is used for testing various scopes

+ +

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Ut enim ad minim venia. + Go +

+ +
+ +
+ +
+ +
\ No newline at end of file