druid-ts 1.1.2 → 1.1.3

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 (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