capybara-ui 0.10.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/lib/capybara-ui.rb +31 -0
- data/lib/capybara-ui/assertions.rb +19 -0
- data/lib/capybara-ui/capybara.rb +7 -0
- data/lib/capybara-ui/checkpoint.rb +111 -0
- data/lib/capybara-ui/conversions.rb +31 -0
- data/lib/capybara-ui/cucumber.rb +5 -0
- data/lib/capybara-ui/dsl.rb +107 -0
- data/lib/capybara-ui/instance_conversions.rb +19 -0
- data/lib/capybara-ui/matchers.rb +28 -0
- data/lib/capybara-ui/optional_dependencies.rb +5 -0
- data/lib/capybara-ui/rails.rb +5 -0
- data/lib/capybara-ui/rails/role.rb +9 -0
- data/lib/capybara-ui/role.rb +19 -0
- data/lib/capybara-ui/text_table.rb +107 -0
- data/lib/capybara-ui/text_table/cell_text.rb +7 -0
- data/lib/capybara-ui/text_table/mapping.rb +40 -0
- data/lib/capybara-ui/text_table/transformations.rb +13 -0
- data/lib/capybara-ui/text_table/void_mapping.rb +8 -0
- data/lib/capybara-ui/version.rb +3 -0
- data/lib/capybara-ui/widgets.rb +61 -0
- data/lib/capybara-ui/widgets/check_box.rb +26 -0
- data/lib/capybara-ui/widgets/cucumber_methods.rb +73 -0
- data/lib/capybara-ui/widgets/document.rb +19 -0
- data/lib/capybara-ui/widgets/dsl.rb +47 -0
- data/lib/capybara-ui/widgets/field.rb +22 -0
- data/lib/capybara-ui/widgets/field_group.rb +329 -0
- data/lib/capybara-ui/widgets/form.rb +26 -0
- data/lib/capybara-ui/widgets/list.rb +200 -0
- data/lib/capybara-ui/widgets/list_item.rb +22 -0
- data/lib/capybara-ui/widgets/parts/container.rb +46 -0
- data/lib/capybara-ui/widgets/parts/struct.rb +117 -0
- data/lib/capybara-ui/widgets/radio_button.rb +62 -0
- data/lib/capybara-ui/widgets/select.rb +57 -0
- data/lib/capybara-ui/widgets/string_value.rb +43 -0
- data/lib/capybara-ui/widgets/table.rb +76 -0
- data/lib/capybara-ui/widgets/text_field.rb +27 -0
- data/lib/capybara-ui/widgets/widget.rb +392 -0
- data/lib/capybara-ui/widgets/widget/node_filter.rb +48 -0
- data/lib/capybara-ui/widgets/widget_class.rb +11 -0
- data/lib/capybara-ui/widgets/widget_name.rb +56 -0
- metadata +240 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
module CapybaraUI
|
2
|
+
# A select.
|
3
|
+
class Select < Field
|
4
|
+
def selected
|
5
|
+
root.all(:xpath, ".//option", visible: true).select(&:selected?).first
|
6
|
+
end
|
7
|
+
|
8
|
+
module Selectable
|
9
|
+
def select
|
10
|
+
root.select_option
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
widget :option, -> (opt) {
|
15
|
+
opt.is_a?(Regexp) ? ["option", text: opt] : [:option, opt]
|
16
|
+
} do
|
17
|
+
include Selectable
|
18
|
+
end
|
19
|
+
|
20
|
+
widget :option_by_value, -> (opt) { "option[value = #{opt.inspect}]" } do
|
21
|
+
include Selectable
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [String] The text of the selected option.
|
25
|
+
def get
|
26
|
+
selected.text unless selected.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [String] The value of the selected option.
|
30
|
+
def value
|
31
|
+
selected.value unless selected.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
# Selects the given +option+.
|
35
|
+
#
|
36
|
+
# You may pass in the option text or value.
|
37
|
+
def set(option)
|
38
|
+
widget(:option, option).select
|
39
|
+
rescue
|
40
|
+
begin
|
41
|
+
widget(:option_by_value, option).select
|
42
|
+
rescue CapybaraUI::MissingWidget => e
|
43
|
+
raise InvalidOption.new(e.message).
|
44
|
+
tap { |x| x.set_backtrace e.backtrace }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# @!method to_s
|
49
|
+
# @return the text of the selected option, or the empty string if
|
50
|
+
# no option is selected.
|
51
|
+
def_delegator :get, :to_s
|
52
|
+
|
53
|
+
def to_cell
|
54
|
+
get
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module CapybaraUI
|
2
|
+
class StringValue < String
|
3
|
+
def to_date(format = nil)
|
4
|
+
format ? Date.strptime(self, format) : super()
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_key
|
8
|
+
fst, rest = first, self[1..-1]
|
9
|
+
decamelized = fst + rest.gsub(/([A-Z])/, '_\1')
|
10
|
+
underscored = decamelized.gsub(/[\W_]+/, '_')
|
11
|
+
stripped = underscored.gsub(/^_|_$/, '')
|
12
|
+
downcased = stripped.downcase
|
13
|
+
key = downcased.to_sym
|
14
|
+
|
15
|
+
key
|
16
|
+
end
|
17
|
+
|
18
|
+
class Money
|
19
|
+
extend Forwardable
|
20
|
+
|
21
|
+
delegate %w(to_i to_f) => :str
|
22
|
+
|
23
|
+
def initialize(str)
|
24
|
+
fail ArgumentError, "can't convert `#{str}` to money" \
|
25
|
+
unless str =~ /^-?\$\d+(?:,\d{3})*(?:\.\d+)?/
|
26
|
+
|
27
|
+
@str = (str =~ /^-/ ? '-' : '') + str.gsub(/^-?\$|,/, '')
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :str
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_usd
|
36
|
+
Money.new(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_split
|
40
|
+
split(',').map(&:strip).map { |e| self.class.new(e) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module CapybaraUI
|
2
|
+
class Table < CapybaraUI::Widget
|
3
|
+
root 'table'
|
4
|
+
|
5
|
+
class Row < CapybaraUI::List
|
6
|
+
def self.column(*args, &block)
|
7
|
+
item(*args, &block)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.header_row(selector, &block)
|
12
|
+
widget :header_row, selector, Row, &block
|
13
|
+
end
|
14
|
+
|
15
|
+
header_row 'thead tr' do
|
16
|
+
column 'th'
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.data_row(selector, &block)
|
20
|
+
widget :data_row, selector, Row, &block
|
21
|
+
end
|
22
|
+
|
23
|
+
data_row 'tbody tr' do
|
24
|
+
column 'td'
|
25
|
+
end
|
26
|
+
|
27
|
+
class Columns
|
28
|
+
include Enumerable
|
29
|
+
|
30
|
+
def initialize(parent)
|
31
|
+
@parent = parent
|
32
|
+
end
|
33
|
+
|
34
|
+
def [](header_or_index)
|
35
|
+
case header_or_index
|
36
|
+
when Integer
|
37
|
+
values_by_index(header_or_index)
|
38
|
+
when String
|
39
|
+
values_by_header(header_or_index)
|
40
|
+
else
|
41
|
+
raise TypeError,
|
42
|
+
"can't convert #{header_or_index.inspect} to Integer or String"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def each(&block)
|
47
|
+
parent.each(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
attr_reader :parent
|
53
|
+
|
54
|
+
def values_by_index(index)
|
55
|
+
parent.rows.transpose[index]
|
56
|
+
end
|
57
|
+
|
58
|
+
def values_by_header(header)
|
59
|
+
values_by_index(find_header_index(header))
|
60
|
+
end
|
61
|
+
|
62
|
+
def find_header_index(header)
|
63
|
+
parent.widget(:header_row).value.find_index(header) or
|
64
|
+
raise ArgumentError, "header not found: #{header.inspect}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def columns
|
69
|
+
Columns.new(self)
|
70
|
+
end
|
71
|
+
|
72
|
+
def rows
|
73
|
+
widgets(:data_row).map(&:value)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module CapybaraUI
|
2
|
+
# A text field.
|
3
|
+
class TextField < Field
|
4
|
+
# @!method get
|
5
|
+
# @return The text field value.
|
6
|
+
def_delegator :root, :value, :get
|
7
|
+
|
8
|
+
# @!method set(value)
|
9
|
+
# Sets the text field value.
|
10
|
+
#
|
11
|
+
# @param value [String] the value to set.
|
12
|
+
def_delegator :root, :set
|
13
|
+
|
14
|
+
# @!method to_s
|
15
|
+
# @return the text field value, or the empty string if the field is
|
16
|
+
# empty.
|
17
|
+
def_delegator :get, :to_s
|
18
|
+
|
19
|
+
def to_cell
|
20
|
+
get
|
21
|
+
end
|
22
|
+
|
23
|
+
def content?
|
24
|
+
get.respond_to?(:empty?) ? ! get.empty? : !! get
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,392 @@
|
|
1
|
+
module CapybaraUI
|
2
|
+
class Widget
|
3
|
+
extend Forwardable
|
4
|
+
extend Widgets::DSL
|
5
|
+
|
6
|
+
include WidgetParts::Struct
|
7
|
+
include WidgetParts::Container
|
8
|
+
include CucumberMethods
|
9
|
+
|
10
|
+
class Removed < StandardError; end
|
11
|
+
|
12
|
+
attr_reader :root
|
13
|
+
|
14
|
+
# @!group Widget macros
|
15
|
+
|
16
|
+
# Defines a new action.
|
17
|
+
#
|
18
|
+
# This is a shortcut to help defining a widget and a method that clicks
|
19
|
+
# on that widget. You can then send a widget instance the message given
|
20
|
+
# by +name+.
|
21
|
+
#
|
22
|
+
# You can access the underlying widget by appending "_widget" to the
|
23
|
+
# action name.
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# # Consider the widget will encapsulate the following HTML
|
27
|
+
# #
|
28
|
+
# # <div id="profile">
|
29
|
+
# # <a href="/profiles/1/edit" rel="edit">Edit</a>
|
30
|
+
# # </div>
|
31
|
+
# class PirateProfile < CapybaraUI::Widget
|
32
|
+
# root "#profile"
|
33
|
+
#
|
34
|
+
# # Declare the action
|
35
|
+
# action :edit, '[rel = edit]'
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# pirate_profile = widget(:pirate_profile)
|
39
|
+
#
|
40
|
+
# # Access the action widget
|
41
|
+
# action_widget = pirate_profile.widget(:edit_widget)
|
42
|
+
# action_widget = pirate_profile.edit_widget
|
43
|
+
#
|
44
|
+
# # Click the link
|
45
|
+
# pirate_profile.edit
|
46
|
+
#
|
47
|
+
# @param name the name of the action
|
48
|
+
# @param selector the selector for the widget that will be clicked
|
49
|
+
def self.action(name, selector = nil)
|
50
|
+
block = if selector
|
51
|
+
wname = :"#{name}_widget"
|
52
|
+
|
53
|
+
widget wname, selector
|
54
|
+
|
55
|
+
-> { widget(wname).click; self }
|
56
|
+
else
|
57
|
+
-> { click; self }
|
58
|
+
end
|
59
|
+
|
60
|
+
define_method name, &block
|
61
|
+
end
|
62
|
+
|
63
|
+
# Creates a delegator for one child widget message.
|
64
|
+
#
|
65
|
+
# Since widgets are accessed through {WidgetParts::Container#widget}, we
|
66
|
+
# can't use {Forwardable} to delegate messages to widgets.
|
67
|
+
#
|
68
|
+
# @param name the name of the receiver child widget
|
69
|
+
# @param widget_message the name of the message to be sent to the child widget
|
70
|
+
# @param method_name the name of the delegator. If +nil+ the method will
|
71
|
+
# have the same name as the message it will send.
|
72
|
+
def self.widget_delegator(name, widget_message, method_name = nil)
|
73
|
+
method_name = method_name || widget_message
|
74
|
+
|
75
|
+
class_eval <<-RUBY
|
76
|
+
def #{method_name}(*args)
|
77
|
+
if args.size == 1
|
78
|
+
widget(:#{name}).#{widget_message} args.first
|
79
|
+
else
|
80
|
+
widget(:#{name}).#{widget_message} *args
|
81
|
+
end
|
82
|
+
end
|
83
|
+
RUBY
|
84
|
+
end
|
85
|
+
|
86
|
+
# @!endgroup
|
87
|
+
|
88
|
+
# Finds a single instance of the current widget in +node+.
|
89
|
+
#
|
90
|
+
# @param node the node we want to search in
|
91
|
+
#
|
92
|
+
# @return a new instance of the current widget class.
|
93
|
+
#
|
94
|
+
# @raise [Capybara::ElementNotFoundError] if the widget can't be found
|
95
|
+
def self.find_in(parent, *args)
|
96
|
+
new(filter.node(parent, *args))
|
97
|
+
rescue Capybara::Ambiguous => e
|
98
|
+
raise AmbiguousWidget.new(e.message).
|
99
|
+
tap { |x| x.set_backtrace e.backtrace }
|
100
|
+
rescue Capybara::ElementNotFound => e
|
101
|
+
raise MissingWidget.new(e.message).
|
102
|
+
tap { |x| x.set_backtrace e.backtrace }
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.find_all_in(parent, *args)
|
106
|
+
filter.nodes(parent, *args).map { |e| new(e) }
|
107
|
+
end
|
108
|
+
|
109
|
+
# Determines if an instance of this widget class exists in
|
110
|
+
# +parent_node+.
|
111
|
+
#
|
112
|
+
# @param parent_node [Capybara::Node] the node we want to search in
|
113
|
+
#
|
114
|
+
# @return +true+ if a widget instance is found, +false+ otherwise.
|
115
|
+
def self.present_in?(parent, *args)
|
116
|
+
filter.node?(parent, *args)
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.not_present_in?(parent, *args)
|
120
|
+
filter.nodeless?(parent, *args)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Sets this widget's default selector.
|
124
|
+
#
|
125
|
+
# You can pass more than one argument to it, or a single Array. Any valid
|
126
|
+
# Capybara selector accepted by Capybara::Node::Finders#find will work.
|
127
|
+
#
|
128
|
+
# === Examples
|
129
|
+
#
|
130
|
+
# Most of the time, your selectors will be Strings:
|
131
|
+
#
|
132
|
+
# class MyWidget < CapybaraUI::Widget
|
133
|
+
# root '.selector'
|
134
|
+
# end
|
135
|
+
#
|
136
|
+
# This will match any element with a class of "selector". For example:
|
137
|
+
#
|
138
|
+
# <span class="selector">Pick me!</span>
|
139
|
+
#
|
140
|
+
# ==== Composite selectors
|
141
|
+
#
|
142
|
+
# If you're using CSS as the query language, it's useful to be able to use
|
143
|
+
# +text: 'Some text'+ to zero in on a specific node:
|
144
|
+
#
|
145
|
+
# class MySpecificWidget < CapybaraUI::Widget
|
146
|
+
# root '.selector', text: 'Pick me!'
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# This is especially useful, e.g., when you want to create a widget
|
150
|
+
# to match a specific error or notification:
|
151
|
+
#
|
152
|
+
# class NoFreeSpace < CapybaraUI::Widget
|
153
|
+
# root '.error', text: 'No free space left!'
|
154
|
+
# end
|
155
|
+
#
|
156
|
+
# So, given the following HTML:
|
157
|
+
#
|
158
|
+
# <body>
|
159
|
+
# <div class="error">No free space left!</div>
|
160
|
+
#
|
161
|
+
# <!-- ... -->
|
162
|
+
# </body>
|
163
|
+
#
|
164
|
+
# You can test for the error's present using the following code:
|
165
|
+
#
|
166
|
+
# document.visible?(:no_free_space) #=> true
|
167
|
+
#
|
168
|
+
# Note: When you want to match text, consider using +I18n.t+ instead of
|
169
|
+
# hard-coding the text, so that your tests don't break when the text changes.
|
170
|
+
#
|
171
|
+
# Finally, you may want to override the query language:
|
172
|
+
#
|
173
|
+
# class MyWidgetUsesXPath < CapybaraUI::Widget
|
174
|
+
# root :xpath, '//some/node'
|
175
|
+
# end
|
176
|
+
def self.root(*selector, &block)
|
177
|
+
@filter = NodeFilter.new(block || selector)
|
178
|
+
end
|
179
|
+
|
180
|
+
class MissingSelector < StandardError
|
181
|
+
end
|
182
|
+
|
183
|
+
def self.filter
|
184
|
+
@filter || superclass.filter
|
185
|
+
rescue NoMethodError
|
186
|
+
raise MissingSelector, 'no selector defined'
|
187
|
+
end
|
188
|
+
|
189
|
+
def self.filter?
|
190
|
+
filter rescue false
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.selector
|
194
|
+
filter.selector
|
195
|
+
end
|
196
|
+
|
197
|
+
def initialize(root)
|
198
|
+
@root = root
|
199
|
+
end
|
200
|
+
|
201
|
+
# Clicks the current widget, or the child widget given by +name+.
|
202
|
+
#
|
203
|
+
# === Usage
|
204
|
+
#
|
205
|
+
# Given the following widget definition:
|
206
|
+
#
|
207
|
+
# class Container < CapybaraUI::Widget
|
208
|
+
# root '#container'
|
209
|
+
#
|
210
|
+
# widget :link, 'a'
|
211
|
+
# end
|
212
|
+
#
|
213
|
+
# Send +click+ with no arguments to trigger a +click+ event on +#container+.
|
214
|
+
#
|
215
|
+
# widget(:container).click
|
216
|
+
#
|
217
|
+
# This is the equivalent of doing the following using Capybara:
|
218
|
+
#
|
219
|
+
# find('#container').click
|
220
|
+
#
|
221
|
+
# Send +click :link+ to trigger a +click+ event on +a+:
|
222
|
+
#
|
223
|
+
# widget(:container).click :link
|
224
|
+
#
|
225
|
+
# This is the equivalent of doing the following using Capybara:
|
226
|
+
#
|
227
|
+
# find('#container a').click
|
228
|
+
def click(*args)
|
229
|
+
if args.empty?
|
230
|
+
root.click
|
231
|
+
else
|
232
|
+
widget(*args).click
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# Hovers over the current widget, or the child widget given by +name+.
|
237
|
+
#
|
238
|
+
# === Usage
|
239
|
+
#
|
240
|
+
# Given the following widget definition:
|
241
|
+
#
|
242
|
+
# class Container < CapybaraUI::Widget
|
243
|
+
# root '#container'
|
244
|
+
#
|
245
|
+
# widget :link, 'a'
|
246
|
+
# end
|
247
|
+
#
|
248
|
+
# Send +hover+ with no arguments to trigger a +hover+ event on +#container+.
|
249
|
+
#
|
250
|
+
# widget(:container).hover
|
251
|
+
#
|
252
|
+
# This is the equivalent of doing the following using Capybara:
|
253
|
+
#
|
254
|
+
# find('#container').hover
|
255
|
+
#
|
256
|
+
# Send +hover :link+ to trigger a +hover+ event on +a+:
|
257
|
+
#
|
258
|
+
# widget(:container).hover :link
|
259
|
+
#
|
260
|
+
# This is the equivalent of doing the following using Capybara:
|
261
|
+
#
|
262
|
+
# find('#container a').hover
|
263
|
+
def hover(*args)
|
264
|
+
if args.empty?
|
265
|
+
root.hover
|
266
|
+
else
|
267
|
+
widget(*args).hover
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Double clicks the current widget, or the child widget given by +name+.
|
272
|
+
#
|
273
|
+
# === Usage
|
274
|
+
#
|
275
|
+
# Given the following widget definition:
|
276
|
+
#
|
277
|
+
# class Container < CapybaraUI::Widget
|
278
|
+
# root '#container'
|
279
|
+
#
|
280
|
+
# widget :link, 'a'
|
281
|
+
# end
|
282
|
+
#
|
283
|
+
# Send +double_click+ with no arguments to trigger an +ondblclick+ event on +#container+.
|
284
|
+
#
|
285
|
+
# widget(:container).double_click
|
286
|
+
#
|
287
|
+
# This is the equivalent of doing the following using Capybara:
|
288
|
+
#
|
289
|
+
# find('#container').double_click
|
290
|
+
def double_click(*args)
|
291
|
+
if args.empty?
|
292
|
+
root.double_click
|
293
|
+
else
|
294
|
+
widget(*args).double_click
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# Right clicks the current widget, or the child widget given by +name+.
|
299
|
+
#
|
300
|
+
# === Usage
|
301
|
+
#
|
302
|
+
# Given the following widget definition:
|
303
|
+
#
|
304
|
+
# class Container < CapybaraUI::Widget
|
305
|
+
# root '#container'
|
306
|
+
#
|
307
|
+
# widget :link, 'a'
|
308
|
+
# end
|
309
|
+
#
|
310
|
+
# Send +right_click+ with no arguments to trigger an +oncontextmenu+ event on +#container+.
|
311
|
+
#
|
312
|
+
# widget(:container).right_click
|
313
|
+
#
|
314
|
+
# This is the equivalent of doing the following using Capybara:
|
315
|
+
#
|
316
|
+
# find('#container').right_click
|
317
|
+
def right_click(*args)
|
318
|
+
if args.empty?
|
319
|
+
root.right_click
|
320
|
+
else
|
321
|
+
widget(*args).right_click
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Determines if the widget underlying an action exists.
|
326
|
+
#
|
327
|
+
# @param name the name of the action
|
328
|
+
#
|
329
|
+
# @raise Missing if an action with +name+ can't be found.
|
330
|
+
#
|
331
|
+
# @return [Boolean] +true+ if the action widget is found, +false+
|
332
|
+
# otherwise.
|
333
|
+
def has_action?(name)
|
334
|
+
raise Missing, "couldn't find `#{name}' action" unless respond_to?(name)
|
335
|
+
|
336
|
+
visible?(:"#{name}_widget")
|
337
|
+
end
|
338
|
+
|
339
|
+
def id
|
340
|
+
root['id']
|
341
|
+
end
|
342
|
+
|
343
|
+
def classes
|
344
|
+
root['class'].split
|
345
|
+
end
|
346
|
+
|
347
|
+
# Determines if the widget has a specific class
|
348
|
+
#
|
349
|
+
# @param name the name of the class
|
350
|
+
#
|
351
|
+
# @return [Boolean] +true+ if the class is found, +false+ otherwise
|
352
|
+
def class?(name)
|
353
|
+
classes.include?(name)
|
354
|
+
end
|
355
|
+
|
356
|
+
def html
|
357
|
+
xml = Nokogiri::HTML(page.body).at(root.path).to_xml
|
358
|
+
|
359
|
+
Nokogiri::XML(xml, &:noblanks).to_xhtml.gsub("\n", "")
|
360
|
+
end
|
361
|
+
|
362
|
+
def text
|
363
|
+
StringValue.new(root.text.strip)
|
364
|
+
end
|
365
|
+
|
366
|
+
# Converts this widget into a string representation suitable to be displayed
|
367
|
+
# in a Cucumber table cell. By default calls #text.
|
368
|
+
#
|
369
|
+
# This method will be called by methods that build tables or rows (usually
|
370
|
+
# #to_table or #to_row) so, in general, you won't call it directly, but feel
|
371
|
+
# free to override it when needed.
|
372
|
+
#
|
373
|
+
# Returns a String.
|
374
|
+
def to_cell
|
375
|
+
text
|
376
|
+
end
|
377
|
+
|
378
|
+
def to_s
|
379
|
+
text
|
380
|
+
end
|
381
|
+
|
382
|
+
def value
|
383
|
+
text
|
384
|
+
end
|
385
|
+
|
386
|
+
private
|
387
|
+
|
388
|
+
def page
|
389
|
+
Capybara.current_session
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|