cucumber-salad 0.3.1 → 0.4.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.
- data/lib/cucumber/salad.rb +8 -1
- data/lib/cucumber/salad/version.rb +1 -1
- data/lib/cucumber/salad/widget_container.rb +1 -1
- data/lib/cucumber/salad/widget_name.rb +1 -2
- data/lib/cucumber/salad/widgets.rb +1 -0
- data/lib/cucumber/salad/widgets/field_group.rb +342 -0
- data/lib/cucumber/salad/widgets/form.rb +2 -63
- data/lib/cucumber/salad/widgets/widget.rb +60 -1
- metadata +26 -8
data/lib/cucumber/salad.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'chronic'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'capybara'
|
2
4
|
|
3
5
|
require 'cucumber/salad/widget_container'
|
4
6
|
require 'cucumber/salad/widget_macros'
|
@@ -15,4 +17,9 @@ require 'cucumber/salad/table/cell_text'
|
|
15
17
|
require 'cucumber/salad/widgets/document'
|
16
18
|
require 'cucumber/salad/dsl'
|
17
19
|
|
18
|
-
|
20
|
+
module Cucumber
|
21
|
+
module Salad
|
22
|
+
# An exception that signals that something is missing.
|
23
|
+
class Missing < StandardError; end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,342 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Salad
|
3
|
+
module Widgets
|
4
|
+
# A group of form fields.
|
5
|
+
#
|
6
|
+
# @todo Explain how to use locators when defining fields, including what
|
7
|
+
# happens when locators are omitted.
|
8
|
+
class FieldGroup < Widget
|
9
|
+
root 'fieldset'
|
10
|
+
|
11
|
+
def self.default_locator(type = nil, &block)
|
12
|
+
alias_method :name_to_locator, type if type
|
13
|
+
|
14
|
+
define_method :name_to_locator, &block if block
|
15
|
+
end
|
16
|
+
|
17
|
+
# The names of all the fields that belong to this field group.
|
18
|
+
#
|
19
|
+
# Field names are automatically added to this group as long as you use
|
20
|
+
# the field definition macros.
|
21
|
+
#
|
22
|
+
# @return [Set] the field names.
|
23
|
+
#
|
24
|
+
# @see field
|
25
|
+
def self.field_names
|
26
|
+
@field_names ||= Set.new
|
27
|
+
end
|
28
|
+
|
29
|
+
# @!group Field definition macros
|
30
|
+
|
31
|
+
# Creates a new checkbox accessor.
|
32
|
+
#
|
33
|
+
# Adds the following methods to the widget:
|
34
|
+
#
|
35
|
+
# <name>:: Gets the current checkbox state, as a boolean. Returns +true+
|
36
|
+
# if the corresponding check box is checked, +false+ otherwise.
|
37
|
+
# <name>=:: Sets the current checkbox state. Pass +true+ to check the
|
38
|
+
# checkbox, +false+ otherwise.
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# # Given the following HTML:
|
42
|
+
# #
|
43
|
+
# # <form>
|
44
|
+
# # <p>
|
45
|
+
# # <label for="checked-box">
|
46
|
+
# # <input type="checkbox" value="1" id="checked-box" checked>
|
47
|
+
# # </p>
|
48
|
+
# # <p>
|
49
|
+
# # <label for="unchecked-box">
|
50
|
+
# # <input type="checkbox" value="1" id="unchecked-box">
|
51
|
+
# # </p>
|
52
|
+
# # </form>
|
53
|
+
# class MyFieldGroup < Cucumber::Salad::Widgets::FieldGroup
|
54
|
+
# root 'form'
|
55
|
+
#
|
56
|
+
# check_box :checked_box, 'checked-box'
|
57
|
+
# check_box :unchecked_box, 'unchecked-box'
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# form = widget(:my_field_group)
|
61
|
+
#
|
62
|
+
# form.checked_box #=> true
|
63
|
+
# form.unchecked_box #=> false
|
64
|
+
#
|
65
|
+
# form.unchecked_box = true
|
66
|
+
# form.unchecked_box #=> true
|
67
|
+
#
|
68
|
+
# @param name the name of the checkbox accessor.
|
69
|
+
# @param locator the locator for the checkbox. If +nil+ the locator will
|
70
|
+
# be derived from +name+.
|
71
|
+
#
|
72
|
+
# @todo Handle checkbox access when the field is disabled (raise an
|
73
|
+
# exception?)
|
74
|
+
def self.check_box(name, locator = nil)
|
75
|
+
field name, locator || name_to_locator(name), CheckBox
|
76
|
+
end
|
77
|
+
|
78
|
+
# Defines a new field.
|
79
|
+
#
|
80
|
+
# @param name the name of the field accessor.
|
81
|
+
# @param locator the field locator.
|
82
|
+
# @param type the field class name.
|
83
|
+
#
|
84
|
+
# @api private
|
85
|
+
def self.field(name, locator, type)
|
86
|
+
raise TypeError, "can't convert `#{name}' to Symbol" \
|
87
|
+
unless name.respond_to?(:to_sym)
|
88
|
+
|
89
|
+
field_names << name.to_sym
|
90
|
+
|
91
|
+
widget name, locator, type do
|
92
|
+
define_method :label do
|
93
|
+
name.to_s.gsub(/_/, ' ').capitalize
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
define_method "#{name}=" do |val|
|
98
|
+
widget(name).set val
|
99
|
+
end
|
100
|
+
|
101
|
+
define_method name do
|
102
|
+
widget(name).get
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Creates a new select accessor.
|
107
|
+
#
|
108
|
+
# Adds the following methods to the widget:
|
109
|
+
#
|
110
|
+
# <name>:: Gets the current selected option. Returns the label of the
|
111
|
+
# selected option, or +nil+, if no option is selected.
|
112
|
+
# <name>=:: Selects an option on the current select. Pass the label of
|
113
|
+
# the option you want to select.
|
114
|
+
#
|
115
|
+
# @example
|
116
|
+
# # Given the following HTML:
|
117
|
+
# #
|
118
|
+
# # <form>
|
119
|
+
# # <p>
|
120
|
+
# # <label for="selected">
|
121
|
+
# # <select id="selected">
|
122
|
+
# # <option selected>Selected option</option>
|
123
|
+
# # <option>Another option</option>
|
124
|
+
# # </select>
|
125
|
+
# # </p>
|
126
|
+
# # <p>
|
127
|
+
# # <label for="deselected">
|
128
|
+
# # <select id="deselected">
|
129
|
+
# # <option>Deselected option</option>
|
130
|
+
# # <option>Another option</option>
|
131
|
+
# # </select>
|
132
|
+
# # </p>
|
133
|
+
# # </form>
|
134
|
+
# class MyFieldGroup < Cucumber::Salad::Widgets::FieldGroup
|
135
|
+
# root 'form'
|
136
|
+
#
|
137
|
+
# select :selected, 'selected'
|
138
|
+
# select :deselected, 'deselected'
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# form = widget(:my_field_group)
|
142
|
+
#
|
143
|
+
# form.selected #=> "Selected option"
|
144
|
+
# form.deselected #=> nil
|
145
|
+
#
|
146
|
+
# form.deselected = "Deselected option"
|
147
|
+
# form.unchecked_box #=> "Deselected option"
|
148
|
+
#
|
149
|
+
# @param name the name of the select accessor.
|
150
|
+
# @param locator the locator for the select. If +nil+ the locator will
|
151
|
+
# be derived from +name+.
|
152
|
+
#
|
153
|
+
# @todo Handle select access when the field is disabled (raise an
|
154
|
+
# exception?)
|
155
|
+
# @todo Raise an exception when an option doesn't exist.
|
156
|
+
# @todo Allow passing the option value to set an option.
|
157
|
+
# @todo Ensure an option with no text returns the empty string.
|
158
|
+
# @todo What to do when +nil+ is passed to the writer?
|
159
|
+
def self.select(name, locator = nil)
|
160
|
+
field name, locator || name_to_locator(name), Select
|
161
|
+
end
|
162
|
+
|
163
|
+
# Creates a new text field accessor.
|
164
|
+
#
|
165
|
+
# Adds the following methods to the widget:
|
166
|
+
#
|
167
|
+
# <name>:: Returns the current text field value, or +nil+ if no value
|
168
|
+
# has been set.
|
169
|
+
# <name>=:: Sets the current text field value.
|
170
|
+
#
|
171
|
+
# @example
|
172
|
+
# # Given the following HTML:
|
173
|
+
# #
|
174
|
+
# # <form>
|
175
|
+
# # <p>
|
176
|
+
# # <label for="text-field">
|
177
|
+
# # <input type="text" value="Content" id="text-field">
|
178
|
+
# # </p>
|
179
|
+
# # <p>
|
180
|
+
# # <label for="empty-field">
|
181
|
+
# # <input type="text" id="empty-field">
|
182
|
+
# # </p>
|
183
|
+
# # </form>
|
184
|
+
# class MyFieldGroup < Cucumber::Salad::Widgets::FieldGroup
|
185
|
+
# root 'form'
|
186
|
+
#
|
187
|
+
# text_field :filled_field, 'text-field'
|
188
|
+
# text_field :empty_field, 'empty-field'
|
189
|
+
# end
|
190
|
+
#
|
191
|
+
# form = widget(:my_field_group)
|
192
|
+
#
|
193
|
+
# form.filled_field #=> "Content"
|
194
|
+
# form.empty_field #=> nil
|
195
|
+
#
|
196
|
+
# form.empty_field = "Not anymore"
|
197
|
+
# form.empty_field #=> "Not anymore"
|
198
|
+
#
|
199
|
+
# @param name the name of the text field accessor.
|
200
|
+
# @param locator the locator for the text field. If +nil+ the locator
|
201
|
+
# will be derived from +name+.
|
202
|
+
#
|
203
|
+
# @todo Handle text field access when the field is disabled (raise an
|
204
|
+
# exception?)
|
205
|
+
def self.text_field(name, locator = nil)
|
206
|
+
field name, locator || name_to_locator(name), TextField
|
207
|
+
end
|
208
|
+
|
209
|
+
# @!endgroup
|
210
|
+
|
211
|
+
# @return This field group's field widgets.
|
212
|
+
def fields
|
213
|
+
self.class.field_names.map { |name| widget(name) }
|
214
|
+
end
|
215
|
+
|
216
|
+
# Sets the given form attributes.
|
217
|
+
#
|
218
|
+
# @param attributes [Hash] the attributes and values we want to set.
|
219
|
+
#
|
220
|
+
# @return the current widget.
|
221
|
+
def set(attributes)
|
222
|
+
attributes.each do |k, v|
|
223
|
+
send "#{k}=", v
|
224
|
+
end
|
225
|
+
|
226
|
+
self
|
227
|
+
end
|
228
|
+
|
229
|
+
# Converts the current field group into a table suitable for diff'ing
|
230
|
+
# with Cucumber::Ast::Table.
|
231
|
+
#
|
232
|
+
# Field labels are determined by the widget name.
|
233
|
+
#
|
234
|
+
# Field values correspond to the return value of each field's +to_s+.
|
235
|
+
#
|
236
|
+
# @return [Array<Array>] the table.
|
237
|
+
def to_table
|
238
|
+
headers = fields.map { |field| field.label.downcase }
|
239
|
+
body = fields.map { |field| field.to_s.downcase }
|
240
|
+
|
241
|
+
[headers, body]
|
242
|
+
end
|
243
|
+
|
244
|
+
# A form field.
|
245
|
+
class Field < Widget
|
246
|
+
def self.find_in(parent, options)
|
247
|
+
new({root: parent.find_field(selector)}.merge(options))
|
248
|
+
end
|
249
|
+
|
250
|
+
def self.present_in?(parent)
|
251
|
+
parent.has_field?(selector)
|
252
|
+
end
|
253
|
+
|
254
|
+
# @return This field's value.
|
255
|
+
#
|
256
|
+
# Override this to get the actual value.
|
257
|
+
def get
|
258
|
+
raise NotImplementedError
|
259
|
+
end
|
260
|
+
|
261
|
+
# Sets the field value.
|
262
|
+
#
|
263
|
+
# Override this to set the value.
|
264
|
+
def set(value)
|
265
|
+
raise NotImplementedError
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
# A check box.
|
270
|
+
class CheckBox < Field
|
271
|
+
# @!method set(value)
|
272
|
+
# Checks or unchecks the current checkbox.
|
273
|
+
#
|
274
|
+
# @param value [Boolean] +true+ to check the checkbox, +false+
|
275
|
+
# otherwise.
|
276
|
+
def_delegator :root, :set
|
277
|
+
|
278
|
+
# @return [Boolean] +true+ if the checkbox is checked, +false+
|
279
|
+
# otherwise.
|
280
|
+
def get
|
281
|
+
!! root.checked?
|
282
|
+
end
|
283
|
+
|
284
|
+
# @return +"yes"+ if the checkbox is checked, +"no"+ otherwise.
|
285
|
+
def to_s
|
286
|
+
get ? 'yes' : 'no'
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
# A select.
|
291
|
+
class Select < Field
|
292
|
+
# @return [String] The text of the selected option.
|
293
|
+
def get
|
294
|
+
option = root.find('[selected]') rescue nil
|
295
|
+
|
296
|
+
option && option.text
|
297
|
+
end
|
298
|
+
|
299
|
+
# Selects the given option.
|
300
|
+
#
|
301
|
+
# @param option [String] The text of the option to select.
|
302
|
+
def set(option)
|
303
|
+
root.find('option', text: option).select_option
|
304
|
+
end
|
305
|
+
|
306
|
+
# @!method to_s
|
307
|
+
# @return the text of the selected option, or the empty string if
|
308
|
+
# no option is selected.
|
309
|
+
def_delegator :get, :to_s
|
310
|
+
end
|
311
|
+
|
312
|
+
# A text field.
|
313
|
+
class TextField < Field
|
314
|
+
# @!method get
|
315
|
+
# @return The text field value.
|
316
|
+
def_delegator :root, :value, :get
|
317
|
+
|
318
|
+
# @!method set(value)
|
319
|
+
# Sets the text field value.
|
320
|
+
#
|
321
|
+
# @param value [String] the value to set.
|
322
|
+
def_delegator :root, :set
|
323
|
+
|
324
|
+
# @!method to_s
|
325
|
+
# @return the text field value, or the empty string if the field is
|
326
|
+
# empty.
|
327
|
+
def_delegator :get, :to_s
|
328
|
+
end
|
329
|
+
|
330
|
+
private
|
331
|
+
|
332
|
+
def label(name)
|
333
|
+
name.to_s.humanize
|
334
|
+
end
|
335
|
+
|
336
|
+
def name_to_locator(name)
|
337
|
+
label(name)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
@@ -1,79 +1,18 @@
|
|
1
1
|
module Cucumber
|
2
2
|
module Salad
|
3
3
|
module Widgets
|
4
|
-
class Form <
|
5
|
-
def self.default_locator(type = nil, &block)
|
6
|
-
alias_method :name_to_locator, type if type
|
7
|
-
|
8
|
-
define_method :name_to_locator, &block if block
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.check_box(name, label = nil)
|
12
|
-
define_method "#{name}=" do |val|
|
13
|
-
l = label || name_to_locator(name)
|
14
|
-
|
15
|
-
if val
|
16
|
-
root.check l
|
17
|
-
else
|
18
|
-
root.uncheck l
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.select(name, *args)
|
24
|
-
opts = args.extract_options!
|
25
|
-
label, = args
|
26
|
-
|
27
|
-
define_method "#{name}=" do |val|
|
28
|
-
l = label || name_to_locator(name)
|
29
|
-
w = opts.fetch(:writer) { ->(v) { v } }
|
30
|
-
|
31
|
-
root.select w.(val).to_s, from: l
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.text_field(name, label = nil)
|
36
|
-
define_method "#{name}=" do |val|
|
37
|
-
l = label || name_to_locator(name)
|
38
|
-
|
39
|
-
root.fill_in l, with: val.to_s
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
4
|
+
class Form < FieldGroup
|
43
5
|
action :submit, '[type = submit]'
|
44
6
|
|
45
|
-
# Sets the given form attributes.
|
46
|
-
#
|
47
|
-
# @param attributes [Hash] the attributes and values we want to set.
|
48
|
-
#
|
49
|
-
# @return the current widget.
|
50
|
-
def set(attributes)
|
51
|
-
attributes.each do |k, v|
|
52
|
-
send "#{k}=", v
|
53
|
-
end
|
54
|
-
|
55
|
-
self
|
56
|
-
end
|
57
|
-
|
58
7
|
# Submit form with +attributes+.
|
59
8
|
#
|
60
|
-
# @param
|
9
|
+
# @param attributes [Hash] the form fields and their values
|
61
10
|
#
|
62
11
|
# @return the current widget
|
63
12
|
def submit_with(attributes)
|
64
13
|
set attributes
|
65
14
|
submit
|
66
15
|
end
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
def label(name)
|
71
|
-
name.to_s.humanize
|
72
|
-
end
|
73
|
-
|
74
|
-
def name_to_locator(name)
|
75
|
-
label(name)
|
76
|
-
end
|
77
16
|
end
|
78
17
|
end
|
79
18
|
end
|
@@ -7,7 +7,13 @@ module Cucumber
|
|
7
7
|
|
8
8
|
include WidgetContainer
|
9
9
|
|
10
|
-
|
10
|
+
# Determines if an instance of this widget class exists in
|
11
|
+
# +parent_node+.
|
12
|
+
#
|
13
|
+
# @param parent_node [Capybara::Node] the node we want to search in
|
14
|
+
#
|
15
|
+
# @return +true+ if a widget instance is found, +false+ otherwise.
|
16
|
+
def self.present_in?(parent_node)
|
11
17
|
parent_node.has_selector?(selector)
|
12
18
|
end
|
13
19
|
|
@@ -43,6 +49,20 @@ module Cucumber
|
|
43
49
|
self.root = settings.fetch(:root)
|
44
50
|
end
|
45
51
|
|
52
|
+
# Determines if the widget underlying an action exists.
|
53
|
+
#
|
54
|
+
# @param name the name of the action
|
55
|
+
#
|
56
|
+
# @raise Missing if an action with +name+ can't be found.
|
57
|
+
#
|
58
|
+
# @return [Boolean] +true+ if the action widget is found, +false+
|
59
|
+
# otherwise.
|
60
|
+
def has_action?(name)
|
61
|
+
raise Missing, "couldn't find `#{name}' action" unless respond_to?(name)
|
62
|
+
|
63
|
+
has_widget?(name)
|
64
|
+
end
|
65
|
+
|
46
66
|
def inspect
|
47
67
|
xml = Nokogiri::HTML(page.body).at(root.path).to_xml
|
48
68
|
|
@@ -50,6 +70,45 @@ module Cucumber
|
|
50
70
|
Nokogiri::XML(xml, &:noblanks).to_xhtml
|
51
71
|
end
|
52
72
|
|
73
|
+
class Reload < Capybara::ElementNotFound; end
|
74
|
+
|
75
|
+
# Reloads the widget, waiting for its contents to change (by default),
|
76
|
+
# or until +wait_time+ expires.
|
77
|
+
#
|
78
|
+
# Call this method to make sure a widget has enough time to update
|
79
|
+
# itself.
|
80
|
+
#
|
81
|
+
# You can pass a block to this method to control what it means for the
|
82
|
+
# widget to be reloaded.
|
83
|
+
#
|
84
|
+
# *Note: does not account for multiple changes to the widget yet.*
|
85
|
+
#
|
86
|
+
# @param wait_time [Numeric] how long we should wait for changes, in
|
87
|
+
# seconds.
|
88
|
+
#
|
89
|
+
# @yield A block that determines what it means for a widget to be
|
90
|
+
# reloaded.
|
91
|
+
# @yieldreturn [Boolean] +true+ if the widget is considered to be
|
92
|
+
# reloaded, +false+ otherwise.
|
93
|
+
#
|
94
|
+
# @return the current widget
|
95
|
+
def reload(wait_time = Capybara.default_wait_time, &test)
|
96
|
+
unless test
|
97
|
+
old_inspect = inspect
|
98
|
+
test = ->{ old_inspect != inspect }
|
99
|
+
end
|
100
|
+
|
101
|
+
root.synchronize(wait_time) do
|
102
|
+
raise Reload unless test.()
|
103
|
+
end
|
104
|
+
|
105
|
+
self
|
106
|
+
rescue Reload
|
107
|
+
# raised on timeout
|
108
|
+
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
53
112
|
def to_s
|
54
113
|
node_text(root)
|
55
114
|
end
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: cucumber-salad
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.4.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- David Leal
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -62,18 +62,18 @@ dependencies:
|
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
|
-
- -
|
65
|
+
- - ~>
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
67
|
+
version: 3.0.0
|
68
68
|
none: false
|
69
|
-
name: rspec
|
69
|
+
name: rspec-given
|
70
70
|
type: :development
|
71
71
|
prerelease: false
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- -
|
74
|
+
- - ~>
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version:
|
76
|
+
version: 3.0.0
|
77
77
|
none: false
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -91,6 +91,22 @@ dependencies:
|
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: '0'
|
93
93
|
none: false
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ~>
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 1.0.0
|
100
|
+
none: false
|
101
|
+
name: capybara-webkit
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ~>
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 1.0.0
|
109
|
+
none: false
|
94
110
|
description: See https://github.com/mojotech/cucumber-salad/README.md
|
95
111
|
email:
|
96
112
|
- dleal@mojotech.com
|
@@ -117,12 +133,14 @@ files:
|
|
117
133
|
- lib/cucumber/salad/widgets/auto_table.rb
|
118
134
|
- lib/cucumber/salad/widgets/base_table.rb
|
119
135
|
- lib/cucumber/salad/widgets/document.rb
|
136
|
+
- lib/cucumber/salad/widgets/field_group.rb
|
120
137
|
- lib/cucumber/salad/widgets/form.rb
|
121
138
|
- lib/cucumber/salad/widgets/list.rb
|
122
139
|
- lib/cucumber/salad/widgets/table.rb
|
123
140
|
- lib/cucumber/salad/widgets/widget.rb
|
124
141
|
homepage: https://github.com/mojotech/cucumber-salad
|
125
|
-
licenses:
|
142
|
+
licenses:
|
143
|
+
- MIT
|
126
144
|
post_install_message:
|
127
145
|
rdoc_options: []
|
128
146
|
require_paths:
|