capybara-ui 0.10.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/lib/capybara/ui.rb +33 -0
  3. data/lib/capybara/ui/assertions.rb +21 -0
  4. data/lib/{capybara-ui → capybara/ui}/capybara.rb +0 -0
  5. data/lib/capybara/ui/checkpoint.rb +113 -0
  6. data/lib/capybara/ui/conversions.rb +33 -0
  7. data/lib/capybara/ui/cucumber.rb +5 -0
  8. data/lib/capybara/ui/dsl.rb +109 -0
  9. data/lib/capybara/ui/instance_conversions.rb +21 -0
  10. data/lib/{capybara-ui → capybara/ui}/matchers.rb +4 -4
  11. data/lib/capybara/ui/optional_dependencies.rb +7 -0
  12. data/lib/capybara/ui/rails.rb +5 -0
  13. data/lib/capybara/ui/rails/role.rb +11 -0
  14. data/lib/capybara/ui/role.rb +21 -0
  15. data/lib/capybara/ui/text_table.rb +109 -0
  16. data/lib/capybara/ui/text_table/cell_text.rb +9 -0
  17. data/lib/capybara/ui/text_table/mapping.rb +42 -0
  18. data/lib/capybara/ui/text_table/transformations.rb +15 -0
  19. data/lib/capybara/ui/text_table/void_mapping.rb +10 -0
  20. data/lib/capybara/ui/version.rb +5 -0
  21. data/lib/capybara/ui/widgets.rb +63 -0
  22. data/lib/capybara/ui/widgets/check_box.rb +28 -0
  23. data/lib/capybara/ui/widgets/cucumber_methods.rb +75 -0
  24. data/lib/capybara/ui/widgets/document.rb +21 -0
  25. data/lib/capybara/ui/widgets/dsl.rb +49 -0
  26. data/lib/capybara/ui/widgets/field.rb +24 -0
  27. data/lib/capybara/ui/widgets/field_group.rb +331 -0
  28. data/lib/capybara/ui/widgets/form.rb +28 -0
  29. data/lib/capybara/ui/widgets/list.rb +202 -0
  30. data/lib/capybara/ui/widgets/list_item.rb +24 -0
  31. data/lib/capybara/ui/widgets/parts/container.rb +48 -0
  32. data/lib/capybara/ui/widgets/parts/struct.rb +119 -0
  33. data/lib/capybara/ui/widgets/radio_button.rb +64 -0
  34. data/lib/capybara/ui/widgets/select.rb +59 -0
  35. data/lib/capybara/ui/widgets/string_value.rb +45 -0
  36. data/lib/capybara/ui/widgets/table.rb +78 -0
  37. data/lib/capybara/ui/widgets/text_field.rb +29 -0
  38. data/lib/capybara/ui/widgets/widget.rb +394 -0
  39. data/lib/capybara/ui/widgets/widget/node_filter.rb +50 -0
  40. data/lib/capybara/ui/widgets/widget_class.rb +13 -0
  41. data/lib/capybara/ui/widgets/widget_name.rb +58 -0
  42. metadata +47 -43
  43. data/lib/capybara-ui.rb +0 -31
  44. data/lib/capybara-ui/assertions.rb +0 -19
  45. data/lib/capybara-ui/checkpoint.rb +0 -111
  46. data/lib/capybara-ui/conversions.rb +0 -31
  47. data/lib/capybara-ui/cucumber.rb +0 -5
  48. data/lib/capybara-ui/dsl.rb +0 -107
  49. data/lib/capybara-ui/instance_conversions.rb +0 -19
  50. data/lib/capybara-ui/optional_dependencies.rb +0 -5
  51. data/lib/capybara-ui/rails.rb +0 -5
  52. data/lib/capybara-ui/rails/role.rb +0 -9
  53. data/lib/capybara-ui/role.rb +0 -19
  54. data/lib/capybara-ui/text_table.rb +0 -107
  55. data/lib/capybara-ui/text_table/cell_text.rb +0 -7
  56. data/lib/capybara-ui/text_table/mapping.rb +0 -40
  57. data/lib/capybara-ui/text_table/transformations.rb +0 -13
  58. data/lib/capybara-ui/text_table/void_mapping.rb +0 -8
  59. data/lib/capybara-ui/version.rb +0 -3
  60. data/lib/capybara-ui/widgets.rb +0 -61
  61. data/lib/capybara-ui/widgets/check_box.rb +0 -26
  62. data/lib/capybara-ui/widgets/cucumber_methods.rb +0 -73
  63. data/lib/capybara-ui/widgets/document.rb +0 -19
  64. data/lib/capybara-ui/widgets/dsl.rb +0 -47
  65. data/lib/capybara-ui/widgets/field.rb +0 -22
  66. data/lib/capybara-ui/widgets/field_group.rb +0 -329
  67. data/lib/capybara-ui/widgets/form.rb +0 -26
  68. data/lib/capybara-ui/widgets/list.rb +0 -200
  69. data/lib/capybara-ui/widgets/list_item.rb +0 -22
  70. data/lib/capybara-ui/widgets/parts/container.rb +0 -46
  71. data/lib/capybara-ui/widgets/parts/struct.rb +0 -117
  72. data/lib/capybara-ui/widgets/radio_button.rb +0 -62
  73. data/lib/capybara-ui/widgets/select.rb +0 -57
  74. data/lib/capybara-ui/widgets/string_value.rb +0 -43
  75. data/lib/capybara-ui/widgets/table.rb +0 -76
  76. data/lib/capybara-ui/widgets/text_field.rb +0 -27
  77. data/lib/capybara-ui/widgets/widget.rb +0 -392
  78. data/lib/capybara-ui/widgets/widget/node_filter.rb +0 -48
  79. data/lib/capybara-ui/widgets/widget_class.rb +0 -11
  80. data/lib/capybara-ui/widgets/widget_name.rb +0 -56
@@ -0,0 +1,28 @@
1
+ module Capybara
2
+ module UI
3
+ class Form < FieldGroup
4
+ root 'form'
5
+
6
+ action :submit, '[type = submit]'
7
+
8
+ # Submit form with +attributes+.
9
+ #
10
+ # @param attributes [Hash] the form fields and their values
11
+ #
12
+ # @return the current widget
13
+ def submit_with(attributes)
14
+ set attributes
15
+ submit
16
+ end
17
+
18
+ def to_table
19
+ info = self.
20
+ class.
21
+ field_names.
22
+ each_with_object({}) { |e, a| a[e.to_s] = widget(e).to_cell }
23
+
24
+ [info]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,202 @@
1
+ module Capybara
2
+ module UI
3
+ # Use a List when you want to treat repeating elements as a unit.
4
+ #
5
+ # === Usage
6
+ #
7
+ # Consider the following HTML:
8
+ #
9
+ # <ul id="colors">
10
+ # <li>Red <span class="pt">Vermelho</span></li>
11
+ # <li>Green <span class="pt">Verde</span></li>
12
+ # <li>Blue <span class="pt">Azul</span></li>
13
+ # </ul>
14
+ #
15
+ # You can then define the following widget:
16
+ #
17
+ # class Colors < Capybara::UI::List
18
+ # root '#colors'
19
+ # item 'li'
20
+ # end
21
+ #
22
+ # Now you'll be able to iterate over each item:
23
+ #
24
+ # # prints:
25
+ # # Red Vermelho
26
+ # # Green Verde
27
+ # # Blue Azul
28
+ # widget(:colors).each do |e|
29
+ # puts e
30
+ # end
31
+ #
32
+ # This is the same as doing the following in Capybara:
33
+ #
34
+ # all('#colors li').each do |e|
35
+ # puts e.text.strip
36
+ # end
37
+ #
38
+ # Note that, by default, the root selector of a List is +ul+ and the list
39
+ # item selector is +li+. So you could wrap the +<ul>+ above simply by using
40
+ # the following:
41
+ #
42
+ # class Colors < Capybara::UI::List
43
+ # end
44
+ #
45
+ # ==== Narrowing items
46
+ #
47
+ # You can define the root selector for your list items using the ::item macro:
48
+ #
49
+ # class PortugueseColors < Capybara::UI::List
50
+ # root '#colors
51
+ # item '.pt'
52
+ # end
53
+ #
54
+ # If you iterate over this list you get the following:
55
+ #
56
+ # # prints:
57
+ # # Vermelho
58
+ # # Verde
59
+ # # Azul
60
+ # widget(:portuguese_colors).each do |e|
61
+ # puts e
62
+ # end
63
+ #
64
+ # You can make a list out of any repeating elements, as long as you can define
65
+ # parent and child selectors.
66
+ #
67
+ # <div id="not-a-list-colors">
68
+ # <div class="child">Red</div>
69
+ # <div class="child">Green</div>
70
+ # <div class="child">Blue</div>
71
+ # </div>
72
+ #
73
+ # You can define the following widget:
74
+ #
75
+ # class NotAListColors < Capybara::UI::List
76
+ # root '#not-a-list-colors'
77
+ # item '.child'
78
+ # end
79
+ class List < Widget
80
+ include Enumerable
81
+
82
+ def_delegators :items, :each, :first, :last
83
+
84
+ root 'ul' unless filter?
85
+
86
+ class << self
87
+ # Configures the List item selector and class.
88
+ #
89
+ # === Usage
90
+ #
91
+ # Given the following HTML:
92
+ #
93
+ # <ul>
94
+ # <li>One</li>
95
+ # <li>Two</li>
96
+ # <li>Three</li>
97
+ # </ul>
98
+ #
99
+ # In its most basic form, allows you to configure the list item selector,
100
+ # using the default list item class (Capybara::UI::ListItem):
101
+ #
102
+ # class Numbers < Capybara::UI::List
103
+ # root 'ul'
104
+ # item 'li'
105
+ # end
106
+ #
107
+ # ==== Extending the list item class
108
+ #
109
+ # You can define the list item class for the current List:
110
+ #
111
+ # class Number < Capybara::UI::Widget
112
+ # # ...
113
+ # end
114
+ #
115
+ # class Numbers < Capybara::UI::List
116
+ # root 'ul'
117
+ # item 'li', Number
118
+ # end
119
+ #
120
+ # widget(:numbers).first.class < Number #=> true
121
+ #
122
+ # Alternatively, you can extend the list item type inline. This is useful
123
+ # when you want to add small extensions to the default list item class.
124
+ # The extensions will apply only to list items of the current List.
125
+ #
126
+ # class Numbers < Capybara::UI::List
127
+ # root 'ul'
128
+ #
129
+ # item 'li' do
130
+ # def upcase
131
+ # text.upcase
132
+ # end
133
+ # end
134
+ #
135
+ # widget(:numbers).first.upcase #=> "ONE"
136
+ # end
137
+ def item(selector, type = ListItem, &block)
138
+ self.item_factory = WidgetClass.new(selector, type, &block)
139
+ end
140
+
141
+ attr_writer :item_factory
142
+
143
+ def item_factory
144
+ @item_factory ||= WidgetClass.new('li', ListItem)
145
+ end
146
+ end
147
+
148
+ def count
149
+ items.count
150
+ end
151
+
152
+ # TODO: Convert value to primitive data structures.
153
+ def empty?
154
+ items.empty?
155
+ end
156
+
157
+ def exclude?(element)
158
+ ! include?(element)
159
+ end
160
+
161
+ def include?(element)
162
+ value.include?(element)
163
+ end
164
+
165
+ def length
166
+ items.length
167
+ end
168
+
169
+ def size
170
+ items.size
171
+ end
172
+
173
+ def to_row
174
+ items.map(&:to_cell)
175
+ end
176
+
177
+ def to_table
178
+ items.map(&:to_row)
179
+ end
180
+
181
+ def value
182
+ items.map(&:value)
183
+ end
184
+
185
+ protected
186
+
187
+ def_delegator 'self.class', :item_factory
188
+
189
+ def item_for(node)
190
+ item_factory.new(node)
191
+ end
192
+
193
+ def item_filter
194
+ item_factory.filter
195
+ end
196
+
197
+ def items
198
+ item_filter.nodes(self).map { |node| item_for(node) }
199
+ end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,24 @@
1
+ module Capybara
2
+ module UI
3
+ class ListItem < Widget
4
+ # Returns this ListItem's contents formatted as a row, for comparison with a
5
+ # Cucumber::Ast::Table. By default, it simply returns an array with a single
6
+ # element--the widget's text.
7
+ #
8
+ # In general, this method will be called by List#to_table.
9
+ #
10
+ # === Overriding
11
+ #
12
+ # Feel free to override this method to return whatever you need it to.
13
+ # Usually, if the default return value isn't what you want, you'll probably
14
+ # want to return a Hash where both keys and values are strings, so that you
15
+ # don't need to worry about column order when you pass the table to
16
+ # Cucumber::Ast::Table#diff!.
17
+ #
18
+ # See List#to_table for more information.
19
+ def to_row
20
+ [to_cell]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,48 @@
1
+ module Capybara
2
+ module UI
3
+ module WidgetParts
4
+ module Container
5
+ include Capybara::UI
6
+
7
+ def has_widget?(name, *args)
8
+ deprecate('has_widget? and its alias widget?', 'visible?')
9
+ widget_class(name).present_in?(self, *args)
10
+ end
11
+
12
+ alias_method :widget?, :has_widget?
13
+
14
+ def visible?(name, *args)
15
+ widget_class(name).present_in?(self, *args)
16
+ end
17
+
18
+ def not_visible?(name, *args)
19
+ widget_class(name).not_present_in?(self, *args)
20
+ end
21
+
22
+ def widget(name, *args)
23
+ first, rest = [*name, *args]
24
+
25
+ widget_class(first).find_in(self, *rest)
26
+ end
27
+
28
+ def widgets(name, *args)
29
+ first, rest = [*name, *args]
30
+
31
+ widget_class(first).find_all_in(self, *rest)
32
+ end
33
+
34
+ private
35
+
36
+ attr_writer :widget_lookup_scope
37
+
38
+ def widget_class(name)
39
+ WidgetName.new(name).to_class(widget_lookup_scope)
40
+ end
41
+
42
+ def widget_lookup_scope
43
+ @widget_lookup_scope || self.class
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,119 @@
1
+ module Capybara
2
+ module UI
3
+ module WidgetParts
4
+ module Struct
5
+ def self.included(target)
6
+ target.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ def attribute(name, selector, &block)
11
+ child = widget(name, selector, &block)
12
+
13
+ class_eval <<-WIDGET
14
+ def #{name}
15
+ widget(:#{name}).value
16
+ end
17
+ WIDGET
18
+
19
+ child
20
+ end
21
+
22
+ def boolean(name, selector, &block)
23
+ child = widget(name, selector, &block)
24
+
25
+ class_eval <<-WIDGET
26
+ def #{name}?
27
+ widget(:#{name}).value
28
+ end
29
+ WIDGET
30
+
31
+ child.class_eval <<-VALUE
32
+ def value
33
+ Capybara::UI::Conversions::Boolean(text)
34
+ end
35
+ VALUE
36
+
37
+ child
38
+ end
39
+
40
+ def date(name, selector, &block)
41
+ child = attribute(name, selector, &block)
42
+
43
+ child.class_eval <<-VALUE
44
+ def value
45
+ Date.parse(text)
46
+ end
47
+ VALUE
48
+
49
+ child
50
+ end
51
+
52
+ def float(name, selector, &block)
53
+ child = attribute(name, selector, &block)
54
+
55
+ child.class_eval <<-VALUE
56
+ def value
57
+ Float(text)
58
+ end
59
+ VALUE
60
+
61
+ child
62
+ end
63
+
64
+ def integer(name, selector, &block)
65
+ child = attribute(name, selector, &block)
66
+
67
+ child.class_eval <<-VALUE
68
+ def value
69
+ Integer(text)
70
+ end
71
+ VALUE
72
+
73
+ child
74
+ end
75
+
76
+ def list(name, selector, options = {}, &block)
77
+ child = widget(name, selector, Capybara::UI::List) do
78
+ item options[:item_selector], options[:item_class] || ListItem
79
+ end
80
+
81
+ class_eval <<-WIDGET
82
+ def #{name}
83
+ widget(:#{name}).value
84
+ end
85
+ WIDGET
86
+
87
+ child.class_eval(&block) if block_given?
88
+
89
+ child
90
+ end
91
+
92
+ def string(name, *args, &block)
93
+ child = attribute(name, *args, &block)
94
+
95
+ child.class_eval <<-VALUE
96
+ def value
97
+ text
98
+ end
99
+ VALUE
100
+
101
+ child
102
+ end
103
+
104
+ def time(name, *args, &block)
105
+ child = attribute(name, *args, &block)
106
+
107
+ child.class_eval <<-VALUE
108
+ def value
109
+ Time.parse(text)
110
+ end
111
+ VALUE
112
+
113
+ child
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,64 @@
1
+ module Capybara
2
+ module UI
3
+ # A radio button.
4
+ class RadioButton < Field
5
+ widget :checked, -> {
6
+ case Capybara.current_driver
7
+ when :rack_test
8
+ ['[checked]']
9
+ else
10
+ ['input:checked']
11
+ end
12
+ }
13
+ widget :checked_label_by_value, -> (val) { [:xpath, ".//label[input[@type='radio' and @value='#{val}']]"] }
14
+ widget :checked_label_by_id, -> (id) { [:xpath, ".//label[@for='#{id}']"] }
15
+ widget :button_by_value, -> (val) { "[value='#{val}']" }
16
+
17
+ def self.root(selector)
18
+ super(["#{selector}"])
19
+ end
20
+
21
+ # @return [String] The text of the checked button's label.
22
+ def get
23
+ if visible?(:checked_label_by_value, value)
24
+ widget(:checked_label_by_value, value).text
25
+ elsif visible?(:checked_label_by_id, id)
26
+ widget(:checked_label_by_id, id).text
27
+ else
28
+ nil
29
+ end
30
+ end
31
+
32
+ # @return [String] The value of the checked button.
33
+ def value
34
+ visible?(:checked) ? widget(:checked).root.value : nil
35
+ end
36
+
37
+ # @return [String] The id of the checked button.
38
+ def id
39
+ visible?(:checked) ? widget(:checked).id : nil
40
+ end
41
+
42
+ # First attempts to choose the button by id or label text
43
+ # Then attempts to choose the button by value
44
+ def set(str)
45
+ root.choose(str)
46
+ rescue
47
+ begin
48
+ widget(:button_by_value, str).root.set(true)
49
+ rescue Capybara::UI::MissingWidget => e
50
+ raise InvalidRadioButton.new(e.message).
51
+ tap { |x| x.set_backtrace e.backtrace }
52
+ end
53
+ end
54
+
55
+ # @return the text of the checked button, or an empty string if
56
+ # no button is checked.
57
+ def_delegator :get, :to_s
58
+
59
+ def to_cell
60
+ get
61
+ end
62
+ end
63
+ end
64
+ end