diff --git a/lib/webcat/cucumber.rb b/lib/webcat/cucumber.rb new file mode 100644 index 00000000..eea29628 --- /dev/null +++ b/lib/webcat/cucumber.rb @@ -0,0 +1,9 @@ +require 'webcat' +require 'webcat/dsl' + +if defined?(Rails) + Webcat.app = ActionController::Dispatcher.new +end + +World(Webcat) + diff --git a/lib/webcat/driver/selenium/rc_server.rb b/lib/webcat/driver/selenium/rc_server.rb deleted file mode 100644 index 9ce72258..00000000 --- a/lib/webcat/driver/selenium/rc_server.rb +++ /dev/null @@ -1,61 +0,0 @@ -module Webcat - module Selenium - - class SeleniumRCServer - unless Kernel.respond_to?(:silence_stream) - def silence_stream(stream) - old_stream = stream.dup - stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null') - stream.sync = true - yield - ensure - stream.reopen(old_stream) - end - end - - def booted? - @booted || false - end - - def boot - return if booted? - silence_stream(STDOUT) do - remote_control.start :background => true - end - wait - @booted = true - at_exit do - silence_stream(STDOUT) do - remote_control.stop - end - end - end - - def remote_control - return @remote_control if @remote_control - - @remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", 5041, 15) - @remote_control.jar_file = jar_path - - return @remote_control - end - - def jar_path - File.expand_path("selenium-server.jar", File.dirname(__FILE__)) - end - - def wait - return true - $stderr.print "==> Waiting for Selenium RC server on port #{Webrat.configuration.selenium_server_port}... " - TCPSocket.wait_for_service_with_timeout(:host => "localhost", :port => 5041, :timeout => 15) - $stderr.print "Ready!\n" - rescue SocketError - $stderr.puts "==> Failed to boot the Selenium RC server... exiting!" - exit - end - - end - - end -end - diff --git a/lib/webcat/driver/selenium/selenium-server.jar b/lib/webcat/driver/selenium/selenium-server.jar deleted file mode 100644 index 7e029034..00000000 Binary files a/lib/webcat/driver/selenium/selenium-server.jar and /dev/null differ diff --git a/lib/webcat/driver/selenium_driver.rb b/lib/webcat/driver/selenium_driver.rb index 190c742c..34a1ef2a 100644 --- a/lib/webcat/driver/selenium_driver.rb +++ b/lib/webcat/driver/selenium_driver.rb @@ -1,57 +1,83 @@ -require 'selenium/client' -require 'webcat/driver/selenium/rc_server' -require 'webcat/core_ext/tcp_socket' - +require 'selenium-webdriver' class Webcat::Driver::Selenium class Node < Struct.new(:node) def text node.text end - - def attribute(name) - value = if name.to_sym == :class - node.class_name + + def [](name) + if name == :value + node.value else - node.send(name.to_sym) + node.attribute(name) end - return value if value and not value.empty? + rescue Selenium::WebDriver::Error::WebDriverError + nil end - + + def set(value) + if tag_name == 'input' and %w(text password hidden file).include?(type) + node.clear + node.send_keys(value.to_s) + elsif tag_name == 'input' and type == 'radio' + node.select + elsif tag_name == 'input' and type == 'checkbox' + node.toggle + elsif tag_name == "textarea" + node.clear + node.send_keys(value.to_s) + end + end + + def select(option) + node.find_element(:xpath, ".//option[text()='#{option}']").select + end + def click node.click end - + def tag_name - # FIXME: this might be the dumbest way ever of getting the tag name - # there has to be something better... - node.to_xml[/^\s*<([a-z0-9\-\:]+)/, 1] + node.tag_name end + + private + + def type + self[:type] + end + end - + attr_reader :app, :rack_server - def self.server - @server ||= Webcat::Selenium::SeleniumRCServer.new + def self.driver + unless @driver + @driver = Selenium::WebDriver.for :firefox + at_exit do + @driver.quit + end + end + @driver end def initialize(app) @app = app @rack_server = Webcat::Server.new(@app) @rack_server.boot - self.class.server.boot end - + def visit(path) - browser.open(url(path)) + driver.navigate.to(url(path)) end - + def body - browser.html + driver.page_source end - + def find(selector) - browser.elements_by_xpath(selector).map { |node| Node.new(node) } + driver.find_elements(:xpath, selector).map { |node| Node.new(node) } end private @@ -59,22 +85,9 @@ private def url(path) rack_server.url(path) end - - def browser - unless @_browser - @_browser = Selenium::Client::Driver.new :host => 'localhost', - :port => 4444, - :browser => "*firefox", - :url => rack_server.url('/'), - :timeout_in_second => 10 - @_browser.start_new_browser_session - - at_exit do - @_browser.close_current_browser_session - end - end - @_browser + + def driver + self.class.driver end end - diff --git a/lib/webcat/session.rb b/lib/webcat/session.rb index a0f0594c..6c547854 100644 --- a/lib/webcat/session.rb +++ b/lib/webcat/session.rb @@ -12,6 +12,8 @@ class Webcat::Session Webcat::Driver::RackTest.new(app) when :culerity Webcat::Driver::Culerity.new(app) + when :selenium + Webcat::Driver::Selenium.new(app) else raise Webcat::DriverNotFoundError, "no driver called #{mode} was found" end diff --git a/spec/driver/selenium_driver_spec.rb b/spec/driver/selenium_driver_spec.rb index 81a7eb31..b9b22861 100644 --- a/spec/driver/selenium_driver_spec.rb +++ b/spec/driver/selenium_driver_spec.rb @@ -5,6 +5,6 @@ describe Webcat::Driver::Selenium do @driver = Webcat::Driver::Selenium.new(TestApp) end - # it_should_behave_like "driver" - # it_should_behave_like "driver with javascript support" + it_should_behave_like "driver" + it_should_behave_like "driver with javascript support" end diff --git a/spec/drivers_spec.rb b/spec/drivers_spec.rb index 85ead06b..243bcddd 100644 --- a/spec/drivers_spec.rb +++ b/spec/drivers_spec.rb @@ -30,7 +30,7 @@ shared_examples_for 'driver' do end it "should find the correct number of elements" do - @driver.find('//a').size.should == 2 + @driver.find('//a').size.should == 3 end it "should extract node texts" do diff --git a/spec/fixtures/test_file.txt b/spec/fixtures/test_file.txt new file mode 100644 index 00000000..0cd972cb --- /dev/null +++ b/spec/fixtures/test_file.txt @@ -0,0 +1 @@ +ThisIsTheTestFile \ No newline at end of file diff --git a/spec/session/selenium_session_spec.rb b/spec/session/selenium_session_spec.rb new file mode 100644 index 00000000..238bc10d --- /dev/null +++ b/spec/session/selenium_session_spec.rb @@ -0,0 +1,23 @@ +require File.expand_path('../spec_helper', File.dirname(__FILE__)) + +describe Webcat::Session do + context 'with selenium driver' do + before do + @session = Webcat::Session.new(:selenium, TestApp) + end + + describe '#driver' do + it "should be a rack test driver" do + @session.driver.should be_an_instance_of(Webcat::Driver::Selenium) + end + end + + describe '#mode' do + it "should remember the mode" do + @session.mode.should == :selenium + end + end + + it_should_behave_like "session" + end +end diff --git a/spec/session_spec.rb b/spec/session_spec.rb index 1ffdc7be..95abf6a5 100644 --- a/spec/session_spec.rb +++ b/spec/session_spec.rb @@ -1,6 +1,12 @@ require File.expand_path('spec_helper', File.dirname(__FILE__)) +require 'nokogiri' + shared_examples_for "session" do + def extract_results(session) + YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.text + end + describe '#app' do it "should remember the application" do @session.app.should == TestApp @@ -10,9 +16,9 @@ shared_examples_for "session" do describe '#visit' do it "should fetch a response from the driver" do @session.visit('/') - @session.body.should == 'Hello world!' + @session.body.should include('Hello world!') @session.visit('/foo') - @session.body.should == 'Another World' + @session.body.should include('Another World') end end @@ -24,21 +30,21 @@ shared_examples_for "session" do context "with id given" do it "should take user to the linked page" do @session.click_link('foo') - @session.body.should == 'Another World' + @session.body.should include('Another World') end end context "with text given" do it "should take user to the linked page" do @session.click_link('labore') - @session.body.should == '
' + params[:form].to_yaml + '' end post '/upload' do