When a user has a game in progress and leaves the page, the only way for them to get back to the game session is by knowing the game session link. I want to add a list of active game sessions to a user’s root login page.

I add a feature test for the case when user has no games in progress. This test already passes since I haven’t updated the HTML template yet.

  describe "user has no games in progress" do
    setup [:create_user, :sign_in_user]

    test "does not show game in progress", %{session: session} do
      session
      |> visit("/")
      |> refute_has(Query.text("Games in Progress"))
    end
  end

I test the test by temporarily adding “Games in Progress” to the template and validate the test is failing as expected. I revert the change now that I know the test logic is correct.

I add another test case for a user with a game in progress and a helper function to setup the active game.

  describe "user has a game in progress" do
    setup [:create_user, :create_game, :sign_in_user]

    test "shows a list of active games", %{session: session, game_id: game_id} do
      session
      |> visit("/")
      |> assert_text("Games in Progress")
      |> find(Query.css("#games-in-progress"), fn element ->
        assert_text(element, game_id)
      end)
    end
  end

  defp create_game(%{user: user}) do
    players = [
      player_fixture(%{user_id: user.id}),
      player_fixture()
    ]

    game = game_fixture(id: "A_GAME", players: players)
    {:ok, _pid} = GameEngine.continue_game(game)

    [game_id: game.id]
  end

This feature test is testing behavior from the browser interface, but I’ll need to implement the desired behavior at a lower unit level. I leave the feature test red and switch focus to building get_active_games_for_user which will encapsulate the logic needed for collecting a list of active games for the specified user id.

I create the first test case for this non-existent function for the simple scenario of there being no active games for a user.


  describe "get_active_games_for_user/1 when no games are active" do
    setup [:create_user]

    test "should return empty list", %{user: user} do
      assert [] == GameEngine.get_active_games_for_user(user.id)
    end
  end

I create the function in the GameEngine module and hard code an empty string return value to make the test pass. This isn’t particularly useful for any caller of the function, but once the happy path is implemented, this test case will already be in place to detect a regression of behavior.

I create a new test case for the scenario of a user with two active games. I don’t know exactly how the domain logic will look or what I need to build for the test scenario setup, but I write the test as if all these already existed. I’ll then work through the compilation errors until the test is functional.

  describe "get_active_games_for_user/1 when user has active games" do
    setup [:create_user, :join_games]

    test "should return a list of user game summaries", ctx do
      active_game_ids = [
        ctx.game1.id,
        ctx.game2.id
      ]

      result = GameEngine.get_active_games_for_user(ctx.user.id)
      assert [game_summary1, game_summary2] = result
      assert Enum.member?(active_game_ids, game_summary1.game_id)
      assert Enum.member?(active_game_ids, game_summary2.game_id)
    end
  end