RSpec.describe Yaks::Mapper::Association do include_context 'yaks context' subject(:association) do described_class.new( name: name, item_mapper: mapper, rel: rel, href: href, link_if: link_if ) end let(:name) { :shoes } let(:mapper) { Yaks::Mapper } let(:rel) { Yaks::Undefined } let(:href) { Yaks::Undefined } let(:link_if) { Yaks::Undefined } its(:name) { should equal :shoes } its(:item_mapper) { should equal Yaks::Mapper } context 'with a minimal constructor' do subject(:association) { described_class.new(name: :foo) } its(:name) { should be :foo } its(:item_mapper) { should be Yaks::Undefined } its(:rel) { should be Yaks::Undefined } its(:href) { should be Yaks::Undefined } its(:link_if) { should be Yaks::Undefined } end let(:parent_mapper_class) { Yaks::Mapper } let(:parent_mapper) { parent_mapper_class.new(yaks_context) } describe '#add_to_resource' do let(:object) { fake(:shoes => []) } let(:rel) { 'rel:shoes' } before do parent_mapper.call(object) stub(association).map_resource(any_args) { Yaks::Resource.new } end it 'should delegate to AssociationMapper' do expect(association.add_to_resource(Yaks::Resource.new, parent_mapper, yaks_context)).to eql Yaks::Resource.new(subresources: [Yaks::Resource.new(rels: ['rel:shoes'])]) end end describe '#render_as_link?' do let(:href) { '/foo/{bar}/baz' } let(:link_if) { -> { env.fetch('env_entry') == 123 } } let(:rack_env) { { 'env_entry' => 123 } } let(:render_as_link?) { association.render_as_link?(parent_mapper) } context 'when evaluating to true' do it 'should resolve :link_if in the context of the mapper' do expect(render_as_link?).to be true end end context 'when evaluating to false' do let(:rack_env) { { 'env_entry' => 0 } } it 'should resolve :link_if in the context of the mapper' do expect(render_as_link?).to be false end end context 'with an Undefined href' do let(:href) { Yaks::Undefined } it 'should return falsey' do expect(render_as_link?).to be_falsey end end context 'with an Undefined link_if' do let(:link_if) { Yaks::Undefined } it 'should return falsey' do expect(render_as_link?).to be_falsey end end end describe '#map_rel' do let(:association_rel) { association.map_rel(policy) } context 'with a rel specified' do let(:rel) { 'http://api.com/rels/shoes' } it 'should use the specified rel' do expect(association_rel).to eql 'http://api.com/rels/shoes' end end context 'without a rel specified' do before do stub(policy).derive_rel_from_association(association) { 'http://api.com/rel/derived' } end it 'should infer a rel based on policy' do expect(association_rel).to eql 'http://api.com/rel/derived' end end end describe '#resolve_association_mapper' do context 'with a specified mapper' do let(:mapper) { :a_specific_mapper_class } it 'should return the mapper' do expect(association.resolve_association_mapper(nil)).to equal :a_specific_mapper_class end end context 'with the mapper undefined' do let(:mapper) { Yaks::Undefined } before do stub(policy).derive_mapper_from_association(association) { :a_derived_mapper_class } end it 'should derive a mapper based on policy' do expect(association.resolve_association_mapper(policy)).to equal :a_derived_mapper_class end end end describe '.create' do it 'should take a name' do expect(described_class.create(:foo).name).to be :foo end it 'should optionally take a mapper' do expect(described_class.create(:foo, mapper: :bar).item_mapper).to be :bar end it 'should take other options' do expect(described_class.create(:foo, mapper: :bar, href: 'xxx').href).to eql 'xxx' end it 'should respect attribute defaults' do expect(described_class.create(:foo, href: 'xxx').item_mapper).to be Yaks::Undefined end it 'should not munge the options hash' do opts = {mapper: :foo} described_class.create(:foo, opts) expect(opts).to eql(mapper: :foo) end end end