spec/attribute_spec.rb in attributor-2.6.1 vs spec/attribute_spec.rb in attributor-3.0
- old
+ new
@@ -91,10 +91,52 @@
it 'includes sub-attributes' do
description[:type][:attributes].should have_key(:id)
end
end
+
+ context 'with an example' do
+
+ let(:attribute_options){ {} }
+ let(:example){ attribute.example }
+ subject(:described){ attribute.describe(false, example: example) }
+
+ context 'using a simple terminal type' do
+ let(:type) { String }
+ its(:keys){ should include(:example) }
+ it 'should have the passed example value' do
+ described.should have_key(:example)
+ described[:example].should eq(example)
+ end
+ it 'should have removed the example from the :type' do
+ described[:type].should_not have_key(:example)
+ end
+
+ end
+
+ context 'using a complex type' do
+ let(:type) { Cormorant }
+ its(:keys){ should_not include(:example) }
+
+ it 'Should see examples in the right places, depending on leaf/no-leaf types' do
+ # String, a leaf attribute type: should have example
+ name_attr = described[:type][:attributes][:name]
+ name_attr.should include(:example)
+ name_attr[:type].should_not include(:example)
+
+ # Struct, a non-leaf attribute type: shouldn't have example
+ ts_attr = described[:type][:attributes][:timestamps]
+ ts_attr.should_not include(:example)
+ ts_attr[:type].should_not include(:example)
+
+ # DateTime inside a Struct, a nested leaf attribute type: should have example
+ born_attr = ts_attr[:type][:attributes][:born_at]
+ born_attr.should include(:example)
+ born_attr[:type].should_not include(:example)
+ end
+ end
+ end
end
context 'parse' do
let(:loaded_object){ double("I'm loaded") }
@@ -133,14 +175,12 @@
}.not_to raise_error
end
end
end
-
context 'example' do
let(:example) { nil }
- let(:attribute_options) { {:example => example} }
context 'with nothing specified' do
let(:attribute_options) { {} }
before do
type.should_receive(:example).and_return(example)
@@ -149,112 +189,145 @@
it 'defers to the type' do
attribute.example.should be example
end
end
+ context 'with an attribute that has the values option set' do
+ let(:values) { ["one", "two"] }
+ let(:attribute_options) { {:values => values} }
+ it 'picks a random value' do
+ values.should include subject.example
+ end
+ end
+
+ context 'deterministic examples' do
+ let(:example) { /\w+/ }
+ let(:attribute_options) { {:example => example} }
+
+ it 'can take a context to pre-seed the random number generator' do
+ example_1 = subject.example(['context'])
+ example_2 = subject.example(['context'])
+
+ example_1.should eq example_2
+ end
+
+ it 'can take a context to pre-seed the random number generator' do
+ example_1 = subject.example(['context'])
+ example_2 = subject.example(['different context'])
+
+ example_1.should_not eq example_2
+ end
+ end
+
+ context 'with an example option' do
+ let(:example){ "Bob" }
+ let(:attribute_options) { {example: example , regexp: /Bob/ } }
+
+ its(:example){ should == example }
+
+ context 'that is not valid' do
+ let(:example){ "Frank" }
+ it 'raises a validation error' do
+ expect{
+ subject.example
+ }.to raise_error(Attributor::AttributorException, /Error generating example/)
+ end
+ end
+ end
+ end
+
+ context 'example_from_options' do
+ let(:example) { nil }
+ let(:generated_example) { example }
+ let(:attribute_options) { {:example => example} }
+ let(:parent){ nil }
+ let(:context){ Attributor::DEFAULT_ROOT_CONTEXT}
+
+ subject(:example_result) { attribute.example_from_options( parent, context ) }
+ before do
+ attribute.should_receive(:load).with( generated_example , an_instance_of(Array) ).and_call_original
+ end
+
context 'with a string' do
let(:example) { "example" }
- its(:example) { should be example }
+ it { should be example }
end
+ context 'with an integer' do
+ let(:type) { Attributor::Integer }
+ let(:example) { 5 }
+ it { should be example }
+ end
+
context 'with a regexp' do
let(:example) { /\w+/ }
+ let(:generated_example) { /\w+/.gen }
-
it 'calls #gen on the regexp' do
- example.should_receive(:gen).and_call_original
- subject.example.should =~ example
+ example.should_receive(:gen).and_return(generated_example)
+
+ example_result.should =~ example
end
context 'for a type with a non-String native_type' do
let(:type) { Attributor::Integer }
- context 'using a regexp' do
- let(:example) { /\d{5}/ }
- it 'coerces the example value properly' do
- example.should_receive(:gen).and_call_original
- type.should_receive(:load).and_call_original
-
- subject.example.should be_kind_of(type.native_type)
- end
+ let(:example) { /\d{5}/ }
+ let(:generated_example) { /\d{5}/.gen }
+
+ it 'coerces the example value properly' do
+ example.should_receive(:gen).and_return(generated_example)
+ type.should_receive(:load).and_call_original
+
+ example_result.should be_kind_of(type.native_type)
end
- context 'usign a native Integer type' do
- let(:example) { 5 }
- it 'coerces the example value properly' do
- type.should_receive(:load).and_call_original
- subject.example.should be_kind_of(type.native_type)
- end
- end
end
+
end
-
context 'with a proc' do
+ let(:parent){ Object.new }
+
context 'with one argument' do
let(:example) { lambda { |obj| 'ok' } }
- let(:some_object) { Object.new }
+ let(:generated_example) { 'ok' }
before do
- example.should_receive(:call).with(some_object).and_call_original
+ example.should_receive(:call).with(parent).and_return(generated_example)
end
it 'passes any given parent through to the example proc' do
- subject.example(nil, parent: some_object).should == 'ok'
+ example_result.should == 'ok'
end
end
context 'with two arguments' do
let(:example) { lambda { |obj, context| "#{context} ok" } }
- let(:some_object) { Object.new }
- let(:some_context) { ['some_context'] }
-
+ let(:generated_example) { "#{context} ok" }
+ let(:context){ ['some_context'] }
before do
- example.should_receive(:call).with(some_object, some_context).and_call_original
+ example.should_receive(:call).with(parent, context).and_return(generated_example)
end
it 'passes any given parent through to the example proc' do
- subject.example(some_context, parent: some_object).should == "#{some_context} ok"
+ example_result.should == "#{context} ok"
end
end
end
context 'with an array' do
- let(:example) { ["one", "two"] }
+ let(:example) { ["one"] }
+ let(:generated_example) { "one" }
it 'picks a random value' do
- example.should include subject.example
+ example.should_receive(:pick).and_call_original
+ example.should include example_result
end
- end
- context 'with an attribute that has the values option set' do
- let(:values) { ["one", "two"] }
- let(:attribute_options) { {:values => values} }
- it 'picks a random value' do
- values.should include subject.example
- end
-
end
- context 'deterministic examples' do
- let(:example) { /\w+/ }
- it 'can take a context to pre-seed the random number generator' do
- example_1 = subject.example(['context'])
- example_2 = subject.example(['context'])
-
- example_1.should eq example_2
- end
-
- it 'can take a context to pre-seed the random number generator' do
- example_1 = subject.example(['context'])
- example_2 = subject.example(['different context'])
-
- example_1.should_not eq example_2
- end
-
-
- end
end
context 'load' do
let(:context){ ['context'] }
let(:value) { '1' }
@@ -284,35 +357,35 @@
let(:type) { Attributor::Boolean }
let(:default_value) { false }
it { should == default_value}
end
-
+
context 'for a Proc-based default value' do
let(:context){ ["$"] }
subject(:result){ attribute.load(value,context) }
context 'with no arguments arguments' do
let(:default_value) { proc { "no_params" } }
it { should == default_value.call }
end
-
+
context 'with 1 argument (the parent)' do
let(:default_value) { proc {|parent| "parent is fake: #{parent.class}" } }
it { should == "parent is fake: Attributor::FakeParent" }
end
-
+
context 'with 2 argument (the parent and the contents)' do
let(:default_value) { proc {|parent,context| "parent is fake: #{parent.class} and context is: #{context}" } }
it { should == "parent is fake: Attributor::FakeParent and context is: [\"$\"]"}
end
-
+
context 'which attempts to use the parent (which is not supported for the moment)' do
let(:default_value) { proc {|parent| "any parent method should spit out warning: [#{parent.something}]" } }
it "should output a warning" do
- begin
+ begin
old_verbose, $VERBOSE = $VERBOSE, nil
Kernel.should_receive(:warn).and_call_original
attribute.load(value,context).should == "any parent method should spit out warning: []"
ensure
$VERBOSE = old_verbose
@@ -635,10 +708,9 @@
let(:attribute_block) { Proc.new{ attribute :angry , required: true } }
let(:attribute_options) { {reference: Chicken, member_options: member_options} }
let(:member_type) { Attributor::Struct }
let(:type) { Attributor::Collection.of(member_type) }
let(:member_options) { {} }
-
context 'the member_attribute of that type' do
subject(:member_attribute) { attribute.type.member_attribute }
it { should be_kind_of(Attributor::Attribute)}
its(:options) { should eq(member_options.merge(reference: Chicken, identity: :email)) }