test-unit-capybara 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8; mode: ruby -*-
2
+ #
3
+ # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ gem "test-unit", ">= 2.4.4"
20
+ gem "capybara", ">= 1.1.3"
21
+ gem "json"
22
+
23
+ group :development, :test do
24
+ gem "rake"
25
+ gem "jeweler"
26
+ gem "yard"
27
+ gem "packnga"
28
+ gem "test-unit-notify"
29
+ end
@@ -0,0 +1,87 @@
1
+ h1. test-unit-capybara
2
+
3
+ "Web site":http://test-unit.rubyforge.org/#test-unit-capybara
4
+
5
+ h2. Description
6
+
7
+ test-unit-capybara is a Capybara adapter for test-unit 2. You can get "Capybara":https://rubygems.org/gems/capybara integrated Test::Unit::TestCase. It also provides useful assertions for Capybara.
8
+
9
+ h2. Install
10
+
11
+ <pre>
12
+ % sudo gem install test-unit-capybara
13
+ </pre>
14
+
15
+ h2. Usage
16
+
17
+ <pre>
18
+ require 'test/unit/capybara'
19
+
20
+ class MyRackApplication
21
+ def call(env)
22
+ html = <<-HTML
23
+ <html>
24
+ <head>
25
+ <title>Welcome! - my site</title>
26
+ </head>
27
+ <body>
28
+ <h1>Welcome!</h1>
29
+ <div class="header">
30
+ <p>No navigation.</p>
31
+ </div>
32
+ </body>
33
+ </html>
34
+ HTML
35
+ [200, {"Content-Type" => "text/html"}, [html]]
36
+ end
37
+ end
38
+
39
+ class TestMyRackApplication < Test::Unit::TestCase
40
+ include Capybara::DSL
41
+
42
+ def setup
43
+ Capybara.app = MyRackApplication.new
44
+ end
45
+
46
+ def test_title
47
+ visit("/")
48
+ within("h1") do
49
+ assert_equal("Welcome!", text)
50
+ end
51
+ end
52
+
53
+ def test_no_sidebar
54
+ visit("/")
55
+ within("body") do
56
+ assert_not_find(".sidebar")
57
+ end
58
+ end
59
+
60
+ def test_header_content
61
+ visit("/")
62
+ within(".header") do
63
+ find("ol.navi")
64
+ # This fails with the following message:
65
+ #
66
+ # <"ol.navi">(:css) expected to find a element in
67
+ # <<div class="header">
68
+ # <p>No navigation.</p>
69
+ # </div>>
70
+ #
71
+ # This messages shows the current context. You don't need to
72
+ # entire HTML. You just see the current context moved by "within".
73
+ # It helps you debug a problem without save_and_open_page.
74
+ end
75
+ end
76
+ end
77
+ </pre>
78
+
79
+ h2. License
80
+
81
+ LGPLv2.1 or later.
82
+
83
+ (Kouhei Sutou has a right to change the license including contributed patches.)
84
+
85
+ h2. Authors
86
+
87
+ * Kouhei Sutou
data/Rakefile CHANGED
@@ -1,33 +1,81 @@
1
1
  # -*- ruby -*-
2
+ #
3
+ # Copyright (C) 2011-2012 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2
18
 
3
- require 'pathname'
19
+ require './lib/test/unit/capybara/version'
4
20
 
5
- base_dir = Pathname(__FILE__).dirname.expand_path
6
- test_unit_dir = (base_dir.parent + "test-unit").expand_path
7
- test_unit_lib_dir = test_unit_dir + "lib"
8
- lib_dir = base_dir + "lib"
21
+ require 'rubygems'
22
+ require 'rubygems/package_task'
23
+ require 'yard'
24
+ require 'jeweler'
25
+ require 'packnga'
9
26
 
10
- $LOAD_PATH.unshift(test_unit_lib_dir.to_s)
11
- $LOAD_PATH.unshift(lib_dir.to_s)
27
+ def cleanup_white_space(entry)
28
+ entry.gsub(/(\A\n+|\n+\z)/, '') + "\n"
29
+ end
12
30
 
13
- require 'test/unit/capybara'
31
+ ENV["VERSION"] ||= Test::Unit::Capybara::VERSION
32
+ version = ENV["VERSION"].dup
33
+ spec = nil
34
+ Jeweler::Tasks.new do |_spec|
35
+ spec = _spec
36
+ spec.name = "test-unit-capybara"
37
+ spec.version = version
38
+ spec.rubyforge_project = "test-unit"
39
+ spec.homepage = "http://test-unit.rubyforge.org/#test-unit-capybara"
40
+ spec.authors = ["Kouhei Sutou"]
41
+ spec.email = ["kou@clear-code.com"]
42
+ entries = File.read("README.textile").split(/^h2\.\s(.*)$/)
43
+ description = cleanup_white_space(entries[entries.index("Description") + 1])
44
+ spec.summary, spec.description, = description.split(/\n\n+/, 3)
45
+ spec.license = "LGPLv2 or later"
46
+ spec.files = FileList["lib/**/*.rb",
47
+ "bin/*",
48
+ "doc/text/*",
49
+ "README.textile",
50
+ "COPYING",
51
+ "Rakefile",
52
+ "Gemfile"]
53
+ spec.test_files = FileList["test/**/*.rb"]
54
+ end
14
55
 
15
- require 'rubygems'
16
- require 'hoe'
56
+ Rake::Task["release"].prerequisites.clear
57
+ Jeweler::RubygemsDotOrgTasks.new do
58
+ end
17
59
 
18
- Test::Unit.run = true
60
+ Gem::PackageTask.new(spec) do |pkg|
61
+ pkg.need_tar_gz = true
62
+ end
19
63
 
20
- version = Test::Unit::Capybara::VERSION
21
- ENV["VERSION"] = version
22
- Hoe.spec('test-unit-capybara') do
23
- self.version = version
24
- self.rubyforge_name = "test-unit"
64
+ document_task = Packnga::DocumentTask.new(spec) do
65
+ end
25
66
 
26
- developer('Kouhei Sutou', 'kou@clear-code.com')
67
+ Packnga::ReleaseTask.new(spec) do |task|
68
+ end
27
69
 
28
- extra_deps << ["test-unit", ">= 2.1.2"]
29
- extra_deps << ["capybara"]
70
+ # XXX: Workaround. This should be fixed in packnga.
71
+ task :htaccess do
72
+ htaccess = "doc/html/test-unit-capybara/.htaccess"
73
+ htaccess_content = File.read(htaccess)
74
+ File.open(htaccess, "w") do |htaccess_file|
75
+ htaccess_file.print(htaccess_content.gsub(/#test-unit-capybara/, ""))
76
+ end
30
77
  end
78
+ task "release:reference:publish" => :htaccess
31
79
 
32
80
  desc "Tag the current revision."
33
81
  task :tag do
@@ -0,0 +1,15 @@
1
+ h1. News
2
+
3
+ h2(#1-0-1). 1.0.1 - 2012-01-16
4
+
5
+ A Capybara integration improvement release.
6
+
7
+ h3. Improvments
8
+
9
+ * Added {Test::Unit::Capybara::Assertions#assert_all}.
10
+ * Added {Test::Unit::Capybara::Assertions#assert_not_find}.
11
+ * Supported Capybara::ElementNotFound as a failure.
12
+
13
+ h2(#1-0-0). 1.0.0 - 2011-05-01
14
+
15
+ The first release!!!
@@ -1,25 +1,37 @@
1
- #--
1
+ # -*- ruby -*-
2
2
  #
3
- # Author:: Kouhei Sutou
4
- # Copyright::
5
- # * Copyright (c) 2011 Kouhei Sutou <kou@clear-code.com>
6
- # License:: LGPLv2+
3
+ # Copyright (C) 2011-2012 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ require "test/unit/capybara/version"
7
20
 
8
21
  require 'capybara'
9
22
  require 'capybara/dsl'
23
+ require "json"
10
24
  require 'test/unit'
11
25
 
12
26
  module Test::Unit
13
27
  module Capybara
14
- VERSION = "1.0.0"
15
-
16
28
  module Adapter
17
29
  class << self
18
30
  def included(mod)
19
31
  mod.module_eval do
20
32
  setup :before => :prepend
21
33
  def setup_capybara
22
- return unless self.class.include?(::Capybara)
34
+ return unless self.class.include?(::Capybara::DSL)
23
35
  extend(Assertions)
24
36
  if self[:js]
25
37
  ::Capybara.current_driver = ::Capybara.javascript_driver
@@ -30,7 +42,7 @@ module Test::Unit
30
42
 
31
43
  teardown :after => :append
32
44
  def teardown_capybara
33
- return unless self.class.include?(::Capybara)
45
+ return unless self.class.include?(::Capybara::DSL)
34
46
  ::Capybara.reset_sessions!
35
47
  ::Capybara.use_default_driver
36
48
  end
@@ -39,33 +51,443 @@ module Test::Unit
39
51
  end
40
52
  end
41
53
 
54
+ # @private
55
+ class ElementNotFound < ::Capybara::ElementNotFound
56
+ attr_reader :node, :query
57
+ def initialize(node, query)
58
+ @node = node
59
+ @query = query
60
+ super(@query.failure_message(:find, @node))
61
+ end
62
+ end
63
+
64
+ # @private
65
+ module FindError
66
+ class << self
67
+ def included(base)
68
+ base.module_eval do
69
+ alias_method :raise_find_error_original, :raise_find_error
70
+ alias_method :raise_find_error, :raise_find_error_for_test_unit
71
+ end
72
+ end
73
+ end
74
+
75
+ def raise_find_error_for_test_unit(*args)
76
+ query = ::Capybara::Query.new(*args)
77
+ raise ElementNotFound.new(self, query)
78
+ end
79
+ end
80
+
81
+ # @private
82
+ class ::Capybara::Node::Base
83
+ include FindError
84
+ end
85
+
86
+ # @private
87
+ module ElementNotFoundHandler
88
+ class << self
89
+ def included(base)
90
+ base.exception_handler(:handle_capybara_element_not_found)
91
+ end
92
+ end
93
+
94
+ private
95
+ def handle_capybara_element_not_found(exception)
96
+ return false unless exception.is_a?(ElementNotFound)
97
+ return false unless respond_to?(:flunk_find)
98
+ query = exception.query
99
+ begin
100
+ flunk_find(exception.node,
101
+ :kind => query.selector.name,
102
+ :locator => query.locator)
103
+ rescue AssertionFailedError => assertion_failed_error
104
+ assertion_failed_error.backtrace.replace(exception.backtrace)
105
+ handle_exception(assertion_failed_error)
106
+ end
107
+ end
108
+ end
109
+
110
+ # @private
111
+ class NodeInspector
112
+ Inspector = ::Test::Unit::Assertions::AssertionMessage::Inspector
113
+ Inspector.register_inspector_class(self)
114
+
115
+ class << self
116
+ def target?(object)
117
+ object.is_a?(::Capybara::Node::Base)
118
+ end
119
+
120
+ def source(node)
121
+ if node.base.respond_to?(:source)
122
+ node.base.source
123
+ else
124
+ node.base.native.to_s
125
+ end
126
+ end
127
+ end
128
+
129
+ def initialize(node, inspected_objects)
130
+ @node = node
131
+ @inspected_objects = inspected_objects
132
+ end
133
+
134
+ def inspect
135
+ @node.inspect.gsub(/>\z/, " #{self.class.source(@node)}>")
136
+ end
137
+
138
+ def pretty_print(q)
139
+ q.text(@node.inspect.gsub(/>\z/, ""))
140
+ q.breakable
141
+ q.text("#{self.class.source(@node)}>")
142
+ end
143
+ end
144
+
42
145
  module Assertions
43
- def assert_body(expected, options={})
146
+ # @private
147
+ AssertionMessage = ::Test::Unit::Assertions::AssertionMessage
148
+
149
+ # Passes if @expected@ == @source@. @source@ is a
150
+ # method provided by Capybara::DSL.
151
+ #
152
+ # @source@ may be parsed depended on response
153
+ # Content-Type before comparing. Here are parsed
154
+ # Content-Types:
155
+ #
156
+ # - @"application/json"@ := It's parsed by @JSON.parse@.
157
+ #
158
+ # @param [Object] expected the expected body
159
+ # content. The actual body may be parsed. It
160
+ # depends on @:content_type@ option.
161
+ #
162
+ # @option options [String] :content_type (nil)
163
+ # the expected Content-Type. If this value is @nil@,
164
+ # Content-Type will not be compared.
165
+ #
166
+ # This value can be specified by abbreviated. Here
167
+ # are abbreviations:
168
+ #
169
+ # - @:json@ := @"application/json"@
170
+ #
171
+ # @yield [expected_response, actual_response] the
172
+ # optional compared responses normalizer.
173
+ # @yieldparam [Hash] expected_response the expected
174
+ # response constructed in the method.
175
+ # @yieldparam [Hash] actual_response the actual
176
+ # response constructed in the method.
177
+ # @yieldreturn [expected_response, actual_response] the
178
+ # normalized compared responses.
179
+ #
180
+ # @example Pass case
181
+ # # Actual response:
182
+ # # Content-Type: application/json
183
+ # # Body: {"status": true}
184
+ # assert_body({"status" => true}, :content_type => :json)
185
+ #
186
+ # @example Failure case
187
+ # # Actual response:
188
+ # # Content-Type: text/html
189
+ # # Body: <html><body>Hello</body></html>
190
+ # assert_body("<html><body>World</body></html>")
191
+ def assert_body(expected, options={}, &block)
44
192
  content_type = options[:content_type]
45
- case content_type
46
- when :json
47
- assert_equal({
48
- :content_type => "application/json",
49
- :body => expected,
50
- },
51
- {
52
- :content_type => page.response_headers["Content-Type"],
53
- :body => JSON.parse(body),
54
- })
193
+ actual_response = {
194
+ :content_type => page_content_type,
195
+ :body => parsed_page_body,
196
+ }
197
+ expected_response = {:body => expected}
198
+ if content_type
199
+ expected_response[:content_type] = normalize_content_type(content_type)
200
+ else
201
+ actual_response.delete(:content_type)
202
+ end
203
+ if block_given?
204
+ expected_response, actual_response = yield(expected_response,
205
+ actual_response)
206
+ end
207
+ assert_equal(expected_response, actual_response)
208
+ end
209
+
210
+ # @param [...] args (see {::Capybara::Node::Finders#all})
211
+ # @return [Array<::Capybara::Element>] The found elements.
212
+ #
213
+ # @see Capybara::Node::Finders#all
214
+ #
215
+ # @overload assert_all(*args)
216
+ # Passes if the selector finds one or more elements
217
+ # from the current node.
218
+ #
219
+ # @example Pass case
220
+ # # Actual response:
221
+ # # <html>
222
+ # # <body>
223
+ # # <h1>Hello</h1>
224
+ # # <h2>Yay!</h2>
225
+ # # <div class="section">
226
+ # # <h2>World</h2>
227
+ # # </div>
228
+ # # </body>
229
+ # # </html>
230
+ # h2_elements = assert_page_all("h2")
231
+ # p h2_elements
232
+ # # => [#<Capybara::Element tag="h2" path="/html/body/h2">,
233
+ # # #<Capybara::Element tag="h2" path="/html/body/div/h2">]
234
+ #
235
+ # @example Failure case
236
+ # # Actual response:
237
+ # # <html>
238
+ # # <body>
239
+ # # <h1>Hello</h1>
240
+ # # <h2>Yay!</h2>
241
+ # # <div class="section">
242
+ # # <h2>World</h2>
243
+ # # </div>
244
+ # # </body>
245
+ # # </html>
246
+ # assert_page_all("h3")
247
+ #
248
+ # @overload assert_all(node, *args)
249
+ # Passes if the selector finds one or more elements
250
+ # from @node@.
251
+ #
252
+ # @param [::Capybara::Node::Base] node The target node.
253
+ #
254
+ # @example Pass case (simple)
255
+ # # Actual response:
256
+ # # <html>
257
+ # # <body>
258
+ # # <h1>Hello</h1>
259
+ # # <h2>Yay!</h2>
260
+ # # <div class="section">
261
+ # # <h2>World</h2>
262
+ # # </div>
263
+ # # </body>
264
+ # # </html>
265
+ # section = assert_find("div.section")
266
+ # p section
267
+ # # => #<Capybara::Element tag="h2" path="/html/body/div">
268
+ # h2_elements = assert_all(section, "h2")
269
+ # p h2_elements
270
+ # # => [#<Capybara::Element tag="h2" path="/html/body/div/h2">]
271
+ def assert_all(*args)
272
+ node = nil
273
+ node = args.shift if args[0].is_a?(::Capybara::Node::Base)
274
+ args = normalize_page_finder_arguments(args)
275
+ format = <<-EOT
276
+ <?>(?) expected to find one or more elements in
277
+ <?>
278
+ EOT
279
+ current_context = node || page.send(:current_node)
280
+ current_context_source = node_source(current_context)
281
+ source_in_message = AssertionMessage.literal(current_context_source)
282
+ full_message = build_message(args[:message],
283
+ format,
284
+ args[:locator],
285
+ args[:kind],
286
+ source_in_message)
287
+ if node
288
+ elements = node.all(*args[:finder_arguments])
289
+ else
290
+ elements = all(*args[:finder_arguments])
291
+ end
292
+ assert_block(full_message) do
293
+ not elements.empty?
294
+ end
295
+ elements
296
+ end
297
+
298
+ # @param [...] args (see {::Capybara::Node::Finders#find})
299
+ #
300
+ # @see ::Capybara::Node::Finders#find
301
+ #
302
+ # @overload assert_not_find(*args, &block)
303
+ # Passes if the selector doesn't find any elements
304
+ # from the current node.
305
+ #
306
+ # @example Pass case
307
+ # # Actual response:
308
+ # # <html>
309
+ # # <body>
310
+ # # <h1>Hello</h1>
311
+ # # <h2>Yay!</h2>
312
+ # # <div class="section">
313
+ # # <h2>World</h2>
314
+ # # </div>
315
+ # # </body>
316
+ # # </html>
317
+ # assert_not_find("h3")
318
+ #
319
+ # @example Failure case
320
+ # # Actual response:
321
+ # # <html>
322
+ # # <body>
323
+ # # <h1>Hello</h1>
324
+ # # <h2>Yay!</h2>
325
+ # # <div class="section">
326
+ # # <h2>World</h2>
327
+ # # </div>
328
+ # # </body>
329
+ # # </html>
330
+ # assert_not_find("h1")
331
+ #
332
+ # @overload assert_not_find(node, *args, &block)
333
+ # Passes if the selector doesn't find any element from @node@.
334
+ #
335
+ # @param [::Capybara::Node::Base] node The target node.
336
+ #
337
+ # @example Pass case
338
+ # # Actual response:
339
+ # # <html>
340
+ # # <body>
341
+ # # <h1>Hello</h1>
342
+ # # <h2>Yay!</h2>
343
+ # # <div class="section">
344
+ # # <h2>World</h2>
345
+ # # </div>
346
+ # # </body>
347
+ # # </html>
348
+ # section = assert_find("section")
349
+ # p section
350
+ # # => #<Capybara::Element tag="h2" path="/html/body/div">
351
+ # assert_not_find(section, "h1")
352
+ #
353
+ # @example Failure case
354
+ # # Actual response:
355
+ # # <html>
356
+ # # <body>
357
+ # # <h1>Hello</h1>
358
+ # # <h2>Yay!</h2>
359
+ # # <div class="section">
360
+ # # <h2>World</h2>
361
+ # # </div>
362
+ # # </body>
363
+ # # </html>
364
+ # section = assert_find("section")
365
+ # p section
366
+ # # => #<Capybara::Element tag="h2" path="/html/body/div">
367
+ # assert_not_find(section, "h2")
368
+ def assert_not_find(*args, &block)
369
+ node = nil
370
+ node = args.shift if args[0].is_a?(::Capybara::Node::Base)
371
+ args = normalize_page_finder_arguments(args)
372
+ if node
373
+ element = node.first(*args[:finder_arguments])
374
+ else
375
+ element = first(*args[:finder_arguments])
376
+ end
377
+ format = <<-EOT
378
+ <?>(?) expected to not find a element but was
379
+ <?> in
380
+ <?>
381
+ EOT
382
+ element_source = nil
383
+ element_source = node_source(element) if element
384
+ current_context = node || page.send(:current_node)
385
+ current_context_source = node_source(current_context)
386
+ source_in_message = AssertionMessage.literal(current_context_source)
387
+ full_message = build_message(args[:message],
388
+ format,
389
+ args[:locator],
390
+ args[:kind],
391
+ AssertionMessage.literal(element_source),
392
+ source_in_message)
393
+ assert_block(full_message) do
394
+ element.nil?
395
+ end
396
+ end
397
+
398
+ # Fails always with {::Capybara::Node::Element} is not
399
+ # found message.
400
+ #
401
+ # @param [::Capybara::Node::Element] base_node The
402
+ # node used as search target.
403
+ # @option options [String] :message The user custom
404
+ # message added to failure message.
405
+ # @option options [String] :locator The query used to
406
+ # find a node.
407
+ #
408
+ # It should be specified for useful failure message.
409
+ # @option options [String] :kind The kind of query.
410
+ #
411
+ # It should be specified for useful failure message.
412
+ def flunk_find(base_node, options={})
413
+ format = <<-EOT
414
+ <?>(?) expected to find a element in
415
+ <?>
416
+ EOT
417
+ base_html = AssertionMessage.literal(node_source(base_node))
418
+ full_message = build_message(options[:message],
419
+ format,
420
+ options[:locator],
421
+ options[:kind],
422
+ base_html)
423
+ assert_block(full_message) do
424
+ false
425
+ end
426
+ end
427
+
428
+ private
429
+ def page_content_type
430
+ page.response_headers["Content-Type"]
431
+ end
432
+
433
+ def parsed_page_body
434
+ case page_content_type
435
+ when "application/json"
436
+ ::JSON.parse(source)
437
+ else
438
+ source
439
+ end
440
+ end
441
+
442
+ def normalize_page_finder_arguments(args)
443
+ args = args.dup
444
+ options = {}
445
+ options = args.pop if args.last.is_a?(Hash)
446
+ if args.size == 1
447
+ locator = args[0]
448
+ if locator[0, 1] == "/"
449
+ kind = :xpath
450
+ args.unshift(kind)
451
+ else
452
+ kind = ::Capybara.default_selector
453
+ end
55
454
  else
56
- format = "unsupported content type: <?>\n" +
57
- "expected: <?>\n" +
58
- " options: <?>"
59
- arguments = [content_type, expected, options]
60
- assert_block(build_message(nil, format, *arguments)) do
61
- false
455
+ kind, locator, = args
456
+ end
457
+ args << options
458
+
459
+ {
460
+ :kind => kind,
461
+ :locator => locator,
462
+ :message => options.delete(:message),
463
+ :finder_arguments => args,
464
+ }
465
+ end
466
+
467
+ def node_source(node)
468
+ if node
469
+ if node.base.respond_to?(:source)
470
+ node.base.source
471
+ else
472
+ node.base.native.to_s
62
473
  end
474
+ else
475
+ source
63
476
  end
64
477
  end
478
+
479
+ # @private
480
+ CONTENT_TYPE_SHORTCUTS = {
481
+ :json => "application/json",
482
+ }
483
+ def normalize_content_type(content_type)
484
+ CONTENT_TYPE_SHORTCUTS[content_type] || content_type
485
+ end
65
486
  end
66
487
  end
67
488
 
68
489
  class TestCase
69
490
  include Capybara::Adapter
491
+ include Capybara::ElementNotFoundHandler
70
492
  end
71
493
  end