Sunday, August 22, 2010

Page Generator Example

Last time I posted I promised some code.  I finally got around to compiling the code into a format that could be placed on this blog.  I borrowed some of these methods from our framework library, but I think this code illustrates how efficient a generator can be for formatting page locators.  Page object pattern is a valuable approach to an automation framework.

Note that this code calls a test helper file.  I have not included that here, but basically it is a file that specifies the gems that are necessary.

require 'rubygems'
gem "rspec", "=1.1.12"
require "spec"
gem "selenium-client", ">=1.2.18"
require "selenium/client"


In the code below there are two generators.  One can be used to get all of the links on the page and the other is used for other html elements.

Once these generators are executed the locators can be placed in a page file.  At the bottom of the output the labels are formatted into the correct accessor format for a page object file.

Below is a ton of code so enjoy!  Let me know if you have any questions.

One final comment in that not of all the links on Google's home page get formatted nicely.  I did not have time to fix the formats.

Hopefully on the next post I will provide the page file and an example of using the page file.

Enjoy!


require File.dirname(__FILE__) + "/../../spec/test_helper"

describe "Generate home page locators for google" do

  append_after(:each) do
    browser.close_current_browser_session
  end

  it "should generate locators for check boxes, text boxes, text areas, input images,and select boxes for the google home page" do

    my_setup("http://www.google.com/")

    browser.open ("/")

    get_source_and_print_elements(browser)
  end

  it "should generate and format the links from the google home page" do

    my_setup("http://www.google.com/")

    browser.open ("/")

    html = browser.get_html_source

    generate_link_instance_variables_from_html(html)
  end


  #  Below are the methods that help to extract out the components from the html and format them into locators and accessors

  def my_setup(target)

    @browser = Selenium::Client::Driver.new \
    :host => ENV['Host'] || "localhost",
    :port => 4444,
    :browser => ENV['SELENIUM_RC_BROWSER'] || "*firefox",
    :url => target,
    :timeout_in_second => 60

    browser.start_new_browser_session

  end

  def browser
    return @browser
  end

  def get_source_and_print_elements(browser)
    html =browser.get_html_source
    html_elements_check_boxes = GooglePage.generate_instance_variables_from_html(:html =>html, :locator_type => "css", :locator => "input[type='checkbox']")
    html_elements_text = GooglePage.generate_instance_variables_from_html(:html =>html, :locator_type => "css", :locator => "input[type='text']")
    html_elements_selectGooglePage.generate_instance_variables_from_html(:html =>html, :locator_type => "css", :locator => "select")
    html_elements_text_area=GooglePage.generate_instance_variables_from_html(:html =>html, :locator_type => "css", :locator => "textarea")
    html_elements_image = GoogleBasePage.generate_instance_variables_from_html(:html =>html, :locator_type => "css", :locator => "input[type='image']")
    html_elements_radio = GooglePage.generate_instance_variables_from_html(:html =>html, :locator_type => "css", :locator => "input[type='radio']")
    html_elements_form = GooglePage.generate_instance_variables_from_html(:html =>html, :locator_type => "css", :locator => "form")
    merge_and_print_elements([html_elements_check_boxes, html_elements_select, html_elements_text,
                              html_elements_text_area, html_elements_image, html_elements_radio, html_elements_form])
  end


  def generate_instance_variables_from_html(options)
    if options.kind_of?(Hash)
      @html = options[:html]
      @locator_type = options[:locator_type]
      @locator = options[:locator]
    end
    doc = Nokogiri::HTML(@html)
    html_elements = {}
    if (@locator_type=="css")
      doc.css(@locator).each do |html_element|
        attribute_name =  html_element.get_attribute("id")
        attribute_value = html_element.get_attribute("id")
        if !attribute_name.nil?
          attribute_name.gsub!('input-', '')
          attribute_name.gsub!('select-', '')
#          attribute_name.gsub!(/([A-Z]+)/, '_\1')
          attribute_name.gsub!('\\', '')
          attribute_name.gsub!(' ', '_')
          attribute_name.gsub!('.', '_')
          attribute_name.gsub!('-', '_')
          attribute_name.gsub!('__', '_')
          attribute_name = attribute_name.to_s.downcase
          puts "@#{attribute_name} = \"#{attribute_value}\"" if $debug
          html_elements[attribute_name]= attribute_value
        end
      end
    end
    return html_elements
  end

  def merge_and_print_elements(page_elements_types)
    html_elements={}
    page_elements_types.each do |element_type|
      html_elements.merge!(element_type)
    end

    puts "found (#{html_elements.length} elements)"

    html_elements.keys.sort.each do |key|
      puts "@#{key} = \"#{html_elements[key]}\""
    end
    html_elements.keys.sort.each do |key|
      print ":#{key}, "
    end
  end

  def generate_link_instance_variables_from_html(html)

    doc = Nokogiri::HTML(html)
    links = {}
    doc.css("a").each do |link|
    #  puts link
      link.text

      links =  format_link_text_from_label(link, links)
    end

    links.each_pair { |key, value| puts "@#{key} =  \"css=a:contains(\\\"#{value}\\\")\"" }
    links.each_key { |key| print ":#{key}, " }

    return links
  end

  def format_link_text(link, links)
    link_content=link.content.to_s.downcase
    link_content = link_content.strip
    link_content.gsub!(' ', '_')
    link_content.gsub!('"', '')
    link_content.gsub!('-', '_')
    link_content.gsub!('+', '_')
    link_content.gsub!('*', '')
    link_content.gsub!('\'', '')
    link_content.chomp
    #puts "#{link_content} --->     #{link.get_attribute("href")} "
    links[link_content] = link.get_attribute("href")
    return links
  end

  def format_link_text_from_label(link, links)
    link_text=link.text.strip
    link_text=link_text.chomp
    link_content=link.content.to_s.downcase
    link_content = link_content.strip
    link_content.gsub!(' ', '_')
    link_content.gsub!('"', '')
    link_content.gsub!('-', '_')
    link_content.gsub!('+', '_')
    link_content.gsub!('*', '')
    link_content.gsub!('\'', '')
    link_content.gsub!('_&_', '_')
    link_content.gsub!('(', '')
    link_content.gsub!(')', '')
    link_content.gsub!(':', '')
    link_content.gsub!('.', '_')
    link_content.gsub!('@', '_')
    link_content.chomp
    links[link_content] = link_text
    return links
  end

end

No comments: