# frozen_string_literal: true RSpec.describe FiniteMachine, 'initial' do before(:each) { stub_const("DummyLogger", Class.new do attr_accessor :level def initialize @level = :pending end end) } it "defaults initial state to :none" do fsm = FiniteMachine.new do event :slow, :green => :yellow event :stop, :yellow => :red end expect(fsm.current).to eql(:none) end it "requires initial state transition from :none" do fsm = FiniteMachine.new do event :init, :none => :green event :slow, :green => :yellow event :stop, :yellow => :red end expect(fsm.current).to eql(:none) fsm.init expect(fsm.current).to eql(:green) end it "allows to specify inital state" do called = [] fsm = FiniteMachine.new do initial :green event :slow, :green => :yellow event :stop, :yellow => :red on_exit :none do |event| called << 'on_exit_none' end on_enter :green do |event| called << 'on_enter_green' end end expect(fsm.current).to eql(:green) expect(called).to be_empty end it "allows to specify initial state through parameter" do fsm = FiniteMachine.new initial: :green do event :slow, :green => :yellow event :stop, :yellow => :red end expect(fsm.current).to eql(:green) end it "allows to specify deferred inital state" do fsm = FiniteMachine.new do initial :green, defer: true event :slow, :green => :yellow event :stop, :yellow => :red end expect(fsm.current).to eql(:none) fsm.init expect(fsm.current).to eql(:green) end it "raises error when specyfying initial without state name" do expect { FiniteMachine.new do initial defer: true event :slow, :green => :yellow event :stop, :yellow => :red end }.to raise_error(FiniteMachine::MissingInitialStateError) end it "allows to specify inital start event" do fsm = FiniteMachine.new do initial :green, event: :start event :slow, :green => :none event :stop, :yellow => :red end expect(fsm.current).to eql(:green) fsm.slow expect(fsm.current).to eql(:none) fsm.start expect(fsm.current).to eql(:green) end it "allows to specify deferred inital start event" do fsm = FiniteMachine.new do initial :green, event: :start, defer: true event :slow, :green => :yellow event :stop, :yellow => :red end expect(fsm.current).to eql(:none) fsm.start expect(fsm.current).to eql(:green) end it "evaluates initial state" do logger = DummyLogger.new fsm = FiniteMachine.new do initial logger.level event :slow, :green => :none event :stop, :yellow => :red end expect(fsm.current).to eql(:pending) end it "doesn't care about state type" do fsm = FiniteMachine.new do initial 1 event :a, 1 => 2 event :b, 2 => 3 end expect(fsm.current).to eql(1) fsm.a expect(fsm.current).to eql(2) fsm.b expect(fsm.current).to eql(3) end it "allows to retrieve initial state" do fsm = FiniteMachine.new do initial :green event :slow, :green => :yellow event :stop, :yellow => :red end expect(fsm.current).to eq(:green) expect(fsm.initial_state).to eq(:green) fsm.slow expect(fsm.current).to eq(:yellow) expect(fsm.initial_state).to eq(:green) end it "allows to retrieve initial state for deferred" do fsm = FiniteMachine.new do initial :green, defer: true event :slow, :green => :yellow event :stop, :yellow => :red end expect(fsm.current).to eq(:none) expect(fsm.initial_state).to eq(:none) fsm.init expect(fsm.current).to eq(:green) expect(fsm.initial_state).to eq(:green) end it "allows to trigger callbacks on initial with :silent option" do called = [] fsm = FiniteMachine.new do initial :green, silent: false event :slow, :green => :yellow on_enter :green do |event| called << 'on_enter_green' end end expect(fsm.current).to eq(:green) expect(called).to eq(['on_enter_green']) end it "allows to trigger callbacks on deferred initial state" do called = [] fsm = FiniteMachine.new do initial :green, silent: false, defer: true event :slow, :green => :yellow on_enter :green do |event| called << 'on_enter_green' end end expect(fsm.current).to eq(:none) fsm.init expect(called).to eq(['on_enter_green']) end end