lib/domkey/view/page_object.rb in domkey-0.1.0 vs lib/domkey/view/page_object.rb in domkey-0.2.0

- old
+ new

@@ -1,120 +1,120 @@ +require 'domkey/view/widgetry_package' +require 'domkey/view/watir_widget' + module Domkey module View + # PageObject represents an semantically essential area in a View + # It is an object that responds to set and value as the main way of sending data to it. + # it is composed of one or more watir elements. + # PageObject encapuslates the widgetry of DOM elements to provide semantic interfact to the user of the widgetry + # + # Compose PageObject with package and container + # + # What is a container? it's a proc, a callable object that plays a role of a container for package widgetry + # container can be one of: + # - browser (default) + # - a pageobject + # + # What is package? it's a proc of DOM elements widgetry that can be found inside the container + # package can be one of the following: + # - definition of single watir element i.e. `-> { text_field(:id, 'foo')}` + # - a pageobject i.e. previously instantiated definition + # - hash where key defines subelement and value a definition or pageobject + # + # Usage: + # Clients would not usually instantate this class. + # A client class which acts as a View would use a :dom factory method to create PageObjects + # Example: + # + # class MyView + # include Domkey::View + # + # dom(:headline) { text_field(id:, 'some_desc_text') } + # + # def property + # PropertyPanel.new browser.div(id: 'container') + # end + # end + # + # class PropertyPanel + # include Domkey::View + # dom(:headline) { text_field(class: 'headline_for_house') } + # end + # + # view = MyView.new + # view.headline.set 'HomeAway Rules!' + # view.value #=> returns 'HomeAway Rules!' + # view.property.headline.set 'Awesome Vactaion Home' + # view.property.headline.value #=> returns 'Awesome Vaction Home' + # class PageObject - attr_accessor :watirproc, :container + # @api private + include WidgetryPackage - # PageObject represents an semantically essential area in a View - # It is an object that responds to set and value as the main way of sending data to it. - # it is composed of one or more watir elements. - # PageObject encapuslates the widgetry of DOM elements to provide semantic interfact to the user of the widgetry - # - # Compose PageObject with watirproc and container - # - # What is a container? it's a proc, a callable object that plays a role of a container for watirproc widgetry - # container can be one of: - # - browser (default) - # - a pageobject - # - # What is watirproc? it's a proc of DOM elements widgetry that can be found inside the container - # watirproc can be one of the following: - # - definition of single watir element i.e. `-> { text_field(:id, 'foo')}` - # - a pageobject i.e. previously instantiated definition - # - hash where key defines subelement and value a definition or pageobject - # - # Usage: - # Clients would not usually instantate this class. - # A client class which acts as a View would use a :dom factory method to create PageObjects - # Example: - # - # class MyView - # include Domkey::View - # - # dom(:headline) { text_field(id:, 'some_desc_text') } - # - # def property - # PropertyPanel.new browser.div(id: 'container') - # end - # end - # - # class PropertyPanel - # include Domkey::View - # dom(:headline) { text_field(class: 'headline_for_house') } - # end - # - # view = MyView.new - # view.headline.set 'HomeAway Rules!' - # view.value #=> returns 'HomeAway Rules!' - # view.property.headline.set 'Awesome Vactaion Home' - # view.property.headline.value #=> returns 'Awesome Vaction Home' - # - def initialize watirproc, container=lambda { Domkey.browser } - @container = container - @watirproc = initialize_this watirproc - end - + # Each Semantic PageObject defines what value means for itself + # @param [SemanticValue] Delegated to WebdriverElement and we expect it to respond to set + # @parma [Hash{Symbol => SemanticValue}] def set value - return instantiator.set(value) unless value.respond_to?(:each_pair) - value.each_pair { |k, v| watirproc.fetch(k).set(v) } + return watir_widget.set value unless value.respond_to?(:each_pair) + value.each_pair { |k, v| package.fetch(k).set(v) } end + alias_method :value=, :set + + # Each Semantic PageObject defines what value means for itself + # @return [SemanticValue] delegated to WebdriverElement and we expect it to respond to value message + # @return [Hash{Symbol => SemanticValue}] def value - return instantiator.value unless watirproc.respond_to?(:each_pair) - Hash[watirproc.map { |key, pageobject| [key, pageobject.value] }] + return watir_widget.value unless package.respond_to?(:each_pair) + Hash[package.map { |key, pageobject| [key, pageobject.value] }] end - # access widgetry of watir elements composing this page object - def element(key=false) - return instantiator unless watirproc.respond_to?(:each_pair) - return watirproc.fetch(key).element if key - Hash[watirproc.map { |key, watirproc| [key, watirproc.element] }] + def options + return watir_widget.options unless package.respond_to?(:each_pair) + Hash[package.map { |key, pageobject| [key, pageobject.options] }] end private - # recursive - def initialize_this watirproc - if watirproc.respond_to?(:each_pair) #hash - Hash[watirproc.map { |key, watirproc| [key, PageObject.new(watirproc, container)] }] + # wrap instantiator with strategy for setting and getting value for watir object + # expects that element to respond to set and value + # @returns [WatirWidget] + def watir_widget + WatirWidget.new(instantiator) + end + + # @api private + # Recursive. Examines each packages and turns each Proc into PageObject + def initialize_this package + if package.respond_to?(:each_pair) #hash + Hash[package.map { |key, package| [key, PageObject.new(package, container)] }] else - if watirproc.respond_to?(:call) #proc + if package.respond_to?(:call) #proc begin # peek inside suitcase that is proc. XXX ouch, ugly - peeked_inside = watirproc.call + peeked_inside = package.call rescue NoMethodError - return watirproc #suitecase exploded, proc returned + return package #suitecase exploded, proc returned end if peeked_inside.respond_to?(:each_pair) # hash return initialize_this peeked_inside elsif peeked_inside.respond_to?(:wd) # watir element return lambda { peeked_inside } - elsif peeked_inside.respond_to?(:watirproc) #pageobject - return peeked_inside.watirproc + elsif peeked_inside.respond_to?(:package) #pageobject + return peeked_inside.package else - fail Exception::Error, "watirproc must be kind of hash, watirelement or pageobject but I got this: #{watirproc}" + fail Exception::Error, "package must be kind of hash, watirelement or pageobject but I got this: #{package}" end - elsif watirproc.respond_to?(:watirproc) #pageobject - return watirproc.watirproc + elsif package.respond_to?(:package) #pageobject + return package.package else - fail Exception::Error, "watirproc must be kind of hash, watirelement or pageobject but I got this: #{watirproc}" + fail Exception::Error, "package must be kind of hash, watirelement or pageobject but I got this: #{package}" end end - end - - # talk to the browser executor. - # returns runtime element in a specified container - # expects that element to respond to set and value - def instantiator - container_instantiator.instance_exec(&watirproc) - end - - # talk to the browser - # returns runtime container element in a browser/driver - def container_instantiator - container.respond_to?(:call) ? container.call : container.send(:instantiator) end end end end \ No newline at end of file