ae_page_objects 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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