lib/testable/region.rb
# Defines an accessor method for an region.
# ..........................
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/PerceivedComplexity
# rubocop:disable Metrics/ParameterLists
# rubocop:disable Metrics/BlockLength
# rubocop:disable Metrics/BlockNesting
# def define_region_accessor(identifier, within: nil, each: nil, collection_class: nil, region_class: nil, &block)
Defines an accessor method for an region.
Defines an accessor method for an region .
def define_region_accessor(identifier, within: nil, each: nil, region_class: nil, collection_class: nil, &block)
        include(Module.new do
          define_method(identifier) do
            class_path = self.class.name ? self.class.name.split('::') : ['TestableRegion']
            namespace =
              if class_path.size > 1
                class_path.pop
                Object.const_get(class_path.join('::'))
              elsif class_path.size == 1
                self.class
              else
                raise Testable::Errors::RegionNamespaceError, "Cannot understand namespace from #{class_path}"
              end
            region_single_class = region_class
            unless region_single_class
              if block_given?
                region_single_class = Class.new
                region_single_class.class_eval { include(Testable) }
                region_single_class.class_eval(&block)
              else
                singular_klass = identifier.to_s.split('_').map(&:capitalize).join
                if each
                  collection_class_name = "#{singular_klass}Region"
                  singular_klass = singular_klass.sub(/s\z/, '')
                end
                singular_klass << 'Region'
                region_single_class = namespace.const_get(singular_klass)
              end
            end
            scope =
              case within
                when Proc
                  instance_exec(&within)
                when Hash
                  region_element.element(within)
                else
                  region_element
              end
            if each
              elements = (scope.exists? ? scope.elements(each) : [])
              if collection_class_name && namespace.const_defined?(collection_class_name)
                region_collection_class = namespace.const_get(collection_class_name)
              elsif collection_class
                region_collection_class = collection_class
              else
                return elements.map { |element| region_single_class.new(@browser, element, self) }
              end
              region_collection_class.class_eval do
                include Enumerable
                attr_reader :region_collection
                define_method(:initialize) do |browser, region_element, region_elements|
                  super(browser, region_element, self)
                  @region_collection =
                    if region_elements.all? { |element| element.is_a?(Watir::Element) }
                      region_elements.map { |element| region_single_class.new(browser, element, self) }
                    else
                      region_elements
                    end
                end
                def each(&block)
                  region_collection.each(&block)
                end
              end
              region_collection_class.new(@browser, scope, elements)
            else
              region_single_class.new(@browser, scope, self)
            end
          end
        end)
      end
def define_region_accessor ( identifier , within : nil , each : nil , region_class : nil , collection_class : nil , & block ) include ( Module . new do define_method ( identifier ) do class_path = self . class . name ? self . class . name . split ( '::' ) : [ 'TestableRegion' ] namespace = if class_path . size > 1 class_path . pop Object . const_get ( class_path . join ( '::' ) ) elsif class_path . size == 1 self . class else raise Testable :: Errors :: RegionNamespaceError , "Cannot understand namespace from #{class_path}" end region_single_class = region_class unless region_single_class if block_given? region_single_class = Class . new region_single_class . class_eval { include ( Testable ) } region_single_class . class_eval ( & block ) else singular_klass = identifier . to_s . split ( '_' ) . map ( & :capitalize ) . join if each collection_class_name = "#{singular_klass}Region" singular_klass = singular_klass . sub ( / s \z / , '' ) end singular_klass << 'Region' region_single_class = namespace . const_get ( singular_klass ) end end scope = case within when Proc instance_exec ( & within ) when Hash region_element . element ( within ) else region_element end if each elements = ( scope . exists? ? scope . elements ( each ) : [ ] ) if collection_class_name && namespace . const_defined? ( collection_class_name ) region_collection_class = namespace . const_get ( collection_class_name ) elsif collection_class region_collection_class = collection_class else return elements . map { | element | region_single_class . new ( @browser , element , self ) } end region_collection_class . class_eval do include Enumerable attr_reader :region_collection define_method ( :initialize ) do | browser , region_element , region_elements | super ( browser , region_element , self ) @region_collection = if region_elements . all? { | element | element . is_a? ( Watir :: Element ) } region_elements . map { | element | region_single_class . new ( browser , element , self ) } else region_elements end end def each ( & block ) region_collection . each ( & block ) end end region_collection_class . new ( @browser , scope , elements ) else region_single_class . new ( @browser , scope , self ) end end end ) end
Defines an accessor method for an region.
Defines an accessor method for an region .
# The class path is what essentially determines the model to # reference that the region is a part of. However, it is possible # to define an inline region, which would effectively make the # class anonymous, and thus not having an actual name. Thus is it # necessary to provide a stand-in name for those cases. # Namespacing is needed in cases where there are nested classes. # It's important to get the full namespace of any classes that are # said to reference the region. # A copy of the passed-in region class is necessary because the # `region_class` is declared outside of this defined function. # And the function could change that class. Thus a reference is # needed to the original `region_class` but also allowing for that # class to be changed. # rubocop:disable Style/MissingElse # rubocop:enable Style/MissingElse # The scope is used to provide a reference to the element that # is said to act as a container for the region. # The `elements` will be a `Watir::HTMLElementCollection`.
identifier
<not_specific>
within
<not_specific>
each
<not_specific>
region_class
<not_specific>
collection_class
<not_specific>
block
<not_specific>