spec/model_helper.rb in ib-ruby-0.7.6 vs spec/model_helper.rb in ib-ruby-0.7.8

- old
+ new

@@ -1,11 +1,139 @@ require 'spec_helper' +require 'db_helper' def codes_and_values_for property Hash[IB::VALUES[property].map { |code, value| [[code, value], value] }] end +def numeric_assigns + {1313 => 1313, + [:foo, 'BAR'] => /is not a number/, + nil => /is not a number/} +end + +def numeric_or_nil_assigns + numeric_assigns.merge(nil => nil) +end + +def to_i_assigns + {[1313, '1313'] => 1313, + ['foo', 'BAR', nil, '', 0] => 0, } # Symbols NOT coerced! They DO have int equivalent +end + +def float_assigns + {13.13 => 13.13, + 13 => 13.0, + nil => /is not a number/, + [:foo, 'BAR'] => /is not a number/} +end + +def to_f_assigns + {13.13 => 13.13, + 13 => 13.0, + [:foo, 'BAR', '', nil, 0] => 0.0} +end + +def float_or_nil_assigns + float_assigns.merge(nil => nil) +end + +def boolean_assigns + {[1, true, 't'] => true, + [0, false, 'f'] => false} +end + +def string_assigns + {[:Bar, 'Bar'] => 'Bar', + [:foo, 'foo'] => 'foo'} +end + +def string_upcase_assigns + {[:cboe, :Cboe, 'cboE', 'CBOE'] => 'CBOE', + [:bar, 'Bar'] => 'BAR', + [:foo, 'foo'] => 'FOO'} +end + +def open_close_assigns + {['SAME', 'same', 'S', 's', :same, 0, '0'] => :same, + ['OPEN', 'open', 'O', 'o', :open, 1, '1'] => :open, + ['CLOSE', 'close', 'C', 'c', :close, 2, '2'] => :close, + ['UNKNOWN', 'unknown', 'U', 'u', :unknown, 3, '3'] => :unknown, + [42, nil, 'Foo', :bar] => /should be same.open.close.unknown/} +end + +def buy_sell_assigns + {['BOT', 'BUY', 'Buy', 'buy', :BUY, :BOT, :Buy, :buy, 'B', :b] => :buy, + ['SELL', 'SLD', 'Sel', 'sell', :SELL, :SLD, :Sell, :sell, 'S', :S] => :sell, + [1, nil, 'ASK', :foo] => /should be buy.sell/ + } +end + +def buy_sell_short_assigns + buy_sell_assigns.merge( + ['SSHORT', 'Short', 'short', :SHORT, :short, 'T', :T] => :short, + ['SSHORTX', 'Shortextemt', 'shortx', :short_exempt, 'X', :X] => :short_exempt, + [1, nil, 'ASK', :foo] => /should be buy.sell.short/) +end + +def test_assigns cases, prop, name + + # For all test cases given as an Array [res1, res2] or Hash {val => res} ... + (cases.is_a?(Array) ? cases.map { |e| [e, e] } : cases).each do |values, result| + #p prop, cases + + # For all values in this test case ... + [values].flatten.each do |value| + #p prop, name, value, result + + # Assigning this value to a property results in ... + case result + when Exception # ... Exception + expect { subject.send "#{prop}=", value }. + to raise_error result + + when Regexp # ... Non-exceptional error, making model invalid + expect { subject.send "#{prop}=", value }.to_not raise_error + subject.valid? # just triggers validation + + #pp subject.errors.messages + + subject.errors.messages.should have_key name + subject.should be_invalid + msg = subject.errors.messages[name].find { |msg| msg =~ result } + msg.should =~ result + + else # ... correct uniform assignment to result + + was_valid = subject.valid? + expect { subject.send "#{prop}=", value }.to_not raise_error + subject.send("#{prop}").should == result + if was_valid + # Assignment keeps validity + subject.errors.messages.should_not have_key name + subject.should be_valid + end + + if name != prop # additional asserts for aliases + + # Assignment to alias changes property as well + subject.send("#{name}").should == result + + # Unsetting alias unsets property as well + subject.send "#{prop}=", nil # unset alias + subject.send("#{prop}").should be_blank #== nil + subject.send("#{name}").should be_blank #== nil + + # Assignment to original property changes alias as well + subject.send "#{name}=", value + subject.send("#{prop}").should == result + end + end + end + end +end + shared_examples_for 'Model' do context 'instantiation without properties' do subject { described_class.new } it_behaves_like 'Model instantiated empty' @@ -16,11 +144,16 @@ it_behaves_like 'Model instantiated with properties' it 'has correct human-readeable format' do - subject.to_human.should == human + case human + when Regexp + subject.to_human.should =~ human + else + subject.to_human.should == human + end end end end shared_examples_for 'Self-equal Model' do @@ -37,14 +170,15 @@ shared_examples_for 'Model instantiated empty' do it { should_not be_nil } it 'sets all properties to defaults' do - defined?(defaults) && defaults.each do |name, value| + subject.default_attributes.each do |name, value| + #p name, value case value - when Module, Class - subject.send(name).should be_a value + when Time + subject.send(name).should be_a Time else subject.send(name).should == value end end end @@ -63,13 +197,10 @@ it_behaves_like 'Model properties' it_behaves_like 'Valid Model' end shared_examples_for 'Model properties' do - context 'essential properties are still set, even if not given explicitely' do - its(:created_at) { should be_a Time } - end it 'allows setting properties' do expect { props.each do |name, value| subject.send("#{name}=", value) @@ -78,113 +209,47 @@ }.to_not raise_error end it 'sets values to properties as directed by its setters' do defined?(assigns) && assigns.each do |props, cases| - #p props, cases - # For each given property ... - [props].flatten.each do |prop| + [props].flatten.each { |prop| test_assigns cases, prop, prop } - # For all test cases given as an Array [res1, res2] or Hash {val => res} ... - (cases.is_a?(Array) ? cases.map { |e| [e, e] } : cases).each do |values, result| - - # For all values in this test case ... - [values].flatten.each do |value| - - # Assigning this value to property results in ... - case result - when Exception # ... Exception - expect { subject.send "#{prop}=", value }. - to raise_error result - - when Regexp # ... Non-exceptional error, making model invalid - expect { subject.send "#{prop}=", value }.to_not raise_error - subject.should be_invalid - - #pp subject.errors.messages - #p value, result - - subject.errors.messages[prop].should_not be_nil - msg = subject.errors.messages[prop].find { |msg| msg =~ result } - msg.should =~ result - - else # ... correct uniform assignment to result - - was_valid = subject.valid? - expect { subject.send "#{prop}=", value }.to_not raise_error - subject.send("#{prop}").should == result - - was_valid && (subject.should be_valid) # assignment keeps validity - end - end - end - end end end + it 'sets values to to aliased properties as well' do + defined?(aliases) && aliases.each do |alinames, cases| + name, aliases = *alinames + # For each original property or alias... + [name, aliases].flatten.each { |prop| test_assigns cases, prop, name } + end + end end shared_examples_for 'Valid Model' do + it 'validates' do - #subject.valid? - #pp subject.errors.messages subject.should be_valid subject.errors.should be_empty end - context 'with DB backend', :db => true do - after(:all) do - #DatabaseCleaner.clean - end - - it 'is saved' do - subject.save.should be_true - end - - it 'is loaded just right' do - models = described_class.find(:all) - model = models.first - #pp model - models.should have_exactly(1).model - model.should == subject - model.should be_valid - props.each do |name, value| - model.send(name).should == value - end - end - end # DB + it_behaves_like 'Valid DB-backed Model' end shared_examples_for 'Invalid Model' do + it 'does not validate' do subject.should_not be_valid subject.should be_invalid subject.errors.should_not be_empty subject.errors.messages.should == errors if defined? errors end - context 'with DB backend', :db => true do - after(:all) do - #DatabaseCleaner.clean - end - - it 'is not saved' do - subject.save.should be_false - end - - it 'is not loaded' do - models = described_class.find(:all) - models.should have_exactly(0).model - end - end # DB + it_behaves_like 'Invalid DB-backed Model' end shared_examples_for 'Contract' do - it 'summary points to itself (ContractDetails artifact' do - subject.summary.should == subject - end - it 'becomes invalid if assigned wrong :sec_type property' do subject.sec_type = 'FOO' subject.should be_invalid subject.errors.messages[:sec_type].should include "should be valid security type" end