hyperclient 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+ require_relative '../test_helper'
2
+ require 'hyperclient/resource'
3
+
4
+ module Hyperclient
5
+ describe Resource do
6
+ let(:response) do
7
+ File.read('test/fixtures/element.json')
8
+ end
9
+
10
+ let(:parsed_response) do
11
+ JSON.parse(response)
12
+ end
13
+
14
+ before do
15
+ Resource.entry_point = 'http://api.example.org'
16
+ end
17
+
18
+ describe 'url' do
19
+ it 'merges the resource url with the entry point' do
20
+ resource = Resource.new('/path/to/resource')
21
+ resource.url.to_s.must_equal 'http://api.example.org/path/to/resource'
22
+ end
23
+
24
+ it 'returns the given url if it cannot merge it' do
25
+ resource = Resource.new('/search={terms}')
26
+ resource.url.to_s.must_equal '/search={terms}'
27
+ end
28
+ end
29
+
30
+ describe 'initialize' do
31
+ before do
32
+ stub_request(:get, 'http://api.example.org')
33
+ end
34
+
35
+ it 'initializes the response when one is given' do
36
+ resource = Resource.new('/', {response: JSON.parse(response)})
37
+
38
+ assert_not_requested(:get, 'http://api.example.org/')
39
+ end
40
+
41
+ it 'updates the resource URL if the response has one' do
42
+ resource = Resource.new('/', {response: JSON.parse(response)})
43
+
44
+ resource.url.must_include '/productions/1'
45
+ end
46
+
47
+ it 'does no update the resource URL if the response does not have one' do
48
+ resource = Resource.new('/', {})
49
+
50
+ resource.url.wont_include '/productions/1'
51
+ end
52
+
53
+ it 'sets the resource name' do
54
+ resource = Resource.new('/', {name: 'posts'})
55
+
56
+ resource.name.must_equal 'posts'
57
+ end
58
+ end
59
+
60
+ describe 'reload' do
61
+ before do
62
+ stub_request(:get, "http://api.example.org/productions/1").
63
+ to_return(:status => 200, :body => response, headers: {content_type: 'application/json'})
64
+ end
65
+
66
+ it 'retrives itself from the API' do
67
+ resource = Resource.new('/productions/1')
68
+ resource.reload
69
+
70
+ assert_requested(:get, 'http://api.example.org/productions/1', times: 1)
71
+ end
72
+
73
+ it 'returns itself' do
74
+ resource = Resource.new('/productions/1')
75
+
76
+ resource.reload.must_equal resource
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,50 @@
1
+ require_relative '../test_helper'
2
+ require 'hyperclient/response'
3
+
4
+ module Hyperclient
5
+ describe Response do
6
+ let (:response) do
7
+ Response.new JSON.parse(File.read('test/fixtures/element.json'))
8
+ end
9
+
10
+ describe 'attributes' do
11
+ it 'returns the resource attributes' do
12
+ response.attributes['title'].must_equal 'Real World ASP.NET MVC3'
13
+ end
14
+
15
+ it 'does not include _links as attributes' do
16
+ response.attributes.wont_include '_links'
17
+ end
18
+
19
+ it 'does not include _embedded as attributes' do
20
+ response.attributes.wont_include '_embedded'
21
+ end
22
+ end
23
+
24
+ describe 'links' do
25
+ it 'returns resources included in the _links section' do
26
+ response.links.filter.must_be_kind_of Resource
27
+ end
28
+ end
29
+
30
+ describe 'resources' do
31
+ it 'returns resources included in the _embedded section' do
32
+ response.resources.author.must_be_kind_of Resource
33
+ response.resources.episodes.first.must_be_kind_of Resource
34
+ response.resources.episodes.last.must_be_kind_of Resource
35
+ end
36
+ end
37
+
38
+ describe 'url' do
39
+ it 'returns the url of the resource grabbed from the response' do
40
+ response.url.must_equal '/productions/1'
41
+ end
42
+
43
+ it 'returns nil when the response does not include the resource url' do
44
+ response = Response.new({_links: {media: {href: '/media/1'}}})
45
+
46
+ response.url.must_equal nil
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,63 @@
1
+ require_relative 'test_helper'
2
+ require 'hyperclient'
3
+
4
+ describe Hyperclient do
5
+ let(:api) do
6
+ Class.new do
7
+ include Hyperclient
8
+ end
9
+ end
10
+
11
+ describe 'entry point' do
12
+ it 'sets the entry point for Hyperclient::Resource' do
13
+ api.entry_point 'http://my.api.org'
14
+
15
+ Hyperclient::Resource.new('/').url.must_include 'http://my.api.org'
16
+ end
17
+ end
18
+
19
+ describe 'entry' do
20
+ before do
21
+ api.entry_point 'http://my.api.org'
22
+ end
23
+
24
+ it 'initializes a Resource at the entry point' do
25
+ api.new.entry.url.must_equal 'http://my.api.org/'
26
+ end
27
+
28
+ it 'sets the Resource name' do
29
+ api.new.name.must_equal 'Entry point'
30
+ end
31
+ end
32
+
33
+ describe 'auth' do
34
+ it 'sets authentication type' do
35
+ api.auth(:digest, nil, nil)
36
+
37
+ api.http_options[:http][:auth][:type].must_equal :digest
38
+ end
39
+
40
+ it 'sets the authentication credentials' do
41
+ api.auth(:digest, 'user', 'secret')
42
+
43
+ api.http_options[:http][:auth][:credentials].must_include 'user'
44
+ api.http_options[:http][:auth][:credentials].must_include 'secret'
45
+ end
46
+ end
47
+
48
+ describe 'method missing' do
49
+ class Hyperclient::Resource
50
+ def foo
51
+ 'foo'
52
+ end
53
+ end
54
+
55
+ it 'delegates undefined methods to the API when they exist' do
56
+ api.new.foo.must_equal 'foo'
57
+ end
58
+
59
+ it 'raises an error when the method does not exist in the API' do
60
+ lambda { api.new.this_method_does_not_exist }.must_raise(NoMethodError)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,7 @@
1
+ gem 'minitest'
2
+
3
+ require 'minitest/spec'
4
+ require 'minitest/autorun'
5
+ require 'turn'
6
+ require 'webmock/minitest'
7
+ require 'json'
metadata CHANGED
@@ -1,32 +1,115 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyperclient
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - Mike Subelsky
8
+ - Oriol Gual
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-06 00:00:00.000000000Z
13
- dependencies: []
14
- description: Proof of concept for interacting with a hypermedia API
12
+ date: 2012-05-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: minitest
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: turn
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: webmock
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: HyperClient is a Ruby Hypermedia API client.
15
79
  email:
16
- - mike@subelsky.com
80
+ - oriol.gual@gmail.com
17
81
  executables: []
18
82
  extensions: []
19
83
  extra_rdoc_files: []
20
84
  files:
85
+ - .gitignore
21
86
  - .rvmrc
87
+ - .travis.yml
88
+ - .yardopts
22
89
  - Gemfile
90
+ - Guardfile
23
91
  - LICENSE
24
- - README.md
92
+ - MIT-LICENSE
25
93
  - Rakefile
94
+ - Readme.md
95
+ - examples/hal_shop.rb
26
96
  - hyperclient.gemspec
27
97
  - lib/hyperclient.rb
98
+ - lib/hyperclient/discoverer.rb
99
+ - lib/hyperclient/http.rb
100
+ - lib/hyperclient/resource.rb
101
+ - lib/hyperclient/response.rb
28
102
  - lib/hyperclient/version.rb
29
- homepage: https://github.com/subelsky/hyperclient
103
+ - test/fixtures/collection.json
104
+ - test/fixtures/element.json
105
+ - test/fixtures/root.json
106
+ - test/hyperclient/discoverer_test.rb
107
+ - test/hyperclient/http_test.rb
108
+ - test/hyperclient/resource_test.rb
109
+ - test/hyperclient/response_test.rb
110
+ - test/hyperclient_test.rb
111
+ - test/test_helper.rb
112
+ homepage: http://codegram.github.com/hyperclient/
30
113
  licenses: []
31
114
  post_install_message:
32
115
  rdoc_options: []
@@ -38,17 +121,32 @@ required_ruby_version: !ruby/object:Gem::Requirement
38
121
  - - ! '>='
39
122
  - !ruby/object:Gem::Version
40
123
  version: '0'
124
+ segments:
125
+ - 0
126
+ hash: -2437981689318086472
41
127
  required_rubygems_version: !ruby/object:Gem::Requirement
42
128
  none: false
43
129
  requirements:
44
130
  - - ! '>='
45
131
  - !ruby/object:Gem::Version
46
132
  version: '0'
133
+ segments:
134
+ - 0
135
+ hash: -2437981689318086472
47
136
  requirements: []
48
137
  rubyforge_project:
49
- rubygems_version: 1.8.15
138
+ rubygems_version: 1.8.23
50
139
  signing_key:
51
140
  specification_version: 3
52
- summary: This client is capable of interacting with hypermedia APIs as described in
53
- http://www.subbu.org/blog/2008/09/on-linking-part-1 and elsewhere
54
- test_files: []
141
+ summary: ''
142
+ test_files:
143
+ - test/fixtures/collection.json
144
+ - test/fixtures/element.json
145
+ - test/fixtures/root.json
146
+ - test/hyperclient/discoverer_test.rb
147
+ - test/hyperclient/http_test.rb
148
+ - test/hyperclient/resource_test.rb
149
+ - test/hyperclient/response_test.rb
150
+ - test/hyperclient_test.rb
151
+ - test/test_helper.rb
152
+ has_rdoc:
data/README.md DELETED
@@ -1,71 +0,0 @@
1
- # Hyperclient
2
-
3
- This gem aims to explore and demonstrate how to write a client for [hypermedia APIs](http://blog.steveklabnik.com/posts/2012-02-23-rest-is-over), formerly
4
- known as REST interfaces that respect the [HATEOAS constraint](http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven).
5
-
6
- Many people have demonstrated how the server should respond. I'm investigating how the client should behave when interacting with a true hypermedia server.
7
-
8
- The gem is being developed against the [Hypertext Application Language](http://stateless.co/hal_specification.html) and [Atompub](http://bitworking.org/projects/atom/rfc5023.html) specifications.
9
-
10
- Contributors welcome!
11
-
12
- ## Installation
13
-
14
- Add this line to your application's Gemfile:
15
-
16
- gem 'hyperclient'
17
-
18
- And then execute:
19
-
20
- $ bundle
21
-
22
- Or install it yourself as:
23
-
24
- $ gem install hyperclient
25
-
26
- ## Usage
27
-
28
- ```ruby
29
- require 'hyperclient'
30
-
31
- # NOTE this is the only URI you ever need to specify yourself. The server will provide all future links.
32
- resource = Hyperclient::Resource.new("http://api.example.com")
33
-
34
- resource.links.each { |l| puts(l.relation => l.uri) }
35
- # {:self => "https://api.example.com"}
36
- # {:orders => "https://api.example.com/orders"}
37
- # {:customers => "https://api.example.com/customers"}
38
-
39
- # since we're at the root level of this API we haven't drilled into any objects yet
40
- pp resource.objects
41
- # []
42
-
43
- orders_resource = resource[:orders].get
44
- pp orders_resource.links
45
- # {:self => "https://api.example.com/orders",
46
- # :next => "https://api.example.com/orders/page/2"}
47
-
48
- # some servers may return embedded objects
49
- orders_resource.objects.each { |l| puts l.class => l.attributes }
50
- # [Hyperclient::Resource => {:id => 50, :item_name => "R2 Motivator", :created_at => "2012-02-03 12:15:02 -0400"},
51
- # Hyperclient::Resource => {:id => 51, :item_name => "Hydrospanner", :created_at => "2012-02-04 13:18:12 -0500"}]
52
-
53
- order_resource = orders_resource.post({ item_name: "Droid Coolant" })
54
- pp order_resource.location
55
- # "https://api.example.com/orders/52"
56
-
57
- pp order_resource.attributes
58
- # {:id => 52, :item_name => "Droid Coolant", :created_at => "2012-03-05 21:31:04 -0500"}
59
- ```
60
-
61
- ## Contributing
62
-
63
- 1. Fork it
64
- 2. Create your feature branch (`git checkout -b my-new-feature`)
65
- 3. Commit your changes (`git commit -am 'Added some feature'`)
66
- 4. Push to the branch (`git push origin my-new-feature`)
67
- 5. Create new Pull Request
68
-
69
- ## Questions?
70
-
71
- Contact me on [Twitter](https://twitter/subelsky) or [email](mike@subelsky.com).