class TestAttacking(unittest.TestCase):

    def setUp(self):
        self.character = Character()
        self.opponent = Character()
        self.opponent.damage = MagicMock()

    @patch("evercraft.roll", return_value=5)
    def test_attacking_rolls_a_d20(self,roll):
        self.character.attack(self.opponent)
        self.assertEqual(roll.call_count, 1)

    @patch("evercraft.roll", return_value=19)
    def test_hits_when_rolling_at_or_over_target_ac(self, roll):
        self.character.attack(self.opponent)
        self.assertEqual(self.opponent.damage.call_count, 1)

    @patch("evercraft.roll", return_value=19)
    def test_hits_doing_default_damage(self, roll):
        self.character.attack(self.opponent)
        self.opponent.damage.assert_called_once_with(DEFAULT_DAMAGE)

    @patch("evercraft.roll", return_value=2)
    def test_miss_when_rolling_below_target_ac(self, roll):
        self.character.attack(self.opponent)
        self.assertEqual(self.opponent.damage.call_count, 0)

    @patch("evercraft.roll", return_value=20)
    def test_critical_hit_does_double_damage(self,roll):
        self.character.attack(self.opponent)
        self.opponent.damage.assert_called_once_with(DEFAULT_DAMAGE * 2)
class TestExperience(unittest.TestCase):

    def setUp(self):
        self.character = Character()
        self.opponent = Character()

    @patch("evercraft.roll", return_value=20)
    def test_xp_gain_on_hit(self, __):
        self.character.attack(self.opponent)
        self.assertEqual(self.character.experience_points(), XP_PER_HIT)

    @patch("evercraft.roll", return_value=2)
    def test_xp_gain_on_miss(self, __):
        self.character.attack(self.opponent)
        self.assertEqual(self.character.experience_points(), 0)

    def test_calculate_level(self):
        cases = [(0,1), (999,1), (1000, 2), (1001, 2), (2000, 3), (3000, 4)]
        for xp, expected_level in cases:
          self.character = Character()
          self.character.add_experience(xp)
          self.assertEqual(self.character.level(), expected_level, 
                           "%s %s"%(xp, self.character.level()))