sawyer 0.5.3 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +5 -0
- data/README.md +53 -10
- data/lib/sawyer/agent.rb +5 -0
- data/lib/sawyer/link_parsers/simple.rb +1 -1
- data/lib/sawyer/relation.rb +10 -1
- data/lib/sawyer/resource.rb +30 -7
- data/lib/sawyer/response.rb +11 -3
- data/lib/sawyer/serializer.rb +13 -5
- data/lib/sawyer.rb +1 -1
- data/sawyer.gemspec +2 -3
- metadata +21 -28
- data/test/agent_test.rb +0 -181
- data/test/helper.rb +0 -7
- data/test/relation_test.rb +0 -165
- data/test/resource_test.rb +0 -168
- data/test/response_test.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bfc34ec8885b709a9131ae0951b0d72bf92ef5292506fb86182dfe776c4f6309
|
4
|
+
data.tar.gz: 445fb9228adc3b153ab1796a9846a031582d1740fbfe37ccae7dc79a4261add5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08bc7993e9eb1c943553e0764746f645e1fa6433072a93a8423dbfe2a56d4fe08a9169a2d5252dc42466432692c798e0686b15e49239b3c8d59d2d5492a0da14'
|
7
|
+
data.tar.gz: 22ee3d437bb65e6013309dbf3704b2d539d984e46f43601333729484ac9a768e4be0fc0feb1d9ad8198ae05d6d24b7b7c520dcd699fd8e391cfa7938d249eff6
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,19 +1,62 @@
|
|
1
1
|
# Sawyer
|
2
2
|
|
3
|
-
Sawyer is an experimental
|
4
|
-
[Faraday][faraday].
|
3
|
+
Sawyer is an experimental hypermedia agent for Ruby built on top of [Faraday][faraday].
|
5
4
|
|
6
5
|
[faraday]: https://github.com/lostisland/faraday
|
7
6
|
|
8
|
-
|
7
|
+
## Installation
|
9
8
|
|
10
|
-
|
11
|
-
knows the technical details of how to communicate with an application.
|
12
|
-
But he also gets overly obsessive about alternate timelines to be of
|
13
|
-
much use.
|
9
|
+
Add this line to your application's Gemfile:
|
14
10
|
|
15
|
-
|
11
|
+
```ruby
|
12
|
+
gem 'sawyer'
|
13
|
+
```
|
16
14
|
|
17
|
-
|
18
|
-
situation, and figures out the next action.
|
15
|
+
And then execute:
|
19
16
|
|
17
|
+
```sh
|
18
|
+
bundle
|
19
|
+
```
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
```sh
|
24
|
+
gem install sawyer
|
25
|
+
```
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require "sawyer"
|
31
|
+
|
32
|
+
# Create a Sawyer agent
|
33
|
+
agent = Sawyer::Agent.new("https://api.github.com",
|
34
|
+
links_parser: Sawyer::LinkParsers::Simple.new)
|
35
|
+
|
36
|
+
# Fetch the root of the API
|
37
|
+
root = agent.root.data
|
38
|
+
|
39
|
+
# Access a resource directly
|
40
|
+
contributors = agent.call(:get, "repos/lostisland/sawyer/contributors").data
|
41
|
+
|
42
|
+
# Load a hypermedia relation
|
43
|
+
top_contributor = contributors.first
|
44
|
+
followers = top_contributor.rels[:followers].get.data
|
45
|
+
```
|
46
|
+
|
47
|
+
For more information, check out the [documentation](http://www.rubydoc.info/gems/sawyer/).
|
48
|
+
|
49
|
+
## Development
|
50
|
+
|
51
|
+
After checking out the repo, run `script/test` to bootstrap the project and run the tests.
|
52
|
+
You can also run `script/console` for an interactive prompt that will allow you to experiment.
|
53
|
+
|
54
|
+
To package the gem, run `script/package`. To release a new version, update the version number in [`lib/sawyer.rb`](lib/sawyer.rb), and then run `script/release`, which will create a git tag for the version, push git commits and tags, and push the .gem file to [rubygems.org](https://rubygems.org).
|
55
|
+
|
56
|
+
## Contributing
|
57
|
+
|
58
|
+
Check out the [contributing guide](CONTRIBUTING.md) for more information on contributing.
|
59
|
+
|
60
|
+
## License
|
61
|
+
|
62
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/sawyer/agent.rb
CHANGED
@@ -48,6 +48,11 @@ module Sawyer
|
|
48
48
|
yield @conn if block_given?
|
49
49
|
end
|
50
50
|
|
51
|
+
# Public: Close the underlying connection.
|
52
|
+
def close
|
53
|
+
@conn.close if @conn.respond_to?(:close)
|
54
|
+
end
|
55
|
+
|
51
56
|
# Public: Retains a reference to the root relations of the API.
|
52
57
|
#
|
53
58
|
# Returns a Sawyer::Relation::Map.
|
@@ -17,7 +17,7 @@ module Sawyer
|
|
17
17
|
inline_links = data.keys.select {|k| k.to_s[LINK_REGEX] }
|
18
18
|
inline_links.each do |key|
|
19
19
|
rel_name = key.to_s == 'url' ? 'self' : key.to_s.gsub(LINK_REGEX, '')
|
20
|
-
links[rel_name.to_sym] = data
|
20
|
+
links[rel_name.to_sym] = data[key]
|
21
21
|
end
|
22
22
|
|
23
23
|
return data, links
|
data/lib/sawyer/relation.rb
CHANGED
@@ -39,8 +39,17 @@ module Sawyer
|
|
39
39
|
@map.keys
|
40
40
|
end
|
41
41
|
|
42
|
+
def to_hash
|
43
|
+
pairs = @map.map do |k, v|
|
44
|
+
[(k.to_s + "_url").to_sym, v.href]
|
45
|
+
end
|
46
|
+
Hash[pairs]
|
47
|
+
end
|
48
|
+
alias :to_h :to_hash
|
49
|
+
|
42
50
|
def inspect
|
43
|
-
|
51
|
+
hash = to_hash
|
52
|
+
hash.respond_to?(:pretty_inspect) ? hash.pretty_inspect : hash.inspect
|
44
53
|
end
|
45
54
|
end
|
46
55
|
|
data/lib/sawyer/resource.rb
CHANGED
@@ -3,7 +3,7 @@ module Sawyer
|
|
3
3
|
SPECIAL_METHODS = Set.new(%w(agent rels fields))
|
4
4
|
attr_reader :_agent, :_rels, :_fields
|
5
5
|
attr_reader :attrs
|
6
|
-
|
6
|
+
include Enumerable
|
7
7
|
|
8
8
|
# Initializes a Resource with the given data.
|
9
9
|
#
|
@@ -82,11 +82,11 @@ module Sawyer
|
|
82
82
|
elsif attr_name && @_fields.include?(attr_name.to_sym)
|
83
83
|
value = @attrs[attr_name.to_sym]
|
84
84
|
case suffix
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
85
|
+
when nil
|
86
|
+
@_metaclass.send(:attr_accessor, attr_name)
|
87
|
+
value
|
88
|
+
when ATTR_PREDICATE then !!value
|
89
|
+
end
|
90
90
|
elsif suffix.nil? && SPECIAL_METHODS.include?(attr_name)
|
91
91
|
instance_variable_get "@_#{attr_name}"
|
92
92
|
elsif attr_name && !@_fields.include?(attr_name.to_sym)
|
@@ -115,18 +115,41 @@ module Sawyer
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
+
def inspect
|
119
|
+
to_attrs.respond_to?(:pretty_inspect) ? to_attrs.pretty_inspect : to_attrs.inspect
|
120
|
+
end
|
121
|
+
|
122
|
+
def each(&block)
|
123
|
+
@attrs.each(&block)
|
124
|
+
end
|
125
|
+
|
118
126
|
# private
|
119
127
|
def to_yaml_properties
|
120
128
|
[:@attrs, :@_fields, :@_rels]
|
121
129
|
end
|
122
130
|
|
131
|
+
def to_attrs
|
132
|
+
hash = self.attrs.clone
|
133
|
+
hash.keys.each do |k|
|
134
|
+
if hash[k].is_a?(Sawyer::Resource)
|
135
|
+
hash[k] = hash[k].to_attrs
|
136
|
+
elsif hash[k].is_a?(Array) && hash[k].all?{|el| el.is_a?(Sawyer::Resource)}
|
137
|
+
hash[k] = hash[k].collect{|el| el.to_attrs}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
hash
|
141
|
+
end
|
142
|
+
|
143
|
+
alias to_hash to_attrs
|
144
|
+
alias to_h to_attrs
|
145
|
+
|
123
146
|
def marshal_dump
|
124
147
|
[@attrs, @_fields, @_rels]
|
125
148
|
end
|
126
149
|
|
127
150
|
def marshal_load(dumped)
|
128
151
|
@attrs, @_fields, @_rels = *dumped.shift(3)
|
152
|
+
@_metaclass = (class << self; self; end)
|
129
153
|
end
|
130
154
|
end
|
131
155
|
end
|
132
|
-
|
data/lib/sawyer/response.rb
CHANGED
@@ -3,7 +3,8 @@ module Sawyer
|
|
3
3
|
attr_reader :agent,
|
4
4
|
:status,
|
5
5
|
:headers,
|
6
|
-
:
|
6
|
+
:env,
|
7
|
+
:body,
|
7
8
|
:rels
|
8
9
|
|
9
10
|
# Builds a Response after a completed request.
|
@@ -15,12 +16,19 @@ module Sawyer
|
|
15
16
|
@status = res.status
|
16
17
|
@headers = res.headers
|
17
18
|
@env = res.env
|
18
|
-
@
|
19
|
+
@body = res.body
|
19
20
|
@rels = process_rels
|
20
21
|
@started = options[:sawyer_started]
|
21
22
|
@ended = options[:sawyer_ended]
|
22
23
|
end
|
23
24
|
|
25
|
+
def data
|
26
|
+
@data ||= begin
|
27
|
+
return(body) unless (headers[:content_type] =~ /json|msgpack/)
|
28
|
+
process_data(agent.decode_body(body))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
24
32
|
# Turns parsed contents from an API response into a Resource or
|
25
33
|
# collection of Resources.
|
26
34
|
#
|
@@ -58,7 +66,7 @@ module Sawyer
|
|
58
66
|
end
|
59
67
|
|
60
68
|
def inspect
|
61
|
-
%(#<#{self.class}: #{@status} @rels=#{@rels.inspect} @data=#{
|
69
|
+
%(#<#{self.class}: #{@status} @rels=#{@rels.inspect} @data=#{data.inspect}>)
|
62
70
|
end
|
63
71
|
end
|
64
72
|
end
|
data/lib/sawyer/serializer.rb
CHANGED
@@ -4,7 +4,9 @@ require 'time'
|
|
4
4
|
module Sawyer
|
5
5
|
class Serializer
|
6
6
|
def self.any_json
|
7
|
-
yajl || multi_json || json
|
7
|
+
yajl || multi_json || json || begin
|
8
|
+
raise RuntimeError, "Sawyer requires a JSON gem: yajl, multi_json, or json"
|
9
|
+
end
|
8
10
|
end
|
9
11
|
|
10
12
|
def self.yajl
|
@@ -58,7 +60,7 @@ module Sawyer
|
|
58
60
|
#
|
59
61
|
# Returns a decoded Object.
|
60
62
|
def decode(data)
|
61
|
-
return nil if data.nil? || data.empty?
|
63
|
+
return nil if data.nil? || data.strip.empty?
|
62
64
|
decode_object(@load.call(data))
|
63
65
|
end
|
64
66
|
|
@@ -100,9 +102,15 @@ module Sawyer
|
|
100
102
|
|
101
103
|
def decode_hash_value(key, value)
|
102
104
|
if time_field?(key, value)
|
103
|
-
|
104
|
-
|
105
|
-
|
105
|
+
if value.is_a?(String)
|
106
|
+
begin
|
107
|
+
Time.parse(value)
|
108
|
+
rescue ArgumentError
|
109
|
+
value
|
110
|
+
end
|
111
|
+
elsif value.is_a?(Integer) || value.is_a?(Float)
|
112
|
+
Time.at(value)
|
113
|
+
else
|
106
114
|
value
|
107
115
|
end
|
108
116
|
elsif value.is_a?(Hash)
|
data/lib/sawyer.rb
CHANGED
data/sawyer.gemspec
CHANGED
@@ -17,13 +17,12 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.homepage = 'https://github.com/lostisland/sawyer'
|
18
18
|
spec.licenses = ['MIT']
|
19
19
|
|
20
|
-
spec.add_dependency 'faraday',
|
21
|
-
spec.add_dependency 'addressable', ['
|
20
|
+
spec.add_dependency 'faraday', ">= 0.9", "< 3"
|
21
|
+
spec.add_dependency 'addressable', ['>= 2.3.5']
|
22
22
|
|
23
23
|
spec.files = %w(Gemfile LICENSE.md README.md Rakefile)
|
24
24
|
spec.files << "#{lib}.gemspec"
|
25
25
|
spec.files += Dir.glob("lib/**/*.rb")
|
26
|
-
spec.files += Dir.glob("test/**/*.rb")
|
27
26
|
spec.files += Dir.glob("script/*")
|
28
27
|
|
29
28
|
dev_null = File.exist?('/dev/null') ? '/dev/null' : 'NUL'
|
metadata
CHANGED
@@ -1,51 +1,51 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sawyer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rick Olson
|
8
8
|
- Wynn Netherland
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-02-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '0.
|
21
|
-
- - <
|
20
|
+
version: '0.9'
|
21
|
+
- - "<"
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: '
|
23
|
+
version: '3'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
|
-
- -
|
28
|
+
- - ">="
|
29
29
|
- !ruby/object:Gem::Version
|
30
|
-
version: '0.
|
31
|
-
- - <
|
30
|
+
version: '0.9'
|
31
|
+
- - "<"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '3'
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: addressable
|
36
36
|
requirement: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 2.3.5
|
41
41
|
type: :runtime
|
42
42
|
prerelease: false
|
43
43
|
version_requirements: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 2.3.5
|
48
|
-
description:
|
48
|
+
description:
|
49
49
|
email: technoweenie@gmail.com
|
50
50
|
executables: []
|
51
51
|
extensions: []
|
@@ -55,7 +55,7 @@ files:
|
|
55
55
|
- LICENSE.md
|
56
56
|
- README.md
|
57
57
|
- Rakefile
|
58
|
-
- sawyer.
|
58
|
+
- lib/sawyer.rb
|
59
59
|
- lib/sawyer/agent.rb
|
60
60
|
- lib/sawyer/link_parsers/hal.rb
|
61
61
|
- lib/sawyer/link_parsers/simple.rb
|
@@ -63,12 +63,7 @@ files:
|
|
63
63
|
- lib/sawyer/resource.rb
|
64
64
|
- lib/sawyer/response.rb
|
65
65
|
- lib/sawyer/serializer.rb
|
66
|
-
-
|
67
|
-
- test/agent_test.rb
|
68
|
-
- test/helper.rb
|
69
|
-
- test/relation_test.rb
|
70
|
-
- test/resource_test.rb
|
71
|
-
- test/response_test.rb
|
66
|
+
- sawyer.gemspec
|
72
67
|
- script/bootstrap
|
73
68
|
- script/console
|
74
69
|
- script/package
|
@@ -78,25 +73,23 @@ homepage: https://github.com/lostisland/sawyer
|
|
78
73
|
licenses:
|
79
74
|
- MIT
|
80
75
|
metadata: {}
|
81
|
-
post_install_message:
|
76
|
+
post_install_message:
|
82
77
|
rdoc_options: []
|
83
78
|
require_paths:
|
84
79
|
- lib
|
85
80
|
required_ruby_version: !ruby/object:Gem::Requirement
|
86
81
|
requirements:
|
87
|
-
- -
|
82
|
+
- - ">="
|
88
83
|
- !ruby/object:Gem::Version
|
89
84
|
version: '0'
|
90
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
86
|
requirements:
|
92
|
-
- -
|
87
|
+
- - ">="
|
93
88
|
- !ruby/object:Gem::Version
|
94
89
|
version: 1.3.5
|
95
90
|
requirements: []
|
96
|
-
|
97
|
-
|
98
|
-
signing_key:
|
91
|
+
rubygems_version: 3.0.9
|
92
|
+
signing_key:
|
99
93
|
specification_version: 2
|
100
94
|
summary: Secret User Agent of HTTP
|
101
95
|
test_files: []
|
102
|
-
has_rdoc:
|
data/test/agent_test.rb
DELETED
@@ -1,181 +0,0 @@
|
|
1
|
-
require File.expand_path("../helper", __FILE__)
|
2
|
-
|
3
|
-
require 'faraday/adapter/test'
|
4
|
-
|
5
|
-
module Sawyer
|
6
|
-
class AgentTest < TestCase
|
7
|
-
|
8
|
-
class InlineRelsParser
|
9
|
-
def parse(data)
|
10
|
-
links = {}
|
11
|
-
data.keys.select {|k| k[/_url$/] }.each {|k| links[k.to_s.gsub(/_url$/, '')] = data.delete(k) }
|
12
|
-
|
13
|
-
return data, links
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def setup
|
18
|
-
@stubs = Faraday::Adapter::Test::Stubs.new
|
19
|
-
@agent = Sawyer::Agent.new "http://foo.com/a/" do |conn|
|
20
|
-
conn.builder.handlers.delete(Faraday::Adapter::NetHttp)
|
21
|
-
conn.adapter :test, @stubs
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_accesses_root_relations
|
26
|
-
@stubs.get '/a/' do |env|
|
27
|
-
assert_equal 'foo.com', env[:url].host
|
28
|
-
|
29
|
-
[200, {'Content-Type' => 'application/json'}, Sawyer::Agent.encode(
|
30
|
-
:_links => {
|
31
|
-
:users => {:href => '/users'}})]
|
32
|
-
end
|
33
|
-
|
34
|
-
assert_equal 200, @agent.root.status
|
35
|
-
|
36
|
-
assert_equal '/users', @agent.rels[:users].href
|
37
|
-
assert_equal :get, @agent.rels[:users].method
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_allows_custom_rel_parsing
|
41
|
-
@stubs.get '/a/' do |env|
|
42
|
-
assert_equal 'foo.com', env[:url].host
|
43
|
-
|
44
|
-
[200, {'Content-Type' => 'application/json'}, Sawyer::Agent.encode(
|
45
|
-
:url => '/',
|
46
|
-
:users_url => '/users',
|
47
|
-
:repos_url => '/repos')]
|
48
|
-
end
|
49
|
-
|
50
|
-
agent = Sawyer::Agent.new "http://foo.com/a/" do |conn|
|
51
|
-
conn.builder.handlers.delete(Faraday::Adapter::NetHttp)
|
52
|
-
conn.adapter :test, @stubs
|
53
|
-
end
|
54
|
-
agent.links_parser = InlineRelsParser.new
|
55
|
-
|
56
|
-
assert_equal 200, agent.root.status
|
57
|
-
|
58
|
-
assert_equal '/users', agent.rels[:users].href
|
59
|
-
assert_equal :get, agent.rels[:users].method
|
60
|
-
assert_equal '/repos', agent.rels[:repos].href
|
61
|
-
assert_equal :get, agent.rels[:repos].method
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_saves_root_endpoint
|
66
|
-
@stubs.get '/a/' do |env|
|
67
|
-
[200, {}, '{}']
|
68
|
-
end
|
69
|
-
|
70
|
-
assert_kind_of Sawyer::Response, @agent.root
|
71
|
-
assert_not_equal @agent.root.time, @agent.start.time
|
72
|
-
end
|
73
|
-
|
74
|
-
def test_starts_a_session
|
75
|
-
@stubs.get '/a/' do |env|
|
76
|
-
assert_equal 'foo.com', env[:url].host
|
77
|
-
|
78
|
-
[200, {'Content-Type' => 'application/json'}, Sawyer::Agent.encode(
|
79
|
-
:_links => {
|
80
|
-
:users => {:href => '/users'}})]
|
81
|
-
end
|
82
|
-
|
83
|
-
res = @agent.start
|
84
|
-
|
85
|
-
assert_equal 200, res.status
|
86
|
-
assert_kind_of Sawyer::Resource, resource = res.data
|
87
|
-
|
88
|
-
assert_equal '/users', resource.rels[:users].href
|
89
|
-
assert_equal :get, resource.rels[:users].method
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_requests_with_body_and_options
|
93
|
-
@stubs.post '/a/b/c' do |env|
|
94
|
-
assert_equal '{"a":1}', env[:body]
|
95
|
-
assert_equal 'abc', env[:request_headers]['x-test']
|
96
|
-
assert_equal 'foo=bar', env[:url].query
|
97
|
-
[200, {}, "{}"]
|
98
|
-
end
|
99
|
-
|
100
|
-
res = @agent.call :post, 'b/c' , {:a => 1},
|
101
|
-
:headers => {"X-Test" => "abc"},
|
102
|
-
:query => {:foo => 'bar'}
|
103
|
-
assert_equal 200, res.status
|
104
|
-
end
|
105
|
-
|
106
|
-
def test_requests_with_body_and_options_to_get
|
107
|
-
@stubs.get '/a/b/c' do |env|
|
108
|
-
assert_nil env[:body]
|
109
|
-
assert_equal 'abc', env[:request_headers]['x-test']
|
110
|
-
assert_equal 'foo=bar', env[:url].query
|
111
|
-
[200, {}, "{}"]
|
112
|
-
end
|
113
|
-
|
114
|
-
res = @agent.call :get, 'b/c' , {:a => 1},
|
115
|
-
:headers => {"X-Test" => "abc"},
|
116
|
-
:query => {:foo => 'bar'}
|
117
|
-
assert_equal 200, res.status
|
118
|
-
end
|
119
|
-
|
120
|
-
def test_encodes_and_decodes_times
|
121
|
-
time = Time.at(Time.now.to_i)
|
122
|
-
data = {
|
123
|
-
:a => 1,
|
124
|
-
:b => true,
|
125
|
-
:c => 'c',
|
126
|
-
:created_at => time,
|
127
|
-
:published_at => nil,
|
128
|
-
:updated_at => "An invalid date",
|
129
|
-
:pub_date => time,
|
130
|
-
:validate => true
|
131
|
-
}
|
132
|
-
data = [data.merge(:foo => [data])]
|
133
|
-
encoded = Sawyer::Agent.encode(data)
|
134
|
-
decoded = Sawyer::Agent.decode(encoded)
|
135
|
-
|
136
|
-
2.times do
|
137
|
-
assert_equal 1, decoded.size
|
138
|
-
decoded = decoded.shift
|
139
|
-
|
140
|
-
assert_equal 1, decoded[:a]
|
141
|
-
assert_equal true, decoded[:b]
|
142
|
-
assert_equal 'c', decoded[:c]
|
143
|
-
assert_equal time, decoded[:created_at], "Did not parse created_at as Time"
|
144
|
-
assert_nil decoded[:published_at]
|
145
|
-
assert_equal "An invalid date", decoded[:updated_at]
|
146
|
-
assert_equal time, decoded[:pub_date], "Did not parse pub_date as Time"
|
147
|
-
assert_equal true, decoded[:validate]
|
148
|
-
decoded = decoded[:foo]
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def test_does_not_encode_non_json_content_types
|
153
|
-
@stubs.get '/a/' do |env|
|
154
|
-
assert_equal 'foo.com', env[:url].host
|
155
|
-
|
156
|
-
[200, {'Content-Type' => 'text/plain'}, "This is plain text"]
|
157
|
-
end
|
158
|
-
res = @agent.call :get, '/a/',
|
159
|
-
:headers => {"Accept" => "text/plain"}
|
160
|
-
assert_equal 200, res.status
|
161
|
-
|
162
|
-
assert_equal "This is plain text", res.data
|
163
|
-
end
|
164
|
-
|
165
|
-
def test_handle_yaml_dump_and_load
|
166
|
-
assert_nothing_raised do
|
167
|
-
require 'yaml'
|
168
|
-
res = Agent.new 'http://example.com', :a => 1
|
169
|
-
YAML.load(YAML.dump(res))
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def test_handle_marshal_dump_and_load
|
174
|
-
assert_nothing_raised do
|
175
|
-
res = Agent.new 'http://example.com', :a => 1
|
176
|
-
Marshal.load(Marshal.dump(res))
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
data/test/helper.rb
DELETED
data/test/relation_test.rb
DELETED
@@ -1,165 +0,0 @@
|
|
1
|
-
require File.expand_path("../helper", __FILE__)
|
2
|
-
|
3
|
-
module Sawyer
|
4
|
-
class RelationTest < TestCase
|
5
|
-
def test_builds_relation_from_hash
|
6
|
-
hash = {:href => '/users/1', :method => 'post'}
|
7
|
-
rel = Sawyer::Relation.from_link(nil, :self, hash)
|
8
|
-
|
9
|
-
assert_equal :self, rel.name
|
10
|
-
assert_equal '/users/1', rel.href
|
11
|
-
assert_equal :post, rel.method
|
12
|
-
assert_equal [:post], rel.available_methods.to_a
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_builds_multiple_rels_from_multiple_methods
|
16
|
-
index = {
|
17
|
-
'comments' => {:href => '/comments', :method => 'get,post'}
|
18
|
-
}
|
19
|
-
|
20
|
-
rels = Sawyer::Relation.from_links(nil, index)
|
21
|
-
assert_equal 1, rels.size
|
22
|
-
assert_equal [:comments], rels.keys
|
23
|
-
|
24
|
-
assert rel = rels[:comments]
|
25
|
-
assert_equal '/comments', rel.href
|
26
|
-
assert_equal :get, rel.method
|
27
|
-
assert_equal [:get, :post], rel.available_methods.to_a
|
28
|
-
assert_kind_of Addressable::Template, rel.href_template
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_builds_rels_from_hash
|
32
|
-
index = {
|
33
|
-
'self' => '/users/1'
|
34
|
-
}
|
35
|
-
|
36
|
-
rels = Sawyer::Relation.from_links(nil, index)
|
37
|
-
|
38
|
-
assert_equal 1, rels.size
|
39
|
-
assert_equal [:self], rels.keys
|
40
|
-
assert rel = rels[:self]
|
41
|
-
assert_equal :self, rel.name
|
42
|
-
assert_equal '/users/1', rel.href
|
43
|
-
assert_equal :get, rel.method
|
44
|
-
assert_equal [:get], rel.available_methods.to_a
|
45
|
-
assert_kind_of Addressable::Template, rel.href_template
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_builds_rels_from_hash_index
|
49
|
-
index = {
|
50
|
-
'self' => {:href => '/users/1'}
|
51
|
-
}
|
52
|
-
|
53
|
-
rels = Sawyer::Relation.from_links(nil, index)
|
54
|
-
|
55
|
-
assert_equal 1, rels.size
|
56
|
-
assert_equal [:self], rels.keys
|
57
|
-
assert rel = rels[:self]
|
58
|
-
assert_equal :self, rel.name
|
59
|
-
assert_equal '/users/1', rel.href
|
60
|
-
assert_equal :get, rel.method
|
61
|
-
assert_equal [:get], rel.available_methods.to_a
|
62
|
-
assert_kind_of Addressable::Template, rel.href_template
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_builds_rels_from_nil
|
66
|
-
rels = Sawyer::Relation.from_links nil, nil
|
67
|
-
assert_equal 0, rels.size
|
68
|
-
assert_equal [], rels.keys
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_relation_api_calls
|
72
|
-
agent = Sawyer::Agent.new "http://foo.com/a/" do |conn|
|
73
|
-
conn.builder.handlers.delete(Faraday::Adapter::NetHttp)
|
74
|
-
conn.adapter :test do |stubs|
|
75
|
-
stubs.get '/a/1' do
|
76
|
-
[200, {}, '{}']
|
77
|
-
end
|
78
|
-
stubs.delete '/a/1' do
|
79
|
-
[204, {}, '{}']
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
rel = Sawyer::Relation.new agent, :self, "/a/1", "get,put,delete"
|
85
|
-
assert_equal :get, rel.method
|
86
|
-
[:get, :put, :delete].each do |m|
|
87
|
-
assert rel.available_methods.include?(m), "#{m.inspect} is not available: #{rel.available_methods.inspect}"
|
88
|
-
end
|
89
|
-
|
90
|
-
assert_equal 200, rel.call.status
|
91
|
-
assert_equal 200, rel.call(:method => :head).status
|
92
|
-
assert_equal 204, rel.call(nil, :method => :delete).status
|
93
|
-
assert_raises ArgumentError do
|
94
|
-
rel.call nil, :method => :post
|
95
|
-
end
|
96
|
-
|
97
|
-
assert_equal 200, rel.head.status
|
98
|
-
assert_equal 200, rel.get.status
|
99
|
-
assert_equal 204, rel.delete.status
|
100
|
-
|
101
|
-
assert_raises ArgumentError do
|
102
|
-
rel.post
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def test_relation_api_calls_with_uri_tempate
|
107
|
-
agent = Sawyer::Agent.new "http://foo.com/a" do |conn|
|
108
|
-
conn.builder.handlers.delete(Faraday::Adapter::NetHttp)
|
109
|
-
conn.adapter :test do |stubs|
|
110
|
-
stubs.get '/octocat/hello' do |env|
|
111
|
-
assert_equal "a=1&b=2", env[:url].query
|
112
|
-
[200, {}, '{}']
|
113
|
-
end
|
114
|
-
|
115
|
-
stubs.get '/a' do
|
116
|
-
[404, {}, '{}']
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
rel = Sawyer::Relation.new agent, :repo, "{/user,repo}{?a,b}"
|
122
|
-
|
123
|
-
assert_equal '', rel.href
|
124
|
-
assert_equal '/octocat', rel.href(:user => :octocat)
|
125
|
-
|
126
|
-
assert_equal 404, rel.get.status
|
127
|
-
assert_equal 200, rel.get(:uri => {'user' => 'octocat', 'repo' => 'hello', 'a' => 1, 'b' => 2}).status
|
128
|
-
end
|
129
|
-
|
130
|
-
def test_handles_invalid_uri
|
131
|
-
hash = {:href => '/this has spaces', :method => 'post'}
|
132
|
-
rel = Sawyer::Relation.from_link(nil, :self, hash)
|
133
|
-
|
134
|
-
assert_equal :self, rel.name
|
135
|
-
assert_equal '/this has spaces', rel.href
|
136
|
-
end
|
137
|
-
|
138
|
-
def test_allows_all_methods_when_not_in_strict_mode
|
139
|
-
|
140
|
-
agent = Sawyer::Agent.new "http://foo.com/a/", :allow_undefined_methods => true do |conn|
|
141
|
-
conn.builder.handlers.delete(Faraday::Adapter::NetHttp)
|
142
|
-
conn.adapter :test do |stubs|
|
143
|
-
stubs.get '/a/1' do
|
144
|
-
[200, {}, '{}']
|
145
|
-
end
|
146
|
-
stubs.delete '/a/1' do
|
147
|
-
[204, {}, '{}']
|
148
|
-
end
|
149
|
-
stubs.post '/a/1' do
|
150
|
-
[200, {}, '{}']
|
151
|
-
end
|
152
|
-
stubs.put '/a/1' do
|
153
|
-
[204, {}, '{}']
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
rel = Sawyer::Relation.new agent, :self, "/a/1"
|
159
|
-
assert_equal 200, rel.get.status
|
160
|
-
assert_equal 200, rel.post.status
|
161
|
-
assert_equal 204, rel.put.status
|
162
|
-
assert_equal 204, rel.delete.status
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
data/test/resource_test.rb
DELETED
@@ -1,168 +0,0 @@
|
|
1
|
-
require File.expand_path("../helper", __FILE__)
|
2
|
-
|
3
|
-
module Sawyer
|
4
|
-
class ResourceTest < TestCase
|
5
|
-
|
6
|
-
def setup
|
7
|
-
@stubs = Faraday::Adapter::Test::Stubs.new
|
8
|
-
@agent = Sawyer::Agent.new "http://foo.com/a/" do |conn|
|
9
|
-
conn.builder.handlers.delete(Faraday::Adapter::NetHttp)
|
10
|
-
conn.adapter :test, @stubs
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_accessible_keys
|
15
|
-
res = Resource.new @agent, :a => 1,
|
16
|
-
:_links => {:self => {:href => '/'}}
|
17
|
-
|
18
|
-
assert_equal 1, res.a
|
19
|
-
assert res.rels[:self]
|
20
|
-
assert_equal @agent, res.agent
|
21
|
-
assert_equal 1, res.fields.size
|
22
|
-
assert res.fields.include?(:a)
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_clashing_keys
|
26
|
-
res = Resource.new @agent, :agent => 1, :rels => 2, :fields => 3,
|
27
|
-
:_links => {:self => {:href => '/'}}
|
28
|
-
|
29
|
-
assert_equal 1, res.agent
|
30
|
-
assert_equal 2, res.rels
|
31
|
-
assert_equal 3, res.fields
|
32
|
-
|
33
|
-
assert res._rels[:self]
|
34
|
-
assert_equal @agent, res._agent
|
35
|
-
assert_equal 3, res._fields.size
|
36
|
-
[:agent, :rels, :fields].each do |f|
|
37
|
-
assert res._fields.include?(f)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_nested_object
|
42
|
-
res = Resource.new @agent,
|
43
|
-
:user => {:id => 1, :_links => {:self => {:href => '/users/1'}}},
|
44
|
-
:_links => {:self => {:href => '/'}}
|
45
|
-
|
46
|
-
assert_equal '/', res.rels[:self].href
|
47
|
-
assert_kind_of Resource, res.user
|
48
|
-
assert_equal 1, res.user.id
|
49
|
-
assert_equal '/users/1', res.user.rels[:self].href
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_nested_collection
|
53
|
-
res = Resource.new @agent,
|
54
|
-
:users => [{:id => 1, :_links => {:self => {:href => '/users/1'}}}],
|
55
|
-
:_links => {:self => {:href => '/'}}
|
56
|
-
|
57
|
-
assert_equal '/', res.rels[:self].href
|
58
|
-
assert_kind_of Array, res.users
|
59
|
-
|
60
|
-
assert user = res.users.first
|
61
|
-
assert_kind_of Resource, user
|
62
|
-
assert_equal 1, user.id
|
63
|
-
assert_equal '/users/1', user.rels[:self].href
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_attribute_predicates
|
67
|
-
res = Resource.new @agent, :a => 1, :b => true, :c => nil, :d => false
|
68
|
-
|
69
|
-
assert res.a?
|
70
|
-
assert res.b?
|
71
|
-
assert !res.c?
|
72
|
-
assert !res.d?
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_attribute_setter
|
76
|
-
res = Resource.new @agent, :a => 1
|
77
|
-
assert_equal 1, res.a
|
78
|
-
assert !res.key?(:b)
|
79
|
-
|
80
|
-
res.b = 2
|
81
|
-
assert_equal 2, res.b
|
82
|
-
assert res.key?(:b)
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_dynamic_attribute_methods_from_getter
|
86
|
-
res = Resource.new @agent, :a => 1
|
87
|
-
assert res.key?(:a)
|
88
|
-
assert res.respond_to?(:a)
|
89
|
-
assert res.respond_to?(:a=)
|
90
|
-
|
91
|
-
assert_equal 1, res.a
|
92
|
-
assert res.respond_to?(:a)
|
93
|
-
assert res.respond_to?(:a=)
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_nillable_attribute_getters
|
97
|
-
res = Resource.new @agent, :a => 1
|
98
|
-
assert !res.key?(:b)
|
99
|
-
assert !res.respond_to?(:b)
|
100
|
-
assert !res.respond_to?(:b=)
|
101
|
-
assert_nil res.b
|
102
|
-
assert_nothing_raised do
|
103
|
-
res.b
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def test_dynamic_attribute_methods_from_setter
|
108
|
-
res = Resource.new @agent, :a => 1
|
109
|
-
assert !res.key?(:b)
|
110
|
-
assert !res.respond_to?(:b)
|
111
|
-
assert !res.respond_to?(:b=)
|
112
|
-
|
113
|
-
res.b = 1
|
114
|
-
assert res.key?(:b)
|
115
|
-
assert res.respond_to?(:b)
|
116
|
-
assert res.respond_to?(:b=)
|
117
|
-
end
|
118
|
-
|
119
|
-
def test_attrs
|
120
|
-
res = Resource.new @agent, :a => 1
|
121
|
-
hash = {:a => 1 }
|
122
|
-
assert_equal hash, res.attrs
|
123
|
-
end
|
124
|
-
|
125
|
-
def test_handle_hash_notation_with_string_key
|
126
|
-
res = Resource.new @agent, :a => 1
|
127
|
-
assert_equal 1, res['a']
|
128
|
-
|
129
|
-
res[:b] = 2
|
130
|
-
assert_equal 2, res.b
|
131
|
-
end
|
132
|
-
|
133
|
-
def test_simple_rel_parsing
|
134
|
-
@agent.links_parser = Sawyer::LinkParsers::Simple.new
|
135
|
-
res = Resource.new @agent,
|
136
|
-
:url => '/',
|
137
|
-
:user => {
|
138
|
-
:id => 1,
|
139
|
-
:url => '/users/1',
|
140
|
-
:followers_url => '/users/1/followers'
|
141
|
-
}
|
142
|
-
|
143
|
-
assert_equal '/', res.rels[:self].href
|
144
|
-
assert_kind_of Resource, res.user
|
145
|
-
assert !res.fields.include?(:url)
|
146
|
-
assert_equal 1, res.user.id
|
147
|
-
assert_equal '/users/1', res.user.rels[:self].href
|
148
|
-
assert !res.user.fields.include?(:url)
|
149
|
-
assert_equal '/users/1/followers', res.user.rels[:followers].href
|
150
|
-
assert !res.user.fields.include?(:followers_url)
|
151
|
-
end
|
152
|
-
|
153
|
-
def test_handle_yaml_dump
|
154
|
-
assert_nothing_raised do
|
155
|
-
require 'yaml'
|
156
|
-
res = Resource.new @agent, :a => 1
|
157
|
-
YAML.dump(res)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def test_handle_marshal_dump
|
162
|
-
assert_nothing_raised do
|
163
|
-
res = Resource.new @agent, :a => 1
|
164
|
-
Marshal.dump(res)
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
data/test/response_test.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
require File.expand_path("../helper", __FILE__)
|
2
|
-
|
3
|
-
module Sawyer
|
4
|
-
class ResponseTest < TestCase
|
5
|
-
def setup
|
6
|
-
@now = Time.now
|
7
|
-
@stubs = Faraday::Adapter::Test::Stubs.new
|
8
|
-
@agent = Sawyer::Agent.new "http://foo.com" do |conn|
|
9
|
-
conn.builder.handlers.delete(Faraday::Adapter::NetHttp)
|
10
|
-
conn.adapter :test, @stubs do |stub|
|
11
|
-
stub.get '/' do
|
12
|
-
[200, {
|
13
|
-
'Content-Type' => 'application/json',
|
14
|
-
'Link' => '</starred?page=2>; rel="next", </starred?page=19>; rel="last"'
|
15
|
-
}, Sawyer::Agent.encode(
|
16
|
-
:a => 1,
|
17
|
-
:_links => {
|
18
|
-
:self => {:href => '/a', :method => 'POST'}
|
19
|
-
}
|
20
|
-
)]
|
21
|
-
end
|
22
|
-
|
23
|
-
stub.get '/emails' do
|
24
|
-
emails = %w(rick@example.com technoweenie@example.com)
|
25
|
-
[200, {'Content-Type' => 'application/json'}, Sawyer::Agent.encode(emails)]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
@res = @agent.start
|
31
|
-
assert_kind_of Sawyer::Response, @res
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_gets_status
|
35
|
-
assert_equal 200, @res.status
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_gets_headers
|
39
|
-
assert_equal 'application/json', @res.headers['content-type']
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_gets_body
|
43
|
-
assert_equal 1, @res.data.a
|
44
|
-
assert_equal [:a], @res.data.fields.to_a
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_gets_rels
|
48
|
-
assert_equal '/starred?page=2', @res.rels[:next].href
|
49
|
-
assert_equal :get, @res.rels[:next].method
|
50
|
-
assert_equal '/starred?page=19', @res.rels[:last].href
|
51
|
-
assert_equal :get, @res.rels[:next].method
|
52
|
-
assert_equal '/a', @res.data.rels[:self].href
|
53
|
-
assert_equal :post, @res.data.rels[:self].method
|
54
|
-
end
|
55
|
-
|
56
|
-
def test_gets_response_timing
|
57
|
-
assert @res.timing > 0
|
58
|
-
assert @res.time >= @now
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_makes_request_from_relation
|
62
|
-
@stubs.post '/a' do
|
63
|
-
[201, {'Content-Type' => 'application/json'}, ""]
|
64
|
-
end
|
65
|
-
|
66
|
-
res = @res.data.rels[:self].call
|
67
|
-
assert_equal 201, res.status
|
68
|
-
assert_nil res.data
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_handles_arrays_of_strings
|
72
|
-
res = @agent.call(:get, '/emails')
|
73
|
-
assert_equal 'rick@example.com', res.data.first
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|