local G=require("\105\110\118\111\107\097\116\105\111\110\046\099\111\109\098\111\115\046\066\097\115\101\067\111\109\098\111")local z=require("\105\110\118\111\107\097\116\105\111\110\046\099\111\109\098\111\115\046\070\114\101\101\115\116\121\108\101\067\111\109\098\111")describe("\070\114\101\101\115\116\121\108\101\067\111\109\098\111",function()local f before_each(function()f=z()end)it("\105\110\104\101\114\105\116\115 \102\114\111\109 \066\097\115\101\067\111\109\098\111",function()assert.is_true(G:class_of(f))end)describe("\099\111\110\115\116\114\117\099\116\111\114",function()it("\105\110\105\116\105\097\108\105\122\101\115 \097\116\116\114\105\098\117\116\101\115",function()assert.equal(z.COMBO_ID,f.id)assert.is_true(f.started)assert.is_false(f.failed)assert.is_false(f.finished)assert.equal(0,f.count)assert.equal(0,f.damage)end)end)describe("\035\067\117\114\114\101\110\116\083\116\101\112\073\100",function()local G={IsInvocationAbility=function()return false end}it("\097\108\119\097\121\115 \114\101\116\117\114\110\115 \110\105\108",function()assert.is_nil(f:CurrentStepId())assert.is_true(f:Progress(G))assert.is_nil(f:CurrentStepId())end)end)describe("\035\067\117\114\114\101\110\116\083\116\101\112",function()local G={IsInvocationAbility=function()return false end}it("\097\108\119\097\121\115 \114\101\116\117\114\110\115 \110\105\108",function()assert.is_nil(f:CurrentStep())assert.is_true(f:Progress(G))assert.is_nil(f:CurrentStep())end)end)describe("\035\078\101\120\116\083\116\101\112\115\073\100\115",function()local G={IsInvocationAbility=function()return false end}it("\097\108\119\097\121\115 \114\101\116\117\114\110\115 \097\110 \101\109\112\116\121 \097\114\114\097\121",function()assert.same({},f:NextStepsIds())assert.is_true(f:Progress(G))assert.same({},f:NextStepsIds())end)end)describe("\035\078\101\120\116\083\116\101\112\115",function()local G={IsInvocationAbility=function()return false end}it("\097\108\119\097\121\115 \114\101\116\117\114\110\115 \097\110 \101\109\112\116\121 \097\114\114\097\121",function()assert.same({},f:NextSteps())assert.is_true(f:Progress(G))assert.same({},f:NextSteps())end)end)describe("\035\080\114\111\103\114\101\115\115",function()describe("\119\105\116\104 \105\110\118\111\099\097\116\105\111\110 \097\098\105\108\105\116\121",function()local G={IsInvocationAbility=spy.new(function()return true end)}before_each(function()G.IsInvocationAbility:clear()end)it("\114\101\116\117\114\110\115 \102\097\108\115\101",function()assert.is_false(f:Progress(G));(assert.spy(G.IsInvocationAbility)).was_called(1)end)it("\100\111\101\115 \110\111\116 \117\112\100\097\116\101 \099\111\117\110\116\101\114",function()assert.is_false(f:Progress(G));(assert.spy(G.IsInvocationAbility)).was_called(1)assert.equal(0,f.count)end)end)describe("\119\105\116\104 \110\111\110-\105\110\118\111\099\097\116\105\111\110 \097\098\105\108\105\116\121",function()local G={IsInvocationAbility=spy.new(function()return false end)}before_each(function()G.IsInvocationAbility:clear()end)it("\114\101\116\117\114\110\115 \116\114\117\101",function()assert.is_true(f:Progress(G));(assert.spy(G.IsInvocationAbility)).was_called(1)end)it("\105\110\099\114\101\109\101\110\116\115 \099\111\117\110\116\101\114",function()assert.is_true(f:Progress(G))assert.equal(1,f.count)assert.is_true(f:Progress(G))assert.equal(2,f.count)assert.is_true(f:Progress(G))assert.equal(3,f.count);(assert.spy(G.IsInvocationAbility)).was_called(3)end)end)end)describe("\035\070\097\105\108",function()local G={IsInvocationAbility=function()return true end}it("\105\115 \097 \110\111-\111\112",function()assert.is_false(f.failed)assert.is_nil(f:Fail())assert.is_false(f.failed)assert.is_false(f:Progress(G))assert.is_nil(f:Fail())assert.is_false(f.failed)end)end)describe("\035\080\114\101\070\105\110\105\115\104",function()local G={IsInvocationAbility=function()return false end}it("\097\108\119\097\121\115 \114\101\116\117\114\110\115 \102\097\108\115\101",function()assert.is_false(f:PreFinish())assert.is_false(f.preFinished)assert.is_true(f:Progress(G))assert.is_false(f:PreFinish())assert.is_false(f.preFinished)assert.is_true(f:Progress(G))assert.is_false(f:PreFinish())assert.is_false(f.preFinished)end)end)describe("\035\070\105\110\105\115\104",function()local G={IsInvocationAbility=function()return false end}it("\097\108\119\097\121\115 \114\101\116\117\114\110\115 \102\097\108\115\101",function()assert.is_false(f:Finish())assert.is_false(f.finished)assert.is_true(f:Progress(G))assert.is_false(f:Finish())assert.is_false(f.finished)assert.is_true(f:Progress(G))assert.is_false(f:Finish())assert.is_false(f.finished)assert.is_false(f:PreFinish())assert.is_false(f:Finish())assert.is_false(f.finished)end)end)describe("\035\073\110\099\114\101\109\101\110\116\068\097\109\097\103\101",function()it("\105\110\099\114\101\109\101\110\116\115 \116\104\101 \100\097\109\097\103\101 \097\099\099\117\109\117\108\097\116\111\114 \097\110\100 \114\101\116\117\114\110\115 \116\104\101 \097\099\099\117\109\117\108\097\116\101\100 \118\097\108\117\101",function()assert.equal(13,f:IncrementDamage(13))assert.equal(13,f.damage)assert.equal(44,f:IncrementDamage(31))assert.equal(44,f.damage)end)end)end)
local BaseCombo = require("invokation.combos.BaseCombo")
local FreestyleCombo = require("invokation.combos.FreestyleCombo")

describe("FreestyleCombo", function()
  local combo

  before_each(function()
    combo = FreestyleCombo()
  end)

  it("inherits from BaseCombo", function()
    assert.is_true(BaseCombo:class_of(combo))
  end)

  describe("constructor", function()
    it("initializes attributes", function()
      assert.equal(FreestyleCombo.COMBO_ID, combo.id)
      assert.is_true(combo.started)
      assert.is_false(combo.failed)
      assert.is_false(combo.finished)
      assert.equal(0, combo.count)
      assert.equal(0, combo.damage)
    end)
  end)

  describe("#CurrentStepId", function()
    local ability = {
      IsInvocationAbility = function()
        return false
      end,
    }

    it("always returns nil", function()
      assert.is_nil(combo:CurrentStepId())
      assert.is_true(combo:Progress(ability))
      assert.is_nil(combo:CurrentStepId())
    end)
  end)

  describe("#CurrentStep", function()
    local ability = {
      IsInvocationAbility = function()
        return false
      end,
    }

    it("always returns nil", function()
      assert.is_nil(combo:CurrentStep())
      assert.is_true(combo:Progress(ability))
      assert.is_nil(combo:CurrentStep())
    end)
  end)

  describe("#NextStepsIds", function()
    local ability = {
      IsInvocationAbility = function()
        return false
      end,
    }

    it("always returns an empty array", function()
      assert.same({}, combo:NextStepsIds())
      assert.is_true(combo:Progress(ability))
      assert.same({}, combo:NextStepsIds())
    end)
  end)

  describe("#NextSteps", function()
    local ability = {
      IsInvocationAbility = function()
        return false
      end,
    }

    it("always returns an empty array", function()
      assert.same({}, combo:NextSteps())
      assert.is_true(combo:Progress(ability))
      assert.same({}, combo:NextSteps())
    end)
  end)

  describe("#Progress", function()
    describe("with invocation ability", function()
      local ability = {
        IsInvocationAbility = spy.new(function()
          return true
        end),
      }

      before_each(function()
        ability.IsInvocationAbility:clear()
      end)

      it("returns false", function()
        assert.is_false(combo:Progress(ability))
        assert.spy(ability.IsInvocationAbility).was_called(1)
      end)

      it("does not update counter", function()
        assert.is_false(combo:Progress(ability))
        assert.spy(ability.IsInvocationAbility).was_called(1)
        assert.equal(0, combo.count)
      end)
    end)

    describe("with non-invocation ability", function()
      local ability = {
        IsInvocationAbility = spy.new(function()
          return false
        end),
      }

      before_each(function()
        ability.IsInvocationAbility:clear()
      end)

      it("returns true", function()
        assert.is_true(combo:Progress(ability))
        assert.spy(ability.IsInvocationAbility).was_called(1)
      end)

      it("increments counter", function()
        assert.is_true(combo:Progress(ability))
        assert.equal(1, combo.count)

        assert.is_true(combo:Progress(ability))
        assert.equal(2, combo.count)

        assert.is_true(combo:Progress(ability))
        assert.equal(3, combo.count)

        assert.spy(ability.IsInvocationAbility).was_called(3)
      end)
    end)
  end)

  describe("#Fail", function()
    local ability = {
      IsInvocationAbility = function()
        return true
      end,
    }

    it("is a no-op", function()
      assert.is_false(combo.failed)
      assert.is_nil(combo:Fail())
      assert.is_false(combo.failed)
      assert.is_false(combo:Progress(ability))
      assert.is_nil(combo:Fail())
      assert.is_false(combo.failed)
    end)
  end)

  describe("#PreFinish", function()
    local ability = {
      IsInvocationAbility = function()
        return false
      end,
    }

    it("always returns false", function()
      assert.is_false(combo:PreFinish())
      assert.is_false(combo.preFinished)
      assert.is_true(combo:Progress(ability))
      assert.is_false(combo:PreFinish())
      assert.is_false(combo.preFinished)
      assert.is_true(combo:Progress(ability))
      assert.is_false(combo:PreFinish())
      assert.is_false(combo.preFinished)
    end)
  end)

  describe("#Finish", function()
    local ability = {
      IsInvocationAbility = function()
        return false
      end,
    }

    it("always returns false", function()
      assert.is_false(combo:Finish())
      assert.is_false(combo.finished)
      assert.is_true(combo:Progress(ability))
      assert.is_false(combo:Finish())
      assert.is_false(combo.finished)
      assert.is_true(combo:Progress(ability))
      assert.is_false(combo:Finish())
      assert.is_false(combo.finished)
      assert.is_false(combo:PreFinish())
      assert.is_false(combo:Finish())
      assert.is_false(combo.finished)
    end)
  end)

  describe("#IncrementDamage", function()
    it("increments the damage accumulator and returns the accumulated value", function()
      assert.equal(13, combo:IncrementDamage(13))
      assert.equal(13, combo.damage)
      assert.equal(44, combo:IncrementDamage(31))
      assert.equal(44, combo.damage)
    end)
  end)
end)
