3.5 KiB · text History b868907
defmodule GitGudWeb.RunnerConnectedTest do
  @moduledoc """
  A runner's first connection shows on the runners pages that list it,
  without a reload: the list refreshes and a toast says so. Announced
  once, however many polls race on the new runner.
  """
  use GitGudWeb.ConnCase, async: false

  import Phoenix.LiveViewTest
  import GitGud.AccountsFixtures
  import GitGud.ForgeFixtures

  alias GitGud.Organizations
  alias GitGud.Repositories.Storage
  alias GitGud.Workflows.Runners

  defp repo_page(conn) do
    {owner, repo} = repository_fixture()
    repo = GitGud.Repo.preload(repo, [:owner, :organization])

    {:ok, lv, _} =
      live(
        log_in_user(conn, owner),
        "/r/#{Storage.repo_handle(repo)}/#{repo.name}/settings/runners"
      )

    {repo, lv}
  end

  test "a repository's runner connecting refreshes the list, with a toast", %{conn: conn} do
    {repo, _} = repo_page(conn)
    {:ok, runner, _uuid, _token} = Runners.create_offline(%{name: "caprica"}, repo)

    # Opened after the runner exists, so it starts out never connected.
    {:ok, lv, _} =
      live(
        log_in_user(conn, repo.owner),
        "/r/#{Storage.repo_handle(repo)}/#{repo.name}/settings/runners"
      )

    assert has_element?(lv, "#runner-row-#{runner.id}", "never connected")
    refute has_element?(lv, "#flash-info")

    {:ok, _} = Runners.touch_last_seen(runner)

    assert has_element?(lv, "#runner-row-#{runner.id}", "last seen")
    assert has_element?(lv, "#flash-info", "Runner 'caprica' connected.")
  end

  test "a global runner connecting shows on a repository's page too", %{conn: conn} do
    {_repo, lv} = repo_page(conn)
    {:ok, runner, _uuid, _token} = Runners.create_offline(%{name: "pool"})

    {:ok, _} = Runners.touch_last_seen(runner)

    assert has_element?(lv, "#runner-row-#{runner.id}", "last seen")
    assert has_element?(lv, "#flash-info", "Runner 'pool' connected.")
  end

  test "another repository's runner connecting doesn't", %{conn: conn} do
    {_repo, lv} = repo_page(conn)
    {_other_owner, other} = repository_fixture()
    {:ok, runner, _uuid, _token} = Runners.create_offline(%{name: "elsewhere"}, other)

    {:ok, _} = Runners.touch_last_seen(runner)

    refute has_element?(lv, "#runner-row-#{runner.id}")
    refute has_element?(lv, "#flash-info")
  end

  test "an org's runner connecting shows on the org's page", %{conn: conn} do
    admin = user_fixture()
    handle = "rc#{System.unique_integer([:positive])}"
    {:ok, org} = Organizations.create_organization(admin, %{"handle" => handle, "name" => handle})
    {:ok, runner, _uuid, _token} = Runners.create_offline(%{name: "builder"}, org)

    {:ok, lv, _} = live(log_in_user(conn, admin), ~p"/orgs/#{handle}/settings/runners")
    assert has_element?(lv, "#runner-row-#{runner.id}", "never connected")

    {:ok, _} = Runners.touch_last_seen(runner)

    assert has_element?(lv, "#runner-row-#{runner.id}", "last seen")
    assert has_element?(lv, "#flash-info", "Runner 'builder' connected.")
  end

  test "announced on the first connection only" do
    {:ok, runner, _uuid, _token} = Runners.create_offline(%{name: "once"})
    Phoenix.PubSub.subscribe(GitGud.PubSub, Runners.topic(:global))

    # Two polls holding the same never-connected runner, as two requests
    # racing on a new runner would.
    {:ok, _} = Runners.touch_last_seen(runner)
    {:ok, _} = Runners.touch_last_seen(runner)

    assert_receive {:runner_connected, %{name: "once"}}
    refute_receive {:runner_connected, _}
    assert GitGud.Repo.reload!(runner).last_seen_at
  end
end