druid-ts 1.1.2 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +21 -0
  3. data/README.md +42 -32
  4. data/features/button.feature +1 -0
  5. data/features/element.feature +4 -0
  6. data/features/generic_elements.feature +24 -0
  7. data/features/html/multi_elements.html +4 -0
  8. data/features/html/nested_elements.html +3 -0
  9. data/features/html/static_elements.html +14 -1
  10. data/features/javascript.feature +6 -0
  11. data/features/label.feature +44 -0
  12. data/features/link.feature +1 -0
  13. data/features/multi_elements.feature +7 -0
  14. data/features/nested_elements.feature +4 -0
  15. data/features/page_level_actions.feature +12 -0
  16. data/features/select_list.feature +5 -3
  17. data/features/step_definations/element_steps.rb +14 -0
  18. data/features/step_definations/generic_element_steps.rb +19 -0
  19. data/features/step_definations/javasript_steps.rb +8 -0
  20. data/features/step_definations/label_steps.rb +19 -0
  21. data/features/step_definations/multi_elements_steps.rb +12 -0
  22. data/features/step_definations/nested_elements_steps.rb +9 -1
  23. data/features/step_definations/page_level_actions_steps.rb +17 -0
  24. data/features/step_definations/select_list_steps.rb +5 -0
  25. data/features/support/page.rb +21 -0
  26. data/lib/druid.rb +17 -0
  27. data/lib/druid/accessors.rb +110 -2
  28. data/lib/druid/assist.rb +26 -1
  29. data/lib/druid/element_locators.rb +42 -6
  30. data/lib/druid/elements.rb +2 -1
  31. data/lib/druid/elements/button.rb +1 -1
  32. data/lib/druid/elements/element.rb +1 -1
  33. data/lib/druid/elements/label.rb +11 -0
  34. data/lib/druid/elements/link.rb +1 -1
  35. data/lib/druid/nested_elements.rb +9 -1
  36. data/lib/druid/page_factory.rb +6 -0
  37. data/lib/druid/version.rb +1 -1
  38. data/spec/druid/accessors_spec.rb +48 -4
  39. data/spec/druid/druid_spec.rb +11 -0
  40. data/spec/druid/element_locators_spec.rb +12 -0
  41. data/spec/druid/elements/button_spec.rb +1 -1
  42. data/spec/druid/elements/label_spec.rb +19 -0
  43. data/spec/druid/elements/link_spec.rb +1 -1
  44. data/spec/druid/page_factory_spec.rb +26 -0
  45. metadata +12 -1
@@ -294,3 +294,15 @@ end
294
294
  Then(/^the text for paragraph (\d+) should be "([^"]*)"$/) do |paragraph_num, text|
295
295
  expect(@elements[paragraph_num.to_i - 1].text).to eql text
296
296
  end
297
+
298
+ When(/^I select the labels with class "([^"]*)"$/) do |class_name|
299
+ @elements = @page.label_elements(:class => class_name)
300
+ end
301
+
302
+ Then(/^I should have (\d+) labels$/) do |num_labels|
303
+ expect(@elements.size).to eql num_labels.to_i
304
+ end
305
+
306
+ Then(/^the text for label (\d+) should be "([^"]*)"$/) do |label_num, text|
307
+ expect(@elements[label_num.to_i - 1].text).to eql text
308
+ end
@@ -27,6 +27,7 @@ class NestedElementsPage
27
27
  h6(:nested_h6) { |page| page.outer_div_element.h6_element }
28
28
  paragraph(:nested_paragraph) { |page| page.outer_div_element.paragraph_element }
29
29
  file_field(:nested_file_field) { |page| page.outer_div_element.file_field_element }
30
+ label(:nested_label) { |page| page.outer_div_element.label_element }
30
31
  unordered_list(:outer_list, :id => 'outer')
31
32
  ordered_list(:ordered_outer, :id => 'ol-outer')
32
33
  end
@@ -205,7 +206,14 @@ When(/^I get the outter ordered list$/) do
205
206
  @list = @page.ordered_outer_element
206
207
  end
207
208
 
208
-
209
209
  Then(/^I should see "([^"]*)" for list item (\d+)$/) do |text, item_num|
210
210
  expect(@list[item_num.to_i - 1].text).to eql text
211
211
  end
212
+
213
+ When(/^I search for a label located in a div$/) do
214
+ @label = @page.nested_label_element
215
+ end
216
+
217
+ Then(/^I should see the nested labels text should be "([^"]*)"$/) do |text|
218
+ expect(@label.text).to eql text
219
+ end
@@ -118,3 +118,20 @@ end
118
118
  When(/^I press the forward button$/) do
119
119
  @page.forward
120
120
  end
121
+
122
+ Then(/^the page should have the expected title$/) do
123
+ expect(@page).to have_expected_title
124
+ end
125
+
126
+ Then(/^the page should have the expected element$/) do
127
+ expect(@page).to have_expected_element
128
+ end
129
+
130
+ Then(/^the page should not have the expected element$/) do
131
+ class FakePage
132
+ include Druid
133
+ expected_element :blah
134
+ end
135
+
136
+ expect(FakePage.new(@driver)).not_to have_expected_element
137
+ end
@@ -64,3 +64,8 @@ end
64
64
  Then(/^the select list should know that "([^"]*)" is selected$/) do |text|
65
65
  expect(@page.select_list_id_element.selected?(text)).to be true
66
66
  end
67
+
68
+ Then(/^the value for the option should be "([^"]*)"$/) do |value|
69
+ @element = @page.send "select_list_#{@how}_element".to_sym
70
+ expect(@element.value).to eql value
71
+ end
@@ -1,5 +1,9 @@
1
1
  class Page
2
2
  include Druid
3
+
4
+ expected_title "Static Elements Page"
5
+ expected_element :hello0
6
+
3
7
  page_url("http://www.baidu.com")
4
8
 
5
9
  link(:google_search_id, :id => "link_id")
@@ -11,6 +15,7 @@ class Page
11
15
  link(:google_search_index, :index => 0)
12
16
  link(:google_search_link, :link => "Google Search")
13
17
  link(:google_search_link_text, :link_text => "Google Search")
18
+ link(:google_search_css, :css => "a.link_class")
14
19
  link(:hello0, {:text => "Hello", :index => 0})
15
20
  link(:hello1, {:text => "Hello", :index => 1})
16
21
  link(:hello2, {:text => "Hello", :index => 2})
@@ -66,6 +71,7 @@ class Page
66
71
  button(:button_value, :value => 'Click Me')
67
72
  button(:button_class_index, :class => "button_class", :index => 0)
68
73
  button(:button_name_index, :name => "button_name", :index => 0)
74
+ button(:button_css, :css => "input[type='submit']")
69
75
 
70
76
  button(:button_image_id, :id => 'button_image_id')
71
77
  button(:button_image_src, :src => 'images/submit.gif')
@@ -117,6 +123,15 @@ class Page
117
123
  span(:span_class_index, :class => "span_class", :index => 0)
118
124
  span(:span_name_index, :name => "span_name", :index => 0)
119
125
 
126
+ label(:label_id, :id => "label_id")
127
+ label(:label_name, :name => "label_name")
128
+ label(:label_class, :class => "label_class")
129
+ label(:label_text, :text => "page-object is the best!")
130
+ label(:label_index, :index => 0)
131
+ label(:label_xpath, :xpath => "//label")
132
+ label(:label_class_index, :class => "label_class", :index => 0)
133
+ label(:label_name_index, :name => "label_name", :index => 0)
134
+
120
135
  image(:image_id, :id => "image_id")
121
136
  image(:image_name, :name => 'image_name')
122
137
  image(:image_class, :class => 'image_class')
@@ -257,4 +272,10 @@ class Page
257
272
  file_field(:file_field_name_index, :name => 'file_field_name', :index => 0)
258
273
 
259
274
  link(:child, :id => 'child')
275
+
276
+ element(:article_id, :article, :id => 'article_id')
277
+ element(:header_id, :header, :id => 'header_id')
278
+ element(:footer_id, :footer, :id => 'footer_id')
279
+ element(:summary_id, :summary, :id => 'summary_id')
280
+ element(:details_id, :details, :id => 'details_id')
260
281
  end
data/lib/druid.rb CHANGED
@@ -242,6 +242,13 @@ module Druid
242
242
  value
243
243
  end
244
244
 
245
+ #
246
+ # Execute javascript on the browser
247
+ #
248
+ def execute_script(script)
249
+ driver.execute_script(script)
250
+ end
251
+
245
252
  #
246
253
  # Attach to a running window. You can locate the window using either
247
254
  # the window's title or url or index, If it failes to connect to a window it will
@@ -267,6 +274,16 @@ module Druid
267
274
  end
268
275
  end
269
276
 
277
+ #
278
+ # Find the element that has focus on the page
279
+ #
280
+ def element_with_focus
281
+ element = driver.execute_script("return document.activeElement")
282
+ type = element.type.to_sym if element.tag_name.to_sym == :input
283
+ cls = Druid::Elements.element_class_for(element.tag_name, type)
284
+ cls.new(element)
285
+ end
286
+
270
287
  #
271
288
  # Override the normal showModalDialog call is it opens a window instead of a dialog.
272
289
  # You will need to attach to the new window in order to continue.
@@ -11,12 +11,51 @@ module Druid
11
11
  # 'goto' method to take you to the page.
12
12
  #
13
13
  # @param [String] the url for the page.
14
+ # @param [Symbol] a method name to call to get the url
14
15
  #
15
16
  def page_url(url)
16
17
  define_method("goto") do
18
+ url = url.kind_of?(Symbol) ? self.send(url) : url
17
19
  driver.goto url
18
20
  end
19
21
  end
22
+ alias_method :direct_url, :page_url
23
+
24
+ #
25
+ # Creates a method that compares the expected_title of a page against the actual.
26
+ # @param [String] expected_title the literal expected title for the page
27
+ # @param [Regexp] expected_title the expected title pattern for the page
28
+ # @return [Boolean]
29
+ # @raise An exception if expected_title does not match actual title
30
+ #
31
+ # @example Specify 'Google' as the expected title of a page
32
+ # expected_title "Google"
33
+ # page.has_expected_title?
34
+ #
35
+ def expected_title(expected_title)
36
+ define_method("has_expected_title?") do
37
+ has_expected_title = expected_title.kind_of?(Regexp) ? expected_title =~ title : expected_title == title
38
+ raise "Expected title '#{expected_title}' instead of '#{title}'" unless has_expected_title
39
+ has_expected_title
40
+ end
41
+ end
42
+
43
+ #
44
+ # Creates a method that provides a way to initialize a page based upon an expected element
45
+ # This is useful for pages that load dynamic content
46
+ # @param [Symbol] the name given to the element in the declaration
47
+ # @param [optional, Interger] timeout default value is 5 seconds
48
+ # @return [boolean]
49
+ #
50
+ # @example Specify a text box named :address expected on the page within 10 seconds
51
+ # expected_element(:address, 10)
52
+ # page.has_expected_element?
53
+ #
54
+ def expected_element(element_name, timeout=5)
55
+ define_method("has_expected_element?") do
56
+ self.respond_to? "#{element_name}_element" and self.send("#{element_name}_element").when_present timeout
57
+ end
58
+ end
20
59
 
21
60
  #
22
61
  # Identify an element as existing within a frame or iframe.
@@ -77,6 +116,8 @@ module Druid
77
116
  # :xpath
78
117
  # :link
79
118
  # :link_text
119
+ # :css
120
+ #
80
121
  def link(name, identifier=nil, &block)
81
122
  define_method(name) do
82
123
  return click_link_for identifier.clone unless block_given?
@@ -183,7 +224,7 @@ module Druid
183
224
 
184
225
  #
185
226
  # adds four methods - one to select an item in a drop-down,
186
- # another to fetch the currently selected item, another
227
+ # another to fetch the currently selected item text, another
187
228
  # to retrieve the select list element, and another to check the
188
229
  # drop down's existence.
189
230
  #
@@ -202,7 +243,7 @@ module Druid
202
243
  def select_list(name, identifier=nil, &block)
203
244
  define_method(name) do
204
245
  return select_list_value_for identifier.clone unless block_given?
205
- self.send("#{name}_element").value
246
+ self.send("#{name}_element").options.each {|o| return o.text if o.selected?}
206
247
  end
207
248
  define_method("#{name}=") do |value|
208
249
  return select_list_value_set(identifier.clone, value) unless block_given?
@@ -284,6 +325,7 @@ module Druid
284
325
  # :xpath
285
326
  # :src
286
327
  # :alt
328
+ # :css
287
329
  #
288
330
  def button(name, identifier=nil, &block)
289
331
  define_method(name) do
@@ -938,5 +980,71 @@ module Druid
938
980
  file_field_for(identifier.clone).exist?
939
981
  end
940
982
  end
983
+
984
+ #
985
+ # adds three methods - one to retrieve the text from a label,
986
+ # another to return the label element, and another to check the label's existence.
987
+ #
988
+ # @example
989
+ # label(:message, :id => 'message')
990
+ # # will generate 'message', 'message_element', and 'message?' methods
991
+ #
992
+ # @param [String] the name used for the generated methods
993
+ # @param [Hash] identifier how we find a label. You can use a multiple parameters
994
+ # by combining of any of the following except xpath. The valid keys are:
995
+ # * :class
996
+ # * :id
997
+ # * :index
998
+ # * :name
999
+ # * :text
1000
+ # * :xpath
1001
+ # @param optional block to be invoked when element method is called
1002
+ #
1003
+ def label(name, identifier=nil, &block)
1004
+ define_method(name) do
1005
+ return label_text_for identifier.clone unless block_given?
1006
+ self.send("#{name}_element").text
1007
+ end
1008
+ define_method("#{name}_element") do
1009
+ return call_block(&block) if block_given?
1010
+ label_for(identifier.clone)
1011
+ end
1012
+ define_method("#{name}?") do
1013
+ return call_block(&block) if block_given?
1014
+ label_for(identifier.clone).exist?
1015
+ end
1016
+ alias_method "#{name}_label".to_sym, "#{name}_element".to_sym
1017
+ end
1018
+
1019
+ #
1020
+ # adds three methods - one to retrieve the text an element, another
1021
+ # to retrieve an element, and another to check the element's existence.
1022
+ #
1023
+ # @example
1024
+ # element(:titile, :id => 'title')
1025
+ # # will generate 'title'm 'title_element', and 'title?' methods
1026
+ #
1027
+ # @param [String] the name used for the generated methods
1028
+ # @param [Hash] identifier how we find an element. You can use a multiple parameters
1029
+ # by combining of any of the following except xpath. The valid keys are:
1030
+ # * :class
1031
+ # * :id
1032
+ # * :index
1033
+ # * :name
1034
+ # * :xpath
1035
+ # @param optional block to be invoked when element method is called
1036
+ #
1037
+ def element(name, tag, identifier=nil, &block)
1038
+ define_method("#{name}") do
1039
+ self.send("#{name}_element").text
1040
+ end
1041
+ define_method("#{name}_element") do
1042
+ return call_block(&block) if block_given?
1043
+ element_for(tag, identifier.clone)
1044
+ end
1045
+ define_method("#{name}?") do
1046
+ self.send("#{name}_element").exist?
1047
+ end
1048
+ end
941
1049
  end
942
1050
  end
data/lib/druid/assist.rb CHANGED
@@ -62,7 +62,7 @@ module Druid
62
62
  end
63
63
 
64
64
  def select_list_value_for identifier
65
- process_call("select_list(identifier).value", Elements::SelectList, identifier)
65
+ process_call("select_list(identifier).options.each {|o| return o.text if o.selected?}", Elements::SelectList, identifier)
66
66
  end
67
67
 
68
68
  def select_list_for identifier
@@ -373,6 +373,31 @@ module Druid
373
373
  find_element("file_field(identifier)", Elements::FileField, identifier)
374
374
  end
375
375
 
376
+ #
377
+ # method to return the text for a label
378
+ #
379
+ def label_text_for(identifier)
380
+ process_call("label(identifier).text", Elements::Label, identifier, nil, 'label')
381
+ end
382
+
383
+ #
384
+ # method to return a Druid::Elements::Label element
385
+ #
386
+ def label_for(identifier)
387
+ find_element("label(identifier)", Elements::Label, identifier, 'label')
388
+ end
389
+
390
+ #
391
+ # method to retrieve an array of label elements
392
+ #
393
+ def labels_for(identifier)
394
+ find_elements("labels(identifier)", Elements::Label, identifier, 'p')
395
+ end
396
+
397
+ def element_for(tag, identifier)
398
+ find_element("#{tag.to_s}(identifier)", Elements::Element, identifier, tag.to_s)
399
+ end
400
+
376
401
  private
377
402
 
378
403
  def find_elements(the_call, type, identifier, tag_name=nil)
@@ -15,6 +15,7 @@ module Druid
15
15
  # * :xpath
16
16
  # * :src
17
17
  # * :alt
18
+ # * :css
18
19
  #
19
20
  def button_element identifier
20
21
  button_for identifier.clone
@@ -23,7 +24,7 @@ module Druid
23
24
  #
24
25
  # Finds all buttons that match the provided identifier
25
26
  #
26
- # @param [Hash] identifier how we find a button. You can use a multiple paramaters
27
+ # @param [Hash] identifier how we find all buttons. You can use a multiple paramaters
27
28
  # by combining of any of the following except xpath. The valid keys are:
28
29
  # * :class
29
30
  # * :id
@@ -34,6 +35,7 @@ module Druid
34
35
  # * :xpath
35
36
  # * :src
36
37
  # * :alt
38
+ # * :css
37
39
  #
38
40
  def button_elements identifier
39
41
  buttons_for identifier.clone
@@ -61,7 +63,7 @@ module Druid
61
63
  #
62
64
  # Finds all text fields that match the provided identifier
63
65
  #
64
- # @param [Hash] identifier how we find a text field. You can use a multiple parameters
66
+ # @param [Hash] identifier how we find all text fields. You can use a multiple parameters
65
67
  # by combining of any of the following except xpath. The valid keys are:
66
68
  #
67
69
  # * :class
@@ -100,7 +102,7 @@ module Druid
100
102
  #
101
103
  # Finds all hidden fields that match the identifier
102
104
  #
103
- # @param [Hash] identifier how we find a hidden field. You can use a multiple parameters
105
+ # @param [Hash] identifier how we find all hidden fields. You can use a multiple parameters
104
106
  # by combining of any of the following except xpath. The valid keys are:
105
107
  #
106
108
  # * :class
@@ -137,7 +139,7 @@ module Druid
137
139
  #
138
140
  # Finds all text areas for the provided identifier
139
141
  #
140
- # @param [Hash] identifier how we find a text area. You can use a multiple parameters
142
+ # @param [Hash] identifier how we find all text areas. You can use a multiple parameters
141
143
  # by combining of any of the following except xpath. The valid keys are:
142
144
  # * :class
143
145
  # * :css
@@ -171,7 +173,7 @@ module Druid
171
173
  #
172
174
  # Finds all select lists for the provided identifier
173
175
  #
174
- # @param [Hash] identifier how we find a select list. You can use a multiple paramaters
176
+ # @param [Hash] identifier how we find all select lists. You can use a multiple paramaters
175
177
  # by combining of any of the following except xpath. The valid keys are:
176
178
  # * :class
177
179
  # * :id
@@ -199,6 +201,7 @@ module Druid
199
201
  # * :name
200
202
  # * :xpath
201
203
  # * :text
204
+ # * :css
202
205
  #
203
206
  def link_element identifier
204
207
  link_for identifier.clone
@@ -207,7 +210,7 @@ module Druid
207
210
  #
208
211
  # Finds all links for the provided identifier
209
212
  #
210
- # @param [Hash] identifier how we find a link. You can use a multiple parameters
213
+ # @param [Hash] identifier how we find all links. You can use a multiple parameters
211
214
  # by combining of any of the following except xpath. The valid keys are:
212
215
  # * :class
213
216
  # * :href
@@ -218,6 +221,7 @@ module Druid
218
221
  # * :name
219
222
  # * :xpath
220
223
  # * :text
224
+ # * :css
221
225
  #
222
226
  def link_elements identifier
223
227
  links_for identifier.clone
@@ -794,5 +798,37 @@ module Druid
794
798
  def file_field_element identifier
795
799
  file_field_for identifier.clone
796
800
  end
801
+
802
+ #
803
+ # Finds a label
804
+ #
805
+ # @param [Hash] identifier how we find a label. You can use a multiple paramaters
806
+ # by combining of any of the following except xpath. The valid keys are:
807
+ # * :class
808
+ # * :id
809
+ # * :index
810
+ # * :name
811
+ # * :text
812
+ # * :xpath
813
+ #
814
+ def label_element(identifier)
815
+ label_for identifier.clone
816
+ end
817
+
818
+ #
819
+ # Finds all labels that match the provided identifier
820
+ #
821
+ # @param [Hash] identifier how we find a label. You can use a multiple paramaters
822
+ # by combining of any of the following except xpath. The valid keys are:
823
+ # * :class
824
+ # * :id
825
+ # * :index
826
+ # * :name
827
+ # * :text
828
+ # * :xpath
829
+ #
830
+ def label_elements(identifier)
831
+ labels_for identifier.clone
832
+ end
797
833
  end
798
834
  end