wrapybara 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Phillip Koebbe
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = wrapybara
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to wrapybara
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Phillip Koebbe. See LICENSE.txt for
18
+ further details.
19
+
data/lib/wrapybara.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'wrapybara/steps'
2
+ require 'wrapybara/methods'
@@ -0,0 +1,150 @@
1
+ module Wrapybara
2
+ module Element
3
+ def get_element(xpath, scope)
4
+ if scope
5
+ # if scope starts with '/html', let's assume (for now) that it's already an xpath
6
+ unless scope =~ /^\/html/
7
+ # if there are multiple scopes (ie, "div1 div2 para1"), the following makes
8
+ # xpath look like "id('div1')/*[@id='div2']/*[@id='para1']"
9
+
10
+ scope = scope.split(' ')
11
+ id = scope.shift
12
+ scope = "id('#{id}')" + scope.inject('') { |output, s| output += "//*[@id='#{s}']" }
13
+ end
14
+
15
+ # xpath might come in like //something, and since we would be looking for an element
16
+ # in the scope of another element, we need to make sure we aren't looking at the whole
17
+ # document by adding the dot at the beginning
18
+ xpath = ".#{xpath}" if xpath[0..1] == '//'
19
+ Capybara.find(scope).find(xpath) rescue nil
20
+ else
21
+ Capybara.find(xpath) rescue nil
22
+ end
23
+ end
24
+
25
+ def element
26
+ @element
27
+ end
28
+
29
+ def path
30
+ element.path
31
+ end
32
+
33
+ def style
34
+ element[:style] || ''
35
+ end
36
+
37
+ def click
38
+ element.click
39
+ end
40
+
41
+ def exists?
42
+ !@element.nil?
43
+ end
44
+
45
+ def should_exist(message = nil)
46
+ message ||= "Expected element #{self.element_identifier} to exist"
47
+ raise UnmetExpectation, message unless self.exists?
48
+ end
49
+
50
+ def should_not_exist(message = nil)
51
+ message ||= "Did not expect element #{self.element_identifier} to exist"
52
+ raise UnmetExpectation, message if self.exists?
53
+ end
54
+
55
+ def should_have_attribute(attribute, value = nil)
56
+ the_attribute = Attribute.new(self, attribute)
57
+ the_attribute.should_exist
58
+ the_attribute.value.should_be value if value
59
+ end
60
+
61
+ def should_not_have_attribute(attribute, value = nil)
62
+ the_attribute = Attribute.new(self, attribute)
63
+ if value
64
+ the_attribute.should_exist
65
+ the_attribute.value.should_not_be value
66
+ else
67
+ the_attribute.should_not_exist
68
+ end
69
+ end
70
+
71
+ def enabled?
72
+ !disabled?
73
+ end
74
+
75
+ def disabled?
76
+ self.should_exist
77
+ ['true', 'disabled'].include?(@element[:disabled])
78
+ end
79
+
80
+ def should_be_enabled
81
+ message = "Expected element #{self.element_identifier} to be enabled"
82
+ raise UnmetExpectation, message unless self.enabled?
83
+ end
84
+
85
+ def should_not_be_enabled
86
+ message = "Did not expect element #{self.element_identifier} to be enabled"
87
+ raise UnmetExpectation, message if self.enabled?
88
+ end
89
+
90
+ def should_be_disabled
91
+ message = "Expected element #{self.element_identifier} to be disabled"
92
+ raise UnmetExpectation, message unless self.disabled?
93
+ end
94
+
95
+ def should_not_be_disabled
96
+ message = "Did not expect element #{self.element_identifier} to be disabled"
97
+ raise UnmetExpectation, message if self.disabled?
98
+ end
99
+
100
+ def visible?
101
+ self.should_exist
102
+
103
+ # determining visibility of something is challenging, to say the least. this approach is to start with the subject element
104
+ # and check its style attribute for display: none or visibility: hidden. if neither is found, work backward up the
105
+ # object hierarchy checking each parent.
106
+
107
+ return false if self.style.downcase.gsub(' ', '') =~ /(display:none|visibility:hidden)/
108
+
109
+ parent = get_element(self.path + '/..', nil)
110
+ while parent && parent.path != '/html'
111
+ style = parent[:style] || ''
112
+ return false if style.downcase.gsub(' ', '') =~ /(display:none|visibility:hidden)/
113
+ parent = get_element(parent.path + '/..', nil)
114
+ end
115
+
116
+ return true
117
+ end
118
+
119
+ def should_be_visible
120
+ message = "Expected content #{self.element_identifier} to be visible"
121
+ raise UnmetExpectation, message unless self.visible?
122
+ end
123
+
124
+ def should_not_be_visible
125
+ message = "Did not expect content #{self.element_identifier} to be visible"
126
+ raise UnmetExpectation, message if self.visible?
127
+ end
128
+
129
+ def within(scope)
130
+ scope ? " within '#{scope}'" : ''
131
+ end
132
+
133
+ def element_identifier
134
+ "#{@how} '#{@identifier}'#{self.within(@scope)}"
135
+ end
136
+
137
+ def parent_identifier
138
+ return '' unless @parent
139
+ "#{@parent.how} '#{@parent.identifier}'#{self.within(@parent.scope)}"
140
+ end
141
+
142
+ def default_scope
143
+ nil
144
+ end
145
+
146
+ def default_how
147
+ 'labeled'
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,32 @@
1
+ module Wrapybara
2
+ class Attribute
3
+ include Element
4
+
5
+ def initialize(parent, attribute)
6
+ @parent = parent
7
+ @attribute = attribute
8
+ end
9
+
10
+ def value
11
+ self
12
+ end
13
+
14
+ def should_exist
15
+ raise UnmetExpectation, "Expected element #{self.parent_identifier} to have attribute '#{@attribute}'" if @parent.element[@attribute].nil?
16
+ end
17
+
18
+ def should_not_exist
19
+ raise UnmetExpectation, "Did not expect element #{self.parent_identifier} to have attribute '#{@attribute}'" unless @parent.element[@attribute].nil?
20
+ end
21
+
22
+ def should_be(value)
23
+ message = "Expected element #{self.parent_identifier} to have attribute '#{@attribute}' with value '#{value}'"
24
+ raise UnmetExpectation, message unless @parent.element[@attribute] == value
25
+ end
26
+
27
+ def should_not_be(value)
28
+ message = "Did not expect element #{self.parent_identifier} to have attribute '#{@attribute}' with value '#{value}'"
29
+ raise UnmetExpectation, message if @parent.element[@attribute] == value
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,27 @@
1
+ module Wrapybara
2
+ class Button
3
+ include Element
4
+
5
+ def initialize(identifier, scope = default_scope, how = default_how)
6
+ @identifier = identifier
7
+ @how = how
8
+ @scope = scope
9
+ xpath = XPath::HTML.button(identifier)
10
+ @element = get_element(xpath, scope)
11
+ end
12
+
13
+ def should_exist
14
+ super "Expected a button #{self.element_identifier} to exist"
15
+ end
16
+
17
+ def should_not_exist
18
+ super "Did not expect a button #{self.element_identifier}' to exist"
19
+ end
20
+
21
+ def click
22
+ self.should_exist
23
+ # Capybara method
24
+ @element.click
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,49 @@
1
+ module Wrapybara
2
+ class Checkbox
3
+ include Element
4
+
5
+ def initialize(identifier, scope = default_scope, how = default_how)
6
+ @identifier = identifier
7
+ @how = how
8
+ @scope = scope
9
+ xpath = XPath::HTML.checkbox(identifier)
10
+ @element = get_element(xpath, scope)
11
+ end
12
+
13
+ def should_exist
14
+ super "Expected a checkbox #{self.element_identifier} to exist"
15
+ end
16
+
17
+ def should_not_exist
18
+ super "Did not expect a checkbox #{self.element_identifier}' to exist"
19
+ end
20
+
21
+ def set(state)
22
+ self.should_exist
23
+ # Capybara method
24
+ @element.set(state)
25
+ end
26
+
27
+ def check
28
+ self.set(true)
29
+ end
30
+
31
+ def uncheck
32
+ self.set(false)
33
+ end
34
+
35
+ def checked?
36
+ self.should_exist
37
+ # Capybara method
38
+ @element.checked?
39
+ end
40
+
41
+ def should_be_checked
42
+ raise UnmetExpectation, "Expected a checkbox #{self.element_identifier} to be checked" unless self.checked?
43
+ end
44
+
45
+ def should_not_be_checked
46
+ raise UnmetExpectation, "Did not expect a checkbox #{self.element_identifier} to be checked" if self.checked?
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,33 @@
1
+ module Wrapybara
2
+ class Content
3
+ include Element
4
+
5
+ def initialize(identifier, scope = default_scope)
6
+ @identifier = identifier
7
+ @scope = scope
8
+ #xpath = XPath::HTML.content(identifier)
9
+ # the %{} string notation is used so double quotes can offset identifier, allowing identifier to contain single quotes/apostrophes.
10
+ # also important to note is that this xpath requires text to be contained in something (div, p, span). any text just floating around
11
+ # on the page will show up with a path of //html, which is not terribly useful later on.
12
+ xpath = %{//*[contains(text(), "#{identifier}")]}
13
+ @element = get_element(xpath, scope)
14
+ end
15
+
16
+ def click
17
+ self.should_be_visible
18
+ super
19
+ end
20
+
21
+ def should_exist
22
+ super "Expected content #{self.element_identifier} to exist"
23
+ end
24
+
25
+ def should_not_exist
26
+ super "Did not expect content #{self.element_identifier} to exist"
27
+ end
28
+
29
+ def element_identifier
30
+ "'#{@identifier}'#{self.within(@scope)}"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ module Wrapybara
2
+ class FileField
3
+ include Element
4
+
5
+ def initialize(identifier, scope = default_scope, how = default_how)
6
+ @identifier = identifier
7
+ @how = how
8
+ @scope = scope
9
+ xpath = XPath::HTML.file_field(identifier)
10
+ @element = get_element(xpath, scope)
11
+ end
12
+
13
+ def attach_file(path)
14
+ self.should_exist
15
+ # Capybara method
16
+ @element.set(path)
17
+ end
18
+
19
+ def should_exist
20
+ super "Expected a file field #{self.element_identifier} to exist"
21
+ end
22
+
23
+ def should_not_exist
24
+ super "Did not expect a file field #{self.element_identifier}' to exist"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,46 @@
1
+ module Wrapybara
2
+ module FillableField
3
+ def fill_in(value)
4
+ self.should_exist
5
+ # Capybara method
6
+ @element.set(value)
7
+ end
8
+
9
+ def value
10
+ self.should_exist
11
+ (@element.value || '').strip
12
+ end
13
+
14
+ def empty?
15
+ self.value == ''
16
+ end
17
+
18
+ def should_be_empty
19
+ raise UnmetExpectation, "Expected text field #{self.element_identifier} to be empty" unless self.empty?
20
+ end
21
+
22
+ def should_not_be_empty
23
+ raise UnmetExpectation, "Did not expect text field #{self.element_identifier} to be empty" if self.empty?
24
+ end
25
+
26
+ def has_content?(content)
27
+ self.value =~ /#{content}/
28
+ end
29
+
30
+ def should_have_content(content)
31
+ if content.blank?
32
+ self.should_be_empty
33
+ else
34
+ raise UnmetExpectation, "Expected text field #{self.element_identifier} to have content '#{content}'" unless self.has_content?(content)
35
+ end
36
+ end
37
+
38
+ def should_not_have_content(content)
39
+ if content.blank?
40
+ self.should_not_be_empty
41
+ else
42
+ raise UnmetExpectation, "Did not expect text field #{self.element_identifier} to have content '#{content}'" if self.has_content?(content)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ module Wrapybara
2
+ class Form
3
+ include Element
4
+
5
+ def initialize(identifier, scope = default_scope, how = default_how)
6
+ @identifier = identifier
7
+ @how = how
8
+ @scope = scope
9
+ xpath = "id('#{identifier}') | id(//label[contains(normalize-space(string(.)), '#{identifier}')]/@for)"
10
+ @element = get_element(xpath, scope)
11
+ end
12
+
13
+ def should_exist
14
+ super "Expected a form #{self.element_identifier} to exist"
15
+ end
16
+
17
+ def should_not_exist
18
+ super "Did not expect a form #{self.element_identifier}' to exist"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module Wrapybara
2
+ class Image
3
+ include Element
4
+
5
+ attr_reader :element, :identifier, :how, :scope
6
+
7
+ def initialize(identifier, scope = default_scope, how = default_how)
8
+ @identifier = identifier
9
+ @how = how
10
+ @scope = scope
11
+ xpath = "//img[@src='#{identifier}' or @id='#{identifier}' or @title='#{identifier}' or @alt='#{identifier}']"
12
+ @element = get_element(xpath, scope)
13
+ end
14
+
15
+ def should_exist
16
+ super "Expected an image #{self.element_identifier} to exist"
17
+ end
18
+
19
+ def should_not_exist
20
+ super "Did not expect an image #{self.element_identifier}' to exist"
21
+ end
22
+ end
23
+ end