diff --git a/test/hyperclient/attributes_test.rb b/test/hyperclient/attributes_test.rb index 5c0587f..128470b 100644 --- a/test/hyperclient/attributes_test.rb +++ b/test/hyperclient/attributes_test.rb @@ -36,5 +36,14 @@ module Hyperclient it 'is a collection' do _(Attributes.ancestors).must_include Collection end + + describe 'when the representation is not a Hash' do + it 'wraps the representation as-is instead of filtering reserved keys' do + representation = 'not a hash' + attributes = Attributes.new(representation) + + _(attributes.instance_variable_get(:@collection)).must_equal representation + end + end end end diff --git a/test/hyperclient/collection_test.rb b/test/hyperclient/collection_test.rb index 290956c..1b29066 100644 --- a/test/hyperclient/collection_test.rb +++ b/test/hyperclient/collection_test.rb @@ -41,6 +41,18 @@ module Hyperclient end end + describe '#to_s' do + it 'returns the wrapped collection as a hash' do + _(collection.to_s).must_be_kind_of Hash + end + end + + describe '#method_missing' do + it 'raises an error for missing keys' do + _(proc { collection.missing_key }).must_raise RuntimeError + end + end + describe 'include?' do it 'returns true for keys that exist' do _(collection.include?('_links')).must_equal true diff --git a/test/hyperclient/curie_test.rb b/test/hyperclient/curie_test.rb index 0f7cfb4..8d9463c 100644 --- a/test/hyperclient/curie_test.rb +++ b/test/hyperclient/curie_test.rb @@ -34,5 +34,12 @@ module Hyperclient _(curie.expand('thumbnail')).must_equal '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/images/thumbnail' end end + + describe 'inspect' do + it 'outputs a custom-friendly output' do + _(curie.inspect).must_include 'Curie' + _(curie.inspect).must_include({ 'name' => 'image', 'href' => '/images/{rel}', 'templated' => true }.to_s) + end + end end end diff --git a/test/hyperclient/entry_point_test.rb b/test/hyperclient/entry_point_test.rb index 8aa3a98..e36a788 100644 --- a/test/hyperclient/entry_point_test.rb +++ b/test/hyperclient/entry_point_test.rb @@ -53,6 +53,19 @@ module Hyperclient _(entry_point.connection).must_be_kind_of Faraday::Connection _(-> { entry_point.connection {} }).must_raise ConnectionAlreadyInitializedError end + + it 'can set the faraday block before a connection has been constructed' do + block = proc { |conn| conn.use Faraday::Request::Instrumentation } + entry_point.faraday_block = block + + _(entry_point.faraday_block).must_equal block + end + + it 'raises a ConnectionAlreadyInitializedError if attempting to modify ' \ + 'the faraday block after a connection has been constructed' do + _(entry_point.connection).must_be_kind_of Faraday::Connection + _(-> { entry_point.faraday_block = proc {} }).must_raise ConnectionAlreadyInitializedError + end end describe 'initialize' do @@ -181,5 +194,11 @@ module Hyperclient end end end + + describe ConnectionAlreadyInitializedError do + it 'has a descriptive message' do + _(ConnectionAlreadyInitializedError.new.message).must_equal 'The connection has already been initialized.' + end + end end end diff --git a/test/hyperclient/link_collection_test.rb b/test/hyperclient/link_collection_test.rb index 7eb49a3..b1e241d 100644 --- a/test/hyperclient/link_collection_test.rb +++ b/test/hyperclient/link_collection_test.rb @@ -79,5 +79,11 @@ module Hyperclient _(null_link).must_be_nil end end + + describe 'invalid collection' do + it 'raises an error when the collection does not respond to collect' do + _(proc { LinkCollection.new('invalid', {}, entry_point) }).must_raise RuntimeError + end + end end end diff --git a/test/hyperclient/link_test.rb b/test/hyperclient/link_test.rb index f4400de..9c6e73a 100644 --- a/test/hyperclient/link_test.rb +++ b/test/hyperclient/link_test.rb @@ -323,6 +323,37 @@ module Hyperclient _(resource.next._links.next._url).must_equal 'http://api.example.org/page3' end + + it 'iterates over paginated, embedded items across pages' do + resource = Resource.new({ '_links' => { 'orders' => { 'href' => '/orders' } } }, entry_point) + + stub_request(entry_point.connection) do |stub| + stub.get('http://api.example.org/orders') do + [200, {}, { '_links' => { 'next' => { 'href' => 'http://api.example.org/orders?page=2' } }, + '_embedded' => { 'orders' => [{ 'id' => 1 }] } }] + end + stub.get('http://api.example.org/orders?page=2') do + [200, {}, { '_embedded' => { 'orders' => [{ 'id' => 2 }] } }] + end + end + + ids = resource._links.orders.map(&:id) + + _(ids).must_equal [1, 2] + end + + it 'returns an Enumerator when called without a block' do + resource = Resource.new({ '_links' => { 'orders' => { 'href' => '/orders' } } }, entry_point) + + stub_request(entry_point.connection) do |stub| + stub.get('http://api.example.org/orders') { [200, {}, { '_embedded' => { 'orders' => [{ 'id' => 1 }] } }] } + end + + enum = resource._links.orders.each + + _(enum).must_be_kind_of Enumerator + _(enum.to_a.first.id).must_equal 1 + end end describe 'resource' do @@ -355,11 +386,51 @@ module Hyperclient _(link.respond_to?(:embedded)).must_equal true end + it 'responds to missing methods that delegate to another resource' do + delegate = mock('Delegate') + resource.expects(:respond_to?).with('orders').returns(true) + resource.expects(:send).with('orders').returns(delegate) + delegate.expects(:respond_to?).with('foo').returns(true) + + _(link.respond_to?(:foo)).must_equal true + end + it 'does not delegate to_ary to resource' do resource.expects(:to_ary).never _([[link, link]].flatten).must_equal [link, link] end + + it 'delegates through delegate_method when the resource responds but returns nil' do + delegate = mock('Delegate') + resource.expects(:respond_to?).with('foo').returns(true) + resource.expects(:send).with(:foo).returns(nil) + resource.expects(:respond_to?).with('orders').returns(true) + resource.expects(:send).with('orders').returns(delegate) + delegate.expects(:respond_to?).with('foo').returns(true) + delegate.expects(:send).with(:foo).returns('delegated result') + + _(link.foo).must_equal 'delegated result' + end + + it 'returns nil from delegate_method when the resource has no matching key' do + keyless_link = Link.new(nil, { 'href' => 'http://myapi.org/orders' }, entry_point) + resource.expects(:respond_to?).with('foo').returns(true) + resource.expects(:send).with(:foo).returns(nil) + + _(keyless_link.foo).must_be_nil + end + + it 'returns nil from delegate_method when the delegate does not respond to the method' do + delegate = mock('Delegate') + resource.expects(:respond_to?).with('foo').returns(true) + resource.expects(:send).with(:foo).returns(nil) + resource.expects(:respond_to?).with('orders').returns(true) + resource.expects(:send).with('orders').returns(delegate) + delegate.expects(:respond_to?).with('foo').returns(false) + + _(link.foo).must_be_nil + end end end end diff --git a/test/hyperclient/resource_test.rb b/test/hyperclient/resource_test.rb index 6c96c12..a566119 100644 --- a/test/hyperclient/resource_test.rb +++ b/test/hyperclient/resource_test.rb @@ -228,5 +228,16 @@ module Hyperclient end end end + + describe 'inspect' do + it 'outputs a custom-friendly output' do + resource = Resource.new({ '_links' => { 'self' => { 'href' => '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/orders/523' } }, 'title' => 'Order' }, + entry_point) + + _(resource.inspect).must_include 'Resource' + _(resource.inspect).must_include 'self_link:' + _(resource.inspect).must_include 'attributes:' + end + end end end