druid-s 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +27 -0
- data/ChangeLog +541 -0
- data/Gemfile +8 -0
- data/README.md +78 -0
- data/Rakefile +33 -0
- data/cucumber.yml +6 -0
- data/druid.gemspec +30 -0
- data/features/area.feature +33 -0
- data/features/async.feature +16 -0
- data/features/audio.feature +61 -0
- data/features/bold.feature +20 -0
- data/features/button.feature +81 -0
- data/features/canvas.feature +34 -0
- data/features/checkbox.feature +48 -0
- data/features/div.feature +45 -0
- data/features/element.feature +281 -0
- data/features/file_field.feature +38 -0
- data/features/form.feature +37 -0
- data/features/frames.feature +76 -0
- data/features/generic_elements.feature +29 -0
- data/features/heading.feature +160 -0
- data/features/hidden_field.feature +39 -0
- data/features/html/async.html +31 -0
- data/features/html/frame_1.html +18 -0
- data/features/html/frame_2.html +16 -0
- data/features/html/frame_3.html +14 -0
- data/features/html/frames.html +12 -0
- data/features/html/hover.html +11 -0
- data/features/html/iframes.html +12 -0
- data/features/html/images/circle.png +0 -0
- data/features/html/images/img_pulpit.jpg +0 -0
- data/features/html/modal.html +17 -0
- data/features/html/modal_1.html +38 -0
- data/features/html/modal_2.html +27 -0
- data/features/html/multi_elements.html +145 -0
- data/features/html/nested_elements.html +75 -0
- data/features/html/nested_frame_1.html +1 -0
- data/features/html/nested_frame_2.html +11 -0
- data/features/html/nested_frame_3.html +14 -0
- data/features/html/nested_frames.html +10 -0
- data/features/html/planets.gif +0 -0
- data/features/html/static_elements.html +203 -0
- data/features/html/success.html +8 -0
- data/features/html/sun.gif +0 -0
- data/features/html/sun.html +7 -0
- data/features/image.feature +47 -0
- data/features/italic.feature +20 -0
- data/features/javascript.feature +28 -0
- data/features/label.feature +43 -0
- data/features/link.feature +56 -0
- data/features/list_item.feature +37 -0
- data/features/modal_dialog.feature +9 -0
- data/features/multi_elements.feature +498 -0
- data/features/nested_elements.feature +121 -0
- data/features/ordered_list.feature +46 -0
- data/features/page_level_actions.feature +116 -0
- data/features/paragraph.feature +33 -0
- data/features/populate_page_with.feature +25 -0
- data/features/radio_button.feature +51 -0
- data/features/radio_button_group.feature +28 -0
- data/features/sample-app/public/04-Death_Becomes_Fur.mp4 +0 -0
- data/features/sample-app/public/04-Death_Becomes_Fur.oga +0 -0
- data/features/sample-app/public/audio_video.html +19 -0
- data/features/sample-app/public/jquery-1.3.2.js +4376 -0
- data/features/sample-app/public/jquery.html +28 -0
- data/features/sample-app/public/movie.mp4 +0 -0
- data/features/sample-app/public/movie.ogg +0 -0
- data/features/sample-app/public/prototype-1.6.0.3.js +4320 -0
- data/features/sample-app/public/prototype.html +32 -0
- data/features/sample-app/sample_app.rb +35 -0
- data/features/section.feature +132 -0
- data/features/select_list.feature +84 -0
- data/features/span.feature +43 -0
- data/features/step_definations/area_steps.rb +23 -0
- data/features/step_definations/async_steps.rb +80 -0
- data/features/step_definations/audio_steps.rb +47 -0
- data/features/step_definations/bold_steps.rb +11 -0
- data/features/step_definations/button_steps.rb +52 -0
- data/features/step_definations/canvas_steps.rb +19 -0
- data/features/step_definations/checkbox_steps.rb +39 -0
- data/features/step_definations/div_steps.rb +28 -0
- data/features/step_definations/element_steps.rb +217 -0
- data/features/step_definations/file_field_steps.rb +31 -0
- data/features/step_definations/form_steps.rb +23 -0
- data/features/step_definations/frame_steps.rb +189 -0
- data/features/step_definations/generic_element_steps.rb +31 -0
- data/features/step_definations/heading_steps.rb +39 -0
- data/features/step_definations/hidden_field_steps.rb +27 -0
- data/features/step_definations/image_steps.rb +35 -0
- data/features/step_definations/italic_steps.rb +11 -0
- data/features/step_definations/javasript_steps.rb +52 -0
- data/features/step_definations/label_steps.rb +19 -0
- data/features/step_definations/link_steps.rb +42 -0
- data/features/step_definations/list_item_steps.rb +24 -0
- data/features/step_definations/modal_dialog_steps.rb +38 -0
- data/features/step_definations/multi_elements_steps.rb +557 -0
- data/features/step_definations/nested_elements_steps.rb +219 -0
- data/features/step_definations/ordered_list_steps.rb +49 -0
- data/features/step_definations/page_level_actions_steps.rb +172 -0
- data/features/step_definations/page_traversal_steps.rb +4 -0
- data/features/step_definations/paragraph_steps.rb +19 -0
- data/features/step_definations/populate_page_with_steps.rb +3 -0
- data/features/step_definations/radio_button_group_steps.rb +32 -0
- data/features/step_definations/radio_button_steps.rb +31 -0
- data/features/step_definations/section_steps.rb +271 -0
- data/features/step_definations/select_list_steps.rb +91 -0
- data/features/step_definations/span_steps.rb +23 -0
- data/features/step_definations/table_cell_steps.rb +27 -0
- data/features/step_definations/table_row_steps.rb +23 -0
- data/features/step_definations/table_steps.rb +109 -0
- data/features/step_definations/text_area_steps.rb +39 -0
- data/features/step_definations/text_field_steps.rb +39 -0
- data/features/step_definations/unordered_list_steps.rb +27 -0
- data/features/step_definations/video_steps.rb +27 -0
- data/features/support/ajax_test_environment.rb +26 -0
- data/features/support/audio_video_page.rb +23 -0
- data/features/support/env.rb +5 -0
- data/features/support/hooks.rb +3 -0
- data/features/support/page.rb +372 -0
- data/features/support/persistent_browser.rb +58 -0
- data/features/support/targets/firefox14_osx.rb +5 -0
- data/features/support/targets/firefox14_windows7.rb +5 -0
- data/features/support/url_helper.rb +50 -0
- data/features/table.feature +127 -0
- data/features/table_cell.feature +42 -0
- data/features/table_row.feature +30 -0
- data/features/text_area.feature +44 -0
- data/features/text_field.feature +53 -0
- data/features/unordered_list.feature +46 -0
- data/features/video.feature +66 -0
- data/lib/druid/accessors.rb +1082 -0
- data/lib/druid/assist.rb +653 -0
- data/lib/druid/element_locators.rb +21 -0
- data/lib/druid/elements/area.rb +9 -0
- data/lib/druid/elements/audio.rb +9 -0
- data/lib/druid/elements/bold.rb +8 -0
- data/lib/druid/elements/button.rb +12 -0
- data/lib/druid/elements/canvas.rb +9 -0
- data/lib/druid/elements/check_box.rb +9 -0
- data/lib/druid/elements/div.rb +9 -0
- data/lib/druid/elements/element.rb +187 -0
- data/lib/druid/elements/file_field.rb +9 -0
- data/lib/druid/elements/form.rb +9 -0
- data/lib/druid/elements/heading.rb +14 -0
- data/lib/druid/elements/hidden_field.rb +9 -0
- data/lib/druid/elements/image.rb +9 -0
- data/lib/druid/elements/italic.rb +9 -0
- data/lib/druid/elements/label.rb +8 -0
- data/lib/druid/elements/link.rb +9 -0
- data/lib/druid/elements/list_item.rb +9 -0
- data/lib/druid/elements/media.rb +11 -0
- data/lib/druid/elements/option.rb +9 -0
- data/lib/druid/elements/ordered_list.rb +29 -0
- data/lib/druid/elements/paragraph.rb +9 -0
- data/lib/druid/elements/radio_button.rb +9 -0
- data/lib/druid/elements/select_list.rb +30 -0
- data/lib/druid/elements/span.rb +9 -0
- data/lib/druid/elements/table.rb +92 -0
- data/lib/druid/elements/table_cell.rb +11 -0
- data/lib/druid/elements/table_row.rb +50 -0
- data/lib/druid/elements/text_area.rb +10 -0
- data/lib/druid/elements/text_field.rb +11 -0
- data/lib/druid/elements/unordered_list.rb +32 -0
- data/lib/druid/elements/video.rb +8 -0
- data/lib/druid/elements.rb +55 -0
- data/lib/druid/javascript/angularjs.rb +12 -0
- data/lib/druid/javascript/jquery.rb +12 -0
- data/lib/druid/javascript/prototype.rb +12 -0
- data/lib/druid/javascript/yui.rb +19 -0
- data/lib/druid/javascript_framework_facade.rb +76 -0
- data/lib/druid/locator_generator.rb +181 -0
- data/lib/druid/nested_elements.rb +56 -0
- data/lib/druid/page_factory.rb +115 -0
- data/lib/druid/page_populator.rb +104 -0
- data/lib/druid/section_collection.rb +17 -0
- data/lib/druid/version.rb +3 -0
- data/lib/druid.rb +452 -0
- data/spec/druid/accessors_spec.rb +1209 -0
- data/spec/druid/druid_spec.rb +295 -0
- data/spec/druid/element_locators_spec.rb +750 -0
- data/spec/druid/elements/bold_spec.rb +12 -0
- data/spec/druid/elements/button_spec.rb +23 -0
- data/spec/druid/elements/check_box_spec.rb +14 -0
- data/spec/druid/elements/div_spec.rb +10 -0
- data/spec/druid/elements/element_spec.rb +250 -0
- data/spec/druid/elements/file_field_spec.rb +13 -0
- data/spec/druid/elements/form_spec.rb +18 -0
- data/spec/druid/elements/heading_spec.rb +30 -0
- data/spec/druid/elements/hidden_field_spec.rb +10 -0
- data/spec/druid/elements/image_spec.rb +23 -0
- data/spec/druid/elements/itatic_spec.rb +11 -0
- data/spec/druid/elements/label_spec.rb +10 -0
- data/spec/druid/elements/link_spec.rb +10 -0
- data/spec/druid/elements/list_item_spec.rb +10 -0
- data/spec/druid/elements/media_spec.rb +12 -0
- data/spec/druid/elements/option_spec.rb +21 -0
- data/spec/druid/elements/ordered_list_spec.rb +38 -0
- data/spec/druid/elements/page_factory_spec.rb +40 -0
- data/spec/druid/elements/paragraph_spec.rb +12 -0
- data/spec/druid/elements/radio_button_spec.rb +14 -0
- data/spec/druid/elements/select_list_spec.rb +51 -0
- data/spec/druid/elements/span_spec.rb +10 -0
- data/spec/druid/elements/table_cell_spec.rb +14 -0
- data/spec/druid/elements/table_row_spec.rb +34 -0
- data/spec/druid/elements/table_spec.rb +47 -0
- data/spec/druid/elements/text_area_spec.rb +13 -0
- data/spec/druid/elements/text_field_spec.rb +22 -0
- data/spec/druid/elements/unordered_list_spec.rb +39 -0
- data/spec/druid/javascript_framework_facade_spec.rb +59 -0
- data/spec/druid/nested_element_spec.rb +128 -0
- data/spec/druid/page_factory_spec.rb +235 -0
- data/spec/druid/page_populator_spec.rb +173 -0
- data/spec/druid/page_section_spec.rb +70 -0
- data/spec/spec_helper.rb +9 -0
- metadata +517 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
require 'druid/nested_elements'
|
|
2
|
+
require 'druid/assist'
|
|
3
|
+
module Druid
|
|
4
|
+
module Elements
|
|
5
|
+
#
|
|
6
|
+
# Contains functionality that is common across all elements
|
|
7
|
+
#
|
|
8
|
+
class Element
|
|
9
|
+
include Druid::NestedElements
|
|
10
|
+
include Druid::Assist
|
|
11
|
+
|
|
12
|
+
attr_accessor :element
|
|
13
|
+
attr_accessor :driver
|
|
14
|
+
|
|
15
|
+
def initialize(element)
|
|
16
|
+
@element = element
|
|
17
|
+
@driver = @element
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# return true if the element is not enabled
|
|
22
|
+
def disabled?
|
|
23
|
+
not enabled?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
# return true if the element exists and is visible
|
|
28
|
+
#
|
|
29
|
+
def present?
|
|
30
|
+
element.present?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# compare this element to another to determine if they are equal
|
|
35
|
+
# @return [Boolean]
|
|
36
|
+
#
|
|
37
|
+
def ==(other)
|
|
38
|
+
other.is_a? self.class and element == other.element
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def check_visible(timeout=Druid.default_element_wait)
|
|
42
|
+
timed_loop(timeout) do |element|
|
|
43
|
+
element.present?
|
|
44
|
+
end
|
|
45
|
+
# wait_until(timeout: timeout, message: "Element not visible in #{timeout} seconds", &:present?)
|
|
46
|
+
end
|
|
47
|
+
# alias_method :when_present, :check_visible
|
|
48
|
+
# alias_method :when_visible, :check_visible
|
|
49
|
+
|
|
50
|
+
def check_exist(timeout=Druid.default_element_wait)
|
|
51
|
+
timed_loop(timeout) do |element|
|
|
52
|
+
element.exists?
|
|
53
|
+
end
|
|
54
|
+
# wait_until(timeout: timeout, &:exist?)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
#
|
|
58
|
+
# find the parent element
|
|
59
|
+
#
|
|
60
|
+
def parent(opt = {})
|
|
61
|
+
parent = element.parent(opt)
|
|
62
|
+
druid_wrapper(parent)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Return the element that exists at the same level of the DOM
|
|
67
|
+
# immediately prior to this element
|
|
68
|
+
#
|
|
69
|
+
def preceding_sibling(opt = {})
|
|
70
|
+
sibling = element.preceding_sibling(opt)
|
|
71
|
+
druid_wrapper(sibling)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# Return the element that exists at the same level of the DOM
|
|
76
|
+
# immediately after this element
|
|
77
|
+
#
|
|
78
|
+
def following_sibling(opt={})
|
|
79
|
+
sibling = element.following_sibling(opt)
|
|
80
|
+
druid_wrapper(sibling)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
#
|
|
84
|
+
# Return all elements that are direct children of this element's parent
|
|
85
|
+
#
|
|
86
|
+
def siblings(opt={})
|
|
87
|
+
siblings = element.siblings(opt)
|
|
88
|
+
siblings.collect {|sibling| druid_wrapper(sibling)}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
#
|
|
92
|
+
# Return all elements that are children of this element
|
|
93
|
+
#
|
|
94
|
+
def children(opt={})
|
|
95
|
+
children = element.children(opt)
|
|
96
|
+
children.collect {|child| druid_wrapper(child)}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
#
|
|
100
|
+
# Return all elements that exist at the same level of the DOM
|
|
101
|
+
# immediately prior to this element
|
|
102
|
+
#
|
|
103
|
+
def preceding_siblings(opt={})
|
|
104
|
+
siblings = element.preceding_siblings(opt)
|
|
105
|
+
siblings.collect {|sibling| druid_wrapper(sibling)}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
#
|
|
109
|
+
# Return all elements that exist at the same level of the DOM
|
|
110
|
+
# immediately after this element
|
|
111
|
+
#
|
|
112
|
+
def following_siblings(opt={})
|
|
113
|
+
siblings = element.following_siblings(opt)
|
|
114
|
+
siblings.collect {|sibling| druid_wrapper(sibling)}
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# Wait until the element is present
|
|
119
|
+
#
|
|
120
|
+
# @param [Integer] (defaults to: 5) seconds to wait before timing out
|
|
121
|
+
#
|
|
122
|
+
def when_present(timeout=Druid.default_element_wait)
|
|
123
|
+
element.wait_until(timeout: timeout, message: "Element not present in #{timeout} seconds", &:present?)
|
|
124
|
+
self
|
|
125
|
+
end
|
|
126
|
+
alias_method :when_visible, :when_present
|
|
127
|
+
|
|
128
|
+
#
|
|
129
|
+
# Waits until the element is not present
|
|
130
|
+
#
|
|
131
|
+
# @param [Integer] (defaults to: 5) seconds to wait before
|
|
132
|
+
# timing out
|
|
133
|
+
#
|
|
134
|
+
def when_not_present(timeout=Druid.default_element_wait)
|
|
135
|
+
element.wait_while(timeout: timeout, message: "Element still present in #{timeout} seconds", &:present?)
|
|
136
|
+
end
|
|
137
|
+
alias_method :when_not_visible, :when_not_present
|
|
138
|
+
|
|
139
|
+
#
|
|
140
|
+
# Waits until the block returns true
|
|
141
|
+
#
|
|
142
|
+
# @param [Integer] (defaults to: 5) seconds to wait before timing out
|
|
143
|
+
# @param [String] the message to display if the event timeouts
|
|
144
|
+
# @param the block to execute when the event occurs
|
|
145
|
+
#
|
|
146
|
+
def wait_until(timeout=Druid.default_element_wait, message=nil, &block)
|
|
147
|
+
element.wait_until(timeout: timeout, message: message, &block)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def name
|
|
151
|
+
element.attribute(:name)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# @private
|
|
155
|
+
# delegate calls to driver element
|
|
156
|
+
def method_missing(*args, &block)
|
|
157
|
+
m = args.shift
|
|
158
|
+
element.send m, *args, &block
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def respond_to_missing?(m,*args)
|
|
162
|
+
element.respond_to?(m) || super
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
protected
|
|
166
|
+
|
|
167
|
+
def druid_wrapper(object)
|
|
168
|
+
type = element.type if object.tag_name.to_sym == :input
|
|
169
|
+
cls = Druid::Elements.element_class_for(object.tag_name, type)
|
|
170
|
+
cls.new(object.to_subtype)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
private
|
|
174
|
+
|
|
175
|
+
def timed_loop(timeout)
|
|
176
|
+
end_time = ::Time.now + timeout
|
|
177
|
+
until ::Time.now > end_time
|
|
178
|
+
result = yield(self)
|
|
179
|
+
return result if result
|
|
180
|
+
sleep 0.5
|
|
181
|
+
end
|
|
182
|
+
false
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
module Elements
|
|
3
|
+
class Heading < Element
|
|
4
|
+
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
Druid::Elements.tag_to_class[:h1] = Druid::Elements::Heading
|
|
8
|
+
Druid::Elements.tag_to_class[:h2] = Druid::Elements::Heading
|
|
9
|
+
Druid::Elements.tag_to_class[:h3] = Druid::Elements::Heading
|
|
10
|
+
Druid::Elements.tag_to_class[:h4] = Druid::Elements::Heading
|
|
11
|
+
Druid::Elements.tag_to_class[:h5] = Druid::Elements::Heading
|
|
12
|
+
Druid::Elements.tag_to_class[:h6] = Druid::Elements::Heading
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
module Elements
|
|
3
|
+
class OrderedList < Element
|
|
4
|
+
attr_accessor :li_element
|
|
5
|
+
|
|
6
|
+
def [](idx)
|
|
7
|
+
list_items[idx]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def items
|
|
11
|
+
list_items.size
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def each(&block)
|
|
15
|
+
list_items.each(&block)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Return Array of ListItem objects that are children of the OrderedList
|
|
20
|
+
#
|
|
21
|
+
def list_items
|
|
22
|
+
@list_items ||= children(tag_name: 'li')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
Druid::Elements.tag_to_class[:ol] = Druid::Elements::OrderedList
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
module Elements
|
|
3
|
+
class SelectList < Element
|
|
4
|
+
|
|
5
|
+
def [](idx)
|
|
6
|
+
options[idx]
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def options
|
|
10
|
+
element.options.map { |e| Druid::Elements::Option.new(e)}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
#
|
|
14
|
+
# @return [Array<String>] An array of strings representing the text of the currently selected options.
|
|
15
|
+
#
|
|
16
|
+
def selected_options
|
|
17
|
+
element.selected_options.map(&:text).compact
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# @return [Array<String>] An array of strings representing the value of the currently selected options.
|
|
22
|
+
def selected_values
|
|
23
|
+
element.selected_options.map(&:value).compact
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Druid::Elements.tag_to_class[:select] = Druid::Elements::SelectList
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
module Elements
|
|
3
|
+
class Table < Element
|
|
4
|
+
#
|
|
5
|
+
# Return the Druid::Elements::Table for the index provided. Index
|
|
6
|
+
# is zero based. If the index provided is a String then it
|
|
7
|
+
# will be matched with the text from any column. The text can be
|
|
8
|
+
# a substring of the full column text.
|
|
9
|
+
#
|
|
10
|
+
# @return [Druid::Elements::TableRow]
|
|
11
|
+
#
|
|
12
|
+
def [](what)
|
|
13
|
+
idx = find_index(what)
|
|
14
|
+
idx && row_items[idx]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
# Returns the number of rows in the table.
|
|
19
|
+
#
|
|
20
|
+
def rows
|
|
21
|
+
row_items.size
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# iterator that yields with a Druid::Elements::TableRow
|
|
26
|
+
#
|
|
27
|
+
# @return [Druid::Elements::TableRow]
|
|
28
|
+
#
|
|
29
|
+
def each(&block)
|
|
30
|
+
row_items.each(&block)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# return the first row
|
|
35
|
+
#
|
|
36
|
+
# @return Druid::Elements::TableRow
|
|
37
|
+
#
|
|
38
|
+
def first_row
|
|
39
|
+
self[0]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# return the last row
|
|
44
|
+
#
|
|
45
|
+
# @return Druid::Elements::TableRow
|
|
46
|
+
#
|
|
47
|
+
def last_row
|
|
48
|
+
self[-1]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
#
|
|
52
|
+
# Returns the Array of values(String) in a column for the index provided. Index
|
|
53
|
+
# is zero based. If the index provided is a String then it
|
|
54
|
+
# will be matched with the text from the header. The text can be a substring of the full header text
|
|
55
|
+
#
|
|
56
|
+
def column_values(what)
|
|
57
|
+
idx = find_index_of_header(what)
|
|
58
|
+
idx && row_items.drop(1).collect{ |row| row.cell(index: idx).text }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def row_items
|
|
64
|
+
meth = stragegy == :descendants ? :trs : :rows
|
|
65
|
+
@row_items ||= element.send(meth).map do |obj|
|
|
66
|
+
Druid::Elements::TableRow.new(obj)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def stragegy
|
|
71
|
+
:children
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def find_index_of_header(what)
|
|
75
|
+
return what if what.is_a? Integer
|
|
76
|
+
row_items[0].cells.find_index do |cell|
|
|
77
|
+
cell.text.include? Regexp.escape(what)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def find_index(what)
|
|
82
|
+
return what if what.is_a? Integer
|
|
83
|
+
row_items.find_index do |row|
|
|
84
|
+
row.cell(text: /#{Regexp.escape(what)}/).exist?
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
Druid::Elements.tag_to_class[:table] = Druid::Elements::Table
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'watir/elements/html_elements'
|
|
2
|
+
module Druid
|
|
3
|
+
module Elements
|
|
4
|
+
class TableRow < Element
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Return the Druid::Elements::TableCell for the index provided. Index
|
|
8
|
+
# is zero based. If the index provided is a String then it
|
|
9
|
+
# will be matched with the text from the columns in the first row.
|
|
10
|
+
#
|
|
11
|
+
def [](what)
|
|
12
|
+
idx = find_index(what)
|
|
13
|
+
idx && cell_items[idx]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#
|
|
17
|
+
# Returns the number of colums in the table
|
|
18
|
+
#
|
|
19
|
+
def columns
|
|
20
|
+
cell_items.size
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
#
|
|
24
|
+
# iterator that yields with a Druid::Elements::TableCell
|
|
25
|
+
#
|
|
26
|
+
def each(&block)
|
|
27
|
+
cell_items.each(&block)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def cell_items
|
|
33
|
+
@cell_items ||= element.cells.map do |obj|
|
|
34
|
+
Druid::Elements::TableCell.new(obj)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def find_index(what)
|
|
39
|
+
return what if what.is_a? Integer
|
|
40
|
+
parent(tag_name: 'table').headers.find_index do |header|
|
|
41
|
+
header.text.include? what
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
Druid::Elements.tag_to_class[:tr] = Druid::Elements::TableRow
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
module Elements
|
|
3
|
+
class UnOrderedList < Element
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# @return [Druid::Elements::ListItem]
|
|
7
|
+
#
|
|
8
|
+
def [](idx)
|
|
9
|
+
list_items[idx]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def items
|
|
13
|
+
list_items.size
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def each(&block)
|
|
17
|
+
list_items.each(&block)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# Return Array of ListItem objects that are children of the UnorderedList
|
|
22
|
+
#
|
|
23
|
+
def list_items
|
|
24
|
+
@list_items ||= children(tag_name: 'li')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Druid::Elements.tag_to_class[:ul] = Druid::Elements::UnOrderedList
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|