module Taza # An abstraction of a web page, place the elements you care about accessing in here as well as specify the filters that apply when trying to access the element. # # Example: # require 'taza' # class HomePage < Taza::Page # element(:foo) {browser.element_by_xpath('some xpath')} # filter :title_given, :foo # # def title_given # browser.title.nil? # end # end # # homepage.foo will return the element specified in the block if the filter returned true class Page attr_accessor :browser class << self def elements # :nodoc: @elements ||= {} end def filters # :nodoc: @filters ||= Hash.new { [] } end end # A element on a page # # Watir Example: # class HomePage < Taza::Page # element(:foo) {browser.element_by_xpath('some xpath')} # end # homepage.foo.click def self.element(name,&block) if name.nil? raise ElementError, "Element name can not be nil" end if !@module.nil? self.elements[@module] = Hash.new if self.elements[@module].nil? self.elements[@module] = self.elements[@module].merge({ name => block }) elsif !self.elements[name].nil? raise ElementError,"Duplicate definations for Element - #{name} on Page - #{self.to_s}" else self.elements[name] = block end end # A filter for element(s) on a page # Example: # class HomePage < Taza::Page # element(:foo) {browser.element_by_xpath('some xpath')} # filter :title_given, :foo # #a filter will apply to all elements if none are specified # filter :some_filter # #a filter will also apply to all elements if the symbol :all is given # filter :another_filter, :all # # def some_filter # true # end # # def some_filter # true # end # # def title_given # browser.title.nil? # end # end def self.filter(method_name, *elements) elements = [:all] if elements.empty? elements.each do |element| self.filters[element] = self.filters[element] << method_name end end def self.page_module(name,&block) puts "Warning: page_module is deprecated; use a partial instead." @module = name yield(block) @module = nil end def self.page_module_filter(method_name, page_module_name, *elements) elements = [page_module_name] if elements.empty? elements.each do |element| self.filters[element] = self.filters[element] << method_name end end def initialize(page_module = nil) add_element_methods(page_module) @active_filters = [] end def add_element_methods(page_module = nil) # :nodoc: self.class.elements.each do |element_name,element_block| if page_module == element_name element_block.each do |key,value| filters = self.class.filters[element_name] + self.class.filters[:all] + self.class.filters[key] add_element_method(:filters => filters, :element_name => key, :element_block => value) end else filters = self.class.filters[element_name] + self.class.filters[:all] add_element_method(:filters => filters, :element_name => element_name, :element_block => element_block) end end end def add_element_method(params) # :nodoc: define_singleton_method(params[:element_name]) do |*args| check_filters(params) self.instance_exec(*args, ¶ms[:element_block]) end end def check_filters(params) # :nodoc: params[:filters].each do |filter_method| unless @active_filters.include?(filter_method) @active_filters << filter_method raise FilterError, "#{filter_method} returned false for #{params[:element_name]}" unless send(filter_method) @active_filters.delete(filter_method) end end end end class FilterError < StandardError; end class ElementError < StandardError; end end