spec/praxis-blueprints/blueprint_spec.rb in praxis-blueprints-2.0.1 vs spec/praxis-blueprints/blueprint_spec.rb in praxis-blueprints-2.1

- old
+ new

@@ -169,32 +169,57 @@ end end context '.describe' do + let(:shallow ) { false } + let(:example_object) { nil } + before do - expect(blueprint_class.attribute.type).to receive(:describe).and_return(type_describe) + expect(blueprint_class.attribute.type).to receive(:describe).with(shallow, example: example_object).and_call_original #.and_return(type_describe) end - let(:type_describe){ {name: "Fake", id: "From Struct attr", other: "type attribute"} } context 'for non-shallow descriptions' do subject(:output){ blueprint_class.describe } + its([:name]){ should eq(blueprint_class.name)} its([:id]){ should eq(blueprint_class.id)} - its([:other]){ should eq("type attribute")} its([:views]){ should be_kind_of(Hash)} it 'should contain the an entry for each view' do subject[:views].keys.should include(:default, :current, :extended, :master) end end context 'for shallow descriptions' do + let(:shallow) { true } + it 'should not include views' do blueprint_class.describe(true).key?(:views).should be(false) end end + + context 'with an example' do + let(:example) { blueprint_class.example } + let(:example_object) { example.object } + let(:shallow) { false } + + subject(:output) { blueprint_class.describe(false, example: example) } + + it 'outputs examples for leaf values using the provided example' do + output[:attributes][:name][:example].should eq example.name + output[:attributes][:age][:example].should eq example.age + + output[:attributes][:full_name].should_not have_key(:example) + output[:attributes][:aliases].should_not have_key(:example) + + parents_attributes = output[:attributes][:parents][:type][:attributes] + parents_attributes[:father][:example].should eq example.parents.father + parents_attributes[:mother][:example].should eq example.parents.mother + end + end end + context '.validate' do let(:hash) { {name: 'bob'} } let(:person) { Person.load(hash) } subject(:errors) { person.validate } @@ -205,219 +230,219 @@ context 'with invalid sub-attribute' do let(:hash) { {name: 'bob', address: {state: "ME"}} } it { should have(1).item } its(:first) { should =~ /Attribute \$.address.state/ } - end + end - context 'for objects of the wrong type' do - it 'raises an error' do - expect { - Person.validate(Object.new) - }.to raise_error(ArgumentError, /Error validating .* as Person for an object of type Object/) - end - end - end + context 'for objects of the wrong type' do + it 'raises an error' do + expect { + Person.validate(Object.new) + }.to raise_error(ArgumentError, /Error validating .* as Person for an object of type Object/) + end + end + end - context '.load' do - let(:hash) do - { - :name => 'Bob', - :full_name => {:first => 'Robert', :last => 'Robertson'}, - :address => {:street => 'main', :state => 'OR'} - } - end - subject(:person) { Person.load(hash) } + context '.load' do + let(:hash) do + { + :name => 'Bob', + :full_name => {:first => 'Robert', :last => 'Robertson'}, + :address => {:street => 'main', :state => 'OR'} + } + end + subject(:person) { Person.load(hash) } - it { should be_kind_of(Person) } + it { should be_kind_of(Person) } - context 'recursively loading sub-attributes' do - context 'for a Blueprint' do - subject(:address) { person.address } - it { should be_kind_of(Address) } - end - context 'for an Attributor::Model' do - subject(:full_name) { person.full_name } - it { should be_kind_of(FullName) } - end - end + context 'recursively loading sub-attributes' do + context 'for a Blueprint' do + subject(:address) { person.address } + it { should be_kind_of(Address) } + end + context 'for an Attributor::Model' do + subject(:full_name) { person.full_name } + it { should be_kind_of(FullName) } + end + end - end + end - context 'decorators' do - let(:name) { 'Soren II' } + context 'decorators' do + let(:name) { 'Soren II' } - let(:object) { Person.example.object } - subject(:person) { Person.new(object, decorators) } + let(:object) { Person.example.object } + subject(:person) { Person.new(object, decorators) } - context 'as a hash' do - let(:decorators) { {name: name} } - it do - pers = person - # binding.pry - pers.name.should eq('Soren II') - end + context 'as a hash' do + let(:decorators) { {name: name} } + it do + pers = person + # binding.pry + pers.name.should eq('Soren II') + end - its(:name) { should be(name) } + its(:name) { should be(name) } - context 'an additional instance with the equivalent hash' do - subject(:additional_person) { Person.new(object, {name: name}) } - it { should_not be person } - end + context 'an additional instance with the equivalent hash' do + subject(:additional_person) { Person.new(object, {name: name}) } + it { should_not be person } + end - context 'an additional instance with the same hash object' do - subject(:additional_person) { Person.new(object, decorators) } - it { should_not be person } - end + context 'an additional instance with the same hash object' do + subject(:additional_person) { Person.new(object, decorators) } + it { should_not be person } + end - context 'an instance of the same object without decorators' do - subject(:additional_person) { Person.new(object) } - it { should_not be person } - end - end + context 'an instance of the same object without decorators' do + subject(:additional_person) { Person.new(object) } + it { should_not be person } + end + end - context 'as an object' do - let(:decorators) { double("decorators", name: name) } - its(:name) { should be(name) } + context 'as an object' do + let(:decorators) { double("decorators", name: name) } + its(:name) { should be(name) } - context 'an additional instance with the same object' do - subject(:additional_person) { Person.new(object, decorators) } - it { should_not be person } - end - end + context 'an additional instance with the same object' do + subject(:additional_person) { Person.new(object, decorators) } + it { should_not be person } + end + end - end + end - context 'with a provided :reference option on attributes' do - context 'that does not match the value set on the class' do + context 'with a provided :reference option on attributes' do + context 'that does not match the value set on the class' do - subject(:mismatched_reference) do - Class.new(Praxis::Blueprint) do - self.reference = Class.new(Praxis::Blueprint) - attributes(reference: Class.new(Praxis::Blueprint)) {} - end - end + subject(:mismatched_reference) do + Class.new(Praxis::Blueprint) do + self.reference = Class.new(Praxis::Blueprint) + attributes(reference: Class.new(Praxis::Blueprint)) {} + end + end - it 'should raise an error' do - expect { - mismatched_reference.attributes - }.to raise_error - end + it 'should raise an error' do + expect { + mismatched_reference.attributes + }.to raise_error + end - end - end + end + end - context '.example' do - context 'with some attribute values provided' do - let(:name) { 'Sir Bobbert' } - subject(:person) { Person.example(name: name) } - its(:name) { should eq(name) } - end - end + context '.example' do + context 'with some attribute values provided' do + let(:name) { 'Sir Bobbert' } + subject(:person) { Person.example(name: name) } + its(:name) { should eq(name) } + end + end - context '.render' do - let(:person) { Person.example } - it 'is an alias to dump' do - rendered = Person.render(person, view: :default) - dumped = Person.dump(person, view: :default) - expect(rendered).to eq(dumped) - end - end + context '.render' do + let(:person) { Person.example } + it 'is an alias to dump' do + rendered = Person.render(person, view: :default) + dumped = Person.dump(person, view: :default) + expect(rendered).to eq(dumped) + end + end - context '#render' do - let(:person) { Person.example } - let(:view_name) { :default } - let(:render_opts) { {} } - subject(:output) { person.render(view: view_name, **render_opts) } + context '#render' do + let(:person) { Person.example } + let(:view_name) { :default } + let(:render_opts) { {} } + subject(:output) { person.render(view: view_name, **render_opts) } - context 'caches rendered views' do - it 'in the instance, by view name' do - person.instance_variable_get(:@rendered_views)[view_name].should be_nil - person.render(view: view_name) - cached = person.instance_variable_get(:@rendered_views)[view_name] - cached.should_not be_nil - end + context 'caches rendered views' do + it 'in the instance, by view name' do + person.instance_variable_get(:@rendered_views)[view_name].should be_nil + person.render(view: view_name) + cached = person.instance_variable_get(:@rendered_views)[view_name] + cached.should_not be_nil + end - it 'and does not re-render a view if one is already cached' do - rendered1 = person.render(view: view_name) - rendered2 = person.render(view: view_name) - rendered1.should be(rendered2) - end + it 'and does not re-render a view if one is already cached' do + rendered1 = person.render(view: view_name) + rendered2 = person.render(view: view_name) + rendered1.should be(rendered2) + end - context 'even when :fields are specified' do - let(:render_opts) { {fields: {email: nil, age: nil, address: {street: nil, state: nil}}} } + context 'even when :fields are specified' do + let(:render_opts) { {fields: {email: nil, age: nil, address: {street: nil, state: nil}}} } - it 'caches the output in a different key than just the view_name' do - plain_view_render = person.render(view: view_name) - fields_render = person.render(view: view_name, **render_opts) - plain_view_render.should_not be(fields_render) - end + it 'caches the output in a different key than just the view_name' do + plain_view_render = person.render(view: view_name) + fields_render = person.render(view: view_name, **render_opts) + plain_view_render.should_not be(fields_render) + end - it 'it still caches the object if rendered for the same fields' do - rendered1 = person.render(view: view_name, **render_opts) - rendered2 = person.render(view: view_name, **render_opts) - rendered1.should be(rendered2) - end + it 'it still caches the object if rendered for the same fields' do + rendered1 = person.render(view: view_name, **render_opts) + rendered2 = person.render(view: view_name, **render_opts) + rendered1.should be(rendered2) + end - it 'it still caches the object if rendered for the same fields (even from an "equivalent" hash)' do - rendered1 = person.render(view: view_name, **render_opts) + it 'it still caches the object if rendered for the same fields (even from an "equivalent" hash)' do + rendered1 = person.render(view: view_name, **render_opts) - equivalent_render_opts = { fields: {age: nil, address: {state: nil, street: nil}, email: nil} } - rendered2 = person.render(view: view_name, **equivalent_render_opts) + equivalent_render_opts = { fields: {age: nil, address: {state: nil, street: nil}, email: nil} } + rendered2 = person.render(view: view_name, **equivalent_render_opts) - rendered1.should be(rendered2) - end - end + rendered1.should be(rendered2) + end + end - end + end - context 'with a sub-attribute that is a blueprint' do + context 'with a sub-attribute that is a blueprint' do - it { should have_key(:name) } - it { should have_key(:address) } - it 'renders the sub-attribute correctly' do - output[:address].should have_key(:street) - output[:address].should have_key(:state) - end + it { should have_key(:name) } + it { should have_key(:address) } + it 'renders the sub-attribute correctly' do + output[:address].should have_key(:street) + output[:address].should have_key(:state) + end - it 'reports a dump error with the appropriate context' do - person.address.should_receive(:state).and_raise("Kaboom") - expect { - person.render(view: view_name, context: ['special_root']) - }.to raise_error(/Error while dumping attribute state of type Address for context special_root.address. Reason: .*Kaboom/) - end - end + it 'reports a dump error with the appropriate context' do + person.address.should_receive(:state).and_raise("Kaboom") + expect { + person.render(view: view_name, context: ['special_root']) + }.to raise_error(/Error while dumping attribute state of type Address for context special_root.address. Reason: .*Kaboom/) + end + end - context 'with sub-attribute that is an Attributor::Model' do - it { should have_key(:full_name) } - it 'renders the model correctly' do - output[:full_name].should be_kind_of(Hash) - output[:full_name].should have_key(:first) - output[:full_name].should have_key(:last) - end - end + context 'with sub-attribute that is an Attributor::Model' do + it { should have_key(:full_name) } + it 'renders the model correctly' do + output[:full_name].should be_kind_of(Hash) + output[:full_name].should have_key(:first) + output[:full_name].should have_key(:last) + end + end - context 'using the `fields` option' do - context 'as a hash' do - subject(:output) { person.render(view: view_name, fields: {address: { state: nil} } ) } - it 'should only have the address rendered' do - output.keys.should == [:address] - end - it 'address should only have state' do - output[:address].keys.should == [:state] - end - end - context 'as a simple array' do - subject(:output) { person.render(view: view_name, fields: [:address] ) } - it 'accepts it as the list of top-level attributes to be rendered' do - output.keys.should == [:address] - end - end - end - end + context 'using the `fields` option' do + context 'as a hash' do + subject(:output) { person.render(view: view_name, fields: {address: { state: nil} } ) } + it 'should only have the address rendered' do + output.keys.should == [:address] + end + it 'address should only have state' do + output[:address].keys.should == [:state] + end + end + context 'as a simple array' do + subject(:output) { person.render(view: view_name, fields: [:address] ) } + it 'accepts it as the list of top-level attributes to be rendered' do + output.keys.should == [:address] + end + end + end + end -end + end