page-object 1.1.0 → 1.1.1

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +1 -0
  4. data/.travis.yml +7 -2
  5. data/ChangeLog +14 -1
  6. data/Gemfile +4 -2
  7. data/README.md +2 -0
  8. data/Rakefile +5 -1
  9. data/features/async.feature +3 -12
  10. data/features/audio.feature +10 -14
  11. data/features/element.feature +21 -0
  12. data/features/gxt_table_extension.feature +1 -2
  13. data/features/html/multi_elements.html +11 -10
  14. data/features/html/static_elements.html +3 -16
  15. data/features/html/widgets.html +20 -0
  16. data/features/italic.feature +21 -0
  17. data/features/multi_elements.feature +28 -22
  18. data/features/sample-app/public/audio_video.html +23 -0
  19. data/features/step_definitions/audio_steps.rb +6 -6
  20. data/features/step_definitions/element_steps.rb +28 -0
  21. data/features/step_definitions/gxt_table_steps.rb +1 -6
  22. data/features/step_definitions/italic_steps.rb +12 -0
  23. data/features/step_definitions/multi_elements_steps.rb +13 -0
  24. data/features/step_definitions/page_traversal_steps.rb +4 -0
  25. data/features/step_definitions/table_row_steps.rb +23 -0
  26. data/features/step_definitions/video_steps.rb +3 -3
  27. data/features/support/audio_video_page.rb +24 -0
  28. data/features/support/page.rb +20 -20
  29. data/features/support/url_helper.rb +4 -0
  30. data/features/table_row.feature +43 -0
  31. data/features/video.feature +1 -5
  32. data/lib/page-object.rb +4 -0
  33. data/lib/page-object/accessors.rb +88 -4
  34. data/lib/page-object/elements.rb +2 -1
  35. data/lib/page-object/elements/element.rb +5 -5
  36. data/lib/page-object/elements/italic.rb +11 -0
  37. data/lib/page-object/elements/ordered_list.rb +1 -1
  38. data/lib/page-object/elements/unordered_list.rb +1 -1
  39. data/lib/page-object/locator_generator.rb +2 -0
  40. data/lib/page-object/platforms/selenium_webdriver/element.rb +37 -0
  41. data/lib/page-object/platforms/selenium_webdriver/ordered_list.rb +10 -8
  42. data/lib/page-object/platforms/selenium_webdriver/page_object.rb +51 -1
  43. data/lib/page-object/platforms/selenium_webdriver/unordered_list.rb +7 -9
  44. data/lib/page-object/platforms/watir_webdriver/element.rb +45 -1
  45. data/lib/page-object/platforms/watir_webdriver/ordered_list.rb +9 -4
  46. data/lib/page-object/platforms/watir_webdriver/page_object.rb +81 -50
  47. data/lib/page-object/platforms/watir_webdriver/unordered_list.rb +11 -5
  48. data/lib/page-object/version.rb +1 -1
  49. data/lib/page-object/widgets.rb +1 -1
  50. data/page-object.gemspec +1 -0
  51. data/spec/page-object/element_locators_spec.rb +124 -80
  52. data/spec/page-object/elements/element_spec.rb +83 -1
  53. data/spec/page-object/elements/italic_spec.rb +29 -0
  54. data/spec/page-object/elements/media_spec.rb +63 -0
  55. data/spec/page-object/elements/ordered_list_spec.rb +6 -22
  56. data/spec/page-object/elements/selenium_element_spec.rb +41 -0
  57. data/spec/page-object/elements/unordered_list_spec.rb +4 -21
  58. data/spec/page-object/elements/video_spec.rb +27 -0
  59. data/spec/page-object/elements/watir_element_spec.rb +48 -0
  60. data/spec/page-object/selenium_accessors_spec.rb +28 -9
  61. data/spec/page-object/watir_accessors_spec.rb +57 -1
  62. data/spec/spec_helper.rb +3 -6
  63. metadata +39 -3
@@ -0,0 +1,23 @@
1
+ <html>
2
+ <head>
3
+ <title>Audio and Video</title>
4
+ </head>
5
+ <body>
6
+
7
+ <h2>Audio & Video</h2>
8
+ <audio controls id="audio" name="audio" class="audio">
9
+ <source src="04-Death_Becomes_Fur.mp4"
10
+ type='audio/mp4'/>
11
+ <source src="04-Death_Becomes_Fur.oga"
12
+ type='audio/ogg; codecs=vorbis'/>
13
+ <p>Your user agent does not support the HTML5 Audio element.</p>
14
+ </audio>
15
+
16
+ <video width="320" height="240" controls="controls" id="video" name="video" class="video">
17
+ <source src="movie.mp4" type="video/mp4" />
18
+ <source src="movie.ogg" type="video/ogg" />
19
+ Your browser does not support the video tag.
20
+ </video>
21
+
22
+ </body>
23
+ </head>
@@ -1,9 +1,13 @@
1
1
  When /^I search for the audio element by "([^\"]*)"$/ do |how|
2
- @element = @page.send "audio_#{how}_element"
2
+ @element = @avpage.send "audio_#{how}_element"
3
3
  end
4
4
 
5
5
  When /^I search for the audio element by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
6
- @element = @page.send "audio_#{param1}_#{param2}_element"
6
+ @element = @avpage.send "audio_#{param1}_#{param2}_element"
7
+ end
8
+
9
+ When /^I retrieve the audio element from the page$/ do
10
+ @element = @avpage.audio_id_element
7
11
  end
8
12
 
9
13
  Then /^I should know the audio is not autoplay$/ do
@@ -18,10 +22,6 @@ Then /^I should know that the audio is paused$/ do
18
22
  @element.should be_paused
19
23
  end
20
24
 
21
- Then /^I should know that the duration is greater than (\d+) seconds$/ do |duration|
22
- @element.duration.should > duration.to_f
23
- end
24
-
25
25
  Then /^I should know that its volume is (\d+)$/ do |volume|
26
26
  @element.volume.should == volume.to_i
27
27
  end
@@ -264,3 +264,31 @@ Then(/^I should know the attribute "(.*?)" includes "(.+)"$/) do |attribute, inc
264
264
  @attr = @element.attribute(attribute)
265
265
  @attr.should include included
266
266
  end
267
+
268
+ Then(/^I should be able to know its location$/) do
269
+ expect(@element.location.y).to be > 0
270
+ expect(@element.location.x).to be > 0
271
+ end
272
+
273
+ Then(/^I should be able to know its size$/) do
274
+ expect(@element.size.width).to be > 0
275
+ expect(@element.size.height).to be > 0
276
+ end
277
+
278
+ Then(/the element height is not 0/) do
279
+ (@element.height.is_a? Integer).should ==true
280
+ @element.height.should > 0
281
+ end
282
+
283
+ Then(/the element width is not 0/) do
284
+ (@element.width.is_a? Integer).should ==true
285
+ @element.width.should > 0
286
+ end
287
+
288
+ Then(/the element centre should be greater than element y position/) do
289
+ @element.centre['y'].should > @element.location.y
290
+ end
291
+
292
+ Then(/the element centre should be greater than element x position/) do
293
+ @element.centre['x'].should > @element.location.x
294
+ end
@@ -12,10 +12,6 @@ Given /^I am on the Gxt Examples page$/ do
12
12
  visit GxtSamplePageObject
13
13
  end
14
14
 
15
- When /^I have the Basic Grid opened$/ do
16
- on(GxtSamplePageObject).basic_grid_element.click
17
- end
18
-
19
15
  When /^I have defined a GxtTable class extending Table$/ do
20
16
  class GxtTable < PageObject::Elements::Table
21
17
 
@@ -36,9 +32,8 @@ When /^I define a page-object using that widget$/ do
36
32
  class GxtSamplePageObject
37
33
  include PageObject
38
34
 
39
- page_url "http://gxtexamplegallery.appspot.com/"
35
+ page_url UrlHelper.widgets
40
36
 
41
- div(:basic_grid, :class => "label_basic_grid")
42
37
  gxt_table(:gxt_table, :class => "x-grid3")
43
38
  end unless class_exists? 'GxtSamplePageObject'
44
39
  end
@@ -0,0 +1,12 @@
1
+ When /^I get the italic text for the "([^\"]*)" element$/ do |el|
2
+ @i = @page.send "#{el}_id"
3
+ end
4
+
5
+ Then /^I should see "([^\"]*)" in italic$/ do |text|
6
+ @i.should == text
7
+ end
8
+
9
+ When /^I search italic text for the (\w+) by "([^"]*)"$/ do |text_decorator, type|
10
+ @i = @page.send "#{text_decorator}_#{type}"
11
+ end
12
+
@@ -32,6 +32,7 @@ class MultiElementsPage
32
32
  file_fields(:the_file_fields, :class => 'file_field_class')
33
33
  elements(:generic_label, :label, :class => 'label')
34
34
  b(:bs)
35
+ i(:is)
35
36
  end
36
37
 
37
38
 
@@ -539,3 +540,15 @@ end
539
540
  Then /^the text for b (\d+) should be "([^\"]*)"$/ do |b_num, text|
540
541
  @elements[b_num.to_i - 1].text.should == text
541
542
  end
543
+
544
+ When /^I select the is$/ do
545
+ @elements = @page.i_elements
546
+ end
547
+
548
+ Then /^I should have (\d+) is$/ do |num_is|
549
+ @elements.size.should == num_is.to_i
550
+ end
551
+
552
+ Then /^the text for i (\d+) should be "([^\"]*)"$/ do |i_num, text|
553
+ @elements[i_num.to_i - 1].text.should == text
554
+ end
@@ -2,3 +2,7 @@ Given /^I am on the static elements page$/ do
2
2
  @page = Page.new(@browser)
3
3
  @page.navigate_to(UrlHelper.static_elements)
4
4
  end
5
+
6
+ Given /^I am on the audio video page$/ do
7
+ @avpage = visit AudioVideoPage
8
+ end
@@ -0,0 +1,23 @@
1
+ When /^I search for the table row by "([^\"]*)"$/ do |how|
2
+ @row_data = @page.send "tr_#{how}"
3
+ end
4
+
5
+ When /^I retrieve a table row element by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
6
+ @row_data = @page.send "tr_#{param1}_#{param2}"
7
+ end
8
+
9
+ When /^I retrieve a table row element while the script is executing$/ do
10
+ @row_data = @page.row_element(:id => 'tr_id').text
11
+ end
12
+
13
+ Then /^I should see that the row exists$/ do
14
+ @page.tr_id?.should == true
15
+ end
16
+
17
+ When /^I retrieve the data from the table row/ do
18
+ @row_data = @page.tr_id
19
+ end
20
+
21
+ Then /^the row data should be '([^"]*)'$/ do |expected|
22
+ @row_data.should == expected
23
+ end
@@ -1,14 +1,14 @@
1
1
 
2
2
  When /^I retrieve the video element$/ do
3
- @element = @page.video_id_element
3
+ @element = @avpage.video_id_element
4
4
  end
5
5
 
6
6
  When /^I search for the video element by "([^\"]*)"$/ do |how|
7
- @element = @page.send "video_#{how}_element"
7
+ @element = @avpage.send "video_#{how}_element"
8
8
  end
9
9
 
10
10
  When /^I search for the video element by "([^\"]*)" and "([^\"]*)"$/ do |param1, param2|
11
- @element = @page.send "video_#{param1}_#{param2}_element"
11
+ @element = @avpage.send "video_#{param1}_#{param2}_element"
12
12
  end
13
13
 
14
14
  Then /^I should know the video is not autoplay$/ do
@@ -0,0 +1,24 @@
1
+ class AudioVideoPage
2
+ include PageObject
3
+
4
+ page_url "http://localhost:4567/audio_video.html"
5
+
6
+ audio(:audio_id, :id => 'audio')
7
+ audio(:audio_name, :name => 'audio')
8
+ audio(:audio_class, :class => 'audio')
9
+ audio(:audio_css, :css => '.audio')
10
+ audio(:audio_index, :index => 0)
11
+ audio(:audio_xpath, :xpath => '//audio')
12
+ audio(:audio_class_index, :class => 'audio', :index => 0)
13
+ audio(:audio_name_index, :name => 'audio', :index => 0)
14
+
15
+ video(:video_id, :id => 'video')
16
+ video(:video_name, :name => 'video')
17
+ video(:video_class, :class => 'video')
18
+ video(:video_css, :css => '.video')
19
+ video(:video_index, :index => 0)
20
+ video(:video_xpath, :xpath => '//video')
21
+ video(:video_class_index, :class => 'video', :index => 0)
22
+ video(:video_name_index, :name => 'video', :index => 0)
23
+
24
+ end
@@ -109,7 +109,7 @@ class Page
109
109
  div(:div_title, :title => 'div_title')
110
110
  div(:div_class_index, :class => "div_class", :index => 0)
111
111
  div(:div_name_index, :name => "div_name", :index => 0)
112
-
112
+
113
113
  div(:div_data_entity, :data_entity => "test")
114
114
 
115
115
  span(:span_id, :id => 'span_id')
@@ -143,6 +143,15 @@ class Page
143
143
  cell(:cell_class_index, :class => "cell_class", :index => 0)
144
144
  cell(:cell_name_index, :name => "cell_name", :index => 0)
145
145
 
146
+ row(:tr_id, :id => 'tr_id')
147
+ row(:tr_class, :class => 'tr_class')
148
+ row(:tr_css, :css => '.tr_class')
149
+ row(:tr_index, :index => 1)
150
+ row(:tr_text, :text => 'Data1 Data2')
151
+ row(:tr_xpath, :xpath => '//table//tbody//tr[1]')
152
+ row(:tr_class_index, :class => "tr_class", :index => 0)
153
+ row(:tr_name_index, :name => "tr_name", :index => 0)
154
+
146
155
  button(:button_id, :id => 'button_id')
147
156
  button(:button_name, :name => 'button_name')
148
157
  button(:button_class, :class => 'button_class')
@@ -333,24 +342,6 @@ class Page
333
342
  canvas(:canvas_class_index, :class => 'canvas', :index => 0)
334
343
  canvas(:canvas_name_index, :name => 'canvas', :index => 0)
335
344
 
336
- audio(:audio_id, :id => 'audio')
337
- audio(:audio_name, :name => 'audio')
338
- audio(:audio_class, :class => 'audio')
339
- audio(:audio_css, :css => '.audio')
340
- audio(:audio_index, :index => 0)
341
- audio(:audio_xpath, :xpath => '//audio')
342
- audio(:audio_class_index, :class => 'audio', :index => 0)
343
- audio(:audio_name_index, :name => 'audio', :index => 0)
344
-
345
- video(:video_id, :id => 'video')
346
- video(:video_name, :name => 'video')
347
- video(:video_class, :class => 'video')
348
- video(:video_css, :css => '.video')
349
- video(:video_index, :index => 0)
350
- video(:video_xpath, :xpath => '//video')
351
- video(:video_class_index, :class => 'video', :index => 0)
352
- video(:video_name_index, :name => 'video', :index => 0)
353
-
354
345
  element(:article_id, :article, :id => 'article_id')
355
346
  element(:header_id, :header, :id => 'header_id')
356
347
  element(:footer_id, :footer, :id => 'footer_id')
@@ -358,7 +349,7 @@ class Page
358
349
  element(:details_id, :details, :id => 'details_id')
359
350
 
360
351
  figure(:figure_id, :id => 'figure_id')
361
-
352
+
362
353
  svg(:svg_id, :id => 'the_svg')
363
354
 
364
355
  b(:b_id, :id => 'b_id')
@@ -369,5 +360,14 @@ class Page
369
360
  b(:b_xpath, :xpath => '//b')
370
361
  b(:b_class_index, :class => 'b_class', :index => 0)
371
362
  b(:b_name_index, :name => 'b_name', :index => 0)
363
+
364
+ i(:i_id, :id => 'i_id')
365
+ i(:i_class, :class => 'i_class')
366
+ i(:i_css, :css => '.i_class')
367
+ i(:i_name, :name => 'i_name')
368
+ i(:i_index, :index => 0)
369
+ i(:i_xpath, :xpath => '//i')
370
+ i(:i_class_index, :class => 'i_class', :index => 0)
371
+ i(:i_name_index, :name => 'i_name', :index => 0)
372
372
  end
373
373
 
@@ -53,5 +53,9 @@ module UrlHelper
53
53
  def double_click
54
54
  "#{files}/double_click.html"
55
55
  end
56
+
57
+ def widgets
58
+ "#{files}/widgets.html"
59
+ end
56
60
  end
57
61
  end
@@ -0,0 +1,43 @@
1
+ Feature: Table Row
2
+
3
+ Background:
4
+ Given I am on the static elements page
5
+
6
+ Scenario: Retrieving the text from a table row
7
+ When I retrieve the data from the table row
8
+ Then the row data should be 'Data1 Data2'
9
+
10
+ Scenario Outline: Locating table rows on the Page
11
+ When I search for the table row by "<search_by>"
12
+ Then the row data should be 'Data1 Data2'
13
+
14
+ Scenarios:
15
+ | search_by |
16
+ | id |
17
+ | class |
18
+ | xpath |
19
+ | css |
20
+
21
+
22
+ @watir_only
23
+ Scenario: Locating table rows on the Page by text
24
+ When I search for the table row by "text"
25
+ Then the row data should be 'Data1 Data2'
26
+
27
+ @watir_only
28
+ Scenario Outline: Locating table rows on the Page with watir
29
+ When I search for the table row by "<search_by>"
30
+ Then the row data should be 'Data1 Data2'
31
+
32
+ Scenarios:
33
+ | search_by |
34
+ | index |
35
+
36
+ Scenario: Locating table row using multiple parameters
37
+ When I retrieve a table row element by "class" and "index"
38
+ Then the row data should be 'Data1 Data2'
39
+
40
+ Scenario: Finding a table row dynamically
41
+ When I retrieve a table row element while the script is executing
42
+ Then I should see that the row exists
43
+ And the row data should be 'Data1 Data2'
@@ -1,7 +1,7 @@
1
1
  Feature: Support for video element
2
2
 
3
3
  Background:
4
- Given I am on the static elements page
4
+ Given I am on the audio video page
5
5
 
6
6
  Scenario: finding an video element
7
7
  When I retrieve the video element
@@ -42,10 +42,6 @@ Feature: Support for video element
42
42
  When I retrieve the video element
43
43
  Then I should know that the video is paused
44
44
 
45
- Scenario: Should know its duration
46
- When I retrieve the video element
47
- Then I should know that the duration is greater than 12 seconds
48
-
49
45
  Scenario: Should know its volume
50
46
  When I retrieve the video element
51
47
  Then I should know that its volume is 1
@@ -49,6 +49,10 @@ module PageObject
49
49
  include LoadsPlatform
50
50
  include ElementLocators
51
51
  include PagePopulator
52
+ extend Forwardable
53
+
54
+ # Forward visibility checks to root so page sections can be tested for existence.
55
+ def_delegators :root, :visible?, :present?, :exists?
52
56
 
53
57
  # @return [Watir::Browser or Selenium::WebDriver::Driver] the platform browser passed to the constructor
54
58
  attr_reader :browser
@@ -207,7 +207,7 @@ module PageObject
207
207
  # * :xpath => Watir and Selenium
208
208
  # @param optional block to be invoked when element method is called
209
209
  #
210
- def text_field(name, identifier={:index => 0}, &block)
210
+ def text_field(name, identifier={:index => 0}, &block)
211
211
  standard_methods(name, identifier, 'text_field_for', &block)
212
212
  define_method(name) do
213
213
  return platform.text_field_value_for identifier.clone unless block_given?
@@ -402,7 +402,7 @@ module PageObject
402
402
  end
403
403
 
404
404
  #
405
- # adds four methods - one to select, another to return if a radio button
405
+ # adds four methods - one to select, another to return if a radio button
406
406
  # is selected, another method to return a PageObject::Elements::RadioButton
407
407
  # object representing the radio button element, and another to check
408
408
  # the radio button's existence.
@@ -637,6 +637,36 @@ module PageObject
637
637
  end
638
638
  alias_method :td, :cell
639
639
 
640
+
641
+ #
642
+ # adds three methods - one to retrieve the text from a table row,
643
+ # another to return the table row element, and another to check the row's
644
+ # existence.
645
+ #
646
+ # @example
647
+ # row(:sums, :id => 'sum_row')
648
+ # # will generate 'sums', 'sums_element', and 'sums?' methods
649
+ #
650
+ # @param [Symbol] the name used for the generated methods
651
+ # @param [Hash] identifier how we find a cell. You can use a multiple parameters
652
+ # by combining of any of the following except xpath. The valid keys are:
653
+ # * :class => Watir and Selenium
654
+ # * :css => Watir and Selenium
655
+ # * :id => Watir and Selenium
656
+ # * :index => Watir and Selenium
657
+ # * :text => Watir only
658
+ # * :xpath => Watir and Selenium
659
+ # * :css => Watir and Selenium
660
+ # @param optional block to be invoked when element method is called
661
+ #
662
+ def row(name, identifier={:index => 0}, &block)
663
+ standard_methods(name, identifier, 'row_for', &block)
664
+ define_method("#{name}") do
665
+ return platform.row_text_for identifier.clone unless block_given?
666
+ self.send("#{name}_element").text
667
+ end
668
+ end
669
+
640
670
  #
641
671
  # adds two methods - one to retrieve the image element, and another to
642
672
  # check the image's existence.
@@ -1145,6 +1175,34 @@ module PageObject
1145
1175
  end
1146
1176
  end
1147
1177
 
1178
+ #
1179
+ # adds three methods - one to retrieve the text of a i element, another to
1180
+ # retrieve a i element, and another to check for it's existence.
1181
+ #
1182
+ # @example
1183
+ # i(:italic, :id => 'title')
1184
+ # # will generate 'italic', 'italic_element', and 'italic?' methods
1185
+ #
1186
+ # @param [Symbol] the name used for the generated methods
1187
+ # @param [Hash] identifier how we find a i. You can use a multiple parameters
1188
+ # by combining of any of the following except xpath. The valid keys are:
1189
+ # * :class => Watir and Selenium
1190
+ # * :css => Watir and Selenium
1191
+ # * :id => Watir and Selenium
1192
+ # * :index => Watir and Selenium
1193
+ # * :name => Watir and Selenium
1194
+ # * :xpath => Watir and Selenium
1195
+ # @param optional block to be invoked when element method is called
1196
+ #
1197
+ def i(name, identifier={:index => 0}, &block)
1198
+ standard_methods(name, identifier,'i_for', &block)
1199
+ define_method(name) do
1200
+ return platform.i_text_for identifier.clone unless block_given?
1201
+ self.send("#{name}_element").text
1202
+ end
1203
+ end
1204
+ alias_method :icon, :i
1205
+
1148
1206
  #
1149
1207
  # adds two methods - one to retrieve a svg, and another to check
1150
1208
  # the svg's existence.
@@ -1189,7 +1247,20 @@ module PageObject
1189
1247
  # * :xpath => Watir and Selenium
1190
1248
  # @param optional block to be invoked when element method is called
1191
1249
  #
1192
- def element(name, tag, identifier={:index => 0}, &block)
1250
+ def element(name, tag=:element, identifier={ :index => 0 }, &block)
1251
+ # default tag to :element
1252
+ #
1253
+ # element 'button', css: 'some css'
1254
+ #
1255
+ # is the same as
1256
+ #
1257
+ # element 'button', :element, css: 'some css'
1258
+ #
1259
+ if tag.is_a?(Hash)
1260
+ identifier = tag
1261
+ tag = :element
1262
+ end
1263
+
1193
1264
  define_method("#{name}") do
1194
1265
  self.send("#{name}_element").text
1195
1266
  end
@@ -1222,7 +1293,20 @@ module PageObject
1222
1293
  # * :xpath => Watir and Selenium
1223
1294
  # @param optional block to be invoked when element method is called
1224
1295
  #
1225
- def elements(name, tag, identifier={:index => 0}, &block)
1296
+ def elements(name, tag=:element, identifier={:index => 0}, &block)
1297
+ # default tag to :element
1298
+ #
1299
+ # elements 'button', css: 'some css'
1300
+ #
1301
+ # is the same as
1302
+ #
1303
+ # elements 'button', :element, css: 'some css'
1304
+ #
1305
+ if tag.is_a?(Hash)
1306
+ identifier = tag
1307
+ tag = :element
1308
+ end
1309
+
1226
1310
  define_method("#{name}_elements") do
1227
1311
  return call_block(&block) if block_given?
1228
1312
  platform.elements_for(tag, identifier.clone)