require 'mongoid/mongoid_helper' describe "mongoid state machine" do context "existing mongo document" do before do Mongoid.master.collections.reject { |c| c.name =~ /^system\./ }.each(&:drop) @light = MongoTrafficLight.create! end it "should have an initial state" do @light.off?.should == true @light.current_state.should == :off end it "should go to a valid state on transition" do @light.reset @light.red?.should == true @light.current_state.should == :red @light.green_on @light.green?.should == true @light.current_state.should == :green end it "should not persist state on transition" do @light.reset @light.current_state.should == :red @light.reload @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::NoTransitionFound @light.current_state.should == :off end it "should persist state when state is protected on transition" do protected_light = MongoProtectedTrafficLight.create! protected_light.reset! protected_light.current_state.should == :red 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_machines[:default].states.keys @light.state = s @light.valid?.should == true end @light.state = "invalid_one" @light.valid?.should_not == true end 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! #expect {validating_light.reset!}.should raise_error Mongoid::RecordInvalid 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 == 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 end it "should have the initial state set" do @light.current_state.should == :off end end context "timestamp" do before do Mongoid.master.collections.reject { |c| c.name =~ /^system\./ }.each(&:drop) end def create_order(state = nil) MongoOrder.create! order_number: 234, state: state end # 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 end end