Changed to use selenium-webdriver and it works!

This commit is contained in:
Jonas Nicklas and Kevin Fitzpatrick 2009-11-14 10:44:46 +01:00 committed by Jonas Nicklas
parent feb29e2d64
commit ac7d044243
11 changed files with 135 additions and 141 deletions

9
lib/webcat/cucumber.rb Normal file
View File

@ -0,0 +1,9 @@
require 'webcat'
require 'webcat/dsl'
if defined?(Rails)
Webcat.app = ActionController::Dispatcher.new
end
World(Webcat)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

1
spec/fixtures/test_file.txt vendored Normal file
View File

@ -0,0 +1 @@
ThisIsTheTestFile

View File

@ -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

View File

@ -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 == '<h1>Bar</h1>'
@session.body.should include('<h1>Bar</h1>')
end
end
context "with title given" do
it "should take user to the linked page" do
@session.click_link('awesome title')
@session.body.should == '<h1>Bar</h1>'
@session.body.should include('<h1>Bar</h1>')
end
end
@ -64,7 +70,7 @@ shared_examples_for "session" do
context "with value given on a submit button" do
before do
@session.click_button('awesome')
@results = YAML.load(@session.body)
@results = extract_results(@session)
end
it "should serialize and submit text fields" do
@ -121,24 +127,21 @@ shared_examples_for "session" do
context "with id given on a submit button" do
it "should submit the associated form" do
@session.click_button('awe123')
results = YAML.load(@session.body)
results['first_name'].should == 'John'
extract_results(@session)['first_name'].should == 'John'
end
end
context "with value given on an image button" do
it "should submit the associated form" do
@session.click_button('okay')
results = YAML.load(@session.body)
results['first_name'].should == 'John'
extract_results(@session)['first_name'].should == 'John'
end
end
context "with id given on an image button" do
it "should submit the associated form" do
@session.click_button('okay556')
results = YAML.load(@session.body)
results['first_name'].should == 'John'
extract_results(@session)['first_name'].should == 'John'
end
end
@ -156,39 +159,39 @@ shared_examples_for "session" do
it "should fill in a text field by id" do
@session.fill_in('form_first_name', :with => 'Harry')
@session.click_button('awesome')
YAML.load(@session.body)['first_name'].should == 'Harry'
extract_results(@session)['first_name'].should == 'Harry'
end
it "should fill in a text field by label" do
@session.fill_in('First Name', :with => 'Harry')
@session.click_button('awesome')
YAML.load(@session.body)['first_name'].should == 'Harry'
extract_results(@session)['first_name'].should == 'Harry'
end
it "should fill in a textarea by id" do
@session.fill_in('form_description', :with => 'Texty text')
@session.click_button('awesome')
YAML.load(@session.body)['description'].should == 'Texty text'
extract_results(@session)['description'].should == 'Texty text'
end
it "should fill in a textarea by label" do
@session.fill_in('Description', :with => 'Texty text')
@session.click_button('awesome')
YAML.load(@session.body)['description'].should == 'Texty text'
extract_results(@session)['description'].should == 'Texty text'
end
it "should fill in a password field by id" do
pending "Culerity doesn't like password fields for some reason" if @session.mode == :culerity
@session.fill_in('form_password', :with => 'supasikrit')
@session.click_button('awesome')
YAML.load(@session.body)['password'].should == 'supasikrit'
extract_results(@session)['password'].should == 'supasikrit'
end
it "should fill in a password field by label" do
pending "Culerity doesn't like password fields for some reason" if @session.mode == :culerity
@session.fill_in('Password', :with => 'supasikrit')
@session.click_button('awesome')
YAML.load(@session.body)['password'].should == 'supasikrit'
extract_results(@session)['password'].should == 'supasikrit'
end
end
@ -200,13 +203,13 @@ shared_examples_for "session" do
it "should choose a radio button by id" do
@session.choose("gender_male")
@session.click_button('awesome')
YAML.load(@session.body)['gender'].should == 'male'
extract_results(@session)['gender'].should == 'male'
end
it "should choose a radio button by label" do
@session.choose("Both")
@session.click_button('awesome')
YAML.load(@session.body)['gender'].should == 'both'
extract_results(@session)['gender'].should == 'both'
end
end
@ -219,7 +222,7 @@ shared_examples_for "session" do
pending "Culerity doesn't like hidden fields for some reason" if @session.mode == :culerity
@session.set_hidden_field("form_token", :to => 'test567')
@session.click_button('awesome')
YAML.load(@session.body)['token'].should == 'test567'
extract_results(@session)['token'].should == 'test567'
end
end
@ -231,13 +234,13 @@ shared_examples_for "session" do
it "should check a checkbox by id" do
@session.check("form_pets_cat")
@session.click_button('awesome')
YAML.load(@session.body)['pets'].should include('dog', 'cat', 'hamster')
extract_results(@session)['pets'].should include('dog', 'cat', 'hamster')
end
it "should check a checkbox by label" do
@session.check("Cat")
@session.click_button('awesome')
YAML.load(@session.body)['pets'].should include('dog', 'cat', 'hamster')
extract_results(@session)['pets'].should include('dog', 'cat', 'hamster')
end
end
@ -250,16 +253,16 @@ shared_examples_for "session" do
pending "Culerity doesn't seem to uncheck this" if @session.mode == :culerity
@session.uncheck("form_pets_hamster")
@session.click_button('awesome')
YAML.load(@session.body)['pets'].should include('dog')
YAML.load(@session.body)['pets'].should_not include('hamster')
extract_results(@session)['pets'].should include('dog')
extract_results(@session)['pets'].should_not include('hamster')
end
it "should uncheck a checkbox by label" do
pending "Culerity doesn't seem to uncheck this" if @session.mode == :culerity
@session.uncheck("Hamster")
@session.click_button('awesome')
YAML.load(@session.body)['pets'].should include('dog')
YAML.load(@session.body)['pets'].should_not include('hamster')
extract_results(@session)['pets'].should include('dog')
extract_results(@session)['pets'].should_not include('hamster')
end
end
@ -271,13 +274,13 @@ shared_examples_for "session" do
it "should select an option from a select box by id" do
@session.select("Finish", :from => 'form_locale')
@session.click_button('awesome')
YAML.load(@session.body)['locale'].should == 'fi'
extract_results(@session)['locale'].should == 'fi'
end
it "should select an option from a select box by label" do
@session.select("Finish", :from => 'Locale')
@session.click_button('awesome')
YAML.load(@session.body)['locale'].should == 'fi'
extract_results(@session)['locale'].should == 'fi'
end
end
@ -305,27 +308,31 @@ shared_examples_for "session" do
it "should set a file path by id" do
@session.attach_file "form_image", __FILE__
@session.click_button('awesome')
YAML.load(@session.body)['image'].should == File.basename(__FILE__)
extract_results(@session)['image'].should == File.basename(__FILE__)
end
it "should set a file path by label" do
@session.attach_file "Image", __FILE__
@session.click_button('awesome')
YAML.load(@session.body)['image'].should == File.basename(__FILE__)
extract_results(@session)['image'].should == File.basename(__FILE__)
end
end
context "with multipart form" do
before do
@test_file_path = File.expand_path('fixtures/test_file.txt', File.dirname(__FILE__))
end
it "should set a file path by id" do
@session.attach_file "form_document", __FILE__
@session.attach_file "form_document", @test_file_path
@session.click_button('Upload')
@session.body.should == File.read(__FILE__)
@session.body.should include(File.read(@test_file_path))
end
it "should set a file path by label" do
@session.attach_file "Document", __FILE__
@session.attach_file "Document", @test_file_path
@session.click_button('Upload')
@session.body.should == File.read(__FILE__)
@session.body.should include(File.read(@test_file_path))
end
end

View File

@ -46,7 +46,7 @@ class TestApp < Sinatra::Base
end
post '/form' do
params[:form].to_yaml
'<pre id="results">' + params[:form].to_yaml + '</pre>'
end
post '/upload' do