require 'spec_helper' module Draper describe DecoratedAssociation do describe "#initialize" do it "accepts valid options" do valid_options = {with: Decorator, scope: :foo, context: {}} expect{DecoratedAssociation.new(Decorator.new(Model.new), :association, valid_options)}.not_to raise_error end it "rejects invalid options" do expect{DecoratedAssociation.new(Decorator.new(Model.new), :association, foo: "bar")}.to raise_error ArgumentError, /Unknown key/ end it "creates a factory" do options = {with: Decorator, context: {foo: "bar"}} Factory.should_receive(:new).with(options) DecoratedAssociation.new(double, :association, options) end describe ":with option" do it "defaults to nil" do Factory.should_receive(:new).with(with: nil, context: anything()) DecoratedAssociation.new(double, :association, {}) end end describe ":context option" do it "defaults to the identity function" do Factory.should_receive(:new).with do |options| options[:context].call(:anything) == :anything end DecoratedAssociation.new(double, :association, {}) end end end describe "#call" do it "calls the factory" do factory = double Factory.stub new: factory associated = double owner_context = {foo: "bar"} source = double(association: associated) owner = double(source: source, context: owner_context) decorated_association = DecoratedAssociation.new(owner, :association, {}) decorated = double factory.should_receive(:decorate).with(associated, context_args: owner_context).and_return(decorated) expect(decorated_association.call).to be decorated end it "memoizes" do factory = double Factory.stub new: factory owner = double(source: double(association: double), context: {}) decorated_association = DecoratedAssociation.new(owner, :association, {}) decorated = double factory.should_receive(:decorate).once.and_return(decorated) expect(decorated_association.call).to be decorated expect(decorated_association.call).to be decorated end context "when the :scope option was given" do it "applies the scope before decoration" do factory = double Factory.stub new: factory scoped = double source = double(association: double(applied_scope: scoped)) owner = double(source: source, context: {}) decorated_association = DecoratedAssociation.new(owner, :association, scope: :applied_scope) decorated = double factory.should_receive(:decorate).with(scoped, anything()).and_return(decorated) expect(decorated_association.call).to be decorated end end end end end