spec/mongoid/mongoid_spec.rb in edge-state-machine-0.0.2 vs spec/mongoid/mongoid_spec.rb in edge-state-machine-0.0.3

- old
+ new

@@ -1,101 +1,7 @@ require 'mongoid/mongoid_helper' -class MongoTrafficLight - include Mongoid::Document - include Mongoid::EdgeStateMachine - field :state - - state_machine do - state :off - - state :red - state :green - state :yellow - - event :red_on do - transitions :to => :red, :from => [:yellow] - end - - event :green_on do - transitions :to => :green, :from => [:red] - end - - event :yellow_on do - transitions :to => :yellow, :from => [:green] - end - - event :reset do - transitions :to => :red, :from => [:off] - end - end -end - -class MongoProtectedTrafficLight < MongoTrafficLight - attr_protected :state -end - -class MongoValidatingTrafficLight < MongoTrafficLight - validate {|t| errors.add(:base, 'This TrafficLight will never validate after creation') unless t.new_record? } -end - -class MongoConditionalValidatingTrafficLight < MongoTrafficLight - validates :name, :presence => true, :length => { :within => 20..40 }, :confirmation => true, :if => :red? -end - -class MongoOrder - include Mongoid::Document - include Mongoid::EdgeStateMachine - - field :state, :type => String - field :order_number, :type => Integer - field :paid_at, :type => DateTime - field :prepared_on, :type => DateTime - field :dispatched_at, :type => DateTime - field :cancellation_date, :type => Date - - state_machine do - state :opened - state :placed - state :paid - state :prepared - state :delivered - state :cancelled - - # no timestamp col is being specified here - should be ignored - event :place do - transitions :from => :opened, :to => :placed - end - - # should set paid_at timestamp - event :pay, :timestamp => true do - transitions :from => :placed, :to => :paid - end - - # should set prepared_on - event :prepare, :timestamp => true do - transitions :from => :paid, :to => :prepared - end - - # should set dispatched_at - event :deliver, :timestamp => "dispatched_at" do - transitions :from => :prepared, :to => :delivered - end - - # should set cancellation_date - event :cancel, :timestamp => :cancellation_date do - transitions :from => [:placed, :paid, :prepared], :to => :cancelled - end - - # should raise an exception as there is no timestamp col - event :reopen, :timestamp => true do - transitions :from => :cancelled, :to => :opened - end - - end -end - describe "mongoid state machine" do context "existing mongo document" do before do Mongoid.master.collections.reject { |c| c.name =~ /^system\./ }.each(&:drop) @@ -119,22 +25,28 @@ it "should not persist state on transition" do @light.reset @light.current_state.should == :red @light.reload - @light.state.should == "off" + @light.state.should == :off end it "should persists state on transition" do @light.reset! @light.current_state.should == :red @light.reload @light.state.should == "red" end + it "should initialize the current state when loaded from database" do + @light.reset! + loaded_light = MongoTrafficLight.find(@light.id) + loaded_light.current_state.should == :red + end + it "should raise error on transition to an invalid state" do - expect { @light.yellow_on }.should raise_error EdgeStateMachine::InvalidTransition + expect { @light.yellow_on }.should raise_error EdgeStateMachine::NoTransitionFound @light.current_state.should == :off end it "should persist state when state is protected on transition" do protected_light = MongoProtectedTrafficLight.create! @@ -143,12 +55,12 @@ protected_light.reload protected_light.state.should == "red" end it "should not validate when try transition with wrong state " do - for s in @light.class.state_machine.states - @light.state = s.name + for s in @light.class.state_machines[:default].states.keys + @light.state = s @light.valid?.should == true end @light.state = "invalid_one" @light.valid?.should_not == true end @@ -156,23 +68,42 @@ it "should raise exception when model validation fails on transition" do validating_light = MongoValidatingTrafficLight.create! expect {validating_light.reset!}.should raise_error Mongoid::Errors::Validations end - #it "should state query method used in a validation condition" do - #validating_light = MongoConditionalValidatingTrafficLight.create! + it "should state query method used in a validation condition" do + validating_light = MongoConditionalValidatingTrafficLight.create! #expect {validating_light.reset!}.should raise_error Mongoid::RecordInvalid - #validating_light.off?.should == true - #end + validating_light.off?.should == true + end it "should reload the model when current state resets" do @light.reset @light.red?.should == true @light.update_attribute(:state, 'green') - @light.reload.green?.should == false # reloaded state should come from instance variable not from database - # because the state can be changed without persist + @light.reload.green?.should == true # reloaded state should come from database end + + describe "scopes" do + it "should be added for each state" do + MongoTrafficLight.should respond_to(:off) + MongoTrafficLight.should respond_to(:red) + end + + it "should not be added for each state" do + #MongoTrafficLightNoScope.should_not respond_to(:off) + #MongoTrafficLightNoScope.should_not respond_to(:red) + end + + it "should behave like scopes" do + 3.times { MongoTrafficLight.create(:state => "off") } + 3.times { MongoTrafficLight.create(:state => "red") } + # one was created before + MongoTrafficLight.off.count.should == 4 + MongoTrafficLight.red.count.should == 3 + end + end end context "new active record" do before do @light = MongoTrafficLight.new @@ -195,57 +126,8 @@ # control case, no timestamp has been set so we should expect default behaviour it "should not raise any exceptions when moving to placed" do @order = create_order expect { @order.place! }.should_not raise_error @order.state.should == "placed" - end - - it "should set paid_at when moving to paid" do - @order = create_order(:placed) - @order.pay! - @order.reload - @order.paid_at.should_not be_nil - end - - it "should set prepared_on when moving to prepared" do - @order = create_order(:paid) - @order.prepare! - @order.reload - @order.prepared_on.should_not be_nil - end - - it "should set dispatched_at when moving to delivered" do - @order = create_order(:prepared) - @order.deliver! - @order.reload - @order.dispatched_at.should_not be_nil - end - - it "should set cancellation_date when moving to cancelled" do - @order = create_order(:placed) - @order.cancel! - @order.reload - @order.cancellation_date.should_not be_nil - end - - it "should raise an exception as there is no attribute when moving to reopened" do - @order = create_order(:cancelled) - expect { @order.re_open! }.should raise_error NoMethodError - @order.reload - end - - it "should raise an exception when passing an invalid value to timestamp options" do - expect { - class MongoOrder - include Mongoid::Document - include Mongoid::EdgeStateMachine - - state_machine do - event :replace, timestamp: 1 do - transitions :from => :prepared, :to => :placed - end - end - end - }.should raise_error ArgumentError end end end \ No newline at end of file