require '../../../../spec_helper'

describe "Freakset.Actor.Rescue", ->

  beforeEach ->
    @Rescue = Freakset.Actor.Rescue

    spyOn(Freakset, 'build').andReturn("innerFreakset")

    @freakset = {
      buildAndRunFreakset: jasmine.createSpy(),
      commit: jasmine.createSpy(),
      innerFreaksets: [],
      klass: Freakset,
      modifyStack: jasmine.createSpy(),
      store: { name: "test" }
    }


  describe '#build', ->

    it 'should create a inner Freakset with an empty stack, passing store and the current Freakset (as outer)', ->
      @Rescue.build @freakset, "scope:rescue", undefined, ->
      expect(Freakset.build).toHaveBeenCalledWith(store: @freakset.store, outerFreakset: @freakset)

    it 'should attach the actor definition to the stack', ->
      @Rescue.build @freakset, "spec:rescue", undefined, ( -> )
      expect(@freakset.modifyStack).toHaveBeenCalled()

    it 'should attach the errFn callback to the actor definition', ->
      errFn = ( -> "errFn" )
      @Rescue.build @freakset, "spec:rescue", errFn, ( -> )
      expect(@freakset.modifyStack.mostRecentCall.args[1].errFn).toEqual errFn

    it 'should invoke the callback and pass the innerFreakset as argument', ->
      fn = jasmine.createSpy()
      @Rescue.build @freakset, "spec:rescue", undefined, fn
      expect(fn).toHaveBeenCalledWith('innerFreakset')

    it 'should keep references of innerFreaksets', ->
      fn = ->
      @Rescue.build @freakset, "spec:rescue", undefined, fn
      expect(@freakset.innerFreaksets.length).toBe(1)
      expect(@freakset.innerFreaksets[0]).toEqual('innerFreakset')

    it 'should return the new (inner) Freakset', ->
      expect(@Rescue.build @freakset, "spec:rescue", undefined, ( -> )).toEqual('innerFreakset')


  describe '#run', ->

    it 'should build and run the inner freakset', ->
      innerFreakset = {}
      innerFreakset['stack'] = [ 'innerStep' ]
      @Rescue.run(@freakset, { type: "rescue", innerFreakset: innerFreakset }) 
      expect(@freakset.buildAndRunFreakset).toHaveBeenCalledWith(stack: innerFreakset.stack, store: @freakset.store, outerFreakset: @freakset)

    describe 'catching errors', ->

      beforeEach ->
        @errFn = jasmine.createSpy()
        @innerFreakset = {}
        @actor = { type: "rescue", innerFreakset: @innerFreakset, errFn: @errFn }

      it 'should not throw an error raised by an inner step', ->
        @Rescue.run(@freakset, @actor)

      it 'should call the errFn and pass the err, Freakset and Actor', ->
        @freakset.buildAndRunFreakset = -> throw 42
        @Rescue.run(@freakset, @actor)
        expect(@errFn).toHaveBeenCalledWith(42, @freakset, @innerFreakset)
