Class: Dill::Widget
- Inherits:
-
Object
- Object
- Dill::Widget
- Extended by:
- Dill::Widgets::DSL, Forwardable
- Defined in:
- lib/dill/widgets/widget.rb,
lib/dill/widgets/widget/node_filter.rb
Direct Known Subclasses
AutoTable::Row, BaseTable, Field, FieldGroup, List, ListItem
Defined Under Namespace
Classes: MissingSelector, NodeFilter, Removed
Widget macros collapse
-
.action(name, selector = nil) ⇒ Object
Defines a new action.
-
.widget_delegator(name, widget_message, method_name = nil) ⇒ Object
Creates a delegator for one child widget message.
Class Method Summary collapse
- .filter ⇒ Object
- .filter? ⇒ Boolean
- .find_all_in(parent, *args) ⇒ Object
-
.find_in(parent, *args) ⇒ Object
Finds a single instance of the current widget in
node
. -
.present_in?(parent) ⇒ Boolean
Determines if an instance of this widget class exists in
parent_node
. -
.root(*selector, &block) ⇒ Object
Sets this widget’s default selector.
- .selector ⇒ Object
Instance Method Summary collapse
-
#absent? ⇒ Boolean
Alias for #gone?.
- #classes ⇒ Object
-
#click(*args) ⇒ Object
Clicks the current widget, or the child widget given by
name
. -
#diff(table, wait_time = Capybara.default_wait_time) ⇒ Object
Compares this widget with the given Cucumber
table
. -
#gone? ⇒ Boolean
Returns
true
if the widget is not visible, or has been removed from the DOM. -
#has_action?(name) ⇒ Boolean
Determines if the widget underlying an action exists.
- #id ⇒ Object
-
#initialize(node) ⇒ Widget
constructor
A new instance of Widget.
- #inspect ⇒ Object
-
#present? ⇒ Boolean
Returns
true
if widget is visible. - #root ⇒ Object
- #text ⇒ Object
-
#to_cell ⇒ Object
Converts this widget into a string representation suitable to be displayed in a Cucumber table cell.
- #to_s ⇒ Object
- #value ⇒ Object
Methods included from Dill::Widgets::DSL
Methods included from Dill::WidgetParts::Container
#has_no_widget?, #has_widget?, #widget, #widgets
Methods included from Dill::WidgetParts::Struct
Constructor Details
#initialize(node) ⇒ Widget
Returns a new instance of Widget.
184 185 186 |
# File 'lib/dill/widgets/widget.rb', line 184 def initialize(node) self.query = node.respond_to?(:call) ? node : -> { node } end |
Class Method Details
.action(name, selector = nil) ⇒ Object
Defines a new action.
This is a shortcut to help defining a widget and a method that clicks on that widget. You can then send a widget instance the message given by name
.
You can access the underlying widget by appending “_widget” to the action name.
46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/dill/widgets/widget.rb', line 46 def self.action(name, selector = nil) block = if selector wname = :"#{name}_widget" wname, selector -> { (wname).click; self } else -> { click; self } end define_method name, &block end |
.filter ⇒ Object
170 171 172 173 174 |
# File 'lib/dill/widgets/widget.rb', line 170 def self.filter @filter || superclass.filter rescue NoMethodError raise MissingSelector, 'no selector defined' end |
.filter? ⇒ Boolean
176 177 178 |
# File 'lib/dill/widgets/widget.rb', line 176 def self.filter? filter rescue false end |
.find_all_in(parent, *args) ⇒ Object
96 97 98 |
# File 'lib/dill/widgets/widget.rb', line 96 def self.find_all_in(parent, *args) filter.nodes(parent, *args).map { |e| new(e) } end |
.find_in(parent, *args) ⇒ Object
Finds a single instance of the current widget in node
.
92 93 94 |
# File 'lib/dill/widgets/widget.rb', line 92 def self.find_in(parent, *args) new(filter.query(parent, *args)) end |
.present_in?(parent) ⇒ Boolean
Determines if an instance of this widget class exists in parent_node
.
106 107 108 |
# File 'lib/dill/widgets/widget.rb', line 106 def self.present_in?(parent) find_in(parent).present? end |
.root(*selector, &block) ⇒ Object
Sets this widget’s default selector.
You can pass more than one argument to it, or a single Array. Any valid Capybara selector accepted by Capybara::Node::Finders#find will work.
Examples
Most of the time, your selectors will be Strings:
class MyWidget < Dill::Widget
root '.selector'
end
This will match any element with a class of “selector”. For example:
Pick me!
Composite selectors
If you’re using CSS as the query language, it’s useful to be able to use text: ‘Some text’ to zero in on a specific node:
class MySpecificWidget < Dill::Widget
root '.selector', text: 'Pick me!'
end
This is especially useful, e.g., when you want to create a widget to match a specific error or notification:
class NoFreeSpace < Dill::Widget
root '.error', text: 'No free space left!'
end
So, given the following HTML:
<body>
<div class="error">No free space left!</div>
<!-- ... -->
</body>
You can test for the error’s present using the following code:
document.(:no_free_space) #=> true
Note: When you want to match text, consider using I18n.t
instead of hard-coding the text, so that your tests don’t break when the text changes.
Finally, you may want to override the query language:
class MyWidgetUsesXPath < Dill::Widget
root :xpath, '//some/node'
end
163 164 165 |
# File 'lib/dill/widgets/widget.rb', line 163 def self.root(*selector, &block) @filter = NodeFilter.new(block || selector) end |
.selector ⇒ Object
180 181 182 |
# File 'lib/dill/widgets/widget.rb', line 180 def self.selector filter.selector end |
.widget_delegator(name, widget_message, method_name = nil) ⇒ Object
Creates a delegator for one child widget message.
Since widgets are accessed through Dill::WidgetParts::Container#widget, we can’t use Forwardable to delegate messages to widgets.
69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/dill/widgets/widget.rb', line 69 def self.(name, , method_name = nil) method_name = method_name || class_eval <<-RUBY def #{method_name}(*args) if args.size == 1 widget(:#{name}).#{} args.first else widget(:#{name}).#{} *args end end RUBY end |
Instance Method Details
#absent? ⇒ Boolean
Alias for #gone?
189 190 191 |
# File 'lib/dill/widgets/widget.rb', line 189 def absent? gone? end |
#classes ⇒ Object
263 264 265 |
# File 'lib/dill/widgets/widget.rb', line 263 def classes root['class'].split end |
#click(*args) ⇒ Object
Clicks the current widget, or the child widget given by name
.
Usage
Given the following widget definition:
class Container < Dill::Widget
root '#container'
:link, 'a'
end
Send click
with no arguments to trigger a click
event on #container
.
(:container).click
This is the equivalent of doing the following using Capybara:
find('#container').click
Send click :link to trigger a click
event on a
:
(:container).click :link
This is the equivalent of doing the following using Capybara:
find('#container a').click
220 221 222 223 224 225 226 |
# File 'lib/dill/widgets/widget.rb', line 220 def click(*args) if args.empty? root.click else (*args).click end end |
#diff(table, wait_time = Capybara.default_wait_time) ⇒ Object
Compares this widget with the given Cucumber table
.
Example
Then(/^some step that takes in a cucumber table$/) do |table|
(:my_widget).diff table
end
235 236 237 |
# File 'lib/dill/widgets/widget.rb', line 235 def diff(table, wait_time = Capybara.default_wait_time) table.diff!(to_table) || true end |
#gone? ⇒ Boolean
Returns true
if the widget is not visible, or has been removed from the DOM.
241 242 243 |
# File 'lib/dill/widgets/widget.rb', line 241 def gone? ! root rescue true end |
#has_action?(name) ⇒ Boolean
Determines if the widget underlying an action exists.
253 254 255 256 257 |
# File 'lib/dill/widgets/widget.rb', line 253 def has_action?(name) raise Missing, "couldn't find `#{name}' action" unless respond_to?(name) (:"#{name}_widget") end |
#id ⇒ Object
259 260 261 |
# File 'lib/dill/widgets/widget.rb', line 259 def id root['id'] end |
#inspect ⇒ Object
267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/dill/widgets/widget.rb', line 267 def inspect inspection = "<!-- #{self.class.name}: -->\n" begin root = self.root xml = Nokogiri::HTML(page.body).at(root.path).to_xml inspection << Nokogiri::XML(xml, &:noblanks).to_xhtml rescue Capybara::NotSupportedByDriverError inspection << "<#{root.tag_name}>\n#{to_s}" rescue Dill::MissingWidget, *page.driver.invalid_element_errors "#<DETACHED>" end end |
#present? ⇒ Boolean
Returns true
if widget is visible.
283 284 285 |
# File 'lib/dill/widgets/widget.rb', line 283 def present? !! root rescue false end |
#root ⇒ Object
287 288 289 290 291 292 293 |
# File 'lib/dill/widgets/widget.rb', line 287 def root query.() rescue Capybara::Ambiguous => e raise wrap_exception(e, AmbiguousWidget) rescue Capybara::ElementNotFound => e raise wrap_exception(e, MissingWidget) end |
#text ⇒ Object
295 296 297 |
# File 'lib/dill/widgets/widget.rb', line 295 def text root.text.strip end |
#to_cell ⇒ Object
Converts this widget into a string representation suitable to be displayed in a Cucumber table cell. By default calls #text.
This method will be called by methods that build tables or rows (usually #to_table or #to_row) so, in general, you won’t call it directly, but feel free to override it when needed.
Returns a String.
307 308 309 |
# File 'lib/dill/widgets/widget.rb', line 307 def to_cell text end |
#to_s ⇒ Object
311 312 313 |
# File 'lib/dill/widgets/widget.rb', line 311 def to_s text end |
#value ⇒ Object
315 316 317 |
# File 'lib/dill/widgets/widget.rb', line 315 def value text end |