ae_page_objects 0.0.1.beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/ae_page_objects.rb +57 -0
 - data/lib/ae_page_objects/concerns/load_ensuring.rb +30 -0
 - data/lib/ae_page_objects/concerns/staleable.rb +29 -0
 - data/lib/ae_page_objects/concerns/visitable.rb +61 -0
 - data/lib/ae_page_objects/core/application.rb +85 -0
 - data/lib/ae_page_objects/core/application_router.rb +60 -0
 - data/lib/ae_page_objects/core/configurable.rb +27 -0
 - data/lib/ae_page_objects/core/configuration.rb +33 -0
 - data/lib/ae_page_objects/core/constant_resolver.rb +33 -0
 - data/lib/ae_page_objects/core/dependencies_hook.rb +21 -0
 - data/lib/ae_page_objects/core/dsl/collection.rb +135 -0
 - data/lib/ae_page_objects/core/dsl/element.rb +45 -0
 - data/lib/ae_page_objects/core/dsl/form_for.rb +30 -0
 - data/lib/ae_page_objects/core/dsl/nested_element.rb +24 -0
 - data/lib/ae_page_objects/core/internal_helpers.rb +9 -0
 - data/lib/ae_page_objects/core/rake_router.rb +148 -0
 - data/lib/ae_page_objects/document.rb +19 -0
 - data/lib/ae_page_objects/element.rb +86 -0
 - data/lib/ae_page_objects/element_proxy.rb +72 -0
 - data/lib/ae_page_objects/elements/checkbox.rb +19 -0
 - data/lib/ae_page_objects/elements/collection.rb +61 -0
 - data/lib/ae_page_objects/elements/form.rb +10 -0
 - data/lib/ae_page_objects/elements/has_one.rb +11 -0
 - data/lib/ae_page_objects/elements/select.rb +7 -0
 - data/lib/ae_page_objects/node.rb +73 -0
 - data/lib/ae_page_objects/version.rb +3 -0
 - metadata +184 -0
 
| 
         @@ -0,0 +1,135 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AePageObjects
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Dsl
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Collection
         
     | 
| 
      
 4 
     | 
    
         
            +
                  extend ActiveSupport::Concern
         
     | 
| 
      
 5 
     | 
    
         
            +
                  include Dsl::Element
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                  module ClassMethods
         
     | 
| 
      
 8 
     | 
    
         
            +
                    include InternalHelpers
         
     | 
| 
      
 9 
     | 
    
         
            +
                    
         
     | 
| 
      
 10 
     | 
    
         
            +
                    # Defines a collection of elements. Blocks are evaluated on the item class used by the 
         
     | 
| 
      
 11 
     | 
    
         
            +
                    # collection. collection() defines a method on the class that returns an instance of a collection
         
     | 
| 
      
 12 
     | 
    
         
            +
                    # class which contains instances of the collection's item class.
         
     | 
| 
      
 13 
     | 
    
         
            +
                    #
         
     | 
| 
      
 14 
     | 
    
         
            +
                    # Supported signatures are described below. 
         
     | 
| 
      
 15 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 16 
     | 
    
         
            +
                    # ------------------------------------------------        
         
     | 
| 
      
 17 
     | 
    
         
            +
                    # Signature: (:is, no :contains, no block)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 19 
     | 
    
         
            +
                    #     collection :addresses, :is => AddressList
         
     | 
| 
      
 20 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 21 
     | 
    
         
            +
                    #   Collection class: AddressList
         
     | 
| 
      
 22 
     | 
    
         
            +
                    #   Item class:       AddressList.item_class
         
     | 
| 
      
 23 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 24 
     | 
    
         
            +
                    # ------------------------------------------------
         
     | 
| 
      
 25 
     | 
    
         
            +
                    # Signature: (no :is, :contains, no block)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 27 
     | 
    
         
            +
                    #     collection :addresses, :contains => Address
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 29 
     | 
    
         
            +
                    #   Collection class: one-off subclass of ::AePageObjects::Collection  
         
     | 
| 
      
 30 
     | 
    
         
            +
                    #   Item class:       Address
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 32 
     | 
    
         
            +
                    # ------------------------------------------------
         
     | 
| 
      
 33 
     | 
    
         
            +
                    # Signature: (:is, :contains, no block)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 35 
     | 
    
         
            +
                    #     collection :addresses, :is => AddressList, :contains => ExtendedAddress
         
     | 
| 
      
 36 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 37 
     | 
    
         
            +
                    #   Collection class: one-off subclass ofAddressList
         
     | 
| 
      
 38 
     | 
    
         
            +
                    #   Item class:       ExtendedAddress
         
     | 
| 
      
 39 
     | 
    
         
            +
                    #   
         
     | 
| 
      
 40 
     | 
    
         
            +
                    # ------------------------------------------------
         
     | 
| 
      
 41 
     | 
    
         
            +
                    # Signature: (no :is, no :contains, block)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 43 
     | 
    
         
            +
                    #     collection :addresses do
         
     | 
| 
      
 44 
     | 
    
         
            +
                    #       element :city
         
     | 
| 
      
 45 
     | 
    
         
            +
                    #       element :state
         
     | 
| 
      
 46 
     | 
    
         
            +
                    #     end
         
     | 
| 
      
 47 
     | 
    
         
            +
                    #   
         
     | 
| 
      
 48 
     | 
    
         
            +
                    #   Collection class: one-off subclass of ::AePageObjects::Collection
         
     | 
| 
      
 49 
     | 
    
         
            +
                    #   Item class:       one-off subclass of ::AePageObjects::Element
         
     | 
| 
      
 50 
     | 
    
         
            +
                    #   Methods defined on item class:
         
     | 
| 
      
 51 
     | 
    
         
            +
                    #     city()  # -> instance of ::AePageObjects::Element
         
     | 
| 
      
 52 
     | 
    
         
            +
                    #     state() # -> instance of ::AePageObjects::Element
         
     | 
| 
      
 53 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 54 
     | 
    
         
            +
                    # ------------------------------------------------
         
     | 
| 
      
 55 
     | 
    
         
            +
                    # Signature: (:is, no :contains, block)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 57 
     | 
    
         
            +
                    #   collection :addresses, :is => AddressList do
         
     | 
| 
      
 58 
     | 
    
         
            +
                    #     element :longitude
         
     | 
| 
      
 59 
     | 
    
         
            +
                    #     element :latitude
         
     | 
| 
      
 60 
     | 
    
         
            +
                    #   end
         
     | 
| 
      
 61 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 62 
     | 
    
         
            +
                    #   Collection class: one-off subclass of AddressList  
         
     | 
| 
      
 63 
     | 
    
         
            +
                    #   Item class:       one-off subclass of AddressList.item_class
         
     | 
| 
      
 64 
     | 
    
         
            +
                    #   Methods defined on item class:
         
     | 
| 
      
 65 
     | 
    
         
            +
                    #     longitude()  # -> instance of ::AePageObjects::Element
         
     | 
| 
      
 66 
     | 
    
         
            +
                    #     latitude() # -> instance of ::AePageObjects::Element
         
     | 
| 
      
 67 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 68 
     | 
    
         
            +
                    # ------------------------------------------------
         
     | 
| 
      
 69 
     | 
    
         
            +
                    # Signature: (no :is, :contains, block)
         
     | 
| 
      
 70 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 71 
     | 
    
         
            +
                    #   collection :addresses, :contains => Address do
         
     | 
| 
      
 72 
     | 
    
         
            +
                    #     element :longitude
         
     | 
| 
      
 73 
     | 
    
         
            +
                    #     element :latitude
         
     | 
| 
      
 74 
     | 
    
         
            +
                    #   end
         
     | 
| 
      
 75 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 76 
     | 
    
         
            +
                    #   Collection class: one-off subclass of ::AePageObjects::Collection  element
         
     | 
| 
      
 77 
     | 
    
         
            +
                    #   Item class:       one-off subclass of Address
         
     | 
| 
      
 78 
     | 
    
         
            +
                    #   Methods defined on item class:
         
     | 
| 
      
 79 
     | 
    
         
            +
                    #     longitude()  # -> instance of ::AePageObjects::Element
         
     | 
| 
      
 80 
     | 
    
         
            +
                    #     latitude() # -> instance of ::AePageObjects::Element
         
     | 
| 
      
 81 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 82 
     | 
    
         
            +
                    # ------------------------------------------------
         
     | 
| 
      
 83 
     | 
    
         
            +
                    # Signature: (:is, :contains, block)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 85 
     | 
    
         
            +
                    #   collection :addresses, :is => AddressList, :contains => Address do
         
     | 
| 
      
 86 
     | 
    
         
            +
                    #     element :longitude
         
     | 
| 
      
 87 
     | 
    
         
            +
                    #     element :latitude
         
     | 
| 
      
 88 
     | 
    
         
            +
                    #   end
         
     | 
| 
      
 89 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 90 
     | 
    
         
            +
                    #   Collection class: one-off subclass of AddressList
         
     | 
| 
      
 91 
     | 
    
         
            +
                    #   Item class:       one-off subclass of Address
         
     | 
| 
      
 92 
     | 
    
         
            +
                    #   Methods defined on item class:
         
     | 
| 
      
 93 
     | 
    
         
            +
                    #     longitude()  # -> instance of ::AePageObjects::Element
         
     | 
| 
      
 94 
     | 
    
         
            +
                    #     latitude() # -> instance of ::AePageObjects::Element
         
     | 
| 
      
 95 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 96 
     | 
    
         
            +
                    def collection(name, options = {}, &block)
         
     | 
| 
      
 97 
     | 
    
         
            +
                      options ||= {}
         
     | 
| 
      
 98 
     | 
    
         
            +
                      
         
     | 
| 
      
 99 
     | 
    
         
            +
                      # only a collection class is specified or the item class
         
     | 
| 
      
 100 
     | 
    
         
            +
                      # specified matches the collection's item class
         
     | 
| 
      
 101 
     | 
    
         
            +
                      if block.blank? && options[:is] && ( 
         
     | 
| 
      
 102 
     | 
    
         
            +
                          options[:contains].blank? || options[:is].item_class == options[:contains] 
         
     | 
| 
      
 103 
     | 
    
         
            +
                        )
         
     | 
| 
      
 104 
     | 
    
         
            +
                        return element(name, options)
         
     | 
| 
      
 105 
     | 
    
         
            +
                      end
         
     | 
| 
      
 106 
     | 
    
         
            +
                      
         
     | 
| 
      
 107 
     | 
    
         
            +
                      options = options.dup
         
     | 
| 
      
 108 
     | 
    
         
            +
                      
         
     | 
| 
      
 109 
     | 
    
         
            +
                      # create/get the collection class
         
     | 
| 
      
 110 
     | 
    
         
            +
                      if options[:is]
         
     | 
| 
      
 111 
     | 
    
         
            +
                        ensure_class_for_param!(:is, options[:is], ::AePageObjects::Collection)
         
     | 
| 
      
 112 
     | 
    
         
            +
                      else
         
     | 
| 
      
 113 
     | 
    
         
            +
                        options[:is] = ::AePageObjects::Collection
         
     | 
| 
      
 114 
     | 
    
         
            +
                        
         
     | 
| 
      
 115 
     | 
    
         
            +
                        raise ArgumentError, "Must specify either a block or a :contains option." if options[:contains].blank? && block.blank?
         
     | 
| 
      
 116 
     | 
    
         
            +
                      end
         
     | 
| 
      
 117 
     | 
    
         
            +
                      
         
     | 
| 
      
 118 
     | 
    
         
            +
                      item_class = options.delete(:contains) || options[:is].item_class
         
     | 
| 
      
 119 
     | 
    
         
            +
                      if block.present?
         
     | 
| 
      
 120 
     | 
    
         
            +
                        item_class = item_class.new_subclass(&block).tap do |new_item_class|
         
     | 
| 
      
 121 
     | 
    
         
            +
                          new_item_class.element_attributes.merge!(item_class.element_attributes)
         
     | 
| 
      
 122 
     | 
    
         
            +
                        end
         
     | 
| 
      
 123 
     | 
    
         
            +
                      end
         
     | 
| 
      
 124 
     | 
    
         
            +
                      
         
     | 
| 
      
 125 
     | 
    
         
            +
                      # since we are creating a new item class, we need to subclass the collection class
         
     | 
| 
      
 126 
     | 
    
         
            +
                      # so we can parameterize the collection class with an item class
         
     | 
| 
      
 127 
     | 
    
         
            +
                      options[:is] = options[:is].new_subclass
         
     | 
| 
      
 128 
     | 
    
         
            +
                      options[:is].item_class = item_class
         
     | 
| 
      
 129 
     | 
    
         
            +
                    
         
     | 
| 
      
 130 
     | 
    
         
            +
                      element(name, options)
         
     | 
| 
      
 131 
     | 
    
         
            +
                    end
         
     | 
| 
      
 132 
     | 
    
         
            +
                  end
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
              end
         
     | 
| 
      
 135 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AePageObjects
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Dsl
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Element
         
     | 
| 
      
 4 
     | 
    
         
            +
                  extend ActiveSupport::Concern
         
     | 
| 
      
 5 
     | 
    
         
            +
                
         
     | 
| 
      
 6 
     | 
    
         
            +
                  module ClassMethods
         
     | 
| 
      
 7 
     | 
    
         
            +
                    
         
     | 
| 
      
 8 
     | 
    
         
            +
                    def inherited(subclass)
         
     | 
| 
      
 9 
     | 
    
         
            +
                      subclass.class_eval do
         
     | 
| 
      
 10 
     | 
    
         
            +
                        class << self
         
     | 
| 
      
 11 
     | 
    
         
            +
                          def element_attributes
         
     | 
| 
      
 12 
     | 
    
         
            +
                            @element_attributes ||= {}
         
     | 
| 
      
 13 
     | 
    
         
            +
                          end
         
     | 
| 
      
 14 
     | 
    
         
            +
                        end
         
     | 
| 
      
 15 
     | 
    
         
            +
                      end
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
                    
         
     | 
| 
      
 18 
     | 
    
         
            +
                    def element(name, options = {})
         
     | 
| 
      
 19 
     | 
    
         
            +
                      options = options.dup
         
     | 
| 
      
 20 
     | 
    
         
            +
                      klass   = field_klass(options)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      
         
     | 
| 
      
 22 
     | 
    
         
            +
                      self.element_attributes[name.to_sym] = klass
         
     | 
| 
      
 23 
     | 
    
         
            +
                    
         
     | 
| 
      
 24 
     | 
    
         
            +
                      define_method name do |&block|
         
     | 
| 
      
 25 
     | 
    
         
            +
                        ElementProxy.new(klass, self, name, options, &block)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                      
         
     | 
| 
      
 28 
     | 
    
         
            +
                      klass
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  
         
     | 
| 
      
 31 
     | 
    
         
            +
                  private
         
     | 
| 
      
 32 
     | 
    
         
            +
                  
         
     | 
| 
      
 33 
     | 
    
         
            +
                    def field_klass(options)
         
     | 
| 
      
 34 
     | 
    
         
            +
                      field_type = options.delete(:is)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    
         
     | 
| 
      
 36 
     | 
    
         
            +
                      if field_type.is_a? Class
         
     | 
| 
      
 37 
     | 
    
         
            +
                        field_type
         
     | 
| 
      
 38 
     | 
    
         
            +
                      else
         
     | 
| 
      
 39 
     | 
    
         
            +
                        ::AePageObjects::Element
         
     | 
| 
      
 40 
     | 
    
         
            +
                      end
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AePageObjects
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Dsl
         
     | 
| 
      
 3 
     | 
    
         
            +
                module FormFor
         
     | 
| 
      
 4 
     | 
    
         
            +
                  extend ActiveSupport::Concern
         
     | 
| 
      
 5 
     | 
    
         
            +
                  include Dsl::Element
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                  module ClassMethods
         
     | 
| 
      
 8 
     | 
    
         
            +
                
         
     | 
| 
      
 9 
     | 
    
         
            +
                    def form_for(form_name, options = {}, &block)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      options ||= {}
         
     | 
| 
      
 11 
     | 
    
         
            +
                    
         
     | 
| 
      
 12 
     | 
    
         
            +
                      raise ArgumentError, ":is option not supported" if options[:is]
         
     | 
| 
      
 13 
     | 
    
         
            +
                      raise ArgumentError, "Block required." unless block.present?
         
     | 
| 
      
 14 
     | 
    
         
            +
                    
         
     | 
| 
      
 15 
     | 
    
         
            +
                      klass = ::AePageObjects::Form.new_subclass(&block)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    
         
     | 
| 
      
 17 
     | 
    
         
            +
                      options      = options.dup
         
     | 
| 
      
 18 
     | 
    
         
            +
                      options[:is] = klass
         
     | 
| 
      
 19 
     | 
    
         
            +
                  
         
     | 
| 
      
 20 
     | 
    
         
            +
                      element(form_name, options)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    
         
     | 
| 
      
 22 
     | 
    
         
            +
                      klass.element_attributes.each do |node_name, node_klazz|
         
     | 
| 
      
 23 
     | 
    
         
            +
                        delegate node_name, :to => form_name
         
     | 
| 
      
 24 
     | 
    
         
            +
                        self.element_attributes[node_name] = node_klazz
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AePageObjects
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Dsl
         
     | 
| 
      
 3 
     | 
    
         
            +
                module NestedElement
         
     | 
| 
      
 4 
     | 
    
         
            +
                  extend ActiveSupport::Concern
         
     | 
| 
      
 5 
     | 
    
         
            +
                  include Dsl::Element
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                  module ClassMethods
         
     | 
| 
      
 8 
     | 
    
         
            +
                    
         
     | 
| 
      
 9 
     | 
    
         
            +
                    def element(name, options = {}, &block)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      raise ArgumentError, ":is option and block not supported together" if options[:is].present? && block_given?
         
     | 
| 
      
 11 
     | 
    
         
            +
                      
         
     | 
| 
      
 12 
     | 
    
         
            +
                      if block_given?
         
     | 
| 
      
 13 
     | 
    
         
            +
                        klass = ::AePageObjects::HasOne.new_subclass(&block)
         
     | 
| 
      
 14 
     | 
    
         
            +
                        
         
     | 
| 
      
 15 
     | 
    
         
            +
                        options = options.dup
         
     | 
| 
      
 16 
     | 
    
         
            +
                        options[:is] = klass
         
     | 
| 
      
 17 
     | 
    
         
            +
                      end
         
     | 
| 
      
 18 
     | 
    
         
            +
                      
         
     | 
| 
      
 19 
     | 
    
         
            +
                      super(name, options)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,9 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AePageObjects
         
     | 
| 
      
 2 
     | 
    
         
            +
              module InternalHelpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                def ensure_class_for_param!(param_name, klass, ancestor_class)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  if klass && ! (klass < ancestor_class)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    raise "#{param_name} <#{klass}> must extend #{ancestor_class}, ->#{klass.ancestors.inspect}"
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,148 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AePageObjects
         
     | 
| 
      
 2 
     | 
    
         
            +
              class RakeRouter
         
     | 
| 
      
 3 
     | 
    
         
            +
                
         
     | 
| 
      
 4 
     | 
    
         
            +
                attr_reader :routes
         
     | 
| 
      
 5 
     | 
    
         
            +
                
         
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize(rake_routes, mounted_prefix = '')
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @mounted_prefix = mounted_prefix || ""
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @routes = ActiveSupport::OrderedHash.new
         
     | 
| 
      
 9 
     | 
    
         
            +
                  route_line_regex = /(\w+)(?:\s[A-Z]+)?\s+(\/.*)\(.:format\).*$/
         
     | 
| 
      
 10 
     | 
    
         
            +
                  
         
     | 
| 
      
 11 
     | 
    
         
            +
                  rake_routes.split("\n").each do |line|
         
     | 
| 
      
 12 
     | 
    
         
            +
                    line = line.strip
         
     | 
| 
      
 13 
     | 
    
         
            +
                    matches = route_line_regex.match(line)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    if matches
         
     | 
| 
      
 15 
     | 
    
         
            +
                      @routes[matches[1].to_sym] = Route.new(matches[2], @mounted_prefix)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
                
         
     | 
| 
      
 20 
     | 
    
         
            +
                def path_recognizes_url?(path, url)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  if path.is_a?(String)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    path.sub(/\/$/, '') == url.sub(/\/$/, '')
         
     | 
| 
      
 23 
     | 
    
         
            +
                  elsif path.is_a?(Symbol)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    route = @routes[path]
         
     | 
| 
      
 25 
     | 
    
         
            +
                    route && route.matches?(url)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def generate_path(named_route, *args)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  if named_route.is_a?(String)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    return Path.new(@mounted_prefix + named_route)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  
         
     | 
| 
      
 34 
     | 
    
         
            +
                  if route = @routes[named_route]
         
     | 
| 
      
 35 
     | 
    
         
            +
                    options = args.extract_options!
         
     | 
| 
      
 36 
     | 
    
         
            +
                    route.generate_path(options)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
                
         
     | 
| 
      
 40 
     | 
    
         
            +
              private
         
     | 
| 
      
 41 
     | 
    
         
            +
              
         
     | 
| 
      
 42 
     | 
    
         
            +
                class Path < String
         
     | 
| 
      
 43 
     | 
    
         
            +
                  attr_reader :params, :regex
         
     | 
| 
      
 44 
     | 
    
         
            +
                  
         
     | 
| 
      
 45 
     | 
    
         
            +
                  def initialize(value)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    super(value.gsub(/(\/)+/, '/').sub(/\(\.\:format\)$/, ''))
         
     | 
| 
      
 47 
     | 
    
         
            +
                    
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @params = parse_params
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @regex  = generate_regex
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  
         
     | 
| 
      
 52 
     | 
    
         
            +
                  def generate(param_values)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    param_values = param_values.symbolize_keys
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @params.values.inject(self) do |path, param|
         
     | 
| 
      
 55 
     | 
    
         
            +
                      param.substitute(path, param_values)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                private
         
     | 
| 
      
 60 
     | 
    
         
            +
                  def parse_params
         
     | 
| 
      
 61 
     | 
    
         
            +
                    # overwrite the required status with the optional
         
     | 
| 
      
 62 
     | 
    
         
            +
                    {}.merge(required_params).merge(optional_params)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
                  
         
     | 
| 
      
 65 
     | 
    
         
            +
                  def find_params(using_regex)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    scan(using_regex).flatten.map(&:to_sym)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  
         
     | 
| 
      
 69 
     | 
    
         
            +
                  def optional_params
         
     | 
| 
      
 70 
     | 
    
         
            +
                    {}.tap do |optional_params|
         
     | 
| 
      
 71 
     | 
    
         
            +
                      find_params(/\(\/\:(\w+)\)/).each do |param_name|
         
     | 
| 
      
 72 
     | 
    
         
            +
                        optional_params[param_name] = Param.new(param_name, true)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      end
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
                  
         
     | 
| 
      
 77 
     | 
    
         
            +
                  def required_params
         
     | 
| 
      
 78 
     | 
    
         
            +
                    {}.tap do |required_params|
         
     | 
| 
      
 79 
     | 
    
         
            +
                      find_params(/\:(\w+)/).each do |param_name|
         
     | 
| 
      
 80 
     | 
    
         
            +
                        required_params[param_name] = Param.new(param_name, false)
         
     | 
| 
      
 81 
     | 
    
         
            +
                      end
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  def generate_regex
         
     | 
| 
      
 86 
     | 
    
         
            +
                    regex_spec = @params.values.inject(self) do |regex_spec, param|
         
     | 
| 
      
 87 
     | 
    
         
            +
                      param.replace_param_in_url(regex_spec)
         
     | 
| 
      
 88 
     | 
    
         
            +
                    end 
         
     | 
| 
      
 89 
     | 
    
         
            +
                    Regexp.new regex_spec
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
                
         
     | 
| 
      
 93 
     | 
    
         
            +
                class Param < Struct.new(:name, :optional)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  include Comparable
         
     | 
| 
      
 95 
     | 
    
         
            +
                  
         
     | 
| 
      
 96 
     | 
    
         
            +
                  alias :optional? :optional
         
     | 
| 
      
 97 
     | 
    
         
            +
                  
         
     | 
| 
      
 98 
     | 
    
         
            +
                  def <=>(other)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    name.to_s <=> other.name.to_s
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
                  
         
     | 
| 
      
 102 
     | 
    
         
            +
                  def eql?(other)
         
     | 
| 
      
 103 
     | 
    
         
            +
                    name == other.name
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
      
 105 
     | 
    
         
            +
                  
         
     | 
| 
      
 106 
     | 
    
         
            +
                  def hash
         
     | 
| 
      
 107 
     | 
    
         
            +
                    name.hash
         
     | 
| 
      
 108 
     | 
    
         
            +
                  end
         
     | 
| 
      
 109 
     | 
    
         
            +
                  
         
     | 
| 
      
 110 
     | 
    
         
            +
                  def replace_param_in_url(url)
         
     | 
| 
      
 111 
     | 
    
         
            +
                    if optional?
         
     | 
| 
      
 112 
     | 
    
         
            +
                      url.gsub("(/:#{name})", '(\/.+)?')
         
     | 
| 
      
 113 
     | 
    
         
            +
                    else
         
     | 
| 
      
 114 
     | 
    
         
            +
                      url.gsub(":#{name}", '(.+)')
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                  
         
     | 
| 
      
 118 
     | 
    
         
            +
                  def substitute(url, values)
         
     | 
| 
      
 119 
     | 
    
         
            +
                    if optional?
         
     | 
| 
      
 120 
     | 
    
         
            +
                      if values[name]
         
     | 
| 
      
 121 
     | 
    
         
            +
                        url.sub("(/:#{name})", "/#{values[name]}")
         
     | 
| 
      
 122 
     | 
    
         
            +
                      else
         
     | 
| 
      
 123 
     | 
    
         
            +
                        url.sub("(/:#{name})", '')
         
     | 
| 
      
 124 
     | 
    
         
            +
                      end
         
     | 
| 
      
 125 
     | 
    
         
            +
                    else
         
     | 
| 
      
 126 
     | 
    
         
            +
                      raise ArgumentError, "Missing required parameter '#{name}' for '#{url}' in #{values.inspect}" unless values.key? name
         
     | 
| 
      
 127 
     | 
    
         
            +
                      url.sub(":#{name}", values[name])
         
     | 
| 
      
 128 
     | 
    
         
            +
                    end
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
                end
         
     | 
| 
      
 131 
     | 
    
         
            +
              
         
     | 
| 
      
 132 
     | 
    
         
            +
                class Route
         
     | 
| 
      
 133 
     | 
    
         
            +
                  def initialize(spec, mounted_prefix)
         
     | 
| 
      
 134 
     | 
    
         
            +
                    @path = Path.new(mounted_prefix + spec)
         
     | 
| 
      
 135 
     | 
    
         
            +
                    @path.freeze
         
     | 
| 
      
 136 
     | 
    
         
            +
                  end
         
     | 
| 
      
 137 
     | 
    
         
            +
                
         
     | 
| 
      
 138 
     | 
    
         
            +
                  def matches?(url)
         
     | 
| 
      
 139 
     | 
    
         
            +
                    url =~ @path.regex
         
     | 
| 
      
 140 
     | 
    
         
            +
                  end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                  def generate_path(options)
         
     | 
| 
      
 143 
     | 
    
         
            +
                    options = options.symbolize_keys
         
     | 
| 
      
 144 
     | 
    
         
            +
                    @path.generate(options)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AePageObjects
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Document < Node
         
     | 
| 
      
 3 
     | 
    
         
            +
                include Concerns::Visitable
         
     | 
| 
      
 4 
     | 
    
         
            +
                
         
     | 
| 
      
 5 
     | 
    
         
            +
                def document
         
     | 
| 
      
 6 
     | 
    
         
            +
                  self
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
                
         
     | 
| 
      
 9 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 10 
     | 
    
         
            +
                  private
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def application
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @application ||= begin
         
     | 
| 
      
 13 
     | 
    
         
            +
                      universe = AePageObjects::DependenciesHook.containing_page_object_universe(self)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      "#{universe.name}::Application".constantize.instance
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AePageObjects
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Element < Node
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :parent, :default_name
         
     | 
| 
      
 4 
     | 
    
         
            +
                
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(parent, name, options_or_locator = {})
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @parent       = parent
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @default_name = name.to_s
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @locator      = nil
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @name         = nil
         
     | 
| 
      
 10 
     | 
    
         
            +
                  
         
     | 
| 
      
 11 
     | 
    
         
            +
                  configure(parse_options(options_or_locator))
         
     | 
| 
      
 12 
     | 
    
         
            +
                  
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @locator ||= default_locator
         
     | 
| 
      
 14 
     | 
    
         
            +
                  
         
     | 
| 
      
 15 
     | 
    
         
            +
                  super(scoped_node)
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
                
         
     | 
| 
      
 18 
     | 
    
         
            +
                def document
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @document ||= begin
         
     | 
| 
      
 20 
     | 
    
         
            +
                    node = self.parent
         
     | 
| 
      
 21 
     | 
    
         
            +
                    
         
     | 
| 
      
 22 
     | 
    
         
            +
                    until node.is_a?(::AePageObjects::Document)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      node = node.parent
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                    
         
     | 
| 
      
 26 
     | 
    
         
            +
                    node
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
                
         
     | 
| 
      
 30 
     | 
    
         
            +
                def __full_name__
         
     | 
| 
      
 31 
     | 
    
         
            +
                  if parent.respond_to?(:__full_name__)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    "#{parent.__full_name__}_#{__name__}"
         
     | 
| 
      
 33 
     | 
    
         
            +
                  else
         
     | 
| 
      
 34 
     | 
    
         
            +
                    __name__
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
                
         
     | 
| 
      
 38 
     | 
    
         
            +
                alias_method :full_name, :__full_name__
         
     | 
| 
      
 39 
     | 
    
         
            +
                
         
     | 
| 
      
 40 
     | 
    
         
            +
                def __name__
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @name || default_name
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
                
         
     | 
| 
      
 44 
     | 
    
         
            +
                alias_method :name, :__name__
         
     | 
| 
      
 45 
     | 
    
         
            +
                
         
     | 
| 
      
 46 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 47 
     | 
    
         
            +
                  super.tap do |str|
         
     | 
| 
      
 48 
     | 
    
         
            +
                    str << "#name:<#{__name__}>"
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
                
         
     | 
| 
      
 52 
     | 
    
         
            +
                def using_default_locator?
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @locator == default_locator
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
                
         
     | 
| 
      
 56 
     | 
    
         
            +
              private
         
     | 
| 
      
 57 
     | 
    
         
            +
              
         
     | 
| 
      
 58 
     | 
    
         
            +
                def configure(options)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @locator = options.delete(:locator)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @name    = options.delete(:name).try(:to_s)
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
              
         
     | 
| 
      
 63 
     | 
    
         
            +
                def parse_options(options_or_locator)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  if options_or_locator.is_a?( Hash )
         
     | 
| 
      
 65 
     | 
    
         
            +
                    options_or_locator.symbolize_keys
         
     | 
| 
      
 66 
     | 
    
         
            +
                  else
         
     | 
| 
      
 67 
     | 
    
         
            +
                    {:locator => options_or_locator}
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
                
         
     | 
| 
      
 71 
     | 
    
         
            +
                def default_locator
         
     | 
| 
      
 72 
     | 
    
         
            +
                  @default_locator ||= Proc.new { "##{__full_name__}" }
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
                
         
     | 
| 
      
 75 
     | 
    
         
            +
                def scoped_node
         
     | 
| 
      
 76 
     | 
    
         
            +
                  if @locator
         
     | 
| 
      
 77 
     | 
    
         
            +
                    locator = eval_locator(@locator)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    if locator.present?
         
     | 
| 
      
 79 
     | 
    
         
            +
                      return parent.find(*locator)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
                  
         
     | 
| 
      
 83 
     | 
    
         
            +
                  parent.node
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     |