Skip to content

Instantly share code, notes, and snippets.

@jarib
Created April 5, 2011 20:44
Show Gist options
  • Save jarib/904503 to your computer and use it in GitHub Desktop.
Save jarib/904503 to your computer and use it in GitHub Desktop.
Nested LoadableComponents in Ruby
require 'selenium-webdriver'
#
# Read more about LoadableComponent here:
#
# http://code.google.com/p/selenium/wiki/LoadableComponent
#
class LoadableComponent
attr_reader :driver
class UnableToLoadComponent < StandardError; end
def initialize(driver, parent = nil)
@driver = driver
@parent = parent
end
def load
raise "subclass' responsibility"
end
def loaded?
raise "subclass' responsibility"
end
def get
load unless loaded?
unless loaded?
raise UnableToLoadComponent, unable_to_load_message
end
self
end
private
def unable_to_load_message
"could not load #{self.class.name}"
end
# shouldn't really live here
def self.wait(timeout, name = :wait)
define_method name do
@wait ||= Selenium::WebDriver::Wait.new(:timeout => timeout)
end
end
end
class Tweeter
def initialize(user, pass)
@user = user
@pass = pass
end
def tweet(str)
main_page.get.tweet str
end
private
def driver
@driver ||= Selenium::WebDriver.for :firefox
end
def login_page
@login_page ||= LoginPage.new(driver, @user, @pass)
end
def main_page
@main_page ||= MainPage.new(driver, login_page)
end
class LoginPage < LoadableComponent
wait 5
def initialize(driver, user, pass)
super(driver)
@user, @pass = user, pass
end
def login
user_field.send_keys @user
password_field.send_keys @pass
sign_in_button.click
end
def load
driver.get "http://twitter.com/login"
wait.until { user_field.displayed? }
end
def loaded?
user_field
true
rescue Selenium::WebDriver::Error::NoSuchElementError
false
end
private
def user_field
driver[:name => 'session[username_or_email]']
end
def password_field
driver[:name => 'session[password]']
end
def sign_in_button
driver[:class => "signin"].first(:xpath => "//button[@type='submit']")
end
end # LoginPage
class MainPage < LoadableComponent
wait 5
def tweet(str)
tweet_box.send_keys str
wait.until { tweet_button.enabled? }
last = last_tweet_id
begin
tweet_button.click
rescue Selenium::WebDriver::Error::ElementNotDisplayedError
raise "firefox needs focus to post a tweet"
end
wait.until { last_tweet_id != last }
end
def load
@parent.get.login
driver.switch_to.default_content # Fx4 bug
end
def loaded?
driver['session']['class'] == "loggedin"
rescue Selenium::WebDriver::Error::NoSuchElementError
false
end
def unable_to_load_message
"could not log in - captcha?"
end
private
def last_tweet_id
driver[:class => "stream-item"]['data-item-id']
end
def tweet_box
driver[:class => "twitter-anywhere-tweet-box-editor"]
end
def tweet_button
driver[:class => "tweet-button"]
end
end # MainPage
end # Tweeter
if __FILE__ == $0
abort "USAGE: #{$PROGRAM_NAME} user pass" unless ARGV.size == 2
Tweeter.new(*ARGV).tweet("#SeConf is awesome! http://tryselenium.org")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment