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
Field, FieldGroup, List, ListItem, Table
Defined Under Namespace
Classes: MissingSelector, NodeFilter, Removed
Constant Summary
Constants included from Dill
Instance Attribute Summary collapse
-
#root ⇒ Object
readonly
Returns the value of attribute root.
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
. - .not_present_in?(parent, *args) ⇒ Boolean
-
.present_in?(parent, *args) ⇒ 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
-
#class?(name) ⇒ Boolean
Determines if the widget has a specific class.
- #classes ⇒ Object
-
#click(*args) ⇒ Object
Clicks the current widget, or the child widget given by
name
. -
#has_action?(name) ⇒ Boolean
Determines if the widget underlying an action exists.
-
#hover(*args) ⇒ Object
Hovers over the current widget, or the child widget given by
name
. - #html ⇒ Object
- #id ⇒ Object
-
#initialize(root) ⇒ Widget
constructor
A new instance of Widget.
- #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_widget?, #not_visible?, #visible?, #widget, #widgets
Methods included from Dill
Methods included from Constructors
Methods included from Dill::WidgetParts::Struct
Constructor Details
Instance Attribute Details
#root ⇒ Object (readonly)
Returns the value of attribute root.
12 13 14 |
# File 'lib/dill/widgets/widget.rb', line 12 def root @root 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.
49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/dill/widgets/widget.rb', line 49 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
183 184 185 186 187 |
# File 'lib/dill/widgets/widget.rb', line 183 def self.filter @filter || superclass.filter rescue NoMethodError raise MissingSelector, 'no selector defined' end |
.filter? ⇒ Boolean
189 190 191 |
# File 'lib/dill/widgets/widget.rb', line 189 def self.filter? filter rescue false end |
.find_all_in(parent, *args) ⇒ Object
105 106 107 |
# File 'lib/dill/widgets/widget.rb', line 105 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
.
95 96 97 98 99 100 101 102 103 |
# File 'lib/dill/widgets/widget.rb', line 95 def self.find_in(parent, *args) new(filter.node(parent, *args)) rescue Capybara::Ambiguous => e raise AmbiguousWidget.new(e.). tap { |x| x.set_backtrace e.backtrace } rescue Capybara::ElementNotFound => e raise MissingWidget.new(e.). tap { |x| x.set_backtrace e.backtrace } end |
.not_present_in?(parent, *args) ⇒ Boolean
119 120 121 |
# File 'lib/dill/widgets/widget.rb', line 119 def self.not_present_in?(parent, *args) filter.nodeless?(parent, *args) end |
.present_in?(parent, *args) ⇒ Boolean
Determines if an instance of this widget class exists in parent_node
.
115 116 117 |
# File 'lib/dill/widgets/widget.rb', line 115 def self.present_in?(parent, *args) filter.node?(parent, *args) 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.visible?(: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
176 177 178 |
# File 'lib/dill/widgets/widget.rb', line 176 def self.root(*selector, &block) @filter = NodeFilter.new(block || selector) end |
.selector ⇒ Object
193 194 195 |
# File 'lib/dill/widgets/widget.rb', line 193 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.
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/dill/widgets/widget.rb', line 72 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
#class?(name) ⇒ Boolean
Determines if the widget has a specific class
298 299 300 |
# File 'lib/dill/widgets/widget.rb', line 298 def class?(name) classes.include?(name) end |
#classes ⇒ Object
289 290 291 |
# File 'lib/dill/widgets/widget.rb', line 289 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
228 229 230 231 232 233 234 |
# File 'lib/dill/widgets/widget.rb', line 228 def click(*args) if args.empty? root.click else (*args).click end end |
#has_action?(name) ⇒ Boolean
Determines if the widget underlying an action exists.
279 280 281 282 283 |
# File 'lib/dill/widgets/widget.rb', line 279 def has_action?(name) raise Missing, "couldn't find `#{name}' action" unless respond_to?(name) visible?(:"#{name}_widget") end |
#hover(*args) ⇒ Object
Hovers over 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 hover
with no arguments to trigger a hover
event on #container
.
(:container).hover
This is the equivalent of doing the following using Capybara:
find('#container').hover
Send hover :link to trigger a hover
event on a
:
(:container).hover :link
This is the equivalent of doing the following using Capybara:
find('#container a').hover
263 264 265 266 267 268 269 |
# File 'lib/dill/widgets/widget.rb', line 263 def hover(*args) if args.empty? root.hover else (*args).hover end end |
#html ⇒ Object
302 303 304 305 306 |
# File 'lib/dill/widgets/widget.rb', line 302 def html xml = Nokogiri::HTML(page.body).at(root.path).to_xml Nokogiri::XML(xml, &:noblanks).to_xhtml.gsub("\n", "") end |
#id ⇒ Object
285 286 287 |
# File 'lib/dill/widgets/widget.rb', line 285 def id root['id'] end |
#text ⇒ Object
308 309 310 |
# File 'lib/dill/widgets/widget.rb', line 308 def text StringValue.new(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.
320 321 322 |
# File 'lib/dill/widgets/widget.rb', line 320 def to_cell text end |
#to_s ⇒ Object
324 325 326 |
# File 'lib/dill/widgets/widget.rb', line 324 def to_s text end |
#value ⇒ Object
328 329 330 |
# File 'lib/dill/widgets/widget.rb', line 328 def value text end |