Created
April 5, 2011 20:44
-
-
Save jarib/904503 to your computer and use it in GitHub Desktop.
Nested LoadableComponents in Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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