page-object 1.1.0 → 1.1.1

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