page-object 2.0.0 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/ChangeLog +10 -0
  4. data/README.md +12 -0
  5. data/Rakefile +2 -12
  6. data/cucumber.yml +2 -4
  7. data/lib/page-object.rb +12 -20
  8. data/lib/page-object/accessors.rb +50 -363
  9. data/lib/page-object/elements/bold.rb +0 -1
  10. data/lib/page-object/elements/button.rb +0 -4
  11. data/lib/page-object/elements/check_box.rb +19 -7
  12. data/lib/page-object/elements/div.rb +0 -4
  13. data/lib/page-object/elements/element.rb +159 -90
  14. data/lib/page-object/elements/file_field.rb +5 -7
  15. data/lib/page-object/elements/form.rb +0 -8
  16. data/lib/page-object/elements/hidden_field.rb +1 -4
  17. data/lib/page-object/elements/image.rb +13 -7
  18. data/lib/page-object/elements/label.rb +0 -4
  19. data/lib/page-object/elements/link.rb +0 -13
  20. data/lib/page-object/elements/list_item.rb +0 -3
  21. data/lib/page-object/elements/ordered_list.rb +30 -5
  22. data/lib/page-object/elements/radio_button.rb +12 -7
  23. data/lib/page-object/elements/select_list.rb +40 -8
  24. data/lib/page-object/elements/span.rb +0 -3
  25. data/lib/page-object/elements/table.rb +26 -5
  26. data/lib/page-object/elements/table_cell.rb +0 -4
  27. data/lib/page-object/elements/table_row.rb +30 -5
  28. data/lib/page-object/elements/text_area.rb +7 -7
  29. data/lib/page-object/elements/text_field.rb +5 -11
  30. data/lib/page-object/elements/unordered_list.rb +30 -5
  31. data/lib/page-object/indexed_properties.rb +1 -0
  32. data/lib/page-object/platforms.rb +0 -1
  33. data/lib/page-object/platforms/watir.rb +26 -4
  34. data/lib/page-object/platforms/watir/page_object.rb +4 -4
  35. data/lib/page-object/version.rb +1 -1
  36. data/lib/page-object/widgets.rb +0 -1
  37. data/page-object.gemspec +1 -15
  38. metadata +5 -47
  39. data/lib/page-object/platforms/selenium_webdriver.rb +0 -30
  40. data/lib/page-object/platforms/selenium_webdriver/button.rb +0 -15
  41. data/lib/page-object/platforms/selenium_webdriver/check_box.rb +0 -29
  42. data/lib/page-object/platforms/selenium_webdriver/element.rb +0 -335
  43. data/lib/page-object/platforms/selenium_webdriver/file_field.rb +0 -16
  44. data/lib/page-object/platforms/selenium_webdriver/form.rb +0 -16
  45. data/lib/page-object/platforms/selenium_webdriver/image.rb +0 -28
  46. data/lib/page-object/platforms/selenium_webdriver/link.rb +0 -23
  47. data/lib/page-object/platforms/selenium_webdriver/ordered_list.rb +0 -41
  48. data/lib/page-object/platforms/selenium_webdriver/page_object.rb +0 -1297
  49. data/lib/page-object/platforms/selenium_webdriver/radio_button.rb +0 -22
  50. data/lib/page-object/platforms/selenium_webdriver/select_list.rb +0 -93
  51. data/lib/page-object/platforms/selenium_webdriver/surrogate_selenium_element.rb +0 -42
  52. data/lib/page-object/platforms/selenium_webdriver/table.rb +0 -42
  53. data/lib/page-object/platforms/selenium_webdriver/table_row.rb +0 -43
  54. data/lib/page-object/platforms/selenium_webdriver/text_area.rb +0 -17
  55. data/lib/page-object/platforms/selenium_webdriver/text_field.rb +0 -17
  56. data/lib/page-object/platforms/selenium_webdriver/unordered_list.rb +0 -37
  57. data/lib/page-object/platforms/watir/check_box.rb +0 -29
  58. data/lib/page-object/platforms/watir/element.rb +0 -295
  59. data/lib/page-object/platforms/watir/file_field.rb +0 -16
  60. data/lib/page-object/platforms/watir/form.rb +0 -16
  61. data/lib/page-object/platforms/watir/image.rb +0 -22
  62. data/lib/page-object/platforms/watir/link.rb +0 -15
  63. data/lib/page-object/platforms/watir/ordered_list.rb +0 -40
  64. data/lib/page-object/platforms/watir/radio_button.rb +0 -22
  65. data/lib/page-object/platforms/watir/select_list.rb +0 -74
  66. data/lib/page-object/platforms/watir/table.rb +0 -38
  67. data/lib/page-object/platforms/watir/table_row.rb +0 -37
  68. data/lib/page-object/platforms/watir/text_area.rb +0 -23
  69. data/lib/page-object/platforms/watir/text_field.rb +0 -16
  70. data/lib/page-object/platforms/watir/unordered_list.rb +0 -42
@@ -6,6 +6,5 @@ module PageObject
6
6
 
7
7
  ::PageObject::Elements.tag_to_class[:b] = ::PageObject::Elements::Bold
8
8
 
9
-
10
9
  end
11
10
  end
@@ -14,10 +14,6 @@ module PageObject
14
14
  super + [:text, :value, :src, :alt, :css]
15
15
  end
16
16
 
17
- def self.selenium_finders
18
- super + [:value, :src, :alt]
19
- end
20
-
21
17
  end
22
18
 
23
19
  ::PageObject::Elements.type_to_class[:submit] = ::PageObject::Elements::Button
@@ -2,9 +2,25 @@ module PageObject
2
2
  module Elements
3
3
  class CheckBox < Element
4
4
 
5
- def initialize(element, platform)
6
- @element = element
7
- include_platform_for platform
5
+ #
6
+ # check the checkbox
7
+ #
8
+ def check
9
+ element.set
10
+ end
11
+
12
+ #
13
+ # uncheck the checkbox
14
+ #
15
+ def uncheck
16
+ element.clear
17
+ end
18
+
19
+ #
20
+ # return true if checkbox is checked
21
+ #
22
+ def checked?
23
+ element.set?
8
24
  end
9
25
 
10
26
  protected
@@ -13,10 +29,6 @@ module PageObject
13
29
  super + [:value, :label]
14
30
  end
15
31
 
16
- def self.selenium_finders
17
- super + [:value, :label, :css]
18
- end
19
-
20
32
  end
21
33
 
22
34
  ::PageObject::Elements.type_to_class[:checkbox] = ::PageObject::Elements::CheckBox
@@ -8,10 +8,6 @@ module PageObject
8
8
  super + [:text, :title]
9
9
  end
10
10
 
11
- def self.selenium_finders
12
- super + [:text, :title]
13
- end
14
-
15
11
  end
16
12
 
17
13
  ::PageObject::Elements.tag_to_class[:div] = ::PageObject::Elements::Div
@@ -1,4 +1,5 @@
1
1
  require 'page-object/nested_elements'
2
+ require 'watir/extensions/select_text'
2
3
 
3
4
  module PageObject
4
5
  module Elements
@@ -6,7 +7,6 @@ module PageObject
6
7
  # Contains functionality that is common across all elements.
7
8
  #
8
9
  # @see PageObject::Platforms::WatirWebDriver::Element for the Watir version of all common methods
9
- # @see PageObject::Platforms::SeleniumWebDriver::Element for the Selenium version of all common methods
10
10
  #
11
11
  class Element
12
12
  include ::PageObject::NestedElements
@@ -18,22 +18,6 @@ module PageObject
18
18
  include_platform_for platform
19
19
  end
20
20
 
21
- #
22
- # click the element
23
- #
24
- def click
25
- element.click
26
- end
27
-
28
-
29
-
30
- #
31
- # return true if the element is enabled
32
- #
33
- def enabled?
34
- element.enabled?
35
- end
36
-
37
21
  #
38
22
  # return true if the element is not enabled
39
23
  #
@@ -41,12 +25,6 @@ module PageObject
41
25
  not enabled?
42
26
  end
43
27
 
44
- #
45
- # get the value of the given CSS property
46
- #
47
- def style(property = nil)
48
- element.style property
49
- end
50
28
 
51
29
  def inspect
52
30
  element.inspect
@@ -81,12 +59,169 @@ module PageObject
81
59
  end
82
60
  end
83
61
 
62
+ #
63
+ # Keeps checking until the element exists
64
+ #
65
+ # @param [Integer] (defaults to: 5) seconds to wait before timing out
66
+ #
84
67
  def check_exists(timeout=::PageObject.default_element_wait)
85
68
  timed_loop(timeout) do |element|
86
69
  element.exists?
87
70
  end
88
71
  end
89
72
 
73
+ #
74
+ # return true if an element is visible
75
+ #
76
+ # def visible?
77
+ # element.present?
78
+ # end
79
+
80
+ #
81
+ # compare this element to another to determine if they are equal
82
+ #
83
+ def ==(other)
84
+ other.is_a? self.class and element == other.element
85
+ end
86
+
87
+ #
88
+ # Get the value of a the given attribute of the element. Will
89
+ # return the current value, even if this has been modified
90
+ # after the page has been loaded. More exactly, this method
91
+ # will return the value of the given attribute, unless that
92
+ # attribute is not present, in which case the value of the
93
+ # property with the same name is returned. If neither value is
94
+ # set, nil is returned. The "style" attribute is converted as
95
+ # best can be to a text representation with a trailing
96
+ # semi-colon. The following are deemed to be "boolean"
97
+ # attributes, and will return either "true" or "false":
98
+ #
99
+ # async, autofocus, autoplay, checked, compact, complete,
100
+ # controls, declare, defaultchecked, defaultselected, defer,
101
+ # disabled, draggable, ended, formnovalidate, hidden, indeterminate,
102
+ # iscontenteditable, ismap, itemscope, loop, multiple, muted,
103
+ # nohref, noresize, noshade, novalidate, nowrap, open, paused,
104
+ # pubdate, readonly, required, reversed, scoped, seamless, seeking,
105
+ # selected, spellcheck, truespeed, willvalidate
106
+ #
107
+ # Finally, the following commonly mis-capitalized
108
+ # attribute/property names are evaluated as expected:
109
+ #
110
+ # class, readonly
111
+ #
112
+ # @param [String]
113
+ # attribute name
114
+ # @return [String,nil]
115
+ # attribute value
116
+ #
117
+ def attribute(attribute_name)
118
+ element.attribute_value attribute_name
119
+ end
120
+
121
+ #
122
+ # find the parent element
123
+ #
124
+ def parent
125
+ parent = element.parent
126
+ type = element.type if parent.tag_name.to_sym == :input
127
+ cls = ::PageObject::Elements.element_class_for(parent.tag_name, type)
128
+ cls.new(parent, :platform => :watir)
129
+ end
130
+
131
+ #
132
+ # Waits until the element is present
133
+ #
134
+ # @param [Integer] (defaults to: 5) seconds to wait before timing out
135
+ #
136
+ def when_present(timeout=::PageObject.default_element_wait)
137
+ element.wait_until(timeout: timeout, message: "Element not present in #{timeout} seconds", &:present?)
138
+ self
139
+ end
140
+
141
+ #
142
+ # Waits until the element is not present
143
+ #
144
+ # @param [Integer] (defaults to: 5) seconds to wait before
145
+ # timing out
146
+ #
147
+ def when_not_present(timeout=::PageObject.default_element_wait)
148
+ element.wait_while(timeout: timeout, message: "Element still present in #{timeout} seconds", &:present?)
149
+ end
150
+
151
+ #
152
+ # Waits until the element is visible
153
+ #
154
+ # @param [Integer] (defaults to: 5) seconds to wait before timing out
155
+ #
156
+ def when_visible(timeout=::PageObject.default_element_wait)
157
+ element.wait_until(timeout: timeout, message: "Element not visible in #{timeout} seconds", &:visible?)
158
+ self
159
+ end
160
+
161
+ #
162
+ # Waits until the element is not visible
163
+ #
164
+ # @param [Integer] (defaults to: 5) seconds to wait before timing out
165
+ #
166
+ def when_not_visible(timeout=::PageObject.default_element_wait)
167
+ element.wait_while(timeout: timeout, message: "Element still visible after #{timeout} seconds", &:visible?)
168
+ end
169
+
170
+ #
171
+ # Waits until the block returns true
172
+ #
173
+ # @param [Integer] (defaults to: 5) seconds to wait before timing out
174
+ # @param [String] the message to display if the event timeouts
175
+ # @param the block to execute when the event occurs
176
+ #
177
+ def wait_until(timeout=::PageObject.default_element_wait, message=nil, &block)
178
+ element.wait_until(timeout: timeout, message: message, &block)
179
+ end
180
+
181
+ #
182
+ # Scroll until the element is viewable
183
+ #
184
+ def scroll_into_view
185
+ element.wd.location_once_scrolled_into_view
186
+ end
187
+
188
+ #
189
+ # location of element (x, y)
190
+ #
191
+ def location
192
+ element.wd.location
193
+ end
194
+
195
+ #
196
+ # size of element (width, height)
197
+ #
198
+ def size
199
+ element.wd.size
200
+ end
201
+
202
+ #
203
+ # Get height of element
204
+ #
205
+ def height
206
+ element.wd.size['height']
207
+ end
208
+
209
+ #
210
+ # Get width of element
211
+ #
212
+ def width
213
+ element.wd.size['width']
214
+ end
215
+
216
+ #
217
+ # Get centre coordinates of element
218
+ #
219
+ def centre
220
+ location = element.wd.location
221
+ size = element.wd.size
222
+ {'y' => (location['y'] + (size['height']/2)), 'x' => (location['x'] + (size['width']/2))}
223
+ end
224
+
90
225
  # @private
91
226
  def self.watir_identifier_for identifier
92
227
  if should_build_watir_xpath(identifier)
@@ -103,33 +238,11 @@ module PageObject
103
238
  all_identities
104
239
  end
105
240
 
106
- # @private
107
- def self.selenium_identifier_for identifier
108
- if identifier.length == 1
109
- identifier = identifier_for identifier, selenium_finders, selenium_mapping
110
- return identifier.keys.first, identifier.values.first
111
- elsif identifier.length > 1
112
- how = :xpath
113
- what = build_xpath_for identifier
114
- return how, what
115
- end
116
- end
117
-
118
241
  # @private
119
242
  # delegate calls to driver element
120
243
  def method_missing(*args, &block)
121
244
  m = args.shift
122
- $stderr.puts "*** DEPRECATION WARNING"
123
- $stderr.puts "*** You are calling a method named #{m} at #{caller[0]}."
124
- $stderr.puts "*** This method does not exist in page-object so it is being passed to the driver."
125
- $stderr.puts "*** This feature will be removed in the near future."
126
- $stderr.puts "*** Please change your code to call the correct page-object method."
127
- $stderr.puts "*** If you are using functionality that does not exist in page-object please request it be added."
128
- begin
129
- element.send m, *args, &block
130
- rescue Exception => e
131
- raise
132
- end
245
+ element.send m, *args, &block
133
246
  end
134
247
 
135
248
  protected
@@ -215,14 +328,6 @@ module PageObject
215
328
  {}
216
329
  end
217
330
 
218
- def self.selenium_finders
219
- [:class, :css, :id, :index, :name, :xpath]
220
- end
221
-
222
- def self.selenium_mapping
223
- {}
224
- end
225
-
226
331
  def include_platform_for platform
227
332
  platform_information = PageObject::Platforms.get
228
333
  raise ArgumentError,"Expected hash with at least a key :platform for platform information! (#{platform.inspect})" unless platform.class == Hash && platform.has_key?(:platform)
@@ -231,29 +336,7 @@ module PageObject
231
336
  raise ArgumentError, "Unknown platform #{platform_name}! Expect platform to be one of the following: #{platform_information.keys.inspect}" unless platform_information.keys.include?(platform_name)
232
337
  base_platform_class = "#{platform_information[platform_name]}::"
233
338
 
234
- self.send :extend, constantize_classname(base_platform_class + "Element")
235
339
  @platform = constantize_classname(base_platform_class+ "PageObject").new(@element)
236
-
237
- # include class specific code
238
- class_to_include = case
239
- when self.class == PageObject::Elements::Element
240
- # already loaded
241
- return true
242
- when self.class.name =~/PageObject:Elements::/
243
- self.class
244
- # inherited classes for example the widgets
245
- else
246
- parent_classes = self.class.ancestors.select { |item| item.name =~/PageObject::Elements::/ }
247
- raise RuntimeError,"Could not identify page-object inherited class for #{self.class}!" if parent_classes.empty?
248
- parent_classes.first
249
- end
250
-
251
- element_type_specific_code = File.expand_path(File.dirname(__FILE__) + "../../platforms/#{platform_name}/"+ get_element_type_underscored(class_to_include) )
252
- if File.exist? element_type_specific_code + '.rb'
253
- require element_type_specific_code
254
- self.send :extend, constantize_classname( base_platform_class + get_element_type(class_to_include) )
255
- end
256
-
257
340
  end
258
341
 
259
342
  def to_ary
@@ -276,20 +359,6 @@ module PageObject
276
359
  name.split("::").inject(Object) { |k,n| k.const_get(n) }
277
360
  end
278
361
 
279
-
280
- def get_element_type(class_name = self.class)
281
- class_name.name.split('::').last
282
- end
283
-
284
- # retrieved from ruby on rails underscore method
285
- def get_element_type_underscored(class_name = self.class)
286
- get_element_type(class_name).to_s.gsub(/::/, '/').
287
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
288
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
289
- tr("-", "_").
290
- downcase
291
- end
292
-
293
362
  end
294
363
  end
295
364
  end
@@ -3,9 +3,11 @@ module PageObject
3
3
  module Elements
4
4
  class FileField < Element
5
5
 
6
- def initialize(element, platform)
7
- @element = element
8
- include_platform_for platform
6
+ #
7
+ # Set the value of the FileField
8
+ #
9
+ def value=(new_value)
10
+ element.set(new_value)
9
11
  end
10
12
 
11
13
  protected
@@ -14,10 +16,6 @@ module PageObject
14
16
  super + [:title, :label]
15
17
  end
16
18
 
17
- def self.selenium_finders
18
- super + [:title, :label]
19
- end
20
-
21
19
  end
22
20
 
23
21
  ::PageObject::Elements.type_to_class[:file] = ::PageObject::Elements::FileField
@@ -2,10 +2,6 @@
2
2
  module PageObject
3
3
  module Elements
4
4
  class Form < Element
5
- def initialize(element, platform)
6
- @element = element
7
- include_platform_for platform
8
- end
9
5
 
10
6
  protected
11
7
 
@@ -13,10 +9,6 @@ module PageObject
13
9
  super + [:action]
14
10
  end
15
11
 
16
- def self.selenium_finders
17
- super + [:action]
18
- end
19
-
20
12
  end
21
13
 
22
14
  ::PageObject::Elements.tag_to_class[:form] = ::PageObject::Elements::Form
@@ -3,7 +3,7 @@ module PageObject
3
3
  class HiddenField < Element
4
4
 
5
5
  def click
6
- raise "click is not available on hidden field element with Selenium or Watir"
6
+ raise "click is not available on the hidden field element"
7
7
  end
8
8
 
9
9
  protected
@@ -12,9 +12,6 @@ module PageObject
12
12
  super + [:text, :value]
13
13
  end
14
14
 
15
- def self.selenium_finders
16
- super + [:value]
17
- end
18
15
  end
19
16
 
20
17
  ::PageObject::Elements.type_to_class[:hidden] = ::PageObject::Elements::HiddenField