ae_page_objects 0.2.0 → 0.3.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.
@@ -1,28 +1,20 @@
1
1
  require 'capybara'
2
2
  require 'capybara/dsl'
3
- require 'active_support'
4
- require 'active_support/core_ext/module/delegation'
5
- require 'active_support/core_ext/hash/keys'
6
- require 'active_support/core_ext/object/try'
7
- require 'active_support/core_ext/class'
8
- require 'active_support/core_ext/module/introspection'
9
3
 
10
4
  require 'ae_page_objects/version'
11
5
 
12
6
  module AePageObjects
13
7
  autoload :Universe, 'ae_page_objects/core/universe'
14
- autoload :Singleton, 'ae_page_objects/core/singleton'
15
8
  autoload :Application, 'ae_page_objects/core/application'
16
9
  autoload :ApplicationRouter, 'ae_page_objects/core/application_router'
17
10
  autoload :RakeRouter, 'ae_page_objects/core/rake_router'
18
- autoload :InternalHelpers, 'ae_page_objects/core/internal_helpers'
19
-
20
- module Dsl
21
- autoload :Element, 'ae_page_objects/core/dsl/element'
22
- autoload :Collection, 'ae_page_objects/core/dsl/collection'
23
- autoload :FormFor, 'ae_page_objects/core/dsl/form_for'
24
- end
25
-
11
+ autoload :Dsl, 'ae_page_objects/core/dsl'
12
+
13
+ autoload :Singleton, 'ae_page_objects/util/singleton'
14
+ autoload :InternalHelpers, 'ae_page_objects/util/internal_helpers'
15
+ autoload :HashSymbolizer, 'ae_page_objects/util/hash_symbolizer'
16
+ autoload :Inflector, 'ae_page_objects/util/inflector'
17
+
26
18
  module Concerns
27
19
  autoload :LoadEnsuring, 'ae_page_objects/concerns/load_ensuring'
28
20
  autoload :Staleable, 'ae_page_objects/concerns/staleable'
@@ -40,6 +32,9 @@ module AePageObjects
40
32
  autoload :Checkbox, 'ae_page_objects/elements/checkbox'
41
33
  end
42
34
 
35
+ require 'ae_page_objects/core_ext/module'
36
+
37
+
43
38
 
44
39
 
45
40
 
@@ -4,8 +4,7 @@ module AePageObjects
4
4
 
5
5
  module Concerns
6
6
  module LoadEnsuring
7
- extend ActiveSupport::Concern
8
-
7
+
9
8
  def initialize(*args)
10
9
  super
11
10
  ensure_loaded!
@@ -4,8 +4,7 @@ module AePageObjects
4
4
 
5
5
  module Concerns
6
6
  module Staleable
7
- extend ActiveSupport::Concern
8
-
7
+
9
8
  def stale?
10
9
  @stale
11
10
  end
@@ -4,8 +4,11 @@ module AePageObjects
4
4
 
5
5
  module Concerns
6
6
  module Visitable
7
- extend ActiveSupport::Concern
8
-
7
+
8
+ def self.included(target)
9
+ target.extend ClassMethods
10
+ end
11
+
9
12
  private
10
13
 
11
14
  def ensure_loaded!
@@ -1,11 +1,17 @@
1
1
  module AePageObjects
2
2
  class Application
3
- include AePageObjects::Singleton
3
+ extend AePageObjects::Singleton
4
4
 
5
5
  class << self
6
6
  private :new
7
7
 
8
- delegate :initialize!, :router=, :to => :instance
8
+ def initialize!
9
+ instance.initialize!
10
+ end
11
+
12
+ def router=(router)
13
+ instance.router = router
14
+ end
9
15
 
10
16
  def inherited(application_class)
11
17
  super
@@ -33,10 +39,17 @@ module AePageObjects
33
39
 
34
40
  attr_writer :router
35
41
 
36
- delegate :universe, :to => 'self.class'
42
+ def universe
43
+ self.class.universe
44
+ end
37
45
 
38
- delegate :path_recognizes_url?, :to => :router
39
- delegate :generate_path, :to => :router
46
+ def path_recognizes_url?(*args)
47
+ self.router.path_recognizes_url?(*args)
48
+ end
49
+
50
+ def generate_path(*args)
51
+ self.router.generate_path(*args)
52
+ end
40
53
 
41
54
  def router
42
55
  @router ||= ApplicationRouter.new
@@ -0,0 +1,195 @@
1
+ module AePageObjects
2
+ module Dsl
3
+ include InternalHelpers
4
+
5
+ def inherited(subclass)
6
+ subclass.class_eval do
7
+ class << self
8
+ def element_attributes
9
+ @element_attributes ||= {}
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ def element(name, options = {}, &block)
16
+ options = options.dup
17
+ options[:name] ||= name
18
+
19
+ klass = field_klass(options, &block)
20
+
21
+ self.element_attributes[name.to_sym] = klass
22
+
23
+ define_method name do |&block|
24
+ ElementProxy.new(klass, self, options, &block)
25
+ end
26
+
27
+ klass
28
+ end
29
+
30
+ # Defines a collection of elements. Blocks are evaluated on the item class used by the
31
+ # collection. collection() defines a method on the class that returns an instance of a collection
32
+ # class which contains instances of the collection's item class.
33
+ #
34
+ # Supported signatures are described below.
35
+ #
36
+ # ------------------------------------------------
37
+ # Signature: (no :is, no :contains, no block)
38
+ #
39
+ # collection :addresses
40
+ #
41
+ # Collection class: ::AePageObjects::Collection
42
+ # Item class: ::AePageObjects::Element
43
+ #
44
+ # ------------------------------------------------
45
+ # Signature: (no :is, no :contains, block)
46
+ #
47
+ # collection :addresses do
48
+ # element :city
49
+ # element :state
50
+ # end
51
+ #
52
+ # Collection class: one-off subclass of ::AePageObjects::Collection
53
+ # Item class: one-off subclass of ::AePageObjects::Element
54
+ # Methods defined on item class:
55
+ # city() # -> instance of ::AePageObjects::Element
56
+ # state() # -> instance of ::AePageObjects::Element
57
+ #
58
+ # ------------------------------------------------
59
+ # Signature: (no :is, :contains, no block)
60
+ #
61
+ # collection :addresses, :contains => Address
62
+ #
63
+ # Collection class: one-off subclass of ::AePageObjects::Collection
64
+ # Item class: Address
65
+ #
66
+ # ------------------------------------------------
67
+ # Signature: (no :is, :contains, block)
68
+ #
69
+ # collection :addresses, :contains => Address do
70
+ # element :longitude
71
+ # element :latitude
72
+ # end
73
+ #
74
+ # Collection class: one-off subclass of ::AePageObjects::Collection element
75
+ # Item class: one-off subclass of Address
76
+ # Methods defined on item class:
77
+ # longitude() # -> instance of ::AePageObjects::Element
78
+ # latitude() # -> instance of ::AePageObjects::Element
79
+ #
80
+ # ------------------------------------------------
81
+ # Signature: (:is, no :contains, no block)
82
+ #
83
+ # collection :addresses, :is => AddressList
84
+ #
85
+ # Collection class: AddressList
86
+ # Item class: AddressList.item_class
87
+ #
88
+ # ------------------------------------------------
89
+ # Signature: (:is, no :contains, block)
90
+ #
91
+ # collection :addresses, :is => AddressList do
92
+ # element :longitude
93
+ # element :latitude
94
+ # end
95
+ #
96
+ # Collection class: one-off subclass of AddressList
97
+ # Item class: one-off subclass of AddressList.item_class
98
+ # Methods defined on item class:
99
+ # longitude() # -> instance of ::AePageObjects::Element
100
+ # latitude() # -> instance of ::AePageObjects::Element
101
+ #
102
+ # ------------------------------------------------
103
+ # Signature: (:is, :contains, no block)
104
+ #
105
+ # collection :addresses, :is => AddressList, :contains => ExtendedAddress
106
+ #
107
+ # Collection class: one-off subclass ofAddressList
108
+ # Item class: ExtendedAddress
109
+ #
110
+ # ------------------------------------------------
111
+ # Signature: (:is, :contains, block)
112
+ #
113
+ # collection :addresses, :is => AddressList, :contains => Address do
114
+ # element :longitude
115
+ # element :latitude
116
+ # end
117
+ #
118
+ # Collection class: one-off subclass of AddressList
119
+ # Item class: one-off subclass of Address
120
+ # Methods defined on item class:
121
+ # longitude() # -> instance of ::AePageObjects::Element
122
+ # latitude() # -> instance of ::AePageObjects::Element
123
+ #
124
+ def collection(name, options = {}, &block)
125
+ options ||= {}
126
+
127
+ # only a collection class is specified or the item class
128
+ # specified matches the collection's item class
129
+ if ! block_given? && options[:is] && (
130
+ options[:contains].nil? || options[:is].item_class == options[:contains]
131
+ )
132
+ return element(name, options)
133
+ end
134
+
135
+ options = options.dup
136
+
137
+ # create/get the collection class
138
+ if options[:is]
139
+ ensure_class_for_param!(:is, options[:is], ::AePageObjects::Collection)
140
+ else
141
+ options[:is] = ::AePageObjects::Collection
142
+ end
143
+
144
+ item_class = options.delete(:contains) || options[:is].item_class
145
+ if block_given?
146
+ item_class = item_class.new_subclass(&block).tap do |new_item_class|
147
+ new_item_class.element_attributes.merge!(item_class.element_attributes)
148
+ end
149
+ end
150
+
151
+ # since we are creating a new item class, we need to subclass the collection class
152
+ # so we can parameterize the collection class with an item class
153
+ options[:is] = options[:is].new_subclass
154
+ options[:is].item_class = item_class
155
+
156
+ element(name, options)
157
+ end
158
+
159
+ def form_for(form_name, options = {}, &block)
160
+ options ||= {}
161
+
162
+ raise ArgumentError, ":is option not supported" if options[:is]
163
+ raise ArgumentError, "Block required." if block.nil?
164
+
165
+ klass = ::AePageObjects::Form.new_subclass(&block)
166
+
167
+ options = options.dup
168
+ options[:is] = klass
169
+
170
+ element(form_name, options)
171
+
172
+ klass.element_attributes.each do |element_name, element_klazz|
173
+ class_eval <<-RUBY
174
+ def #{element_name}(*args, &block)
175
+ #{form_name}.#{element_name}(*args, &block)
176
+ end
177
+ RUBY
178
+
179
+ self.element_attributes[element_name] = element_klazz
180
+ end
181
+ end
182
+
183
+ private
184
+
185
+ def field_klass(options, &block)
186
+ klass = options.delete(:is) || ::AePageObjects::Element
187
+
188
+ if block_given?
189
+ klass.new_subclass(&block)
190
+ else
191
+ klass
192
+ end
193
+ end
194
+ end
195
+ end
@@ -5,7 +5,7 @@ module AePageObjects
5
5
 
6
6
  def initialize(rake_routes, mounted_prefix = '')
7
7
  @mounted_prefix = mounted_prefix || ""
8
- @routes = ActiveSupport::OrderedHash.new
8
+ @routes = {}
9
9
  route_line_regex = /(\w+)(?:\s[A-Z]+)?\s+(\/.*)\(.:format\).*$/
10
10
 
11
11
  rake_routes.split("\n").each do |line|
@@ -32,11 +32,11 @@ module AePageObjects
32
32
  end
33
33
 
34
34
  if route = @routes[named_route]
35
- options = args.extract_options!
35
+ options = args.last.is_a?(Hash) ? args.pop : {}
36
36
  route.generate_path(options)
37
37
  end
38
38
  end
39
-
39
+
40
40
  private
41
41
 
42
42
  class Path < String
@@ -50,7 +50,7 @@ module AePageObjects
50
50
  end
51
51
 
52
52
  def generate(param_values)
53
- param_values = param_values.symbolize_keys
53
+ param_values = HashSymbolizer.new(param_values).symbolize_keys
54
54
  @params.values.inject(self) do |path, param|
55
55
  param.substitute(path, param_values)
56
56
  end
@@ -142,7 +142,7 @@ module AePageObjects
142
142
  end
143
143
 
144
144
  def generate_path(options)
145
- options = options.symbolize_keys
145
+ options = HashSymbolizer.new(options).symbolize_keys
146
146
  @path.generate(options)
147
147
  end
148
148
  end
@@ -1,10 +1,10 @@
1
1
  module AePageObjects
2
2
  module Universe
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- class << self
7
- attr_accessor :page_objects_application_class
3
+ def self.included(target)
4
+ target.class_eval do
5
+ class << self
6
+ attr_accessor :page_objects_application_class
7
+ end
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,34 @@
1
+ # lifted from activesupport
2
+
3
+ class Module
4
+
5
+ # Returns the name of the module containing this one.
6
+ #
7
+ # M::N.parent_name # => "M"
8
+ def parent_name
9
+ unless defined? @parent_name
10
+ @parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
11
+ end
12
+ @parent_name
13
+ end
14
+
15
+ # Returns the module which contains this one according to its name.
16
+ #
17
+ # module M
18
+ # module N
19
+ # end
20
+ # end
21
+ # X = M::N
22
+ #
23
+ # M::N.parent # => M
24
+ # X.parent # => M
25
+ #
26
+ # The parent of top-level and anonymous modules is Object.
27
+ #
28
+ # M.parent # => Object
29
+ # Module.new.parent # => Object
30
+ #
31
+ def parent
32
+ parent_name ? AePageObjects::Inflector.constantize(parent_name) : Object
33
+ end
34
+ end
@@ -38,7 +38,12 @@ module AePageObjects
38
38
 
39
39
  def __full_name__
40
40
  if parent.respond_to?(:__full_name__)
41
- [ parent.__full_name__, __name__ ].compact.presence.try(:join, '_')
41
+ name_parts = [ parent.__full_name__, __name__ ].compact
42
+ if name_parts.empty?
43
+ nil
44
+ else
45
+ name_parts.join('_')
46
+ end
42
47
  else
43
48
  __name__
44
49
  end
@@ -70,12 +75,14 @@ module AePageObjects
70
75
 
71
76
  def configure(options)
72
77
  @locator = options.delete(:locator)
73
- @name = options.delete(:name).try(:to_s)
78
+ @name = options.delete(:name)
79
+
80
+ @name = @name.to_s if @name
74
81
  end
75
82
 
76
83
  def parse_options(options_or_locator)
77
84
  if options_or_locator.is_a?( Hash )
78
- options_or_locator.symbolize_keys
85
+ HashSymbolizer.new(options_or_locator).symbolize_keys
79
86
  else
80
87
  {:locator => options_or_locator}
81
88
  end
@@ -88,7 +95,7 @@ module AePageObjects
88
95
  def scoped_node
89
96
  if @locator
90
97
  locator = eval_locator(@locator)
91
- if locator.present?
98
+ if ! locator.empty?
92
99
  return parent.find(*locator)
93
100
  end
94
101
  end
@@ -27,7 +27,8 @@ module AePageObjects
27
27
  # Provided so that visible? can be asked without
28
28
  # an explicit check for present? first.
29
29
  def visible?
30
- !!presence.try(:visible?)
30
+ inst = presence
31
+ ! inst.nil? && inst.visible?
31
32
  end
32
33
 
33
34
  def not_visible?
@@ -41,7 +42,7 @@ module AePageObjects
41
42
  end
42
43
 
43
44
  def present?
44
- presence.present?
45
+ ! presence.nil?
45
46
  end
46
47
 
47
48
  def not_present?
@@ -1,8 +1,15 @@
1
1
  module AePageObjects
2
2
  class Collection < Element
3
- class_attribute :item_class, :instance_writer => false
3
+ class << self
4
+ attr_accessor :item_class
5
+ end
6
+
4
7
  self.item_class = Element
5
8
 
9
+ def item_class
10
+ self.class.item_class
11
+ end
12
+
6
13
  def at(index, &block)
7
14
  if index >= size || index < 0
8
15
  nil
@@ -1,12 +1,6 @@
1
1
  module AePageObjects
2
2
  class Node
3
3
  module Methods
4
- extend ActiveSupport::Concern
5
-
6
- include Dsl::Element
7
- include Dsl::Collection
8
- include Dsl::FormFor
9
-
10
4
  def initialize(capybara_node = Capybara.current_session)
11
5
  @node = capybara_node
12
6
  end
@@ -19,20 +13,27 @@ module AePageObjects
19
13
  raise "Must implement!"
20
14
  end
21
15
 
22
- delegate :current_url, :to => 'self.class'
23
- delegate :current_url_without_params, :to => 'self.class'
16
+ def current_url
17
+ self.class.current_url
18
+ end
19
+
20
+ def current_url_without_params
21
+ self.class.current_url_without_params
22
+ end
24
23
 
25
- delegate :find, :to => :node
26
- delegate :all, :to => :node
27
- delegate :value, :to => :node
28
- delegate :set, :to => :node
29
- delegate :text, :to => :node
30
- delegate :visible?, :to => :node
24
+ METHODS_TO_DELEGATE_TO_NODE = [:find, :all, :value, :set, :text, :visible?]
25
+ METHODS_TO_DELEGATE_TO_NODE.each do |m|
26
+ class_eval <<-RUBY
27
+ def #{m}(*args, &block)
28
+ node.send(:#{m}, *args, &block)
29
+ end
30
+ RUBY
31
+ end
31
32
 
32
33
  private
33
34
 
34
35
  def eval_locator(locator)
35
- return unless locator
36
+ return [] unless locator
36
37
 
37
38
  if locator.respond_to?(:call)
38
39
  locator = instance_eval(&locator)
@@ -40,26 +41,29 @@ module AePageObjects
40
41
 
41
42
  locator.is_a?(Array) ? locator : [locator.to_s]
42
43
  end
44
+ end
43
45
 
44
- module ClassMethods
45
-
46
- def current_url
47
- Capybara.current_session.current_url.sub(/^https?:\/\/[^\/]*/, '')
48
- end
46
+ module ClassMethods
47
+ def current_url
48
+ Capybara.current_session.current_url.sub(/^https?:\/\/[^\/]*/, '')
49
+ end
49
50
 
50
- def current_url_without_params
51
- current_url.sub(/\?.*/, '')
52
- end
51
+ def current_url_without_params
52
+ current_url.sub(/\?.*/, '')
53
+ end
53
54
 
54
- def new_subclass(&block)
55
- klass = Class.new(self)
56
- klass.class_eval(&block) if block
57
- klass
58
- end
55
+ def new_subclass(&block)
56
+ klass = Class.new(self)
57
+ klass.class_eval(&block) if block
58
+ klass
59
59
  end
60
60
  end
61
-
61
+
62
+ extend Dsl
63
+
62
64
  include Methods
65
+ extend ClassMethods
66
+
63
67
  include Concerns::LoadEnsuring
64
68
  include Concerns::Staleable
65
69
  end
@@ -0,0 +1,16 @@
1
+ module AePageObjects
2
+ class HashSymbolizer
3
+
4
+ def initialize(hash)
5
+ @hash = hash
6
+ end
7
+
8
+ def symbolize_keys
9
+ @hash.dup.tap do |hash|
10
+ hash.keys.each do |key|
11
+ hash[(key.to_sym rescue key) || key] = hash.delete(key)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ module AePageObjects
2
+ module Inflector
3
+ extend self
4
+
5
+ # Ruby 1.9 introduces an inherit argument for Module#const_get and
6
+ # #const_defined? and changes their default behavior.
7
+ if Module.method(:const_get).arity == 1
8
+ # Tries to find a constant with the name specified in the argument string:
9
+ #
10
+ # "Module".constantize # => Module
11
+ # "Test::Unit".constantize # => Test::Unit
12
+ #
13
+ # The name is assumed to be the one of a top-level constant, no matter whether
14
+ # it starts with "::" or not. No lexical context is taken into account:
15
+ #
16
+ # C = 'outside'
17
+ # module M
18
+ # C = 'inside'
19
+ # C # => 'inside'
20
+ # "C".constantize # => 'outside', same as ::C
21
+ # end
22
+ #
23
+ # NameError is raised when the name is not in CamelCase or the constant is
24
+ # unknown.
25
+ def constantize(camel_cased_word)
26
+ names = camel_cased_word.split('::')
27
+ names.shift if names.empty? || names.first.empty?
28
+
29
+ constant = Object
30
+ names.each do |name|
31
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
32
+ end
33
+ constant
34
+ end
35
+ else
36
+ def constantize(camel_cased_word) #:nodoc:
37
+ names = camel_cased_word.split('::')
38
+ names.shift if names.empty? || names.first.empty?
39
+
40
+ constant = Object
41
+ names.each do |name|
42
+ constant = constant.const_defined?(name, false) ? constant.const_get(name) : constant.const_missing(name)
43
+ end
44
+ constant
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ module AePageObjects
2
+ module Singleton
3
+ def instance
4
+ @instance ||= new
5
+ end
6
+
7
+ def respond_to?(*args)
8
+ super || instance.respond_to?(*args)
9
+ end
10
+
11
+ def configure(&block)
12
+ class_eval(&block)
13
+ end
14
+
15
+ protected
16
+
17
+ def method_missing(*args, &block)
18
+ instance.send(*args, &block)
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module AePageObjects
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ae_page_objects
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Donnie Tognazzini
@@ -15,27 +15,12 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-07-05 00:00:00 Z
18
+ date: 2013-07-08 00:00:00 Z
19
19
  dependencies:
20
- - !ruby/object:Gem::Dependency
21
- type: :runtime
22
- name: activesupport
23
- version_requirements: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 7
29
- segments:
30
- - 3
31
- - 0
32
- version: "3.0"
33
- requirement: *id001
34
- prerelease: false
35
20
  - !ruby/object:Gem::Dependency
36
21
  type: :runtime
37
22
  name: capybara
38
- version_requirements: &id002 !ruby/object:Gem::Requirement
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
39
24
  none: false
40
25
  requirements:
41
26
  - - ~>
@@ -45,12 +30,12 @@ dependencies:
45
30
  - 1
46
31
  - 1
47
32
  version: "1.1"
48
- requirement: *id002
33
+ requirement: *id001
49
34
  prerelease: false
50
35
  - !ruby/object:Gem::Dependency
51
36
  type: :runtime
52
37
  name: nokogiri
53
- version_requirements: &id003 !ruby/object:Gem::Requirement
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
54
39
  none: false
55
40
  requirements:
56
41
  - - ~>
@@ -61,12 +46,12 @@ dependencies:
61
46
  - 5
62
47
  - 9
63
48
  version: 1.5.9
64
- requirement: *id003
49
+ requirement: *id002
65
50
  prerelease: false
66
51
  - !ruby/object:Gem::Dependency
67
52
  type: :development
68
53
  name: appraisal
69
- version_requirements: &id004 !ruby/object:Gem::Requirement
54
+ version_requirements: &id003 !ruby/object:Gem::Requirement
70
55
  none: false
71
56
  requirements:
72
57
  - - ~>
@@ -77,12 +62,12 @@ dependencies:
77
62
  - 5
78
63
  - 1
79
64
  version: 0.5.1
80
- requirement: *id004
65
+ requirement: *id003
81
66
  prerelease: false
82
67
  - !ruby/object:Gem::Dependency
83
68
  type: :development
84
69
  name: mocha
85
- version_requirements: &id005 !ruby/object:Gem::Requirement
70
+ version_requirements: &id004 !ruby/object:Gem::Requirement
86
71
  none: false
87
72
  requirements:
88
73
  - - "="
@@ -93,12 +78,12 @@ dependencies:
93
78
  - 13
94
79
  - 3
95
80
  version: 0.13.3
96
- requirement: *id005
81
+ requirement: *id004
97
82
  prerelease: false
98
83
  - !ruby/object:Gem::Dependency
99
84
  type: :development
100
85
  name: selenium-webdriver
101
- version_requirements: &id006 !ruby/object:Gem::Requirement
86
+ version_requirements: &id005 !ruby/object:Gem::Requirement
102
87
  none: false
103
88
  requirements:
104
89
  - - ">="
@@ -107,7 +92,7 @@ dependencies:
107
92
  segments:
108
93
  - 0
109
94
  version: "0"
110
- requirement: *id006
95
+ requirement: *id005
111
96
  prerelease: false
112
97
  description: Capybara Page Objects pattern
113
98
  email:
@@ -125,13 +110,10 @@ files:
125
110
  - lib/ae_page_objects/concerns/visitable.rb
126
111
  - lib/ae_page_objects/core/application.rb
127
112
  - lib/ae_page_objects/core/application_router.rb
128
- - lib/ae_page_objects/core/dsl/collection.rb
129
- - lib/ae_page_objects/core/dsl/element.rb
130
- - lib/ae_page_objects/core/dsl/form_for.rb
131
- - lib/ae_page_objects/core/internal_helpers.rb
113
+ - lib/ae_page_objects/core/dsl.rb
132
114
  - lib/ae_page_objects/core/rake_router.rb
133
- - lib/ae_page_objects/core/singleton.rb
134
115
  - lib/ae_page_objects/core/universe.rb
116
+ - lib/ae_page_objects/core_ext/module.rb
135
117
  - lib/ae_page_objects/document.rb
136
118
  - lib/ae_page_objects/element.rb
137
119
  - lib/ae_page_objects/element_proxy.rb
@@ -140,6 +122,10 @@ files:
140
122
  - lib/ae_page_objects/elements/form.rb
141
123
  - lib/ae_page_objects/elements/select.rb
142
124
  - lib/ae_page_objects/node.rb
125
+ - lib/ae_page_objects/util/hash_symbolizer.rb
126
+ - lib/ae_page_objects/util/inflector.rb
127
+ - lib/ae_page_objects/util/internal_helpers.rb
128
+ - lib/ae_page_objects/util/singleton.rb
143
129
  - lib/ae_page_objects/version.rb
144
130
  homepage: http://github.com/appfolio/ae_page_objects
145
131
  licenses:
@@ -1,141 +0,0 @@
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: (no :is, no :contains, no block)
18
- #
19
- # collection :addresses
20
- #
21
- # Collection class: ::AePageObjects::Collection
22
- # Item class: ::AePageObjects::Element
23
- #
24
- # ------------------------------------------------
25
- # Signature: (no :is, no :contains, block)
26
- #
27
- # collection :addresses do
28
- # element :city
29
- # element :state
30
- # end
31
- #
32
- # Collection class: one-off subclass of ::AePageObjects::Collection
33
- # Item class: one-off subclass of ::AePageObjects::Element
34
- # Methods defined on item class:
35
- # city() # -> instance of ::AePageObjects::Element
36
- # state() # -> instance of ::AePageObjects::Element
37
- #
38
- # ------------------------------------------------
39
- # Signature: (no :is, :contains, no block)
40
- #
41
- # collection :addresses, :contains => Address
42
- #
43
- # Collection class: one-off subclass of ::AePageObjects::Collection
44
- # Item class: Address
45
- #
46
- # ------------------------------------------------
47
- # Signature: (no :is, :contains, block)
48
- #
49
- # collection :addresses, :contains => Address do
50
- # element :longitude
51
- # element :latitude
52
- # end
53
- #
54
- # Collection class: one-off subclass of ::AePageObjects::Collection element
55
- # Item class: one-off subclass of Address
56
- # Methods defined on item class:
57
- # longitude() # -> instance of ::AePageObjects::Element
58
- # latitude() # -> instance of ::AePageObjects::Element
59
- #
60
- # ------------------------------------------------
61
- # Signature: (:is, no :contains, no block)
62
- #
63
- # collection :addresses, :is => AddressList
64
- #
65
- # Collection class: AddressList
66
- # Item class: AddressList.item_class
67
- #
68
- # ------------------------------------------------
69
- # Signature: (:is, no :contains, block)
70
- #
71
- # collection :addresses, :is => AddressList do
72
- # element :longitude
73
- # element :latitude
74
- # end
75
- #
76
- # Collection class: one-off subclass of AddressList
77
- # Item class: one-off subclass of AddressList.item_class
78
- # Methods defined on item class:
79
- # longitude() # -> instance of ::AePageObjects::Element
80
- # latitude() # -> instance of ::AePageObjects::Element
81
- #
82
- # ------------------------------------------------
83
- # Signature: (:is, :contains, no block)
84
- #
85
- # collection :addresses, :is => AddressList, :contains => ExtendedAddress
86
- #
87
- # Collection class: one-off subclass ofAddressList
88
- # Item class: ExtendedAddress
89
- #
90
- # ------------------------------------------------
91
- # Signature: (:is, :contains, block)
92
- #
93
- # collection :addresses, :is => AddressList, :contains => Address do
94
- # element :longitude
95
- # element :latitude
96
- # end
97
- #
98
- # Collection class: one-off subclass of AddressList
99
- # Item class: one-off subclass of Address
100
- # Methods defined on item class:
101
- # longitude() # -> instance of ::AePageObjects::Element
102
- # latitude() # -> instance of ::AePageObjects::Element
103
- #
104
- def collection(name, options = {}, &block)
105
- options ||= {}
106
-
107
- # only a collection class is specified or the item class
108
- # specified matches the collection's item class
109
- if block.blank? && options[:is] && (
110
- options[:contains].blank? || options[:is].item_class == options[:contains]
111
- )
112
- return element(name, options)
113
- end
114
-
115
- options = options.dup
116
-
117
- # create/get the collection class
118
- if options[:is]
119
- ensure_class_for_param!(:is, options[:is], ::AePageObjects::Collection)
120
- else
121
- options[:is] = ::AePageObjects::Collection
122
- end
123
-
124
- item_class = options.delete(:contains) || options[:is].item_class
125
- if block.present?
126
- item_class = item_class.new_subclass(&block).tap do |new_item_class|
127
- new_item_class.element_attributes.merge!(item_class.element_attributes)
128
- end
129
- end
130
-
131
- # since we are creating a new item class, we need to subclass the collection class
132
- # so we can parameterize the collection class with an item class
133
- options[:is] = options[:is].new_subclass
134
- options[:is].item_class = item_class
135
-
136
- element(name, options)
137
- end
138
- end
139
- end
140
- end
141
- end
@@ -1,47 +0,0 @@
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 = {}, &block)
19
- options = options.dup
20
- options[:name] ||= name
21
-
22
- klass = field_klass(options, &block)
23
-
24
- self.element_attributes[name.to_sym] = klass
25
-
26
- define_method name do |&block|
27
- ElementProxy.new(klass, self, options, &block)
28
- end
29
-
30
- klass
31
- end
32
-
33
- private
34
-
35
- def field_klass(options, &block)
36
- klass = options.delete(:is) || ::AePageObjects::Element
37
-
38
- if block_given?
39
- klass.new_subclass(&block)
40
- else
41
- klass
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,30 +0,0 @@
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 |element_name, element_klazz|
23
- delegate element_name, :to => form_name
24
- self.element_attributes[element_name] = element_klazz
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,25 +0,0 @@
1
- module AePageObjects
2
- module Singleton
3
- extend ActiveSupport::Concern
4
-
5
- module ClassMethods
6
- def instance
7
- @instance ||= new
8
- end
9
-
10
- def respond_to?(*args)
11
- super || instance.respond_to?(*args)
12
- end
13
-
14
- def configure(&block)
15
- class_eval(&block)
16
- end
17
-
18
- protected
19
-
20
- def method_missing(*args, &block)
21
- instance.send(*args, &block)
22
- end
23
- end
24
- end
25
- end