134 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
		
		
			
		
	
	
			134 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
| 
								 | 
							
								defmodule RPGTest do
							 | 
						||
| 
								 | 
							
								  use ExUnit.Case
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  alias RPG.{Edible, Character, LoafOfBread, ManaPotion, Poison, EmptyBottle}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  defmodule NewItem do
							 | 
						||
| 
								 | 
							
								    defstruct []
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  describe "Edible" do
							 | 
						||
| 
								 | 
							
								    @tag task_id: 1
							 | 
						||
| 
								 | 
							
								    test "is a protocol" do
							 | 
						||
| 
								 | 
							
								      assert Edible.__protocol__(:functions) == [eat: 2]
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 1
							 | 
						||
| 
								 | 
							
								    test "cannot eat a completely new item" do
							 | 
						||
| 
								 | 
							
								      assert_raise Protocol.UndefinedError, fn ->
							 | 
						||
| 
								 | 
							
								        Edible.eat(%NewItem{}, %Character{})
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  describe "LoafOfBread" do
							 | 
						||
| 
								 | 
							
								    @tag task_id: 2
							 | 
						||
| 
								 | 
							
								    test "implements the Edible protocol" do
							 | 
						||
| 
								 | 
							
								      {:consolidated, modules} = Edible.__protocol__(:impls)
							 | 
						||
| 
								 | 
							
								      assert LoafOfBread in modules
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 2
							 | 
						||
| 
								 | 
							
								    test "eating it increases health" do
							 | 
						||
| 
								 | 
							
								      character = %Character{health: 50}
							 | 
						||
| 
								 | 
							
								      {_byproduct, %Character{} = character} = Edible.eat(%LoafOfBread{}, character)
							 | 
						||
| 
								 | 
							
								      assert character.health == 55
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 2
							 | 
						||
| 
								 | 
							
								    test "eating it has no byproduct" do
							 | 
						||
| 
								 | 
							
								      character = %Character{}
							 | 
						||
| 
								 | 
							
								      {byproduct, %Character{}} = Edible.eat(%LoafOfBread{}, character)
							 | 
						||
| 
								 | 
							
								      assert byproduct == nil
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 2
							 | 
						||
| 
								 | 
							
								    test "eating it does not affect mana" do
							 | 
						||
| 
								 | 
							
								      character = %Character{mana: 77}
							 | 
						||
| 
								 | 
							
								      {_byproduct, %Character{} = character} = Edible.eat(%LoafOfBread{}, character)
							 | 
						||
| 
								 | 
							
								      assert character.mana == 77
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  describe "ManaPotion" do
							 | 
						||
| 
								 | 
							
								    @tag task_id: 3
							 | 
						||
| 
								 | 
							
								    test "implements the Edible protocol" do
							 | 
						||
| 
								 | 
							
								      {:consolidated, modules} = Edible.__protocol__(:impls)
							 | 
						||
| 
								 | 
							
								      assert ManaPotion in modules
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 3
							 | 
						||
| 
								 | 
							
								    test "eating it increases mana" do
							 | 
						||
| 
								 | 
							
								      character = %Character{mana: 10}
							 | 
						||
| 
								 | 
							
								      {_byproduct, %Character{} = character} = Edible.eat(%ManaPotion{strength: 6}, character)
							 | 
						||
| 
								 | 
							
								      assert character.mana == 16
							 | 
						||
| 
								 | 
							
								      {_byproduct, %Character{} = character} = Edible.eat(%ManaPotion{strength: 9}, character)
							 | 
						||
| 
								 | 
							
								      assert character.mana == 25
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 3
							 | 
						||
| 
								 | 
							
								    test "eating it produces an empty bottle" do
							 | 
						||
| 
								 | 
							
								      character = %Character{}
							 | 
						||
| 
								 | 
							
								      {byproduct, %Character{}} = Edible.eat(%ManaPotion{}, character)
							 | 
						||
| 
								 | 
							
								      assert byproduct == %EmptyBottle{}
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 3
							 | 
						||
| 
								 | 
							
								    test "eating it does not affect health" do
							 | 
						||
| 
								 | 
							
								      character = %Character{health: 4}
							 | 
						||
| 
								 | 
							
								      {_byproduct, %Character{} = character} = Edible.eat(%ManaPotion{strength: 6}, character)
							 | 
						||
| 
								 | 
							
								      assert character.health == 4
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  describe "Poison" do
							 | 
						||
| 
								 | 
							
								    @tag task_id: 4
							 | 
						||
| 
								 | 
							
								    test "implements the Edible protocol" do
							 | 
						||
| 
								 | 
							
								      {:consolidated, modules} = Edible.__protocol__(:impls)
							 | 
						||
| 
								 | 
							
								      assert Poison in modules
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 4
							 | 
						||
| 
								 | 
							
								    test "eating it brings health down to 0" do
							 | 
						||
| 
								 | 
							
								      character = %Character{health: 120}
							 | 
						||
| 
								 | 
							
								      {_byproduct, %Character{} = character} = Edible.eat(%Poison{}, character)
							 | 
						||
| 
								 | 
							
								      assert character.health == 0
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 4
							 | 
						||
| 
								 | 
							
								    test "eating it produces an empty bottle" do
							 | 
						||
| 
								 | 
							
								      character = %Character{}
							 | 
						||
| 
								 | 
							
								      {byproduct, %Character{}} = Edible.eat(%Poison{}, character)
							 | 
						||
| 
								 | 
							
								      assert byproduct == %EmptyBottle{}
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @tag task_id: 4
							 | 
						||
| 
								 | 
							
								    test "eating it does not affect mana" do
							 | 
						||
| 
								 | 
							
								      character = %Character{mana: 99}
							 | 
						||
| 
								 | 
							
								      {_byproduct, %Character{} = character} = Edible.eat(%Poison{}, character)
							 | 
						||
| 
								 | 
							
								      assert character.mana == 99
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @tag task_id: 4
							 | 
						||
| 
								 | 
							
								  test "eating many things one after another" do
							 | 
						||
| 
								 | 
							
								    items = [
							 | 
						||
| 
								 | 
							
								      %LoafOfBread{},
							 | 
						||
| 
								 | 
							
								      %ManaPotion{strength: 10},
							 | 
						||
| 
								 | 
							
								      %ManaPotion{strength: 2},
							 | 
						||
| 
								 | 
							
								      %LoafOfBread{}
							 | 
						||
| 
								 | 
							
								    ]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    character = %Character{health: 100, mana: 100}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    character =
							 | 
						||
| 
								 | 
							
								      Enum.reduce(items, character, fn item, character ->
							 | 
						||
| 
								 | 
							
								        {_, character} = Edible.eat(item, character)
							 | 
						||
| 
								 | 
							
								        character
							 | 
						||
| 
								 | 
							
								      end)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    assert character.health == 110
							 | 
						||
| 
								 | 
							
								    assert character.mana == 112
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								end
							 |