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,55 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
module Elements
|
|
3
|
+
class << self
|
|
4
|
+
|
|
5
|
+
def type_to_class
|
|
6
|
+
@type_to_class ||= {}
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# method to return the collection of tag_name class mappings
|
|
10
|
+
def tag_to_class
|
|
11
|
+
@tag_to_class ||= {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# method to return the element for a tag_name
|
|
16
|
+
#
|
|
17
|
+
def element_class_for(tag_name, type=nil)
|
|
18
|
+
return type_to_class[type.to_sym] if type
|
|
19
|
+
tag_to_class[tag_name.to_sym] || Druid::Elements::Element
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
require 'druid/elements/element'
|
|
26
|
+
require 'druid/elements/ordered_list'
|
|
27
|
+
require 'druid/elements/unordered_list'
|
|
28
|
+
require 'druid/elements/table'
|
|
29
|
+
require 'druid/elements/table_row'
|
|
30
|
+
require 'druid/elements/select_list'
|
|
31
|
+
require 'druid/elements/link'
|
|
32
|
+
require 'druid/elements/button'
|
|
33
|
+
require 'druid/elements/check_box'
|
|
34
|
+
require 'druid/elements/radio_button'
|
|
35
|
+
require 'druid/elements/text_field'
|
|
36
|
+
require 'druid/elements/div'
|
|
37
|
+
require 'druid/elements/table_cell'
|
|
38
|
+
require 'druid/elements/image'
|
|
39
|
+
require 'druid/elements/span'
|
|
40
|
+
require 'druid/elements/hidden_field'
|
|
41
|
+
require 'druid/elements/list_item'
|
|
42
|
+
require 'druid/elements/text_area'
|
|
43
|
+
require 'druid/elements/form'
|
|
44
|
+
require 'druid/elements/option'
|
|
45
|
+
require 'druid/elements/heading'
|
|
46
|
+
require 'druid/elements/paragraph'
|
|
47
|
+
require 'druid/elements/file_field'
|
|
48
|
+
require 'druid/elements/label'
|
|
49
|
+
require 'druid/elements/area'
|
|
50
|
+
require 'druid/elements/canvas'
|
|
51
|
+
require 'druid/elements/media'
|
|
52
|
+
require 'druid/elements/audio'
|
|
53
|
+
require 'druid/elements/video'
|
|
54
|
+
require 'druid/elements/bold'
|
|
55
|
+
require 'druid/elements/italic'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
module Javascript
|
|
3
|
+
|
|
4
|
+
module YUI
|
|
5
|
+
#
|
|
6
|
+
# return the number of pending ajax requests
|
|
7
|
+
#
|
|
8
|
+
def self.pending_requests
|
|
9
|
+
"var inProgress=0
|
|
10
|
+
for(var i=0; i < YAHOO.util.Connect._transaction_id; i++) {
|
|
11
|
+
if(YAHOO.util.Connect.isCallInProgress(i))
|
|
12
|
+
inProgress++;
|
|
13
|
+
}
|
|
14
|
+
return inProgress;"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'druid/javascript/jquery'
|
|
2
|
+
require 'druid/javascript/prototype'
|
|
3
|
+
require 'druid/javascript/yui'
|
|
4
|
+
require 'druid/javascript/angularjs'
|
|
5
|
+
|
|
6
|
+
module Druid
|
|
7
|
+
#
|
|
8
|
+
# Provide hooks into different common Javascript Frameworks.
|
|
9
|
+
# Currently this module only supports jQuery and Prototype but it
|
|
10
|
+
# has ability for you to plug your own framework into it and
|
|
11
|
+
# therefore have it work with this gem. You do this by calling the
|
|
12
|
+
# #add_framework method. The module you provide must implement the
|
|
13
|
+
# necessary methods. Please look at the jQuery or Prototype
|
|
14
|
+
# implementations to determine the necessary methods
|
|
15
|
+
#
|
|
16
|
+
module JavascriptFrameworkFacade
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
#
|
|
20
|
+
# Set the framework to use
|
|
21
|
+
#
|
|
22
|
+
# @param [Symbol] the framework to use. :jquery and :prototype, :yui,
|
|
23
|
+
# and :angularjs are supported
|
|
24
|
+
#
|
|
25
|
+
def framework=(framework)
|
|
26
|
+
initialize_script_builder unless @builder
|
|
27
|
+
raise unknown_framework(framework) unless @builder[framework]
|
|
28
|
+
@framework = framework
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def add_framework(key, value)
|
|
32
|
+
raise invalid_framework unless value.respond_to? :pending_requests
|
|
33
|
+
initialize_script_builder unless @builder
|
|
34
|
+
@builder[key] = value
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#
|
|
38
|
+
# Get the framework that will be used
|
|
39
|
+
#
|
|
40
|
+
def framework
|
|
41
|
+
@framework
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def script_builder
|
|
45
|
+
initialize_script_builder unless @builder
|
|
46
|
+
@builder[@framework]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
#
|
|
50
|
+
# get the javascript to determine number of pending requests
|
|
51
|
+
#
|
|
52
|
+
def pending_requests
|
|
53
|
+
script_builder.pending_requests
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def initialize_script_builder
|
|
59
|
+
@builder = {
|
|
60
|
+
:jquery => Druid::Javascript::JQuery,
|
|
61
|
+
:prototype => Druid::Javascript::Prototype,
|
|
62
|
+
:yui => Druid::Javascript::YUI,
|
|
63
|
+
:angularjs => Druid::Javascript::AngularJS
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def unknown_framework(framework)
|
|
68
|
+
"You specified the Javascript framework #{framework} and it is unknown to the system"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def invalid_framework
|
|
72
|
+
"The Javascript framework you provided does not implement the necessary methods"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
module LocatorGenerator
|
|
3
|
+
|
|
4
|
+
BASIC_ELEMENTS = %i(
|
|
5
|
+
abbr
|
|
6
|
+
address
|
|
7
|
+
animate
|
|
8
|
+
animate_motion
|
|
9
|
+
animate_transform
|
|
10
|
+
article
|
|
11
|
+
as
|
|
12
|
+
aside
|
|
13
|
+
base
|
|
14
|
+
bdi
|
|
15
|
+
bdo
|
|
16
|
+
blockquote
|
|
17
|
+
body
|
|
18
|
+
br
|
|
19
|
+
caption
|
|
20
|
+
circle
|
|
21
|
+
cite
|
|
22
|
+
code
|
|
23
|
+
col
|
|
24
|
+
colgroup
|
|
25
|
+
command
|
|
26
|
+
cursor
|
|
27
|
+
data
|
|
28
|
+
datalist
|
|
29
|
+
dd
|
|
30
|
+
defs
|
|
31
|
+
del
|
|
32
|
+
desc
|
|
33
|
+
details
|
|
34
|
+
dfn
|
|
35
|
+
dialog
|
|
36
|
+
discard
|
|
37
|
+
dl
|
|
38
|
+
dt
|
|
39
|
+
ellipse
|
|
40
|
+
em
|
|
41
|
+
embed
|
|
42
|
+
fieldset
|
|
43
|
+
figcaption
|
|
44
|
+
figure
|
|
45
|
+
font
|
|
46
|
+
footer
|
|
47
|
+
foreign_object
|
|
48
|
+
g
|
|
49
|
+
head
|
|
50
|
+
header
|
|
51
|
+
hgroup
|
|
52
|
+
hr
|
|
53
|
+
html
|
|
54
|
+
ins
|
|
55
|
+
kbd
|
|
56
|
+
keygen
|
|
57
|
+
legend
|
|
58
|
+
line
|
|
59
|
+
linear_gradient
|
|
60
|
+
main
|
|
61
|
+
map
|
|
62
|
+
mark
|
|
63
|
+
marker
|
|
64
|
+
menu
|
|
65
|
+
menuitem
|
|
66
|
+
mesh_gradient
|
|
67
|
+
mesh_patch
|
|
68
|
+
mesh_row
|
|
69
|
+
meta
|
|
70
|
+
metadata
|
|
71
|
+
meter
|
|
72
|
+
mpath
|
|
73
|
+
nav
|
|
74
|
+
noscript
|
|
75
|
+
object
|
|
76
|
+
optgroup
|
|
77
|
+
output
|
|
78
|
+
p
|
|
79
|
+
param
|
|
80
|
+
path
|
|
81
|
+
pattern
|
|
82
|
+
polygon
|
|
83
|
+
polyline
|
|
84
|
+
pre
|
|
85
|
+
progress
|
|
86
|
+
q
|
|
87
|
+
radial_gradient
|
|
88
|
+
rect
|
|
89
|
+
rp
|
|
90
|
+
rt
|
|
91
|
+
ruby
|
|
92
|
+
s
|
|
93
|
+
samp
|
|
94
|
+
script
|
|
95
|
+
section
|
|
96
|
+
set
|
|
97
|
+
small
|
|
98
|
+
source
|
|
99
|
+
stop
|
|
100
|
+
strong
|
|
101
|
+
style
|
|
102
|
+
sub
|
|
103
|
+
summary
|
|
104
|
+
sup
|
|
105
|
+
switch
|
|
106
|
+
symbol
|
|
107
|
+
template
|
|
108
|
+
text_path
|
|
109
|
+
thread
|
|
110
|
+
time
|
|
111
|
+
title
|
|
112
|
+
track
|
|
113
|
+
tspan
|
|
114
|
+
u
|
|
115
|
+
use
|
|
116
|
+
var
|
|
117
|
+
view
|
|
118
|
+
wbr
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
ADVANCED_ELEMENTS = %i(
|
|
123
|
+
text_field
|
|
124
|
+
hidden_field
|
|
125
|
+
text_area
|
|
126
|
+
select_list
|
|
127
|
+
link
|
|
128
|
+
checkbox
|
|
129
|
+
radio_button
|
|
130
|
+
button
|
|
131
|
+
div
|
|
132
|
+
span
|
|
133
|
+
table
|
|
134
|
+
cell
|
|
135
|
+
row
|
|
136
|
+
image
|
|
137
|
+
form
|
|
138
|
+
list_item
|
|
139
|
+
ordered_list
|
|
140
|
+
unordered_list
|
|
141
|
+
h1
|
|
142
|
+
h2
|
|
143
|
+
h3
|
|
144
|
+
h4
|
|
145
|
+
h5
|
|
146
|
+
h6
|
|
147
|
+
paragraph
|
|
148
|
+
label
|
|
149
|
+
file_field
|
|
150
|
+
area
|
|
151
|
+
canvas
|
|
152
|
+
audio
|
|
153
|
+
video
|
|
154
|
+
b
|
|
155
|
+
i
|
|
156
|
+
svg
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def self.generate_locators(target)
|
|
160
|
+
ADVANCED_ELEMENTS.each do |tag|
|
|
161
|
+
target.send(:define_method, "#{tag.to_s}_element") do |*identifier|
|
|
162
|
+
self.send "#{tag.to_s}_for", locator(identifier).clone
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
target.send(:define_method, "#{tag.to_s}_elements") do |*identifier|
|
|
166
|
+
self.send "#{tag.to_s}s_for", identifier[0] ? identifier[0].clone : {}
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
BASIC_ELEMENTS.each do |tag|
|
|
171
|
+
target.send(:define_method, "#{tag.to_s}_element") do |*identifier|
|
|
172
|
+
self.send :element_for, tag, locator(identifier)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
target.send(:define_method, "#{tag.to_s}_elements") do |*identifier|
|
|
176
|
+
self.send(:elements_for, tag, identifier[0] ? identifier[0] : {})
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'druid/locator_generator'
|
|
2
|
+
|
|
3
|
+
module Druid
|
|
4
|
+
module NestedElements
|
|
5
|
+
|
|
6
|
+
def self.included(cls)
|
|
7
|
+
Druid::LocatorGenerator.generate_locators(cls)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def locator(identifier)
|
|
13
|
+
identifier[0] ? identifier[0] : {:index => 0}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# [:text_field,
|
|
17
|
+
# :hidden_field,
|
|
18
|
+
# :text_area,
|
|
19
|
+
# :select_list,
|
|
20
|
+
# :link,
|
|
21
|
+
# :checkbox,
|
|
22
|
+
# :radio_button,
|
|
23
|
+
# :button,
|
|
24
|
+
# :div,
|
|
25
|
+
# :span,
|
|
26
|
+
# :table,
|
|
27
|
+
# :cell,
|
|
28
|
+
# :image,
|
|
29
|
+
# :form,
|
|
30
|
+
# :list_item,
|
|
31
|
+
# :unordered_list,
|
|
32
|
+
# :ordered_list,
|
|
33
|
+
# :h1,
|
|
34
|
+
# :h2,
|
|
35
|
+
# :h3,
|
|
36
|
+
# :h4,
|
|
37
|
+
# :h5,
|
|
38
|
+
# :h6,
|
|
39
|
+
# :paragraph,
|
|
40
|
+
# :label,
|
|
41
|
+
# :file_field,
|
|
42
|
+
# :area,
|
|
43
|
+
# :canvas,
|
|
44
|
+
# :audio,
|
|
45
|
+
# :video].each do |tag|
|
|
46
|
+
# define_method("#{tag.to_s}_element") do |*identifier|
|
|
47
|
+
# self.send "#{tag.to_s}_for", locator(identifier)
|
|
48
|
+
# end
|
|
49
|
+
#
|
|
50
|
+
# define_method("#{tag.to_s}_elements") do |*identifier|
|
|
51
|
+
# self.send "#{tag.to_s}s_for", locator(identifier)
|
|
52
|
+
# end
|
|
53
|
+
# end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'page_navigation'
|
|
2
|
+
|
|
3
|
+
module Druid
|
|
4
|
+
#
|
|
5
|
+
# Module to facilitate to creating of page objects in step definitions. You
|
|
6
|
+
# can make the methods below available to all of your step definitions by adding
|
|
7
|
+
# this module to World. This idea was first discussed in Alister Scott's blog
|
|
8
|
+
# entry http://watirmelon.com/2011/06/07/removing-local-page-references-from-cucumber-steps/.
|
|
9
|
+
#
|
|
10
|
+
# @example Making the PageFactory available to your step definitions
|
|
11
|
+
# World Druid::PageFactory
|
|
12
|
+
#
|
|
13
|
+
# @example Visiting a page for the first time in a Scenario
|
|
14
|
+
# visit_page MyPageObject do |page|
|
|
15
|
+
# page.name = 'Tim'
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# @example using a page that has already been visited in a Scenario
|
|
19
|
+
# on_page MyPageObject do |page|
|
|
20
|
+
# page.name.should == 'Tim'
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# If you plan to use the navigate_to method you will need to ensure you setup the possible
|
|
24
|
+
# routes ahead of time. You must always have a default route in order for this to work. Here
|
|
25
|
+
# is an example of how you define routes:
|
|
26
|
+
#
|
|
27
|
+
# @example Example routes defined in env.rb
|
|
28
|
+
# Druid::PageFactory.routes = {
|
|
29
|
+
# :default => [[PageOne,:method1], [PageTwoA,:method2], [PageThree,:method3],
|
|
30
|
+
# :another_route => [[PageOne,:method1,"arg1"], [PageTwoB,:method2b], [PageThree,:method3]]
|
|
31
|
+
# }
|
|
32
|
+
# Notice the first entry of :another_route is passing an argument
|
|
33
|
+
# to the method
|
|
34
|
+
# You must also call the navigation_method on each page.
|
|
35
|
+
module PageFactory
|
|
36
|
+
include PageNavigation
|
|
37
|
+
# attr_accessor :page
|
|
38
|
+
#
|
|
39
|
+
# Create and navigate to a page object. The navigation will only work if the
|
|
40
|
+
# 'page_url' method was call on the page object.
|
|
41
|
+
#
|
|
42
|
+
# @param [PageObject, String] a class that has included the
|
|
43
|
+
# Druid module or a string containing the name of the class
|
|
44
|
+
# @param Hash values that is pass through to page class a
|
|
45
|
+
# available in the @params instance variable
|
|
46
|
+
# @param an optional block to be called
|
|
47
|
+
# @return [PageObject] the newly created page object
|
|
48
|
+
#
|
|
49
|
+
def visit_page(page_class, params={:using_params => {}}, &block)
|
|
50
|
+
on_page page_class, params, true, &block
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Support 'visit' for readability of usage
|
|
54
|
+
alias_method :visit, :visit_page
|
|
55
|
+
#
|
|
56
|
+
# Create a page object.
|
|
57
|
+
#
|
|
58
|
+
# @param [PageObject, String] a class that has included the Druid module or a string containing the name of the class
|
|
59
|
+
# @param Hash values that is pass through to page class a
|
|
60
|
+
# available in the @params instance variable.
|
|
61
|
+
# @param [Bool] should the page be visited? default is false.
|
|
62
|
+
# @param an optional block to be called
|
|
63
|
+
# @return [PageObject] the newly created page object
|
|
64
|
+
#
|
|
65
|
+
def on_page(page_class, params={:using_params => {}}, visit=false, &block)
|
|
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
|
|
68
|
+
merged = page_class.params.merge(params[:using_params])
|
|
69
|
+
page_class.instance_variable_set("@merged_params", merged) unless merged.empty?
|
|
70
|
+
@current_page = page_class.new(@driver, visit)
|
|
71
|
+
block.call @current_page if block
|
|
72
|
+
@current_page
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Support 'on' for readability of usage
|
|
76
|
+
alias_method :on, :on_page
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
# Create a page object if and only if the current page is the same page to be created
|
|
80
|
+
#
|
|
81
|
+
# @example
|
|
82
|
+
# original:
|
|
83
|
+
# on_page(NewProduct).save if @current_page.class == NewProduct
|
|
84
|
+
# on_page(EditProduct).save if @current_page.class == EditProduct
|
|
85
|
+
# new:
|
|
86
|
+
# if_page NewProduct do |page|
|
|
87
|
+
# page.save
|
|
88
|
+
# end
|
|
89
|
+
# if_page EditProduct do |page|
|
|
90
|
+
# page.update
|
|
91
|
+
# end
|
|
92
|
+
# @param [PageObject, String] a class that has included the Druid module or a string containing the name of the class
|
|
93
|
+
# @param Hash values that is pass through to page class a
|
|
94
|
+
# available in the @params instance variable
|
|
95
|
+
# @param [block] an optional block to be called
|
|
96
|
+
# @return [PageObject] the newly created page object
|
|
97
|
+
def if_page(page_class, params={:using_params => {}}, &block)
|
|
98
|
+
page_class = class_from_string(page_class) if page_class.is_a? String
|
|
99
|
+
return @current_page unless @current_page.class == page_class
|
|
100
|
+
on_page(page_class, params, false, &block)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# support 'if' for readability of usage
|
|
104
|
+
alias_method :if, :if_page
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def class_from_string(str)
|
|
109
|
+
str.split('::').inject(Object) do |mod, class_name|
|
|
110
|
+
mod.const_get(class_name)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
module PagePopulator
|
|
3
|
+
#
|
|
4
|
+
# This method will populate all matched page TextFields,
|
|
5
|
+
# TextAreas, SelectLists, FileFields, Checkboxes, and Radio Buttons from the
|
|
6
|
+
# Hash passed as an argument. The way it find an element is by
|
|
7
|
+
# matching the Hash key to the name you provided when declaring
|
|
8
|
+
# the element on your page.
|
|
9
|
+
#
|
|
10
|
+
# Checkbox and Radio Button values must be true or false.
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# class ExamplePage
|
|
14
|
+
# include PageObject
|
|
15
|
+
#
|
|
16
|
+
# text_field(:username, :id => 'username_id')
|
|
17
|
+
# checkbox(:active, :id => 'active_id')
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# ...
|
|
21
|
+
#
|
|
22
|
+
# @browser = Watir::Browser.new :firefox
|
|
23
|
+
# example_page = ExamplePage.new(@browser)
|
|
24
|
+
# example_page.populate_page_with :username => 'a name', :active => true
|
|
25
|
+
#
|
|
26
|
+
# @param data [Hash] the data to use to populate this page. The key
|
|
27
|
+
# can be either a string or a symbol. The value must be a string
|
|
28
|
+
# for TextField, TextArea, SelectList and FileField must be true or
|
|
29
|
+
# false for a Checkbox or RadioButton.
|
|
30
|
+
#
|
|
31
|
+
def populate_page_with(data)
|
|
32
|
+
data.to_h.each do |key, value|
|
|
33
|
+
populate_section(key, value) if value.respond_to?(:to_h)
|
|
34
|
+
populate_value(self, key, value)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def populate_section(section, data)
|
|
41
|
+
return unless self.respond_to? section
|
|
42
|
+
data.to_h.each do |key, value|
|
|
43
|
+
populate_value(self.send(section), key, value)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def populate_value(receiver, key, value)
|
|
48
|
+
populate_checkbox(receiver, key, value) if is_checkbox?(receiver, key) and is_enabled?(receiver, key)
|
|
49
|
+
populate_radiobuttongroup(receiver, key, value) if is_radiobuttongroup?(receiver, key)
|
|
50
|
+
populate_radiobutton(receiver, key, value) if is_radiobutton?(receiver, key) and is_enabled?(receiver, key)
|
|
51
|
+
populate_select_list(receiver, key, value) if is_select_list?(receiver, key)
|
|
52
|
+
populate_text(receiver, key, value) if is_text?(receiver, key) and is_enabled?(receiver, key)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def populate_text(receiver, key, value)
|
|
56
|
+
receiver.send "#{key}=", value
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def populate_checkbox(receiver, key, value)
|
|
60
|
+
return receiver.send "check_#{key}" if value
|
|
61
|
+
return receiver.send "uncheck_#{key}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def populate_radiobutton(receiver, key, value)
|
|
65
|
+
return receiver.send "select_#{key}" if value
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def populate_radiobuttongroup(receiver, key, value)
|
|
69
|
+
return receiver.send "select_#{key}", value
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def populate_select_list(receiver, key, value)
|
|
73
|
+
receiver.send "#{key}=", value
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def is_text?(receiver, key)
|
|
77
|
+
return false if is_select_list?(receiver, key)
|
|
78
|
+
receiver.respond_to?("#{key}=".to_sym)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def is_checkbox?(receiver, key)
|
|
82
|
+
receiver.respond_to?("check_#{key}".to_sym)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def is_radiobutton?(receiver, key)
|
|
86
|
+
receiver.respond_to?("select_#{key}".to_sym)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def is_radiobuttongroup?(receiver, key)
|
|
90
|
+
receiver.respond_to?("select_#{key}".to_sym) and receiver.respond_to?("#{key}_values")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def is_select_list?(receiver, key)
|
|
94
|
+
receiver.respond_to?("#{key}_options".to_sym)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def is_enabled?(receiver, key)
|
|
98
|
+
return false if is_radiobuttongroup?(receiver, key)
|
|
99
|
+
return true if (receiver.send "#{key}_element").tag_name == "textarea"
|
|
100
|
+
element = receiver.send("#{key}_element")
|
|
101
|
+
element.enabled? and element.present?
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Druid
|
|
2
|
+
class SectionCollection < Array
|
|
3
|
+
|
|
4
|
+
def find_by values_hash
|
|
5
|
+
find do |section|
|
|
6
|
+
values_hash.all? { |key, value| value === section.public_send(key) }
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def select_by values_hash
|
|
11
|
+
matches = select do |section|
|
|
12
|
+
values_hash.all? { |key, value| value === section.public_send(key) }
|
|
13
|
+
end
|
|
14
|
+
self.class[*matches]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|