kookaburra 0.27.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,17 +1,18 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'patron'
4
- gem 'json_pure'
3
+ gem 'rest-client'
5
4
 
6
5
  # Add dependencies to develop your gem here.
7
6
  # Include everything needed to run rake, tests, features, etc.
8
7
  group :development do
8
+ gem 'jruby-openssl', :platforms => :jruby
9
9
  gem 'rspec'
10
10
  gem 'capybara'
11
11
  gem 'yard'
12
- gem 'redcarpet', '~> 1.0' # used to format documentation
12
+ gem 'kramdown' # used by yard to format documentation, but not a dependency as far as the yard gem is concerned
13
13
  gem 'jeweler'
14
14
  gem 'reek'
15
15
  gem 'sinatra'
16
- gem 'find_a_port', '>= 1.0.1'
16
+ gem 'find_a_port'
17
+ gem 'json'
17
18
  end
data/Gemfile.lock CHANGED
@@ -2,6 +2,7 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  addressable (2.3.2)
5
+ bouncy-castle-java (1.5.0146.1)
5
6
  capybara (1.1.2)
6
7
  mime-types (>= 1.16)
7
8
  nokogiri (>= 1.3.3)
@@ -9,10 +10,11 @@ GEM
9
10
  rack-test (>= 0.5.4)
10
11
  selenium-webdriver (~> 2.0)
11
12
  xpath (~> 0.1.4)
12
- childprocess (0.3.4)
13
+ childprocess (0.3.5)
13
14
  ffi (~> 1.0, >= 1.0.6)
14
15
  diff-lcs (1.1.3)
15
- ffi (1.1.0)
16
+ ffi (1.1.5)
17
+ ffi (1.1.5-java)
16
18
  find_a_port (1.0.1)
17
19
  git (1.2.5)
18
20
  jeweler (1.8.4)
@@ -20,28 +22,32 @@ GEM
20
22
  git (>= 1.2.5)
21
23
  rake
22
24
  rdoc
23
- json (1.7.4)
24
- json_pure (1.7.4)
25
+ jruby-openssl (0.7.7)
26
+ bouncy-castle-java (>= 1.5.0146.1)
27
+ json (1.7.5)
28
+ json (1.7.5-java)
29
+ kramdown (0.14.0)
25
30
  libwebsocket (0.1.5)
26
31
  addressable
27
32
  mime-types (1.19)
28
33
  multi_json (1.3.6)
29
34
  nokogiri (1.5.5)
30
- patron (0.4.18)
35
+ nokogiri (1.5.5-java)
31
36
  rack (1.4.1)
32
37
  rack-protection (1.2.0)
33
38
  rack
34
- rack-test (0.6.1)
39
+ rack-test (0.6.2)
35
40
  rack (>= 1.0)
36
41
  rake (0.9.2.2)
37
42
  rdoc (3.12)
38
43
  json (~> 1.4)
39
- redcarpet (1.17.2)
40
44
  reek (1.2.12)
41
45
  ripper_ruby_parser (~> 0.0.7)
42
46
  ruby2ruby (~> 1.2.5)
43
47
  ruby_parser (~> 2.0)
44
48
  sexp_processor (~> 3.0)
49
+ rest-client (1.6.7)
50
+ mime-types (>= 1.16)
45
51
  ripper_ruby_parser (0.0.8)
46
52
  sexp_processor (~> 3.0)
47
53
  rspec (2.11.0)
@@ -49,9 +55,9 @@ GEM
49
55
  rspec-expectations (~> 2.11.0)
50
56
  rspec-mocks (~> 2.11.0)
51
57
  rspec-core (2.11.1)
52
- rspec-expectations (2.11.2)
58
+ rspec-expectations (2.11.3)
53
59
  diff-lcs (~> 1.1.3)
54
- rspec-mocks (2.11.1)
60
+ rspec-mocks (2.11.3)
55
61
  ruby2ruby (1.2.5)
56
62
  ruby_parser (~> 2.0)
57
63
  sexp_processor (~> 3.0)
@@ -64,7 +70,7 @@ GEM
64
70
  multi_json (~> 1.0)
65
71
  rubyzip
66
72
  sexp_processor (3.2.0)
67
- sinatra (1.3.2)
73
+ sinatra (1.3.3)
68
74
  rack (~> 1.3, >= 1.3.6)
69
75
  rack-protection (~> 1.2)
70
76
  tilt (~> 1.3, >= 1.3.3)
@@ -74,16 +80,18 @@ GEM
74
80
  yard (0.8.2.1)
75
81
 
76
82
  PLATFORMS
83
+ java
77
84
  ruby
78
85
 
79
86
  DEPENDENCIES
80
87
  capybara
81
- find_a_port (>= 1.0.1)
88
+ find_a_port
82
89
  jeweler
83
- json_pure
84
- patron
85
- redcarpet (~> 1.0)
90
+ jruby-openssl
91
+ json
92
+ kramdown
86
93
  reek
94
+ rest-client
87
95
  rspec
88
96
  sinatra
89
97
  yard
data/README.markdown CHANGED
@@ -3,6 +3,11 @@
3
3
  Kookaburra is a framework for implementing the [Window Driver] [Window Driver] pattern in
4
4
  order to keep acceptance tests maintainable.
5
5
 
6
+ ## Requirements ##
7
+
8
+ Requires Ruby 1.9. Tested with both MRI and JRUBY (not that you must run
9
+ JRuby in 1.9 compatability mode.)
10
+
6
11
  ## Installation ##
7
12
 
8
13
  Kookaburra is available as a Rubygem and [published on Rubygems.org] [Kookaburra Gem],
@@ -111,13 +116,14 @@ and shut down a Rack application server. Just add the following to
111
116
 
112
117
  require 'kookaburra/test_helpers'
113
118
  require 'thwait'
119
+ require 'find_a_port' # from the find_a_port gem
114
120
 
115
121
  # Change these to the files that define your custom GivenDriver and UIDriver
116
122
  # implementations.
117
123
  require 'my_app/kookaburra/given_driver'
118
124
  require 'my_app/kookaburra/ui_driver'
119
125
 
120
- APP_PORT = ENV['APP_PORT'] || 3009
126
+ APP_PORT = FindAPort.available_port
121
127
 
122
128
  # c.app_host below should be set to whatever the root URL of your running
123
129
  # application is.
@@ -141,6 +147,10 @@ and shut down a Rack application server. Just add the following to
141
147
  c.before(:all, :type => :request) do
142
148
  # Run the server process in a forked process, and get a handle on that
143
149
  # process, so that it can be shut down after the tests run.
150
+ #
151
+ # Note that you cannot fork under JRuby and will need to use a thread.
152
+ # See `spec/integration/test_a_rack_application_spec.rb` for an
153
+ # example.
144
154
  @rack_server_pid = fork do
145
155
  Capybara.server_port = APP_PORT
146
156
  Capybara::Server.new(MyApplication).boot
@@ -205,13 +215,14 @@ and shut down a Rack application server. Just add the following to
205
215
 
206
216
  require 'kookaburra/test_helpers'
207
217
  require 'thwait'
218
+ require 'find_a_port' # from the find_a_port gem
208
219
 
209
220
  # Change these to the files that define your custom GivenDriver and UIDriver
210
221
  # implementations.
211
222
  require 'my_app/kookaburra/given_driver'
212
223
  require 'my_app/kookaburra/ui_driver'
213
224
 
214
- APP_PORT = ENV['APP_PORT'] || 3009
225
+ APP_PORT = FindAPort.available_port
215
226
 
216
227
  # c.app_host below should be set to whatever the root URL of your running
217
228
  # application is.
@@ -227,12 +238,16 @@ and shut down a Rack application server. Just add the following to
227
238
 
228
239
  World(Kookaburra::TestHelpers)
229
240
 
230
- # Start the application server prior to running a group of integration
231
- # specs. `MyApplication` below should be replaced with the object that
241
+ # Start the application server prior to running the tests.
242
+ # `MyApplication` below should be replaced with the object that
232
243
  # implements the Rack `#call` interface for your application. For a Rails
233
244
  # app, this would be along the lines of `MyAppName::Application`.
234
245
  # Runs the server process in a forked process, and get a handle on that
235
246
  # process, so that it can be shut down after the tests run.
247
+ #
248
+ # Note that you cannot fork under JRuby and will need to use a thread.
249
+ # See `spec/integration/test_a_rack_application_spec.rb` for an
250
+ # example.
236
251
  @rack_server_pid = fork do
237
252
  Capybara.server_port = APP_PORT
238
253
  Capybara::Server.new(MyApplication).boot
@@ -519,32 +534,32 @@ rather than driving a web browser.
519
534
 
520
535
  #### API Driver ####
521
536
 
522
- The `Kookaburra::APIDriver` is used to interact with an application's external
523
- web services API. You tell Kookaburra about your API by creating a subclass of
524
- `Kookaburra::APIDriver` for your application. Because different applications may
525
- implement different types of APIs, Kookaburra will provide more than one base
526
- APIDriver class. At the moment, only a JSON API is supported via
527
- `Kookaburra::JsonApiDriver`:
537
+ The `Kookaburra::APIDriver` is used to interact with an application's
538
+ external web services API. You tell Kookaburra about your API by
539
+ creating a subclass of `Kookaburra::APIDriver` for your application,
540
+ specifying how requests should be encoded and decoded, and specifying
541
+ any headers that should be present on every request.
528
542
 
529
543
  # lib/my_app/kookaburra/api_driver.rb
530
544
 
531
- class MyApp::Kookaburra::APIDriver < Kookaburra::JsonApiDriver
545
+ class MyApp::Kookaburra::APIDriver < Kookaburra::APIDriver
546
+ encode_with { |data| JSON.dump(data) }
547
+ decode_with { |data| JSON.parse(data) }
548
+ header 'Content-Type', 'application/json'
549
+ header 'Accept', 'application/json'
550
+
532
551
  def create_account(account_data)
533
- post '/api/v1/accounts', account_data
552
+ post '/api/accounts', account_data
534
553
  end
535
554
 
536
555
  def get_account(id)
537
- get '/api/v1/accounts/%d' % id
556
+ get '/api/accounts/%d' % id
538
557
  end
539
558
  end
540
559
 
541
- Regardless of the type of APIDriver, the content of your application's APIDriver
542
- should consist mainly of mappings between discrete actions and HTTP requests to
543
- the specified URL paths. Each driver will implement `#post`, `#get`, `#put` and
544
- `#delete` in such a way that any Ruby data structure provided as parameters will
545
- be appropriately translated to the API's required data format, and any response
546
- body from the API request will be translated into a Ruby data structure and
547
- returned.
560
+ The content of your application's APIDriver should consist mainly of
561
+ mappings between discrete actions and HTTP requests to the specified URL
562
+ paths.
548
563
 
549
564
  #### UI Driver ####
550
565
 
@@ -623,12 +638,13 @@ You describe the various user interface components by sub-classing
623
638
  ### The Application Driver Layer ###
624
639
 
625
640
  `Kookaburra::APIDriver`, `Kookaburra::UIDriver` and
626
- `Kookaburra::UIDriver::UIComponent` rely on the Application Driver layer to
627
- interact with your application. In the case of the `APIDriver`, Kookaburra uses
628
- the [Patron] [Patron] library to send HTTP requests to your application. The
629
- `UIDriver` and `UIComponent` rely on whatever is passed to `Kookaburra.new` as
630
- the `:browser` option. Presently, we have only used Capybara as the application
631
- driver for Kookaburra.
641
+ `Kookaburra::UIDriver::UIComponent` rely on the Application Driver layer
642
+ to interact with your application. In the case of the `APIDriver`,
643
+ Kookaburra uses the [RestClient] [RestClient] library to send HTTP
644
+ requests to your application. The `UIDriver` and `UIComponent` rely on
645
+ whatever is passed to `Kookaburra.new` as the `:browser` option.
646
+ Presently, we have only used Capybara as the application driver for
647
+ Kookaburra.
632
648
 
633
649
  It's possible that something other than Capybara could be passed in, as long as
634
650
  that something presented the same API. In reality, using something other than
@@ -664,4 +680,4 @@ further details.
664
680
  [RSpec]: http://rspec.info "RSpec.info: home"
665
681
  [Cucumber]: http://cukes.info/ "Cucumber - Making BDD fun"
666
682
  [Pull Request]: https://github.com/projectdx/kookaburra/pull/new/master "Send a pull request - GitHub"
667
- [Patron]: https://github.com/toland/patron "toland/patron"
683
+ [RestClient]: https://github.com/archiloque/rest-client "archiloque/rest-client -GitHub"
data/Rakefile CHANGED
@@ -29,8 +29,25 @@ require 'rspec/core/rake_task'
29
29
 
30
30
  task :default => :spec
31
31
 
32
- desc 'Run specs'
33
- RSpec::Core::RakeTask.new
32
+ # TODO: figure out how to get rake task working under JRuby and rbenv
33
+ if defined?(JRUBY_VERSION) && ENV['RBENV_VERSION']
34
+ desc 'Run specs'
35
+ task :spec do
36
+ msg = <<-EOM
37
+ ********************************************************************************
38
+ * You appear to be running under JRuby and using rbenv.
39
+ *
40
+ * For some reason the `rake spec` command isn't working correctly in
41
+ * these circumstances. However, you should be able to just run the
42
+ * `rspec` command directly.
43
+ ********************************************************************************
44
+ EOM
45
+ raise msg
46
+ end
47
+ else
48
+ desc 'Run specs'
49
+ RSpec::Core::RakeTask.new
50
+ end
34
51
 
35
52
  require 'reek/rake/task'
36
53
  Reek::Rake::Task.new do |t|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.27.0
1
+ 1.0.0
data/kookaburra.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "kookaburra"
8
- s.version = "0.27.0"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["John Wilger", "Sam Livingston-Gray", "Ravi Gadad"]
12
- s.date = "2012-08-21"
12
+ s.date = "2012-10-14"
13
13
  s.description = "Cucumber + Capybara = Kookaburra? It made sense at the time."
14
14
  s.email = "johnwilger@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -35,7 +35,6 @@ Gem::Specification.new do |s|
35
35
  "lib/kookaburra/dependency_accessor.rb",
36
36
  "lib/kookaburra/exceptions.rb",
37
37
  "lib/kookaburra/given_driver.rb",
38
- "lib/kookaburra/json_api_driver.rb",
39
38
  "lib/kookaburra/mental_model.rb",
40
39
  "lib/kookaburra/mental_model_matcher.rb",
41
40
  "lib/kookaburra/test_helpers.rb",
@@ -47,7 +46,6 @@ Gem::Specification.new do |s|
47
46
  "spec/integration/test_a_rack_application_spec.rb",
48
47
  "spec/kookaburra/api_driver_spec.rb",
49
48
  "spec/kookaburra/configuration_spec.rb",
50
- "spec/kookaburra/json_api_driver_spec.rb",
51
49
  "spec/kookaburra/mental_model_matcher_spec.rb",
52
50
  "spec/kookaburra/mental_model_spec.rb",
53
51
  "spec/kookaburra/test_helpers_spec.rb",
@@ -70,39 +68,42 @@ Gem::Specification.new do |s|
70
68
  s.specification_version = 3
71
69
 
72
70
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
73
- s.add_runtime_dependency(%q<patron>, [">= 0"])
74
- s.add_runtime_dependency(%q<json_pure>, [">= 0"])
71
+ s.add_runtime_dependency(%q<rest-client>, [">= 0"])
72
+ s.add_development_dependency(%q<jruby-openssl>, [">= 0"])
75
73
  s.add_development_dependency(%q<rspec>, [">= 0"])
76
74
  s.add_development_dependency(%q<capybara>, [">= 0"])
77
75
  s.add_development_dependency(%q<yard>, [">= 0"])
78
- s.add_development_dependency(%q<redcarpet>, ["~> 1.0"])
76
+ s.add_development_dependency(%q<kramdown>, [">= 0"])
79
77
  s.add_development_dependency(%q<jeweler>, [">= 0"])
80
78
  s.add_development_dependency(%q<reek>, [">= 0"])
81
79
  s.add_development_dependency(%q<sinatra>, [">= 0"])
82
- s.add_development_dependency(%q<find_a_port>, [">= 1.0.1"])
80
+ s.add_development_dependency(%q<find_a_port>, [">= 0"])
81
+ s.add_development_dependency(%q<json>, [">= 0"])
83
82
  else
84
- s.add_dependency(%q<patron>, [">= 0"])
85
- s.add_dependency(%q<json_pure>, [">= 0"])
83
+ s.add_dependency(%q<rest-client>, [">= 0"])
84
+ s.add_dependency(%q<jruby-openssl>, [">= 0"])
86
85
  s.add_dependency(%q<rspec>, [">= 0"])
87
86
  s.add_dependency(%q<capybara>, [">= 0"])
88
87
  s.add_dependency(%q<yard>, [">= 0"])
89
- s.add_dependency(%q<redcarpet>, ["~> 1.0"])
88
+ s.add_dependency(%q<kramdown>, [">= 0"])
90
89
  s.add_dependency(%q<jeweler>, [">= 0"])
91
90
  s.add_dependency(%q<reek>, [">= 0"])
92
91
  s.add_dependency(%q<sinatra>, [">= 0"])
93
- s.add_dependency(%q<find_a_port>, [">= 1.0.1"])
92
+ s.add_dependency(%q<find_a_port>, [">= 0"])
93
+ s.add_dependency(%q<json>, [">= 0"])
94
94
  end
95
95
  else
96
- s.add_dependency(%q<patron>, [">= 0"])
97
- s.add_dependency(%q<json_pure>, [">= 0"])
96
+ s.add_dependency(%q<rest-client>, [">= 0"])
97
+ s.add_dependency(%q<jruby-openssl>, [">= 0"])
98
98
  s.add_dependency(%q<rspec>, [">= 0"])
99
99
  s.add_dependency(%q<capybara>, [">= 0"])
100
100
  s.add_dependency(%q<yard>, [">= 0"])
101
- s.add_dependency(%q<redcarpet>, ["~> 1.0"])
101
+ s.add_dependency(%q<kramdown>, [">= 0"])
102
102
  s.add_dependency(%q<jeweler>, [">= 0"])
103
103
  s.add_dependency(%q<reek>, [">= 0"])
104
104
  s.add_dependency(%q<sinatra>, [">= 0"])
105
- s.add_dependency(%q<find_a_port>, [">= 1.0.1"])
105
+ s.add_dependency(%q<find_a_port>, [">= 0"])
106
+ s.add_dependency(%q<json>, [">= 0"])
106
107
  end
107
108
  end
108
109
 
@@ -1,91 +1,205 @@
1
+ require 'restclient'
1
2
  require 'kookaburra/exceptions'
2
- require 'delegate'
3
- require 'patron'
4
3
 
5
4
  class Kookaburra
6
- class APIDriver < SimpleDelegator
7
- # Wraps `http_client` in a `SimpleDelegator` that causes request methods to
8
- # either return the response body or raise an exception on an unexpected
9
- # response status code.
5
+ # Communicate with a Web Services API
6
+ #
7
+ # You will create a subclass of `APIDriver` in your testing
8
+ # implementation to be used with you subclass of
9
+ # `Kookaburra::GivenDriver`. While the `GivenDriver` implements the
10
+ # "business domain" DSL for setting up your application state, the
11
+ # `APIDriver` maps discreet operations to your application's web
12
+ # service API and can (optionally) handle encoding input data and
13
+ # decoding response bodies to and from your preferred serialization
14
+ # format.
15
+ class APIDriver
16
+ class << self
17
+ # Serializes input data
18
+ #
19
+ # If specified, any input data provided to `APIDriver#post`,
20
+ # `APIDriver#put` or `APIDriver#request` will be processed through
21
+ # this function prior to being sent to the HTTP server.
22
+ #
23
+ # @yieldparam data [Object] The data parameter that was passed to
24
+ # the request method
25
+ # @yieldreturn [String] The text to be used as the request body
26
+ #
27
+ # @example
28
+ # class MyAPIDriver < Kookaburra::APIDriver
29
+ # encode_with { |data| JSON.dump(data) }
30
+ # # ...
31
+ # end
32
+ def encode_with(&block)
33
+ define_method(:encode) do |data|
34
+ return if data.nil?
35
+ block.call(data)
36
+ end
37
+ end
38
+
39
+ # Deserialize response body
40
+ #
41
+ # If specified, the response bodies of all requests made using
42
+ # this `APIDriver` will be processed through this function prior
43
+ # to being returned.
44
+ #
45
+ # @yieldparam data [String] The response body sent by the HTTP
46
+ # server
47
+ #
48
+ # @yieldreturn [Object] The result of parsing the response body
49
+ # through this function
50
+ #
51
+ # @example
52
+ # class MyAPIDriver < Kookaburra::APIDriver
53
+ # decode_with { |data| JSON.parse(data) }
54
+ # # ...
55
+ # end
56
+ def decode_with(&block)
57
+ define_method(:decode) do |data|
58
+ block.call(data)
59
+ end
60
+ end
61
+
62
+ # Set custom HTTP headers
63
+ #
64
+ # Can be called multiple times to set HTTP headers that will be
65
+ # provided with every request made by the `APIDriver`.
66
+ #
67
+ # @param [String] name The name of the header, e.g. 'Content-Type'
68
+ # @param [String] value The value to which the header is set
69
+ #
70
+ # @example
71
+ # class MyAPIDriver < Kookaburra::APIDriver
72
+ # header 'Content-Type', 'application/json'
73
+ # header 'Accept', 'application/json'
74
+ # # ...
75
+ # end
76
+ def header(name, value)
77
+ headers[name] = value
78
+ end
79
+
80
+ # Used to retrieve the list of headers within the instance. Not
81
+ # intended to be used elsewhere.
82
+ #
83
+ # @private
84
+ def headers
85
+ @headers ||= {}
86
+ end
87
+ end
88
+
89
+ # Create a new `APIDriver` instance
10
90
  #
11
91
  # @param [Kookaburra::Configuration] configuration
12
- # @param [Patron::Session] http_client
13
- def initialize(configuration, http_client = Patron::Session.new)
14
- http_client.base_url = configuration.app_host
15
- super(http_client)
92
+ # @param [RestClient] http_client (optional) Generally only
93
+ # overriden when testing Kookaburra itself
94
+ def initialize(configuration, http_client = RestClient)
95
+ @configuration = configuration
96
+ @http_client = http_client
16
97
  end
17
98
 
18
- # Makes a POST request via the `:http_client`
99
+ # Convenience method to make a POST request
19
100
  #
20
- # @param [String] path The path to request (e.g. "/foo")
21
- # @param [Hash, String] data The post data. If a Hash is provided, it will
22
- # be converted to an 'application/x-www-form-urlencoded' post body.
23
- # @option options [Integer] :expected_response_status (201) The HTTP status
24
- # code that you expect the server to respond with.
25
- # @raise [Kookaburra::UnexpectedResponse] raised if the HTTP status of the
26
- # response does not match the `:expected_response_status`
27
- def post(path, data, options = {})
28
- request(:post, path, options, data)
101
+ # @see APIDriver#request
102
+ def post(path, data)
103
+ request(:post, path, data)
29
104
  end
30
105
 
31
- # Makes a PUT request via the `:http_client`
106
+ # Convenience method to make a PUT request
32
107
  #
33
- # @param [String] path The path to request (e.g. "/foo")
34
- # @param [Hash, String] data The post data. If a Hash is provided, it will
35
- # be converted to an 'application/x-www-form-urlencoded' post body.
36
- # @option options [Integer] :expected_response_status (201) The HTTP status
37
- # code that you expect the server to respond with.
38
- # @raise [Kookaburra::UnexpectedResponse] raised if the HTTP status of the
39
- # response does not match the `:expected_response_status`
40
- def put(path, data, options = {})
41
- request(:put, path, options, data)
108
+ # @see APIDriver#request
109
+ def put(path, data)
110
+ request(:put, path, data)
42
111
  end
43
112
 
44
- # Makes a GET request via the `:http_client`
113
+ # Convenience method to make a GET request
45
114
  #
46
- # @param [String] path The path to request (e.g. "/foo")
47
- # @option options [Integer] :expected_response_status (201) The HTTP status
48
- # code that you expect the server to respond with.
49
- # @raise [Kookaburra::UnexpectedResponse] raised if the HTTP status of the
50
- # response does not match the `:expected_response_status`
51
- def get(path, options = {})
52
- request(:get, path, options)
115
+ # @see APIDriver#request
116
+ def get(path)
117
+ request(:get, path)
53
118
  end
54
119
 
55
- # Makes a DELETE request via the `:http_client`
120
+ # Convenience method to make a DELETE request
121
+ #
122
+ # @see APIDriver#request
123
+ def delete(path)
124
+ request(:delete, path)
125
+ end
126
+
127
+ # Make an HTTP request
128
+ #
129
+ # If you need to make a request other than the typical GET, POST,
130
+ # PUT and DELETE, you can use this method directly.
131
+ #
132
+ # This *will* follow redirects when the server's response code is in
133
+ # the 3XX range. If the response is a 303, the request will be
134
+ # transformed into a GET request.
56
135
  #
57
- # @param [String] path The path to request (e.g. "/foo")
58
- # @option options [Integer] :expected_response_status (201) The HTTP status
59
- # code that you expect the server to respond with.
60
- # @raise [Kookaburra::UnexpectedResponse] raised if the HTTP status of the
61
- # response does not match the `:expected_response_status`
62
- def delete(path, options = {})
63
- request(:delete, path, options)
136
+ # @see APIDriver.encode_with
137
+ # @see APIDriver.decode_with
138
+ # @see APIDriver.header
139
+ # @see APIDriver#get
140
+ # @see APIDriver#post
141
+ # @see APIDriver#put
142
+ # @see APIDriver#delete
143
+ #
144
+ # @param [Symbol] method The HTTP verb to use with the request
145
+ # @param [String] path The path to request. Will be joined with the
146
+ # `Kookaburra::Configuration#app_host` setting to build the
147
+ # URL unless a full URL is specified here.
148
+ # @param [Object] data The data to be posted in the request body. If
149
+ # an encoder was specified, this can be any type of object as
150
+ # long as the encoder can serialize it into a String. If no
151
+ # encoder was specified, then this can be one of:
152
+ #
153
+ # * a String - will be passed as is
154
+ # * a Hash - will be encoded as normal HTTP form params
155
+ # * a Hash containing references to one or more Files - will
156
+ # set the content type to multipart/form-data
157
+ #
158
+ # @return [Object] The response body returned by the server. If a
159
+ # decoder was specified, this will return the result of
160
+ # parsing the response body through the decoder function.
161
+ #
162
+ # @raise [Kookaburra::UnexpectedResponse] Raised if the HTTP
163
+ # response received is not in the 2XX-3XX range.
164
+ def request(method, path, data = nil)
165
+ data = encode(data)
166
+ response = @http_client.send(method, url_for(path), *[data, headers].compact)
167
+ decode(response.body)
168
+ rescue RestClient::Exception => e
169
+ raise_unexpected_response(e)
64
170
  end
65
171
 
66
172
  private
67
173
 
68
- def request(type, path, options = {}, data = nil)
69
- # don't send a data argument if it's not passed in, because some methods
70
- # on target object may not have the proper arity (i.e. #get and #delete).
71
- if path.nil?
72
- raise ArgumentError, "You must specify a request URL, but it was nil."
73
- end
74
- args = [type, path, data, options].compact
75
- response = __getobj__.send(*args)
174
+ def headers
175
+ self.class.headers
176
+ end
76
177
 
77
- check_response_status!(type, response, options)
78
- response.body
178
+ def url_for(path)
179
+ URI.join(base_url, path).to_s
79
180
  end
80
181
 
81
- def check_response_status!(request_type, response, options)
82
- verb = request_type.to_s.upcase
83
- expected_status = options[:expected_response_status] || (200..299)
84
- unless expected_status === response.status
85
- raise UnexpectedResponse, "#{verb} to #{response.url} responded with " \
86
- + "#{response.status} status, not #{expected_status} as expected\n\n" \
87
- + response.body
88
- end
182
+ def base_url
183
+ @configuration.app_host
184
+ end
185
+
186
+ def encode(data)
187
+ data
188
+ end
189
+
190
+ def decode(data)
191
+ data
192
+ end
193
+
194
+ def raise_unexpected_response(exception)
195
+ message = <<-END
196
+ Unexpected response from server: #{exception.message}
197
+
198
+ #{exception.http_body}
199
+ END
200
+ new_exception = UnexpectedResponse.new(message)
201
+ new_exception.set_backtrace(exception.backtrace)
202
+ raise new_exception
89
203
  end
90
204
  end
91
205
  end
@@ -5,7 +5,7 @@ class Kookaburra
5
5
  # test preconditions. Unlike {Kookaburra::APIDriver}, which is meant to be a
6
6
  # simple mapping to your application's API, a method in the GivenDriver may be
7
7
  # comprised of several distinct API calls as well as access to Kookaburra's
8
- # test data store.
8
+ # test data store via `#mental_model`.
9
9
  #
10
10
  # @abstract Subclass and implement your Given DSL.
11
11
  #
@@ -1,5 +1,5 @@
1
1
  require 'kookaburra/test_helpers'
2
- require 'kookaburra/json_api_driver'
2
+ require 'kookaburra/api_driver'
3
3
  require 'capybara'
4
4
  require 'thwait'
5
5
  require 'find_a_port'
@@ -182,7 +182,12 @@ describe "testing a Rack application with Kookaburra" do
182
182
  end
183
183
  end
184
184
 
185
- class MyAPIDriver < Kookaburra::JsonApiDriver
185
+ class MyAPIDriver < Kookaburra::APIDriver
186
+ encode_with { |data| JSON.dump(data) }
187
+ decode_with { |data| JSON.parse(data) }
188
+ header 'Content-Type', 'application/json'
189
+ header 'Accept', 'application/json'
190
+
186
191
  def create_user(user_data)
187
192
  post '/users', user_data
188
193
  end
@@ -315,17 +320,29 @@ describe "testing a Rack application with Kookaburra" do
315
320
  end
316
321
 
317
322
  before(:all) do
318
- @rack_server_pid = fork do
323
+ start_server = lambda {
319
324
  Capybara.server_port = APP_PORT
320
325
  Capybara::Server.new(JsonApiApp.new).boot
321
326
  ThreadsWait.all_waits(Thread.list)
327
+ }
328
+ if defined?(JRUBY_VERSION)
329
+ # Can't `fork` in JRuby. This doesn't provide the state
330
+ # isolation that you get with forking (AFAIK, I'm no JVM
331
+ # expert, though), but it lets the tests run and pass.
332
+ Thread.new { start_server.call }
333
+ else
334
+ @rack_server_pid = fork do
335
+ start_server.call
336
+ end
322
337
  end
323
338
  sleep 1 # Give the server a chance to start up.
324
339
  end
325
340
 
326
341
  after(:all) do
327
- Process.kill(9, @rack_server_pid)
328
- Process.wait
342
+ unless defined?(JRUBY_VERSION)
343
+ Process.kill(9, @rack_server_pid)
344
+ Process.wait
345
+ end
329
346
  end
330
347
 
331
348
  it "runs the tests against the app" do
@@ -1,159 +1,102 @@
1
1
  require 'kookaburra/api_driver'
2
2
 
3
3
  describe Kookaburra::APIDriver do
4
+ def url_for(uri)
5
+ URI.join('http://example.com', uri).to_s
6
+ end
7
+
4
8
  let(:configuration) { stub('Configuration', :app_host => 'http://example.com') }
5
9
 
6
10
  let(:api) { Kookaburra::APIDriver.new(configuration, client) }
7
11
 
8
- let(:response) {
9
- stub('Patron::Response', :body => 'foo', :status => 200, :url => '/foo')
10
- }
12
+ let(:response) { stub('RestClient::Response', body: 'foo', code: 200) }
11
13
 
12
- let(:client) {
13
- mock('Patron::Session', :post => response, :get => response,
14
- :put => response, :delete => response, :base_url= => nil)
15
- }
16
-
17
- describe '#initialize' do
18
- it 'instantiates a new http client if no :http_client option is passed' do
19
- Patron::Session.should_receive(:new).and_return(stub.as_null_object)
20
- Kookaburra::APIDriver.new(configuration)
21
- end
14
+ let(:client) { stub('RestClient') }
22
15
 
23
- it 'does not instantiate a new http client if an :http_client option is passed' do
24
- Patron::Session.should_receive(:new).never
25
- Kookaburra::APIDriver.new(configuration, client)
26
- end
16
+ it 'sends POST requests to the server and returns the response body' do
17
+ client.should_receive(:post).with(url_for('/foo'), 'bar', {}) \
18
+ .and_return(response)
19
+ api.post('/foo', 'bar').should == 'foo'
27
20
  end
28
21
 
29
- describe '#post' do
30
- before(:each) do
31
- response.stub!(:status => 201)
32
- end
33
-
34
- it 'delegates to the http client' do
35
- client.should_receive(:post).with('/foo', 'bar', {}) \
36
- .and_return(response)
37
- api.post('/foo', 'bar')
38
- end
39
-
40
- it 'returns the response body' do
41
- api.post('/foo', 'bar').should == 'foo'
42
- end
43
-
44
- it 'does not raise an UnexpectedResponse if the response status matches the specified expectation' do
45
- response.stub!(:status => 666)
46
- lambda { api.post('/foo', 'bar', :expected_response_status => 666) } \
47
- .should_not raise_error
48
- end
49
-
50
- it 'raises an UnexpectedResponse if the response status is not the specified status' do
51
- lambda { api.post('/foo', 'bar', :expected_response_status => 666) } \
52
- .should raise_error(Kookaburra::UnexpectedResponse,
53
- "POST to /foo responded with 201 status, not 666 as expected\n\nfoo")
54
- end
55
-
56
- it 'is OK by default with a response status of 201' do
57
- lambda { api.post('/foo', 'bar') } \
58
- .should_not raise_error(Kookaburra::UnexpectedResponse)
59
- end
60
-
61
- it 'is OK by default with a response status of 200' do
62
- response.stub!(:status => 200)
63
- lambda { api.post('/foo', 'bar') } \
64
- .should_not raise_error(Kookaburra::UnexpectedResponse)
65
- end
66
-
67
- it 'raises an ArgumentError with a useful message if no request path is specified' do
68
- lambda { api.post(nil, 'bar') } \
69
- .should raise_error(ArgumentError, "You must specify a request URL, but it was nil.")
70
- end
22
+ it 'sends PUT requests to the server and returns the response body' do
23
+ client.should_receive(:put).with(url_for('/foo'), 'bar', {}) \
24
+ .and_return(response)
25
+ api.put('/foo', 'bar').should == 'foo'
71
26
  end
72
27
 
73
- describe '#put' do
74
- it 'delegates to the http client' do
75
- client.should_receive(:put).with('/foo', 'bar', {}) \
76
- .and_return(response)
77
- api.put('/foo', 'bar')
78
- end
79
-
80
- it 'returns the response body' do
81
- api.put('/foo', 'bar').should == 'foo'
82
- end
83
-
84
- it 'does not raise an UnexpectedResponse if the response status matches the specified expectation' do
85
- response.stub!(:status => 666)
86
- lambda { api.put('/foo', 'bar', :expected_response_status => 666) } \
87
- .should_not raise_error
88
- end
89
-
90
- it 'raises an UnexpectedResponse if the response status is not the specified status' do
91
- lambda { api.put('/foo', 'bar', :expected_response_status => 666) } \
92
- .should raise_error(Kookaburra::UnexpectedResponse,
93
- "PUT to /foo responded with 200 status, not 666 as expected\n\nfoo")
94
- end
95
-
96
- it 'raises an ArgumentError with a useful message if no request path is specified' do
97
- lambda { api.put(nil, 'bar') } \
98
- .should raise_error(ArgumentError, "You must specify a request URL, but it was nil.")
99
- end
28
+ it 'sends GET requests to the server and returns the response body' do
29
+ client.should_receive(:get).with(url_for('/foo'), {}) \
30
+ .and_return(response)
31
+ api.get('/foo').should == 'foo'
100
32
  end
101
33
 
102
- describe '#get' do
103
- it 'delegates to the http client' do
104
- client.should_receive(:get).with('/foo', {}) \
105
- .and_return(response)
106
- api.get('/foo')
107
- end
108
-
109
- it 'returns the response body' do
110
- api.get('/foo').should == 'foo'
111
- end
112
-
113
- it 'does not raise an UnexpectedResponse if the response status matches the specified expectation' do
114
- response.stub!(:status => 666)
115
- lambda { api.get('/foo', :expected_response_status => 666) } \
116
- .should_not raise_error
117
- end
118
-
119
- it 'raises an UnexpectedResponse if the response status is not the specified status' do
120
- lambda { api.get('/foo', :expected_response_status => 666) } \
121
- .should raise_error(Kookaburra::UnexpectedResponse,
122
- "GET to /foo responded with 200 status, not 666 as expected\n\nfoo")
123
- end
124
-
125
- it 'raises an ArgumentError with a useful message if no request path is specified' do
126
- lambda { api.get(nil) } \
127
- .should raise_error(ArgumentError, "You must specify a request URL, but it was nil.")
128
- end
34
+ it 'sends DELETE requests to the server and returns the response body' do
35
+ client.should_receive(:delete).with(url_for('/foo'), {}) \
36
+ .and_return(response)
37
+ api.delete('/foo').should == 'foo'
129
38
  end
130
39
 
131
- describe '#delete' do
132
- it 'delegates to the http client' do
133
- client.should_receive(:delete).with('/foo', {}) \
134
- .and_return(response)
135
- api.delete('/foo')
40
+ describe 'any type of HTTP request' do
41
+ before(:each) do
42
+ client.stub!(:http_verb => response)
136
43
  end
137
44
 
138
45
  it 'returns the response body' do
139
- api.delete('/foo').should == 'foo'
140
- end
141
-
142
- it 'does not raise an UnexpectedResponse if the response status matches the specified expectation' do
143
- response.stub!(:status => 666)
144
- lambda { api.delete('/foo', :expected_response_status => 666) } \
145
- .should_not raise_error
146
- end
147
-
148
- it 'raises an UnexpectedResponse if the response status is not the specified status' do
149
- lambda { api.delete('/foo', :expected_response_status => 666) } \
150
- .should raise_error(Kookaburra::UnexpectedResponse,
151
- "DELETE to /foo responded with 200 status, not 666 as expected\n\nfoo")
152
- end
153
-
154
- it 'raises an ArgumentError with a useful message if no request path is specified' do
155
- lambda { api.delete(nil) } \
156
- .should raise_error(ArgumentError, "You must specify a request URL, but it was nil.")
46
+ api.request(:http_verb, '/foo', 'bar').should == 'foo'
47
+ end
48
+
49
+ it 'raises an UnexpectedResponse if the request is not successful' do
50
+ response.stub!(code: 500)
51
+ client.stub!(:http_verb).and_raise(RestClient::Exception.new(response))
52
+ lambda { api.request(:http_verb, '/foo') } \
53
+ .should raise_error(Kookaburra::UnexpectedResponse)
54
+ end
55
+
56
+ context 'when custom headers are specified' do
57
+ let(:api) {
58
+ klass = Class.new(Kookaburra::APIDriver) do
59
+ header 'Header-Foo', 'Baz'
60
+ header 'Header-Bar', 'Bam'
61
+ end
62
+ klass.new(configuration, client)
63
+ }
64
+
65
+ it "sets headers on requests" do
66
+ client.should_receive(:http_verb).with(url_for('/foo'), {}, 'Header-Foo' => 'Baz', 'Header-Bar' => 'Bam')
67
+ api.request(:http_verb, '/foo', {})
68
+ end
69
+ end
70
+
71
+ context 'when a custom encoder is specified' do
72
+ let(:api) {
73
+ klass = Class.new(Kookaburra::APIDriver) do
74
+ encode_with { |data| :some_encoded_data }
75
+ end
76
+ klass.new(configuration, client)
77
+ }
78
+
79
+ it "encodes input to requests" do
80
+ client.should_receive(:http_verb) do |_, data, _|
81
+ data.should == :some_encoded_data
82
+ response
83
+ end
84
+
85
+ api.request(:http_verb, '/foo', :ruby_data)
86
+ end
87
+ end
88
+
89
+ context 'when a custom decoder is specified' do
90
+ let(:api) {
91
+ klass = Class.new(Kookaburra::APIDriver) do
92
+ decode_with { |data| :some_decoded_data }
93
+ end
94
+ klass.new(configuration, client)
95
+ }
96
+
97
+ it "decodes response bodies from requests" do
98
+ api.request(:http_verb, '/foo').should == :some_decoded_data
99
+ end
157
100
  end
158
101
  end
159
102
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kookaburra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,10 +11,10 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-08-21 00:00:00.000000000 Z
14
+ date: 2012-10-14 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
- name: patron
17
+ name: rest-client
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  none: false
20
20
  requirements:
@@ -30,14 +30,14 @@ dependencies:
30
30
  - !ruby/object:Gem::Version
31
31
  version: '0'
32
32
  - !ruby/object:Gem::Dependency
33
- name: json_pure
33
+ name: jruby-openssl
34
34
  requirement: !ruby/object:Gem::Requirement
35
35
  none: false
36
36
  requirements:
37
37
  - - ! '>='
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0'
40
- type: :runtime
40
+ type: :development
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  none: false
@@ -94,21 +94,21 @@ dependencies:
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
96
  - !ruby/object:Gem::Dependency
97
- name: redcarpet
97
+ name: kramdown
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  none: false
100
100
  requirements:
101
- - - ~>
101
+ - - ! '>='
102
102
  - !ruby/object:Gem::Version
103
- version: '1.0'
103
+ version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  none: false
108
108
  requirements:
109
- - - ~>
109
+ - - ! '>='
110
110
  - !ruby/object:Gem::Version
111
- version: '1.0'
111
+ version: '0'
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: jeweler
114
114
  requirement: !ruby/object:Gem::Requirement
@@ -164,7 +164,7 @@ dependencies:
164
164
  requirements:
165
165
  - - ! '>='
166
166
  - !ruby/object:Gem::Version
167
- version: 1.0.1
167
+ version: '0'
168
168
  type: :development
169
169
  prerelease: false
170
170
  version_requirements: !ruby/object:Gem::Requirement
@@ -172,7 +172,23 @@ dependencies:
172
172
  requirements:
173
173
  - - ! '>='
174
174
  - !ruby/object:Gem::Version
175
- version: 1.0.1
175
+ version: '0'
176
+ - !ruby/object:Gem::Dependency
177
+ name: json
178
+ requirement: !ruby/object:Gem::Requirement
179
+ none: false
180
+ requirements:
181
+ - - ! '>='
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ type: :development
185
+ prerelease: false
186
+ version_requirements: !ruby/object:Gem::Requirement
187
+ none: false
188
+ requirements:
189
+ - - ! '>='
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
176
192
  description: Cucumber + Capybara = Kookaburra? It made sense at the time.
177
193
  email: johnwilger@gmail.com
178
194
  executables: []
@@ -199,7 +215,6 @@ files:
199
215
  - lib/kookaburra/dependency_accessor.rb
200
216
  - lib/kookaburra/exceptions.rb
201
217
  - lib/kookaburra/given_driver.rb
202
- - lib/kookaburra/json_api_driver.rb
203
218
  - lib/kookaburra/mental_model.rb
204
219
  - lib/kookaburra/mental_model_matcher.rb
205
220
  - lib/kookaburra/test_helpers.rb
@@ -211,7 +226,6 @@ files:
211
226
  - spec/integration/test_a_rack_application_spec.rb
212
227
  - spec/kookaburra/api_driver_spec.rb
213
228
  - spec/kookaburra/configuration_spec.rb
214
- - spec/kookaburra/json_api_driver_spec.rb
215
229
  - spec/kookaburra/mental_model_matcher_spec.rb
216
230
  - spec/kookaburra/mental_model_spec.rb
217
231
  - spec/kookaburra/test_helpers_spec.rb
@@ -238,7 +252,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
238
252
  version: '0'
239
253
  segments:
240
254
  - 0
241
- hash: -3018150638405994021
255
+ hash: -1361909781639378810
242
256
  required_rubygems_version: !ruby/object:Gem::Requirement
243
257
  none: false
244
258
  requirements:
@@ -1,65 +0,0 @@
1
- require 'delegate'
2
- require 'json'
3
- require 'kookaburra/api_driver'
4
-
5
- class Kookaburra
6
- # Delegates all methods (by default) to and instance of
7
- # {Kookaburra::APIDriver}.
8
- #
9
- # Expects the application's API to accept and respond with JSON formatted
10
- # data. All methods will decode the response body using
11
- # `ActiveSupport::JSON.decode`. Methods that take input data ({#post} and
12
- # {#put}) will encode the post data using `ActiveSupport::JSON.encode`.
13
- class JsonApiDriver < SimpleDelegator
14
- #
15
- # Sets both the "Content-Type" and "Accept" headers to "application/json".
16
- #
17
- # @param [Kookaburra::Configuration] configuration
18
- # @param [Kookaburra::APIDriver] api_driver (Kookaburra::APIDriver.new)
19
- # The APIDriver instance to be delegated to. Changing this is probably
20
- # only useful for testing Kookaburra itself.
21
- def initialize(configuration, api_driver = nil)
22
- api_driver = api_driver || APIDriver.new(configuration)
23
- api_driver.headers.merge!(
24
- 'Content-Type' => 'application/json',
25
- 'Accept' => 'application/json'
26
- )
27
- super(api_driver)
28
- end
29
-
30
- def post(path, data, *args)
31
- request(:post, path, data, *args)
32
- end
33
-
34
- def put(path, data, *args)
35
- request(:put, path, data, *args)
36
- end
37
-
38
- def get(path, *args)
39
- request(:get, path, nil, *args)
40
- end
41
-
42
- def delete(path, *args)
43
- request(:delete, path, nil, *args)
44
- end
45
-
46
- private
47
-
48
- def request(type, path, data = nil, *args)
49
- # don't want to send data to methods that don't accept it
50
- args = [path, *([encode(data), args].reject(&:nil?))].flatten
51
-
52
- output = __getobj__.send(type, *args)
53
-
54
- decode(output)
55
- end
56
-
57
- def encode(data)
58
- JSON.dump(data) unless data.nil?
59
- end
60
-
61
- def decode(data)
62
- JSON.parse(data)
63
- end
64
- end
65
- end
@@ -1,95 +0,0 @@
1
- require 'kookaburra/json_api_driver'
2
-
3
- describe Kookaburra::JsonApiDriver do
4
- let(:response) { '{"foo":"bar"}' }
5
-
6
- let(:api) {
7
- stub('APIDriver', :get => response, :post => response, :put => response,
8
- :delete => response, :headers => {})
9
- }
10
-
11
- let(:configuration) {
12
- stub('Configuration')
13
- }
14
-
15
- let(:json) { Kookaburra::JsonApiDriver.new(stub('Configuration'), api) }
16
-
17
- describe '#initialize' do
18
- it 'instantiates a new APIDriver if no :api_driver option is passed' do
19
- Kookaburra::APIDriver.should_receive(:new) \
20
- .with(configuration) \
21
- .and_return(api)
22
- Kookaburra::JsonApiDriver.new(configuration)
23
- end
24
-
25
- it 'does not instantiate a new APIDriver if an :api_driver option is passed' do
26
- Kookaburra::APIDriver.should_receive(:new).never
27
- Kookaburra::JsonApiDriver.new(configuration, api)
28
- end
29
-
30
- it 'sets appropriate headers for a JSON API request' do
31
- Kookaburra::JsonApiDriver.new(configuration, api)
32
- api.headers.should == {
33
- 'Content-Type' => 'application/json',
34
- 'Accept' => 'application/json'
35
- }
36
- end
37
- end
38
-
39
- it 'delegates to a Kookaburra::APIDriver by default' do
40
- api.stub!(:foo => :bar)
41
- json.foo.should == :bar
42
- end
43
-
44
- describe '#post' do
45
- it 'delegates to the api driver as a JSON request' do
46
- api.should_receive(:post) \
47
- .with('/foo', '{"foo":"bar"}') \
48
- .and_return('{"baz":"bam"}')
49
- json.post('/foo', 'foo' => 'bar')
50
- end
51
-
52
- it 'returns the JSON-decoded response body' do
53
- json.post('/foo', :bar => :baz).should == {'foo' => 'bar'}
54
- end
55
- end
56
-
57
- describe '#put' do
58
- it 'delegates to the api driver as a JSON request' do
59
- api.should_receive(:put) \
60
- .with('/foo', '{"foo":"bar"}') \
61
- .and_return('{"baz":"bam"}')
62
- json.put('/foo', 'foo' => 'bar')
63
- end
64
-
65
- it 'returns the JSON-decoded response body' do
66
- json.put('/foo', :bar => :baz).should == {'foo' => 'bar'}
67
- end
68
- end
69
-
70
- describe '#get' do
71
- it 'delegates to the api driver as a JSON request' do
72
- api.should_receive(:get) \
73
- .with('/foo') \
74
- .and_return('{"baz":"bam"}')
75
- json.get('/foo')
76
- end
77
-
78
- it 'returns the JSON-decoded response body' do
79
- json.get('/foo').should == {'foo' => 'bar'}
80
- end
81
- end
82
-
83
- describe '#delete' do
84
- it 'delegates to the api driver as a JSON request' do
85
- api.should_receive(:delete) \
86
- .with('/foo') \
87
- .and_return('{"baz":"bam"}')
88
- json.delete('/foo')
89
- end
90
-
91
- it 'returns the JSON-decoded response body' do
92
- json.delete('/foo').should == {'foo' => 'bar'}
93
- end
94
- end
95
- end