druid-ts 1.1.8 → 1.2.0

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