druid-ts 1.1.8 → 1.2.0

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +27 -0
  3. data/features/bold.feature +21 -0
  4. data/features/element.feature +7 -0
  5. data/features/frames.feature +15 -0
  6. data/features/html/frames.html +3 -3
  7. data/features/html/iframes.html +2 -2
  8. data/features/html/multi_elements.html +1 -0
  9. data/features/html/static_elements.html +25 -8
  10. data/features/javascript.feature +10 -1
  11. data/features/link.feature +4 -0
  12. data/features/multi_elements.feature +6 -0
  13. data/features/radio_button_group.feature +28 -0
  14. data/features/section.feature +128 -0
  15. data/features/select_list.feature +4 -0
  16. data/features/step_definations/bold_steps.rb +11 -0
  17. data/features/step_definations/element_steps.rb +8 -0
  18. data/features/step_definations/frame_steps.rb +53 -11
  19. data/features/step_definations/javasript_steps.rb +9 -0
  20. data/features/step_definations/link_steps.rb +8 -0
  21. data/features/step_definations/multi_elements_steps.rb +13 -0
  22. data/features/step_definations/radio_button_group_steps.rb +32 -0
  23. data/features/step_definations/section_steps.rb +262 -0
  24. data/features/step_definations/table_steps.rb +9 -0
  25. data/features/support/env.rb +1 -0
  26. data/features/support/page.rb +16 -5
  27. data/features/table.feature +18 -14
  28. data/lib/druid.rb +42 -30
  29. data/lib/druid/accessors.rb +188 -55
  30. data/lib/druid/assist.rb +46 -4
  31. data/lib/druid/elements.rb +1 -0
  32. data/lib/druid/elements/bold.rb +8 -0
  33. data/lib/druid/elements/element.rb +16 -3
  34. data/lib/druid/elements/link.rb +7 -0
  35. data/lib/druid/elements/radio_button.rb +0 -7
  36. data/lib/druid/elements/select_list.rb +2 -2
  37. data/lib/druid/elements/table.rb +7 -0
  38. data/lib/druid/javascript/angularjs.rb +12 -0
  39. data/lib/druid/javascript_framework_facade.rb +5 -3
  40. data/lib/druid/locator_generator.rb +1 -0
  41. data/lib/druid/page_factory.rb +1 -0
  42. data/lib/druid/page_populator.rb +10 -1
  43. data/lib/druid/sections.rb +29 -0
  44. data/lib/druid/version.rb +1 -1
  45. data/spec/druid/accessors_spec.rb +79 -13
  46. data/spec/druid/druid_spec.rb +2 -1
  47. data/spec/druid/element_locators_spec.rb +26 -4
  48. data/spec/druid/elements/bold_spec.rb +21 -0
  49. data/spec/druid/elements/link_spec.rb +1 -1
  50. data/spec/druid/elements/page_factory_spec.rb +2 -2
  51. data/spec/druid/elements/radio_button_spec.rb +0 -5
  52. data/spec/druid/elements/select_list_spec.rb +3 -3
  53. data/spec/druid/page_factory_spec.rb +15 -15
  54. data/spec/druid/page_populator_spec.rb +4 -4
  55. data/spec/druid/page_section_spec.rb +61 -0
  56. data/spec/spec_helper.rb +1 -0
  57. metadata +20 -1
data/lib/druid/assist.rb CHANGED
@@ -81,10 +81,6 @@ module Druid
81
81
  process_call("radio(identifier).set", Elements::RadioButton, identifier)
82
82
  end
83
83
 
84
- def clear_radio identifier
85
- process_call("radio(identifier).clear", Elements::RadioButton, identifier)
86
- end
87
-
88
84
  def radio_selected? identifier
89
85
  process_call("radio(identifier).set?", Elements::RadioButton, identifier)
90
86
  end
@@ -508,6 +504,38 @@ module Druid
508
504
  find_elements("element(identifier)", Elements::Element, identifier)
509
505
  end
510
506
 
507
+ #
508
+ # method to retrieve the text for a b
509
+ #
510
+ def b_text_for(identifier)
511
+ process_call("b(identifier).text", Elements::Bold, identifier, nil, 'b')
512
+ end
513
+
514
+ def b_for(identifier)
515
+ find_element("b(identifier)", Elements::Bold, identifier, 'b')
516
+ end
517
+
518
+ #
519
+ # method to retrieve all b elements
520
+ #
521
+ def bs_for(identifier)
522
+ find_elements("bs(identifier)", Elements::Bold, identifier, 'b')
523
+ end
524
+
525
+ #
526
+ # method to return a Druid rooted at an element
527
+ #
528
+ def page_for(identifier, section_class)
529
+ find_page(identifier, section_class)
530
+ end
531
+
532
+ #
533
+ # method to return a collection of Druids rooted at elements
534
+ #
535
+ def pages_for(identifier, section_class)
536
+ SectionCollection.new(find_pages(identifier, section_class))
537
+ end
538
+
511
539
  private
512
540
 
513
541
  def find_elements(the_call, type, identifier, tag_name=nil)
@@ -524,6 +552,20 @@ module Druid
524
552
  type.new(element)
525
553
  end
526
554
 
555
+ def find_pages(identifier, section_class)
556
+ identifier, frame_identifiers = parse_identifiers(identifier, Elements::Element, 'element')
557
+ elements = driver.instance_eval "#{nested_frames(frame_identifiers)}elements(identifier)"
558
+ switch_to_default_content(frame_identifiers)
559
+ elements.map { |element| section_class.new(element) }
560
+ end
561
+
562
+ def find_page(identifier, section_class)
563
+ identifier, frame_identifiers = parse_identifiers(identifier, Elements::Element, 'element')
564
+ element = driver.instance_eval "#{nested_frames(frame_identifiers)}element(identifier)"
565
+ switch_to_default_content(frame_identifiers)
566
+ section_class.new(element)
567
+ end
568
+
527
569
  def process_call(the_call, type, identifier, value=nil, tag_name=nil)
528
570
  identifier, frame_identifiers = parse_identifiers(identifier, type, tag_name)
529
571
  value = driver.instance_eval "#{nested_frames(frame_identifiers)}#{the_call}"
@@ -51,3 +51,4 @@ require 'druid/elements/canvas'
51
51
  require 'druid/elements/media'
52
52
  require 'druid/elements/audio'
53
53
  require 'druid/elements/video'
54
+ require 'druid/elements/bold'
@@ -0,0 +1,8 @@
1
+ module Druid
2
+ module Elements
3
+ class Bold < Element
4
+
5
+ end
6
+ Druid::Elements.tag_to_class[:b] = Druid::Elements::Bold
7
+ end
8
+ end
@@ -1,3 +1,5 @@
1
+ require 'watir-webdriver'
2
+ require 'watir-webdriver/extensions/select_text'
1
3
  require 'druid/nested_elements'
2
4
  require 'druid/assist'
3
5
  module Druid
@@ -88,6 +90,13 @@ module Druid
88
90
  element.attribute_value attribute_name
89
91
  end
90
92
 
93
+ #
94
+ # retrieve the class name for an element
95
+ #
96
+ def class_name
97
+ element.class_name
98
+ end
99
+
91
100
  #
92
101
  # Click this element
93
102
  #
@@ -153,6 +162,10 @@ module Druid
153
162
  element.focus
154
163
  end
155
164
 
165
+ def select_text text
166
+ element.select_text text
167
+ end
168
+
156
169
  #
157
170
  # get the id of element
158
171
  #
@@ -280,7 +293,7 @@ module Druid
280
293
  protected
281
294
 
282
295
  def self.have_to_build_xpath(identifier)
283
- ['table', 'span', 'div', 'td', 'li', 'ol', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'label', 'area', 'canvas', 'audio', 'video'].include? identifier[:tag_name] and identifier[:name]
296
+ ['table', 'span', 'div', 'td', 'li', 'ol', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'label', 'area', 'canvas', 'audio', 'video','b'].include? identifier[:tag_name] and identifier[:name]
284
297
  end
285
298
 
286
299
  def self.build_xpath_for identifier
@@ -295,14 +308,14 @@ module Druid
295
308
  end
296
309
  xpath = ".//button"
297
310
  xpath << "[#{attribute_expression(btn_ident)}]" unless btn_ident.empty?
298
- xpath << "[#{idx+1}]" if idx
311
+ xpath = "(#{xpath})[#{idx+1}]" if idx
299
312
  identifier[:type] = %w[button reset submit image]
300
313
  xpath << " | .//input"
301
314
  else
302
315
  xpath = ".//#{tag_locator}"
303
316
  end
304
317
  xpath << "[#{attribute_expression(identifier)}]" unless identifier.empty?
305
- xpath << "[#{idx+1}]" if idx
318
+ xpath = "(#{xpath})[#{idx+1}]" if idx
306
319
  xpath
307
320
  end
308
321
 
@@ -2,6 +2,13 @@ module Druid
2
2
  module Elements
3
3
  class Link < Element
4
4
 
5
+ #
6
+ # return the href fot the link
7
+ #
8
+ def href
9
+ element.href
10
+ end
11
+
5
12
  protected
6
13
 
7
14
  def self.finders
@@ -12,13 +12,6 @@ module Druid
12
12
  element.set
13
13
  end
14
14
 
15
- #
16
- # Clear the RadioButton
17
- #
18
- def clear
19
- element.clear
20
- end
21
-
22
15
  #
23
16
  # Return if it is selected
24
17
  #
@@ -7,11 +7,11 @@ module Druid
7
7
  end
8
8
 
9
9
  def [](idx)
10
- Druid::Elements::Option.new(options[idx])
10
+ options[idx]
11
11
  end
12
12
 
13
13
  def options
14
- element.options
14
+ element.options.map { |e| Druid::Elements::Option.new(e)}
15
15
  end
16
16
 
17
17
  #
@@ -45,6 +45,13 @@ module Druid
45
45
  self[-1]
46
46
  end
47
47
 
48
+ #
49
+ # return the table as hashes
50
+ #
51
+ def hashes
52
+ element.hashes
53
+ end
54
+
48
55
  private
49
56
 
50
57
  def find_index_by_title(row_title)
@@ -0,0 +1,12 @@
1
+ module Druid
2
+ module Javascript
3
+ module AngularJS
4
+ #
5
+ # return the number of pending ajax requests
6
+ #
7
+ def self.pending_requests
8
+ 'return angular.element(document.body).injector().get(\'$http\').pendingRequests.length;'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,6 +1,7 @@
1
1
  require 'druid/javascript/jquery'
2
2
  require 'druid/javascript/prototype'
3
3
  require 'druid/javascript/yui'
4
+ require 'druid/javascript/angularjs'
4
5
 
5
6
  module Druid
6
7
  #
@@ -18,8 +19,8 @@ module Druid
18
19
  #
19
20
  # Set the framework to use
20
21
  #
21
- # @param [Symbol] the framework to use. :jquery and :prototype
22
- # are supported
22
+ # @param [Symbol] the framework to use. :jquery and :prototype, :yui,
23
+ # and :angularjs are supported
23
24
  #
24
25
  def framework=(framework)
25
26
  initialize_script_builder unless @builder
@@ -58,7 +59,8 @@ module Druid
58
59
  @builder = {
59
60
  :jquery => Druid::Javascript::JQuery,
60
61
  :prototype => Druid::Javascript::Prototype,
61
- :yui => Druid::Javascript::YUI
62
+ :yui => Druid::Javascript::YUI,
63
+ :angularjs => Druid::Javascript::AngularJS
62
64
  }
63
65
  end
64
66
 
@@ -100,6 +100,7 @@ module Druid
100
100
  :canvas,
101
101
  :audio,
102
102
  :video,
103
+ :b,
103
104
  :svg]
104
105
 
105
106
  def self.generate_locators(target)
@@ -64,6 +64,7 @@ module Druid
64
64
  #
65
65
  def on_page(page_class, params={:using_params => {}}, visit=false, &block)
66
66
  page_class = class_from_string(page_class) if page_class.is_a? String
67
+ return super(page_class, params, visit, &block) unless page_class.ancestors.include? Druid
67
68
  merged = page_class.params.merge(params[:using_params])
68
69
  page_class.instance_variable_set("@merged_params", merged) unless merged.empty?
69
70
  @current_page = page_class.new(@driver, visit)
@@ -31,6 +31,7 @@ module Druid
31
31
  def populate_page_with(data)
32
32
  data.each do |key, value|
33
33
  populate_checkbox(key, value) if is_checkbox?(key) and is_enabled?(key)
34
+ populate_radiobuttongroup(key, value) if is_radiobuttongroup?(key)
34
35
  populate_radiobutton(key, value) if is_radiobutton?(key) and is_enabled?(key)
35
36
  populate_text(key, value) if is_text?(key) and is_enabled?(key)
36
37
  end
@@ -49,7 +50,10 @@ module Druid
49
50
 
50
51
  def populate_radiobutton(key, value)
51
52
  return self.send "select_#{key}" if value
52
- return self.send "clear_#{key}"
53
+ end
54
+
55
+ def populate_radiobuttongroup(key, value)
56
+ return self.send "select_#{key}", value
53
57
  end
54
58
 
55
59
  def is_text?(key)
@@ -64,7 +68,12 @@ module Druid
64
68
  respond_to?("select_#{key}".to_sym)
65
69
  end
66
70
 
71
+ def is_radiobuttongroup?(key)
72
+ respond_to?("select_#{key}".to_sym) and respond_to?("#{key}_values")
73
+ end
74
+
67
75
  def is_enabled?(key)
76
+ return false if is_radiobuttongroup?(key)
68
77
  return true if (self.send "#{key}_element").tag_name == "textarea"
69
78
  element = self.send("#{key}_element")
70
79
  element.enabled? and element.visible?
@@ -0,0 +1,29 @@
1
+ module Druid
2
+ class SectionCollection
3
+ include Enumerable
4
+
5
+ def initialize sections
6
+ @sections = sections
7
+ end
8
+
9
+ def each &block
10
+ @sections.each &block
11
+ end
12
+
13
+ def [] index
14
+ @sections[index]
15
+ end
16
+
17
+ def find_by values_hash
18
+ @sections.find { |section|
19
+ values_hash.all? { |key, value| value === section.public_send(key) }
20
+ }
21
+ end
22
+
23
+ def select_by values_hash
24
+ SectionCollection.new @sections.select { |section|
25
+ values_hash.all? { |key, value| value === section.public_send(key) }
26
+ }
27
+ end
28
+ end
29
+ end
data/lib/druid/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Druid
2
- VERSION = "1.1.8"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -1,5 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
+ class GenericPage
4
+ include Druid
5
+
6
+ wait_for_expected_title 'expected title'
7
+ end
8
+
3
9
  class AccessorsTestDruid
4
10
  include Druid
5
11
 
@@ -15,7 +21,7 @@ class AccessorsTestDruid
15
21
  div(:message, :id => 'message_id')
16
22
  table(:cart, :id => 'cart_id')
17
23
  cell(:total, :id => 'total')
18
- span(:alert, :id => 'alert_id')
24
+ span(:alert_span, :id => 'alert_id')
19
25
  image(:logo, :id => 'logo')
20
26
  hidden_field(:social_security_number, :id => 'ssn')
21
27
  form(:login, :id => 'login')
@@ -35,6 +41,7 @@ class AccessorsTestDruid
35
41
  canvas(:my_canvas, :id => 'canvas_id')
36
42
  audio(:acdc, :id => 'audio_id')
37
43
  video(:movie, :id => 'video_id')
44
+ b(:bold, :id => 'bold')
38
45
  end
39
46
 
40
47
  class BlockDruid
@@ -67,7 +74,7 @@ class BlockDruid
67
74
  div :footer do |element|
68
75
  "div"
69
76
  end
70
- span :alert do |element|
77
+ span :alert_span do |element|
71
78
  "span"
72
79
  end
73
80
  table :cart do |element|
@@ -127,6 +134,9 @@ class BlockDruid
127
134
  video :movie do |element|
128
135
  "video"
129
136
  end
137
+ b :bold do |element|
138
+ "b"
139
+ end
130
140
  end
131
141
 
132
142
  class TestDruidBackUp
@@ -172,6 +182,10 @@ describe Druid::Accessors do
172
182
  expect(driver).not_to receive(:goto)
173
183
  TestDruidBackUp.new(driver,true)
174
184
  end
185
+
186
+ it "should provide the page url" do
187
+ expect(druid.page_url_value).to eql "http://apple.com"
188
+ end
175
189
  end
176
190
 
177
191
  describe "validating the page title" do
@@ -562,7 +576,6 @@ describe Druid::Accessors do
562
576
  expect(druid).to respond_to :first_element
563
577
  expect(druid).to respond_to :select_first
564
578
  expect(druid).to respond_to :first_selected?
565
- expect(druid).to respond_to :clear_first
566
579
  end
567
580
 
568
581
  it "should call a block on the element method when present" do
@@ -576,11 +589,6 @@ describe Druid::Accessors do
576
589
  druid.select_first
577
590
  end
578
591
 
579
- it "should clear a radio button" do
580
- expect(driver).to receive_message_chain(:radio, :clear)
581
- druid.clear_first
582
- end
583
-
584
592
  it "should determine if a radio is selected" do
585
593
  expect(driver).to receive_message_chain(:radio, :set?).and_return(true)
586
594
  expect(druid.first_selected?).to be true
@@ -665,24 +673,24 @@ describe Druid::Accessors do
665
673
  describe "span accessors" do
666
674
  context "when called on a page object" do
667
675
  it "should generate accessor methods" do
668
- expect(druid).to respond_to :alert
669
- expect(druid).to respond_to :alert_element
676
+ expect(druid).to respond_to :alert_span
677
+ expect(druid).to respond_to :alert_span_element
670
678
  end
671
679
 
672
680
  it "should call a block on the element method when present" do
673
- expect(block_druid.alert_element).to eql "span"
681
+ expect(block_druid.alert_span_element).to eql "span"
674
682
  end
675
683
  end
676
684
 
677
685
  context "implementation" do
678
686
  it "should retrieve the text from a span" do
679
687
  expect(driver).to receive_message_chain(:span, :text).and_return('Alert')
680
- expect(druid.alert).to eql 'Alert'
688
+ expect(druid.alert_span).to eql 'Alert'
681
689
  end
682
690
 
683
691
  it "should retrieve the span element from the page" do
684
692
  expect(driver).to receive(:span)
685
- expect(druid.alert_element).to be_instance_of Druid::Elements::Span
693
+ expect(druid.alert_span_element).to be_instance_of Druid::Elements::Span
686
694
  end
687
695
  end
688
696
  end
@@ -1112,4 +1120,62 @@ describe Druid::Accessors do
1112
1120
  end
1113
1121
  end
1114
1122
  end
1123
+
1124
+ describe "b accessors" do
1125
+ context "when called on a page object" do
1126
+ it "should generate accessor methods" do
1127
+ expect(druid).to respond_to(:bold)
1128
+ expect(druid).to respond_to(:bold_element)
1129
+ expect(druid).to respond_to(:bold?)
1130
+ end
1131
+
1132
+ it "should call a block on the element method when present" do
1133
+ expect(block_druid.bold_element).to eql "b"
1134
+ end
1135
+ end
1136
+
1137
+ it "should retrieve the text from the b" do
1138
+ expect(driver).to receive(:b).and_return(driver)
1139
+ expect(driver).to receive(:text).and_return("value")
1140
+ expect(druid.bold).to eql "value"
1141
+ end
1142
+
1143
+ it "should retrieve the element from the page" do
1144
+ expect(driver).to receive(:b).and_return(driver)
1145
+ element = druid.bold_element
1146
+ expect(element).to be_instance_of Druid::Elements::Bold
1147
+ end
1148
+ end
1149
+ end
1150
+
1151
+ describe "accessors" do
1152
+ let(:driver) { mock_driver }
1153
+ let(:page) { GenericPage.new driver}
1154
+
1155
+ context '#wait_for_expected_title' do
1156
+ before(:each) do
1157
+ allow(driver).to receive(:wait_until).and_yield
1158
+ end
1159
+
1160
+ it "true if already there" do
1161
+ allow(driver).to receive(:title).and_return 'expected title'
1162
+ expect(page.wait_for_expected_title?).to be_truthy
1163
+ end
1164
+
1165
+ it "does not wait if it already is there" do
1166
+ allow(driver).to receive(:title).and_return 'expected title'
1167
+ expect(driver).to_not receive(:wait_until)
1168
+ expect(page.wait_for_expected_title?).to be_truthy
1169
+ end
1170
+
1171
+ it "errors when it does not match" do
1172
+ allow(driver).to receive(:title).and_return 'wrong title'
1173
+ expect { page.wait_for_expected_title? }.to raise_error "Expected title 'expected title' instead of 'wrong title'"
1174
+ end
1175
+
1176
+ it 'pick up when the title changes' do
1177
+ allow(driver).to receive(:title).and_return 'wrong title', 'expected title'
1178
+ expect(page.wait_for_expected_title?).to be_truthy
1179
+ end
1180
+ end
1115
1181
  end