roar 0.12.2 → 0.12.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04161ea9b3e943c2369825c6a3c426cfae97550d
4
- data.tar.gz: f7a7a96c45646273d7355938becde08c0549d8b1
3
+ metadata.gz: 36037871272f0ad904505c747eeabb1a09c96c58
4
+ data.tar.gz: 964389ed57a09eb10a95f02a292865c909bda5d1
5
5
  SHA512:
6
- metadata.gz: 766eddbf40e6931caaf003a895598799c1d40efea0ba4854a1938995c0a7c0a41b96cfe1e69593c9a89538b9426305aff2f34dcd617a60a95f14840398296e54
7
- data.tar.gz: ec8585e4bc27fb429895db8d2026c70aade0b360d5b6d741d4d67c7eddc0306194947514061f8f1fe6361822ddceb5e1370b6ff671430c9628b5af5781c791e4
6
+ metadata.gz: 33c07296b014315ac382722598061026f629d95ce212e6c6f98f49068a9eb5c0939eef39fc26d54b7a267f9e5e4c266f0fc7a4391787ad7958b1451ed4614a1f
7
+ data.tar.gz: 7391c7bc51baee1d3bf8c3c6eb3b37762b4182c36cdb8474e3f0a027e5184156e1153d37890c68a7b2bc5c3ca92d943cf7ffc20151279fe74efae38baf627914
@@ -1,10 +1,8 @@
1
1
  matrix:
2
2
  include:
3
3
  - rvm: 1.9.3
4
- gemfile: gemfiles/Gemfile.representable-1.6.ruby-1.9
4
+ gemfile: gemfiles/Gemfile.representable-1.7
5
5
  - rvm: 2.0.0
6
- gemfile: gemfiles/Gemfile.representable-1.6.ruby-1.9
7
- # - rvm: 1.8.7
8
- # gemfile: gemfiles/Gemfile.representable-1.5.ruby-1.8
6
+ gemfile: gemfiles/Gemfile.representable-1.7
9
7
  notifications:
10
8
  irc: "irc.freenode.org#cells"
@@ -1,3 +1,15 @@
1
+ # 0.12.3
2
+
3
+ * Allow basic authentication with `basic_auth: [:admin, :password]`.
4
+ * Allow HTTPS.
5
+ * Removed `NetHTTP#do_request`. It is in `NetHTTP::Request` now.
6
+
7
+ ### Changes for `HttpVerbs#get` and friends:
8
+
9
+ * They now yield the request object to add headers etc before request is sent.
10
+ * They NO LONGER support positional arguments but one hash with `uri: "https://roar.de", body:, .. as: ..` and so on.
11
+
12
+
1
13
  # 0.12.2
2
14
 
3
15
  * Fix a bug where hyperlinks from nested objects weren't rendered in XML.
data/Gemfile CHANGED
@@ -3,5 +3,5 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in roar.gemspec
4
4
  gemspec
5
5
 
6
- gem "representable", :path => "../representable"
7
- gem "sinatra", path: "../sinatra"
6
+ #gem "representable", :path => "../representable"
7
+ gem "sinatra-contrib", :git => "git@github.com:apotonick/sinatra-contrib.git", :branch => "runner"
@@ -476,13 +476,13 @@ class Song < OpenStruct
476
476
  end
477
477
  ```
478
478
 
479
- ### HTTP Support
479
+ ## HTTP Support
480
480
 
481
481
  The `Feature::Client` module mixes all necessary methods into the client class, e.g. it provides HTTP support
482
482
 
483
483
  ```ruby
484
484
  song = Song.new(title: "Roxanne")
485
- song.post("http://localhost:4567/songs", "application/json")
485
+ song.post(uri: "http://localhost:4567/songs", as: "application/json")
486
486
 
487
487
  song.id #=> 42
488
488
  ```
@@ -500,7 +500,7 @@ Roar works with all HTTP request types, check out `GET`.
500
500
 
501
501
  ```ruby
502
502
  song = Client::Song.new
503
- song.get("http://localhost:4567/songs/1", "application/json")
503
+ song.get(uri: "http://localhost:4567/songs/1", as: "application/json")
504
504
 
505
505
  song.title #=> "Roxanne"
506
506
  song.links[:self].href #=> http://localhost/songs/1
@@ -508,6 +508,31 @@ song.links[:self].href #=> http://localhost/songs/1
508
508
 
509
509
  As `GET` is not supposed to send any data, you can use `#get` on an empty object to populate it with the server data.
510
510
 
511
+ ### HTTPS
512
+
513
+ Roar supports SSL connections - they are automatically detected via the protocol.
514
+
515
+ ```ruby
516
+ song.get(uri: "https://localhost:4567/songs/1")`
517
+ ```
518
+
519
+ ### Basic Authentication
520
+
521
+ The HTTP verbs allow you to specify credentials for HTTP basic auth.
522
+
523
+ ```ruby
524
+ song.get(uri: "http://localhost:4567/songs/1", basic_auth: ["username", "secret_password"])
525
+ ```
526
+
527
+ ### Request customization
528
+
529
+ All verbs yield the request object before the request is sent, allowing to modify it. It is a `Net::HTTP::Request` instance (unless you use Faraday).
530
+
531
+ ```ruby
532
+ song.get(uri: "http://localhost:4567/songs/1") do |req|
533
+ req.add_field("Cookie", "Yumyum")
534
+ end
535
+ ```
511
536
 
512
537
  ## XML
513
538
 
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'representable', '~> 1.7.0'
6
+ gem "sinatra-contrib", :git => "git@github.com:apotonick/sinatra-contrib.git", :branch => "runner"
@@ -5,9 +5,6 @@ module Roar
5
5
  module Representer
6
6
  module Feature
7
7
  module HttpVerbs
8
- # TODO:
9
- # req.basic_auth 'user', 'pass'
10
- # Net::HTTP.start(uri.host, uri.port, use_ssl: true
11
8
 
12
9
  class << self
13
10
  attr_accessor :transport_engine
@@ -34,33 +31,33 @@ module Roar
34
31
 
35
32
  # Serializes the object, POSTs it to +url+ with +format+, deserializes the returned document
36
33
  # and updates properties accordingly.
37
- def post(url, format)
38
- response = http.post_uri(url, serialize, format)
34
+ def post(url, format, options={}, &block)
35
+ response = http.post_uri(options.merge(:uri => url, :body => serialize, :as => format), &block)
39
36
  handle_response(response)
40
37
  end
41
38
 
42
39
  # GETs +url+ with +format+, deserializes the returned document and updates properties accordingly.
43
- def get(url, format)
44
- response = http.get_uri(url, format)
40
+ def get(url, format, options={}, &block)
41
+ response = http.get_uri(options.merge(:uri => url, :as => format), &block)
45
42
  handle_response(response)
46
43
  end
47
44
 
48
45
  # Serializes the object, PUTs it to +url+ with +format+, deserializes the returned document
49
46
  # and updates properties accordingly.
50
- def put(url, format)
51
- response = http.put_uri(url, serialize, format)
47
+ def put(url, format, options={}, &block)
48
+ response = http.put_uri(options.merge(:uri => url, :body => serialize, :as => format), &block)
52
49
  handle_response(response)
53
50
  self
54
51
  end
55
52
 
56
- def patch(url, format)
57
- response = http.patch_uri(url, serialize, format)
53
+ def patch(url, format, options={}, &block)
54
+ response = http.patch_uri(options.merge(:uri => url, :body => serialize, :as => format), &block)
58
55
  handle_response(response)
59
56
  self
60
57
  end
61
58
 
62
- def delete(url, format)
63
- http.delete_uri(url, format)
59
+ def delete(url, format, options={}, &block)
60
+ http.delete_uri(options.merge(:uri => url, :as => format), &block)
64
61
  self
65
62
  end
66
63
 
@@ -13,27 +13,27 @@ module Roar
13
13
  # @see http://rubydoc.info/gems/faraday/file/README.md Faraday README
14
14
  class Faraday
15
15
 
16
- def get_uri(uri, as)
16
+ def get_uri(uri, as, *args)
17
17
  build_connection(uri, as).get
18
18
  end
19
19
 
20
- def post_uri(uri, body, as)
20
+ def post_uri(uri, body, as, *args)
21
21
  build_connection(uri, as).post(nil, body)
22
22
  end
23
23
 
24
- def put_uri(uri, body, as)
24
+ def put_uri(uri, body, as, *args)
25
25
  build_connection(uri, as).put(nil, body)
26
26
  end
27
27
 
28
- def patch_uri(uri, body, as)
28
+ def patch_uri(uri, body, as, *args)
29
29
  build_connection(uri, as).patch(nil, body)
30
30
  end
31
31
 
32
- def delete_uri(uri, as)
32
+ def delete_uri(uri, as, *args)
33
33
  build_connection(uri, as).delete
34
34
  end
35
35
 
36
- private
36
+ private
37
37
 
38
38
  def build_connection(uri, as)
39
39
  ::Faraday::Connection.new(
@@ -5,49 +5,112 @@ module Roar
5
5
  module Representer
6
6
  # Implements the (HTTP) transport interface with Net::HTTP.
7
7
  module Transport
8
- # Definitions: every call returns a Response object responding to #body.
8
+ # Low-level interface for HTTP. The #get_uri and friends accept an options and an optional block, invoke
9
+ # the HTTP request and return the request object.
10
+ #
11
+ # The following options are available:
9
12
  class NetHTTP
10
- # TODO: generically handle return codes.
11
- def get_uri(uri, as)
12
- do_request(Net::HTTP::Get, uri, as)
13
+ class Request # TODO: implement me.
14
+ def initialize(options)
15
+ @uri = parse_uri(options[:uri]) # TODO: add :uri.
16
+ @as = options[:as]
17
+ @body = options[:body]
18
+ @options = options
19
+
20
+ @http = Net::HTTP.new(uri.host, uri.port)
21
+ end
22
+
23
+ def call(what)
24
+ @req = what.new(uri.request_uri)
25
+
26
+ # if options[:ssl]
27
+ # uri.port = Net::HTTP.https_default_port()
28
+ # end
29
+ https!
30
+ basic_auth!
31
+
32
+ req.content_type = as
33
+ req["accept"] = as # TODO: test me. # DISCUSS: if Accept is not set, rails treats this request as as "text/html".
34
+ req.body = body if body
35
+
36
+ yield req if block_given?
37
+
38
+ http.request(req).tap do |res|
39
+ raise UnauthorizedError if res.is_a?(Net::HTTPUnauthorized) # FIXME: make this better. # DISCUSS: abstract all that crap here?
40
+ end
41
+ end
42
+
43
+ def get
44
+ call(Net::HTTP::Get)
45
+ end
46
+
47
+ private
48
+ attr_reader :uri, :as, :body, :options, :req, :http
49
+
50
+ def parse_uri(url)
51
+ uri = URI(url)
52
+ raise "Incorrect URL `#{url}`. Maybe you forgot http://?" if uri.instance_of?(URI::Generic)
53
+ uri
54
+ end
55
+
56
+ def https!
57
+ return unless uri.scheme == 'https'
58
+
59
+ @http.use_ssl = true
60
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
61
+ end
62
+
63
+ def basic_auth!
64
+ return unless options[:basic_auth]
65
+
66
+ @req.basic_auth(*options[:basic_auth])
67
+ end
13
68
  end
14
69
 
15
- def post_uri(uri, body, as)
16
- do_request(Net::HTTP::Post, uri, as, body)
70
+
71
+ def get_uri(*options, &block)
72
+ call(Net::HTTP::Get, *options, &block)
17
73
  end
18
74
 
19
- def put_uri(uri, body, as)
20
- do_request(Net::HTTP::Put, uri, as, body)
75
+ def post_uri(*options, &block)
76
+ call(Net::HTTP::Post, *options, &block)
21
77
  end
22
78
 
23
- def patch_uri(uri, body, as)
24
- do_request(Net::HTTP::Patch, uri, as, body)
79
+ def put_uri(*options, &block)
80
+ call(Net::HTTP::Put, *options, &block)
25
81
  end
26
82
 
27
- def delete_uri(uri, as)
28
- do_request(Net::HTTP::Delete, uri, as)
83
+ def delete_uri(*options, &block)
84
+ call(Net::HTTP::Delete, *options, &block)
29
85
  end
30
86
 
31
- private
32
- def do_request(what, uri, as, body="")
33
- # DISCUSS: can this be made easier?
34
- uri = parse_uri(uri)
35
- http = Net::HTTP.new(uri.host, uri.port)
36
- req = what.new(uri.request_uri)
87
+ def patch_uri(*options, &block)
88
+ call(Net::HTTP::Patch, *options, &block)
89
+ end
37
90
 
91
+ private
92
+ def call(what, *args, &block)
93
+ options = handle_deprecated_args(args)
94
+ # TODO: generically handle return codes.
95
+ Request.new(options).call(what, &block)
96
+ end
38
97
 
39
- req.content_type = as
40
- req["accept"] = as # TODO: test me. # DISCUSS: if Accept is not set, rails treats this request as as "text/html".
41
- req.body = body if body
98
+ def handle_deprecated_args(args) # TODO: remove in 1.0.
99
+ if args.size > 1
100
+ warn %{DEPRECATION WARNING: #get_uri, #post_uri, #put_uri, #delete_uri and #patch_uri no longer accept positional arguments. Please call them as follows:
101
+ get_uri(uri: "http://localhost/songs", as: "application/json")
102
+ post_uri(uri: "http://localhost/songs", as: "application/json", body: "{'id': 1}")
103
+ Thank you and have a lovely day.}
104
+ return {:uri => args[0], :as => args[1]} if args.size == 2
105
+ return {:uri => args[0], :as => args[2], :body => args[1]}
106
+ end
42
107
 
43
- http.request(req)
108
+ args.first
44
109
  end
45
110
 
46
- def parse_uri(url)
47
- uri = URI(url)
48
- raise "Incorrect URL `#{url}`. Maybe you forgot http://?" if uri.instance_of?(URI::Generic)
49
- uri
50
- end
111
+ end
112
+
113
+ class UnauthorizedError < RuntimeError # TODO: raise this from Faraday, too.
51
114
  end
52
115
  end
53
116
  end
@@ -1,3 +1,3 @@
1
1
  module Roar
2
- VERSION = "0.12.2"
2
+ VERSION = "0.12.3"
3
3
  end
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
 
24
24
  s.add_development_dependency "rake", ">= 0.10.1"
25
25
  s.add_development_dependency "test_xml", ">= 0.1.6"
26
- s.add_development_dependency "minitest", ">= 5.0.0"
26
+ s.add_development_dependency "minitest", "= 5.0.0"
27
27
  s.add_development_dependency "sinatra"
28
28
  s.add_development_dependency "virtus"
29
29
  s.add_development_dependency "faraday"
@@ -4,8 +4,6 @@ require 'roar/representer/json/collection_json'
4
4
  class CollectionJsonTest < MiniTest::Spec
5
5
  let(:song) { OpenStruct.new(:title => "scarifice", :length => 43) }
6
6
 
7
- # FIXME: test absence of ::items, ::template, etc.
8
-
9
7
  representer_for([Roar::Representer::JSON::CollectionJSON]) do
10
8
  version "1.0"
11
9
  href { "//songs/" }
@@ -50,7 +48,7 @@ class CollectionJsonTest < MiniTest::Spec
50
48
  },
51
49
 
52
50
  "queries"=>[
53
- {:rel=>:search, :href=>"//search",
51
+ {:rel=>:search, :href=>"//search",
54
52
  :data=>[
55
53
  {:name=>"q", :value=>""}
56
54
  ]
@@ -120,7 +120,9 @@ class HalJsonTest < MiniTest::Spec
120
120
  it "doesn't require _links and _embedded to be present" do
121
121
  @album.from_json("{\"id\":2}")
122
122
  assert_equal 2, @album.id
123
- assert_equal [], @album.songs
123
+
124
+ # in newer representables, this is not overwritten to an empty [] anymore.
125
+ assert_equal ["Beer"], @album.songs.map(&:title)
124
126
  @album.links.must_equal({})
125
127
  end
126
128
  end
@@ -10,6 +10,8 @@ class HttpVerbsTest < MiniTest::Spec
10
10
  attr_accessor :name, :label
11
11
  end
12
12
 
13
+ let (:band) { OpenStruct.new(:name => "bodyjar").extend(Roar::Representer::Feature::HttpVerbs, BandRepresenter) }
14
+
13
15
 
14
16
  describe "HttpVerbs" do
15
17
  before do
@@ -105,7 +107,42 @@ class HttpVerbsTest < MiniTest::Spec
105
107
  end
106
108
  end
107
109
 
108
- # HEAD, OPTIONs?
110
+ describe "HTTPS and Authentication" do
111
+ let (:song) { OpenStruct.new(:name => "bodyjar").extend(Roar::Representer::Feature::HttpVerbs, BandRepresenter) }
112
+
113
+ describe "Basic Auth: passing manually" do
114
+
115
+ end
116
+
117
+ describe "HTTPS: passing manually" do
118
+ verbs do |verb|
119
+ it "allows #{verb}" do
120
+ song.send(verb, "https://localhost:8443/bands/bodyjar", "application/json")
121
+
122
+ if verb == "delete"
123
+ song.name.must_equal "bodyjar"
124
+ else
125
+ song.name.must_equal "Bodyjar"
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ describe "HTTPS+Basic Auth: passing manually" do
132
+ it "allows GET" do
133
+ song.get("https://localhost:8443/protected", "application/json", :basic_auth => [:admin, :password])
134
+
135
+ song.name.must_equal "Bodyjar"
136
+ end
137
+ end
138
+ end
109
139
 
140
+ describe "request customization" do
141
+ it "yields the request object" do
142
+ band.get("http://localhost:4567/cookies", "application/json") do |req|
143
+ req.add_field("Cookie", "Yumyum")
144
+ end.name.must_equal "Bodyjar"
145
+ end
146
+ end
110
147
  end
111
148
  end
@@ -1,30 +1,41 @@
1
1
  require "integration/band_representer"
2
- #require '/home/nick/projects/sinatra/test/integration_helper'
3
- class ServerRunner# < IntegrationHelper::Server
2
+ require 'sinatra/runner'
3
+
4
+ class ServerRunner < Sinatra::Runner
4
5
  def app_file
5
6
  File.expand_path("../server.rb", __FILE__)
6
7
  end
7
8
 
8
- def run
9
- puts command
10
- puts @pipe = IO.popen(command)
11
- sleep 2
9
+ def command
10
+ "bundle exec ruby #{app_file} -p #{port} -e production"
12
11
  end
13
12
 
13
+ def ping_path # to be overwritten
14
+ '/ping'
15
+ end
16
+ end
17
+
18
+ class SslServerRunner < ServerRunner
14
19
  def command
15
- "cd #{File.expand_path("..", __FILE__)} && bundle exec ruby #{app_file} -p 4567 -e production"
20
+ "bundle exec ruby #{File.expand_path("../ssl_server.rb", __FILE__)}"
16
21
  end
17
22
 
18
- def kill
19
- puts "Killling : #{@pipe.pid.inspect}"
20
- Process.kill("KILL", @pipe.pid)
23
+ def port
24
+ 8443
25
+ end
26
+
27
+ def protocol
28
+ "https"
21
29
  end
22
30
  end
23
- runner = ServerRunner.new
24
- #at_exit { puts "killing it:"; runner.kill }
25
31
 
32
+ runner = ServerRunner.new
26
33
  runner.run
27
34
 
35
+ ssl_runner = SslServerRunner.new
36
+ ssl_runner.run
37
+
28
38
  MiniTest::Unit.after_tests do
29
39
  runner.kill
40
+ ssl_runner.kill
30
41
  end
@@ -2,6 +2,7 @@ require "bundler/setup"
2
2
  require "sinatra"
3
3
  require "ostruct"
4
4
  require "roar/representer/json"
5
+ require "sinatra/multi_route"
5
6
 
6
7
  require File.expand_path("../band_representer.rb", __FILE__)
7
8
 
@@ -75,3 +76,34 @@ end
75
76
  delete '/bands/metallica' do
76
77
  status 204
77
78
  end
79
+
80
+
81
+ helpers do
82
+ def protected!
83
+ return if authorized?
84
+ headers['WWW-Authenticate'] = 'Basic realm="Restricted Area"'
85
+ halt 401, "Not authorized\n"
86
+ end
87
+
88
+ def authorized?
89
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
90
+ @auth.provided? and @auth.basic? and @auth.credentials and @auth.credentials == ['admin', 'password']
91
+ end
92
+ end
93
+
94
+ route :get, :post, :put, :delete, "/protected/bands/bodyjar" do
95
+ protected!
96
+
97
+ OpenStruct.new(:name => "Bodyjar").
98
+ extend(Integration::BandRepresenter).
99
+ to_json
100
+ end
101
+
102
+ route :get, :post, :put, :delete, "/cookies" do
103
+ raise "No cookies!" unless request.env["HTTP_COOKIE"] == "Yumyum"
104
+ %{{"name": "Bodyjar"}}
105
+ end
106
+
107
+ get "/ping" do
108
+ "1"
109
+ end
@@ -0,0 +1,60 @@
1
+ require 'sinatra/base'
2
+ require 'webrick'
3
+ require 'webrick/https'
4
+ require 'openssl'
5
+ require 'sinatra/multi_route'
6
+
7
+ name = "/C=US/ST=SomeState/L=SomeCity/O=Organization/OU=Unit/CN=localhost"
8
+ ca = OpenSSL::X509::Name.parse(name)
9
+ key = OpenSSL::PKey::RSA.new(1024)
10
+ crt = OpenSSL::X509::Certificate.new
11
+ crt.version = 2
12
+ crt.serial = 1
13
+ crt.subject = ca
14
+ crt.issuer = ca
15
+ crt.public_key = key.public_key
16
+ crt.not_before = Time.now
17
+ crt.not_after = Time.now + 1 * 365 * 24 * 60 * 60 # 1 year
18
+ webrick_options = {
19
+ :Port => 8443,
20
+ :SSLEnable => true,
21
+ :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
22
+ :SSLCertificate => crt,
23
+ :SSLPrivateKey => key,
24
+ :SSLCertName => [[ "CN", WEBrick::Utils::getservername ]],
25
+ }
26
+
27
+ class SslServer < Sinatra::Base
28
+ register Sinatra::MultiRoute
29
+
30
+ get '/ping' do
31
+ "1"
32
+ end
33
+
34
+ route :get, :post, :put, :delete, "/bands/bodyjar" do
35
+ %{{"name": "Bodyjar"}}
36
+ end
37
+
38
+ # FIXME: redundant with server.rb.
39
+ helpers do
40
+ def protected!
41
+ return if authorized?
42
+ headers['WWW-Authenticate'] = 'Basic realm="Restricted Area"'
43
+ halt 401, "Not authorized\n"
44
+ end
45
+
46
+ def authorized?
47
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
48
+ @auth.provided? and @auth.basic? and @auth.credentials and @auth.credentials == ['admin', 'password']
49
+ end
50
+ end
51
+
52
+ get "/protected" do
53
+ protected!
54
+
55
+ %{{"name": "Bodyjar"}}
56
+ end
57
+ end
58
+ server = ::Rack::Handler::WEBrick
59
+
60
+ server.run(SslServer, webrick_options)
@@ -5,44 +5,80 @@ class NetHTTPTransportTest < MiniTest::Spec
5
5
  let(:url) { "http://localhost:4567/method" }
6
6
  let(:body) { "booty" }
7
7
  let(:as) { "application/xml" }
8
- before do
9
- @transport = Roar::Representer::Transport::NetHTTP.new
10
- end
8
+ let (:transport) { Roar::Representer::Transport::NetHTTP.new }
11
9
 
12
10
  it "#get_uri returns response" do
13
- @transport.get_uri(url, as).must_match_net_response :get, url, as
11
+ transport.get_uri(:uri => url, :as => as).must_match_net_response :get, url, as
14
12
  end
15
13
 
16
14
  it "#post_uri returns response" do
17
- @transport.post_uri(url, body, as).must_match_net_response :post, url, as, body
15
+ transport.post_uri(:uri => url, :as => as, :body => body).must_match_net_response :post, url, as, body
18
16
  end
19
17
 
20
18
  it "#put_uri returns response" do
21
- @transport.put_uri(url, body, as).must_match_net_response :put, url, as, body
19
+ transport.put_uri(:uri => url, :as => as, :body => body).must_match_net_response :put, url, as, body
22
20
  end
23
21
 
24
22
  it "#delete_uri returns response" do
25
- @transport.delete_uri(url, as).must_match_net_response :delete, url, as
23
+ transport.delete_uri(:uri => url, :as => as).must_match_net_response :delete, url, as
26
24
  end
27
25
 
28
26
  it "#patch_uri returns response" do
29
- @transport.patch_uri(url, body, as).must_match_net_response :patch, url, as, body
27
+ transport.patch_uri(:uri => url, :as => as, :body => body).must_match_net_response :patch, url, as, body
30
28
  end
31
29
 
32
30
  it "complains with invalid URL" do
33
31
  assert_raises RuntimeError do
34
- @transport.get_uri("example.com", as)
32
+ transport.get_uri(:uri => "example.com", :as => as)
33
+ end
34
+ end
35
+
36
+ # TODO: test all verbs.
37
+ describe "request customization" do
38
+ #verbs do |verb|
39
+ verb = "get"
40
+ it "#{verb} yields the request object" do
41
+ transport.send("#{verb}_uri", :uri => "http://localhost:4567/cookies", :as => "application/json") do |req|
42
+ req.add_field("Cookie", "Yumyum")
43
+ end.body.must_equal %{{"name": "Bodyjar"}}
44
+ end
45
+ #end
46
+ end
47
+
48
+ describe "basic auth" do
49
+ it "raises when no credentials provided" do
50
+ assert_raises Roar::Representer::Transport::UnauthorizedError do
51
+ transport.get_uri(:uri => "http://localhost:4567/protected/bands/bodyjar", :as => "application/json")
52
+ end
53
+ end
54
+
55
+ it "raises when wrong credentials provided" do
56
+ assert_raises Roar::Representer::Transport::UnauthorizedError do
57
+ transport.get_uri(:uri => "http://localhost:4567/protected/bands/bodyjar", :as => "application/json", :basic_auth => ["admin", "wrong--!!!--password"])
58
+ end
59
+ end
60
+
61
+ it "what" do
62
+ transport.get_uri(:uri => "http://localhost:4567/protected/bands/bodyjar", :as => "application/json", :basic_auth => ["admin", "password"])
63
+ end
64
+ end
65
+
66
+ describe "deprecations" do
67
+ it "old GET API still works" do
68
+ transport.get_uri(url, as).must_match_net_response :get, url, as
69
+ end
70
+
71
+ it "old POST API still works" do
72
+ transport.post_uri(url, body, as).must_match_net_response :post, url, as, body
35
73
  end
36
74
  end
37
75
  end
38
76
 
39
77
  module MiniTest::Assertions
40
-
41
78
  def assert_net_response(type, response, url, as, body = nil)
42
79
  # TODO: Assert headers
43
80
  assert_equal "<method>#{type}#{(' - ' + body) if body}</method>", response.body
44
81
  end
45
-
46
82
  end
47
83
 
48
84
  Net::HTTPOK.infect_an_assertion :assert_net_response, :must_match_net_response
@@ -46,6 +46,10 @@ MiniTest::Spec.class_eval do
46
46
  def self.representer!(*args)
47
47
  representer_for(*args)
48
48
  end
49
+
50
+ def self.verbs(&block)
51
+ %w(get post put delete).each(&block)
52
+ end
49
53
  end
50
54
 
51
55
  Roar::Representer::Feature::Hypermedia::Hyperlink.class_eval do
metadata CHANGED
@@ -1,125 +1,125 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.2
4
+ version: 0.12.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-19 00:00:00.000000000 Z
11
+ date: 2014-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: representable
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.6.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.6.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.10.1
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.10.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: test_xml
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: 0.1.6
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.1.6
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - '='
60
60
  - !ruby/object:Gem::Version
61
61
  version: 5.0.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - '='
67
67
  - !ruby/object:Gem::Version
68
68
  version: 5.0.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sinatra
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: virtus
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: faraday
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: json
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  description: Streamlines the development of RESTful, resource-oriented architectures
@@ -130,8 +130,8 @@ executables: []
130
130
  extensions: []
131
131
  extra_rdoc_files: []
132
132
  files:
133
- - .gitignore
134
- - .travis.yml
133
+ - ".gitignore"
134
+ - ".travis.yml"
135
135
  - CHANGES.markdown
136
136
  - Gemfile
137
137
  - LICENSE
@@ -140,9 +140,7 @@ files:
140
140
  - TODO.markdown
141
141
  - examples/example.rb
142
142
  - examples/example_server.rb
143
- - gemfiles/Gemfile.representable-1.5.ruby-1.8
144
- - gemfiles/Gemfile.representable-1.5.ruby-1.9
145
- - gemfiles/Gemfile.representable-1.6.ruby-1.9
143
+ - gemfiles/Gemfile.representable-1.7
146
144
  - lib/roar.rb
147
145
  - lib/roar/decorator.rb
148
146
  - lib/roar/representer.rb
@@ -165,13 +163,14 @@ files:
165
163
  - test/faraday_http_transport_test.rb
166
164
  - test/hal_json_test.rb
167
165
  - test/hal_links_test.rb
168
- - test/http_verbs_feature_test.rb
166
+ - test/http_verbs_test.rb
169
167
  - test/hypermedia_feature_test.rb
170
168
  - test/hypermedia_test.rb
171
169
  - test/integration/Gemfile
172
170
  - test/integration/band_representer.rb
173
171
  - test/integration/runner.rb
174
172
  - test/integration/server.rb
173
+ - test/integration/ssl_server.rb
175
174
  - test/json_representer_test.rb
176
175
  - test/net_http_transport_test.rb
177
176
  - test/representer_test.rb
@@ -187,18 +186,38 @@ require_paths:
187
186
  - lib
188
187
  required_ruby_version: !ruby/object:Gem::Requirement
189
188
  requirements:
190
- - - '>='
189
+ - - ">="
191
190
  - !ruby/object:Gem::Version
192
191
  version: '0'
193
192
  required_rubygems_version: !ruby/object:Gem::Requirement
194
193
  requirements:
195
- - - '>='
194
+ - - ">="
196
195
  - !ruby/object:Gem::Version
197
196
  version: '0'
198
197
  requirements: []
199
198
  rubyforge_project: roar
200
- rubygems_version: 2.0.3
199
+ rubygems_version: 2.2.1
201
200
  signing_key:
202
201
  specification_version: 4
203
202
  summary: Resource-oriented architectures in Ruby.
204
- test_files: []
203
+ test_files:
204
+ - test/client_test.rb
205
+ - test/coercion_feature_test.rb
206
+ - test/collection_json_test.rb
207
+ - test/decorator_test.rb
208
+ - test/faraday_http_transport_test.rb
209
+ - test/hal_json_test.rb
210
+ - test/hal_links_test.rb
211
+ - test/http_verbs_test.rb
212
+ - test/hypermedia_feature_test.rb
213
+ - test/hypermedia_test.rb
214
+ - test/integration/Gemfile
215
+ - test/integration/band_representer.rb
216
+ - test/integration/runner.rb
217
+ - test/integration/server.rb
218
+ - test/integration/ssl_server.rb
219
+ - test/json_representer_test.rb
220
+ - test/net_http_transport_test.rb
221
+ - test/representer_test.rb
222
+ - test/test_helper.rb
223
+ - test/xml_representer_test.rb
@@ -1,6 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec :path => '../'
4
-
5
- gem 'representable', '~> 1.5.2'
6
- gem 'json'
@@ -1,5 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec path: '../'
4
-
5
- gem 'representable', '~> 1.5.2'
@@ -1,5 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec path: '../'
4
-
5
- gem 'representable', '~> 1.6.0'