kelp 0.1.9 → 0.2.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/Gemfile.lock +1 -1
- data/History.md +10 -0
- data/examples/sinatra_app/features/checkbox_fail.feature +11 -0
- data/examples/sinatra_app/features/dropdown.feature +4 -4
- data/examples/sinatra_app/features/dropdown_fail.feature +28 -0
- data/examples/sinatra_app/features/field.feature +57 -0
- data/examples/sinatra_app/features/field_fail.feature +31 -0
- data/examples/sinatra_app/features/visibility.feature +96 -6
- data/examples/sinatra_app/features/visibility_fail.feature +30 -2
- data/examples/sinatra_app/views/form.erb +14 -0
- data/features/kelp_step_definitions.feature +101 -12
- data/features/step_definitions/app_steps.rb +24 -8
- data/kelp.gemspec +1 -1
- data/lib/kelp.rb +0 -15
- data/lib/kelp/attribute.rb +26 -4
- data/lib/kelp/checkbox.rb +33 -8
- data/lib/kelp/dropdown.rb +37 -11
- data/lib/kelp/exceptions.rb +4 -2
- data/lib/kelp/field.rb +80 -41
- data/lib/kelp/helper.rb +8 -1
- data/lib/kelp/navigation.rb +14 -8
- data/lib/kelp/scoping.rb +1 -3
- data/lib/kelp/visibility.rb +152 -167
- data/rails_generators/kelp/templates/web_steps.rb +2 -2
- data/spec/attribute_spec.rb +4 -4
- data/spec/checkbox_spec.rb +4 -4
- data/spec/dropdown_spec.rb +10 -10
- data/spec/field_spec.rb +15 -15
- data/spec/navigation_spec.rb +2 -2
- data/spec/spec_helper.rb +0 -9
- data/spec/visibility_spec.rb +40 -103
- metadata +8 -5
data/lib/kelp/helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'kelp/exceptions'
|
2
|
+
|
1
3
|
module Kelp
|
2
4
|
module Helper
|
3
5
|
# Convert a Cucumber::Ast::Table or multiline string into
|
@@ -14,11 +16,16 @@ module Kelp
|
|
14
16
|
# A slightly friendlier version of Capybara's `find_field`, which actually
|
15
17
|
# tells you which locator failed to match (instead of giving a useless
|
16
18
|
# Unable to find '#<XPath::Union:0xXXXXXXX>' message).
|
19
|
+
#
|
20
|
+
# @raise [Kelp::FieldNotFound]
|
21
|
+
# If no field with the given locator could be found
|
22
|
+
#
|
17
23
|
def nice_find_field(locator)
|
18
24
|
begin
|
19
25
|
field = find_field(locator)
|
20
26
|
rescue Capybara::ElementNotFound
|
21
|
-
raise
|
27
|
+
raise Kelp::FieldNotFound,
|
28
|
+
"Could not find field: '#{locator}'"
|
22
29
|
end
|
23
30
|
end
|
24
31
|
|
data/lib/kelp/navigation.rb
CHANGED
@@ -76,6 +76,9 @@ module Kelp
|
|
76
76
|
# Human-readable page name (mapped to a pathname by your `path_to` function),
|
77
77
|
# or an absolute path beginning with `/`.
|
78
78
|
#
|
79
|
+
# @raise [Kelp::Unexpected]
|
80
|
+
# If actual page path doesn't match the expected path
|
81
|
+
#
|
79
82
|
# @since 0.1.9
|
80
83
|
#
|
81
84
|
def should_be_on_page(page_name_or_path)
|
@@ -88,10 +91,10 @@ module Kelp
|
|
88
91
|
expect_path = page_name_or_path
|
89
92
|
end
|
90
93
|
actual_path = URI.parse(current_url).path
|
91
|
-
if actual_path
|
92
|
-
|
93
|
-
|
94
|
-
|
94
|
+
if actual_path != expect_path
|
95
|
+
raise Kelp::Unexpected,
|
96
|
+
"Expected to be on page: '#{expect_path}'" + \
|
97
|
+
"\nActually on page: '#{actual_path}'"
|
95
98
|
end
|
96
99
|
end
|
97
100
|
|
@@ -101,6 +104,9 @@ module Kelp
|
|
101
104
|
# @param [Hash] params
|
102
105
|
# Key => value parameters, as they would appear in the URL
|
103
106
|
#
|
107
|
+
# @raise [Kelp::Unexpected]
|
108
|
+
# If actual query parameters don't match expected parameters
|
109
|
+
#
|
104
110
|
# @since 0.1.9
|
105
111
|
#
|
106
112
|
def should_have_query(params)
|
@@ -110,10 +116,10 @@ module Kelp
|
|
110
116
|
params.each_pair do |k,v|
|
111
117
|
expected_params[k] = v.split(',')
|
112
118
|
end
|
113
|
-
if actual_params
|
114
|
-
|
115
|
-
|
116
|
-
|
119
|
+
if actual_params != expected_params
|
120
|
+
raise Kelp::Unexpected,
|
121
|
+
"Expected query params: '#{expected_params.inspect}'" + \
|
122
|
+
"\nActual query params: '#{actual_params.inspect}'"
|
117
123
|
end
|
118
124
|
end
|
119
125
|
|
data/lib/kelp/scoping.rb
CHANGED
@@ -12,10 +12,8 @@ module Kelp
|
|
12
12
|
# by features/support/selectors.rb, generated by cucumber-rails.
|
13
13
|
if defined? selector_for
|
14
14
|
within(*selector_for(locator)) { yield }
|
15
|
-
# Otherwise,
|
16
|
-
# and fall back on the Capybara locator syntax (CSS or XPath)
|
15
|
+
# Otherwise, fall back on the Capybara locator syntax (CSS or XPath)
|
17
16
|
else
|
18
|
-
locator.gsub!(/^"(.*?)"$/, '\1')
|
19
17
|
if locator =~ /\.?\//
|
20
18
|
within(:xpath, locator) { yield }
|
21
19
|
else
|
data/lib/kelp/visibility.rb
CHANGED
@@ -12,6 +12,28 @@ module Kelp
|
|
12
12
|
include Scoping
|
13
13
|
include XPaths
|
14
14
|
|
15
|
+
# Return `true` if the current page contains the given text or regular expression,
|
16
|
+
# or `false` if it does not.
|
17
|
+
#
|
18
|
+
# @param [String, Regexp] text_or_regexp
|
19
|
+
# Text or regular expression to look for
|
20
|
+
#
|
21
|
+
# @raise [ArgumentError]
|
22
|
+
# If the given argument isn't a String or Regexp
|
23
|
+
#
|
24
|
+
# @since 0.2.0
|
25
|
+
#
|
26
|
+
def page_contains?(text_or_regexp)
|
27
|
+
if text_or_regexp.class == String
|
28
|
+
return page.has_content?(text_or_regexp)
|
29
|
+
elsif text_or_regexp.class == Regexp
|
30
|
+
return page.has_xpath?('.//*', :text => text_or_regexp)
|
31
|
+
else
|
32
|
+
raise ArgumentError, "Expected String or Regexp, got #{text_or_regexp.class}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
15
37
|
# Verify the presence of content on the page. Passes when all the given items
|
16
38
|
# are found on the page, and fails if any of them are not found.
|
17
39
|
#
|
@@ -30,20 +52,16 @@ module Kelp
|
|
30
52
|
# If any of the expected text strings are not seen in the given scope
|
31
53
|
#
|
32
54
|
def should_see(texts, scope={})
|
33
|
-
texts = [texts] if (texts.class == String || texts.class == Regexp)
|
34
|
-
unexpected = []
|
35
55
|
in_scope(scope) do
|
36
|
-
texts.
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
56
|
+
texts = [texts] if (texts.class == String || texts.class == Regexp)
|
57
|
+
# Select all expected values that don't appear on the page
|
58
|
+
unexpected = texts.select do |text|
|
59
|
+
!page_contains?(text)
|
60
|
+
end
|
61
|
+
if !unexpected.empty?
|
62
|
+
raise Kelp::Unexpected,
|
63
|
+
"Expected to see: #{texts.inspect}\nDid not see: #{unexpected.inspect}"
|
42
64
|
end
|
43
|
-
end
|
44
|
-
if !unexpected.empty?
|
45
|
-
raise Kelp::Unexpected,
|
46
|
-
"Expected to see: #{texts.inspect}\nDid not see: #{unexpected.inspect}"
|
47
65
|
end
|
48
66
|
end
|
49
67
|
|
@@ -52,7 +70,7 @@ module Kelp
|
|
52
70
|
# items are found on the page, and fails if any of them are found.
|
53
71
|
#
|
54
72
|
# @param [String, Regexp, Array] texts
|
55
|
-
# Text(s) or
|
73
|
+
# Text(s) or Regexp(s) to look for
|
56
74
|
# @param [Hash] scope
|
57
75
|
# Scoping keywords as understood by {#in_scope}
|
58
76
|
#
|
@@ -60,149 +78,16 @@ module Kelp
|
|
60
78
|
# If any of the expected text strings are seen in the given scope
|
61
79
|
#
|
62
80
|
def should_not_see(texts, scope={})
|
63
|
-
texts = [texts] if (texts.class == String || texts.class == Regexp)
|
64
|
-
unexpected = []
|
65
81
|
in_scope(scope) do
|
66
|
-
texts.
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
unexpected << text
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
if !unexpected.empty?
|
75
|
-
raise Kelp::Unexpected,
|
76
|
-
"Expected not to see: #{texts.inspect}\nDid see: #{unexpected.inspect}"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
|
-
# Ensure that the current page content includes a String or Regexp.
|
82
|
-
#
|
83
|
-
# @param [String, Regexp] text_or_regexp
|
84
|
-
# Content you expect to be on the page
|
85
|
-
#
|
86
|
-
def page_should_contain(text_or_regexp)
|
87
|
-
if text_or_regexp.class == String
|
88
|
-
page_should_contain_text(text_or_regexp)
|
89
|
-
elsif text_or_regexp.class == Regexp
|
90
|
-
page_should_contain_regexp(text_or_regexp)
|
91
|
-
else
|
92
|
-
raise ArgumentError, "Expected String or Regexp, got #{text_or_regexp.class}"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
# Ensure that the current page content does not include a String or Regexp.
|
98
|
-
#
|
99
|
-
# @param [String, Regexp] text_or_regexp
|
100
|
-
# Content you expect to be missing from the page
|
101
|
-
#
|
102
|
-
def page_should_not_contain(text_or_regexp)
|
103
|
-
if text_or_regexp.class == String
|
104
|
-
page_should_not_contain_text(text_or_regexp)
|
105
|
-
elsif text_or_regexp.class == Regexp
|
106
|
-
page_should_not_contain_regexp(text_or_regexp)
|
107
|
-
else
|
108
|
-
raise ArgumentError, "Expected String or Regexp, got #{text_or_regexp.class}"
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
|
113
|
-
# Ensure that the current page content includes a String.
|
114
|
-
#
|
115
|
-
# @param [String] text
|
116
|
-
# Content you expect to be on the page
|
117
|
-
#
|
118
|
-
def page_should_contain_text(text)
|
119
|
-
if Kelp.driver == :capybara
|
120
|
-
if page.respond_to? :should
|
121
|
-
page.should have_content(text)
|
122
|
-
else
|
123
|
-
assert page.has_content?(text)
|
124
|
-
end
|
125
|
-
elsif Kelp.driver == :webrat
|
126
|
-
if defined?(Spec::Rails::Matchers)
|
127
|
-
response.should contain(text)
|
128
|
-
else
|
129
|
-
assert_contain text
|
130
|
-
end
|
131
|
-
else
|
132
|
-
raise NotImplementedError, "Unsupported driver: #{Kelp.driver}"
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
|
137
|
-
# Ensure that the current page content matches a Regexp.
|
138
|
-
#
|
139
|
-
# @param [Regexp] regexp
|
140
|
-
# Content you expect to match
|
141
|
-
#
|
142
|
-
def page_should_contain_regexp(regexp)
|
143
|
-
if Kelp.driver == :capybara
|
144
|
-
if page.respond_to? :should
|
145
|
-
page.should have_xpath('.//*', :text => regexp)
|
146
|
-
else
|
147
|
-
assert page.has_xpath?('.//*', :text => regexp)
|
148
|
-
end
|
149
|
-
elsif Kelp.driver == :webrat
|
150
|
-
if defined?(Spec::Rails::Matchers)
|
151
|
-
response.should contain(regexp)
|
152
|
-
else
|
153
|
-
assert_match(regexp, response_body)
|
154
|
-
end
|
155
|
-
else
|
156
|
-
raise NotImplementedError, "Unsupported driver: #{Kelp.driver}"
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
|
161
|
-
# Ensure that the current page content does not include a String.
|
162
|
-
#
|
163
|
-
# @param [String] text
|
164
|
-
# Content you expect to be missing from the page
|
165
|
-
#
|
166
|
-
def page_should_not_contain_text(text)
|
167
|
-
if Kelp.driver == :capybara
|
168
|
-
if page.respond_to? :should
|
169
|
-
page.should have_no_content(text)
|
170
|
-
else
|
171
|
-
assert page.has_no_content?(text)
|
172
|
-
end
|
173
|
-
elsif Kelp.driver == :webrat
|
174
|
-
if defined?(Spec::Rails::Matchers)
|
175
|
-
response.should_not contain(text)
|
176
|
-
else
|
177
|
-
hc = Webrat::Matchers::HasContent.new(text)
|
178
|
-
assert !hc.matches?(content), hc.negative_failure_message
|
179
|
-
end
|
180
|
-
else
|
181
|
-
raise NotImplementedError, "Unsupported driver: #{Kelp.driver}"
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
|
186
|
-
# Ensure that the current page content does not match a Regexp.
|
187
|
-
#
|
188
|
-
# @param [Regexp] regexp
|
189
|
-
# Content you expect to fail matching
|
190
|
-
#
|
191
|
-
def page_should_not_contain_regexp(regexp)
|
192
|
-
if Kelp.driver == :capybara
|
193
|
-
if page.respond_to? :should
|
194
|
-
page.should have_no_xpath('.//*', :text => regexp)
|
195
|
-
else
|
196
|
-
assert page.has_no_xpath?('.//*', :text => regexp)
|
82
|
+
texts = [texts] if (texts.class == String || texts.class == Regexp)
|
83
|
+
# Select all unexpected values that do appear on the page
|
84
|
+
unexpected = texts.select do |text|
|
85
|
+
page_contains?(text)
|
197
86
|
end
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
else
|
202
|
-
assert_not_contain(regexp)
|
87
|
+
if !unexpected.empty?
|
88
|
+
raise Kelp::Unexpected,
|
89
|
+
"Expected not to see: #{texts.inspect}\nDid see: #{unexpected.inspect}"
|
203
90
|
end
|
204
|
-
else
|
205
|
-
raise NotImplementedError, "Unsupported driver: #{Kelp.driver}"
|
206
91
|
end
|
207
92
|
end
|
208
93
|
|
@@ -221,12 +106,13 @@ module Kelp
|
|
221
106
|
# @param [Hash] scope
|
222
107
|
# Scoping keywords as understood by {#in_scope}
|
223
108
|
#
|
109
|
+
# @raise [Kelp::Unexpected]
|
110
|
+
# If no row is found containing all strings in `texts`
|
111
|
+
#
|
224
112
|
def should_see_in_same_row(texts, scope={})
|
225
113
|
in_scope(scope) do
|
226
|
-
if
|
227
|
-
|
228
|
-
elsif Kelp.driver == :webrat
|
229
|
-
raise NotImplementedError, "Not implemented yet"
|
114
|
+
if !page.has_xpath?(xpath_row_containing(texts))
|
115
|
+
raise Kelp::Unexpected, "Expected, but did not see: #{texts.inspect} in the same row"
|
230
116
|
end
|
231
117
|
end
|
232
118
|
end
|
@@ -245,12 +131,13 @@ module Kelp
|
|
245
131
|
# @param [Hash] scope
|
246
132
|
# Scoping keywords as understood by {#in_scope}
|
247
133
|
#
|
134
|
+
# @raise [Kelp::Unexpected]
|
135
|
+
# If a row is found containing all strings in `texts`
|
136
|
+
#
|
248
137
|
def should_not_see_in_same_row(texts, scope={})
|
249
138
|
in_scope(scope) do
|
250
|
-
if
|
251
|
-
|
252
|
-
elsif Kelp.driver == :webrat
|
253
|
-
raise NotImplementedError, "Not implemented yet"
|
139
|
+
if page.has_xpath?(xpath_row_containing(texts))
|
140
|
+
raise Kelp::Unexpected, "Did not expect, but did see: #{texts.inspect} in the same row"
|
254
141
|
end
|
255
142
|
end
|
256
143
|
end
|
@@ -276,9 +163,7 @@ module Kelp
|
|
276
163
|
def should_see_button(button_text, scope={})
|
277
164
|
in_scope(scope) do
|
278
165
|
xpath = XPath::HTML.button(button_text)
|
279
|
-
|
280
|
-
page.should have_xpath(xpath)
|
281
|
-
rescue rspec_unexpected
|
166
|
+
if !page.has_xpath?(xpath)
|
282
167
|
raise Kelp::Unexpected, "Expected to see button '#{button_text}', but button does not exist."
|
283
168
|
end
|
284
169
|
end
|
@@ -305,14 +190,114 @@ module Kelp
|
|
305
190
|
def should_not_see_button(button_text, scope={})
|
306
191
|
in_scope(scope) do
|
307
192
|
xpath = XPath::HTML.button(button_text)
|
308
|
-
|
309
|
-
page.should have_no_xpath(xpath)
|
310
|
-
rescue rspec_unexpected
|
193
|
+
if page.has_xpath?(xpath)
|
311
194
|
raise Kelp::Unexpected, "Did not expect to see button '#{button_text}', but button exists."
|
312
195
|
end
|
313
196
|
end
|
314
197
|
end
|
315
198
|
|
199
|
+
|
200
|
+
# -------------------------------------------------------------------
|
201
|
+
# DEPRECATED METHODS
|
202
|
+
# These will be removed in a future release of Kelp. Do not use them.
|
203
|
+
# -------------------------------------------------------------------
|
204
|
+
|
205
|
+
|
206
|
+
# Ensure that the current page content includes a String or Regexp.
|
207
|
+
#
|
208
|
+
# @deprecated
|
209
|
+
# Use {#should_see} instead
|
210
|
+
#
|
211
|
+
# @param [String, Regexp] text_or_regexp
|
212
|
+
# Content you expect to be on the page
|
213
|
+
#
|
214
|
+
def page_should_contain(text_or_regexp)
|
215
|
+
warn "WARNING: page_should_contain is deprecated. Use should_see instead."
|
216
|
+
if !page_contains?(text_or_regexp)
|
217
|
+
raise Kelp::Unexpected
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
# Ensure that the current page content does not include a String or Regexp.
|
223
|
+
#
|
224
|
+
# @deprecated
|
225
|
+
# Use {#should_not_see} instead
|
226
|
+
#
|
227
|
+
# @param [String, Regexp] text_or_regexp
|
228
|
+
# Content you expect to be missing from the page
|
229
|
+
#
|
230
|
+
def page_should_not_contain(text_or_regexp)
|
231
|
+
warn "WARNING: page_should_not_contain is deprecated. Use should_not_see instead."
|
232
|
+
if page_contains?(text_or_regexp)
|
233
|
+
raise Kelp::Unexpected
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
# Ensure that the current page content includes a String.
|
239
|
+
#
|
240
|
+
# @deprecated
|
241
|
+
# Use {#should_see} instead
|
242
|
+
#
|
243
|
+
# @param [String] text
|
244
|
+
# Content you expect to be on the page
|
245
|
+
#
|
246
|
+
def page_should_contain_text(text)
|
247
|
+
warn "WARNING: page_should_contain_text is deprecated. Use should_see instead."
|
248
|
+
if !page.has_content?(text)
|
249
|
+
raise Kelp::Unexpected
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
# Ensure that the current page content matches a Regexp.
|
255
|
+
#
|
256
|
+
# @deprecated
|
257
|
+
# Use {#should_see} instead
|
258
|
+
#
|
259
|
+
# @param [Regexp] regexp
|
260
|
+
# Content you expect to match
|
261
|
+
#
|
262
|
+
def page_should_contain_regexp(regexp)
|
263
|
+
warn "WARNING: page_should_contain_regexp is deprecated. Use should_see instead."
|
264
|
+
if !page.has_xpath?('.//*', :text => regexp)
|
265
|
+
raise Kelp::Unexpected
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
# Ensure that the current page content does not include a String.
|
271
|
+
#
|
272
|
+
# @deprecated
|
273
|
+
# Use {#should_not_see} instead
|
274
|
+
#
|
275
|
+
# @param [String] text
|
276
|
+
# Content you expect to be missing from the page
|
277
|
+
#
|
278
|
+
def page_should_not_contain_text(text)
|
279
|
+
warn "WARNING: page_should_not_contain_text is deprecated. Use should_not_see instead."
|
280
|
+
if page.has_content?(text)
|
281
|
+
raise Kelp::Unexpected
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
# Ensure that the current page content does not match a Regexp.
|
287
|
+
#
|
288
|
+
# @deprecated
|
289
|
+
# Use {#should_not_see} instead
|
290
|
+
#
|
291
|
+
# @param [Regexp] regexp
|
292
|
+
# Content you expect to fail matching
|
293
|
+
#
|
294
|
+
def page_should_not_contain_regexp(regexp)
|
295
|
+
warn "WARNING: page_should_not_contain_regexp is deprecated. Use should_not_see instead."
|
296
|
+
if page.has_xpath?('.//*', :text => regexp)
|
297
|
+
raise Kelp::Unexpected
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
316
301
|
end
|
317
302
|
end
|
318
303
|
|