defmodule GitGudWeb.PrLive.ReopenTest do
@moduledoc """
Closing and reopening a pull request, and who is allowed to.
"""
use GitGudWeb.ConnCase, async: false
import Phoenix.LiveViewTest
import GitGud.AccountsFixtures
import GitGud.ForgeFixtures
alias GitGud.Events
alias GitGud.Organizations
alias GitGud.PullRequests
alias GitGud.Repositories
defp pr_path(repo, pr) do
handle = Repositories.Storage.repo_handle(GitGud.Repo.preload(repo, [:owner, :organization]))
~p"/r/#{handle}/#{repo.name}/pulls/#{pr.number}"
end
defp close!(pr) do
{:ok, pr} = PullRequests.set_state(pr, "closed")
pr
end
test "the author can reopen their own closed PR", %{conn: conn} do
{user, repo} = repository_fixture()
pr = pr_with_branches(repo, user) |> close!()
{:ok, lv, html} = live(log_in_user(conn, user), pr_path(repo, pr))
assert html =~ "This pull request is closed."
lv |> element("button", "Reopen") |> render_click()
assert PullRequests.get_pull_request!(repo, pr.number).state == "open"
end
test "a repo admin can reopen someone else's closed PR", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
author = user_fixture()
pr =
repo
|> pr_with_branches(author)
|> close!()
{:ok, lv, _html} = live(log_in_user(conn, owner), pr_path(repo, pr))
lv |> element("button", "Reopen") |> render_click()
assert PullRequests.get_pull_request!(repo, pr.number).state == "open"
end
test "an org admin can reopen a PR in the org's repo", %{conn: conn} do
admin = user_fixture()
{:ok, org} =
Organizations.create_organization(admin, %{
"handle" => "reopen-org",
"visibility" => "public"
})
{:ok, repo} =
Repositories.create_repository_for_org(org, admin, %{
"name" => "org-pr-repo",
"visibility" => "public"
})
author = user_fixture()
pr = pr_with_branches(repo, author) |> close!()
{:ok, lv, _html} = live(log_in_user(conn, admin), pr_path(repo, pr))
lv |> element("button", "Reopen") |> render_click()
assert PullRequests.get_pull_request!(repo, pr.number).state == "open"
end
test "an unrelated user gets no reopen button", %{conn: conn} do
{_owner, repo} = repository_fixture(%{visibility: "public"})
author = user_fixture()
pr = pr_with_branches(repo, author) |> close!()
outsider = user_fixture()
{:ok, lv, html} = live(log_in_user(conn, outsider), pr_path(repo, pr))
assert html =~ "This pull request is closed."
refute has_element?(lv, "button[phx-click=toggle_state]")
end
test "an unrelated user can't reopen by sending the event", %{conn: conn} do
{_owner, repo} = repository_fixture(%{visibility: "public"})
author = user_fixture()
pr = pr_with_branches(repo, author) |> close!()
outsider = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, outsider), pr_path(repo, pr))
render_hook(lv, "toggle_state", %{})
assert PullRequests.get_pull_request!(repo, pr.number).state == "closed"
end
test "an anonymous visitor can't either", %{conn: conn} do
{user, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, user) |> close!()
{:ok, lv, _html} = live(conn, pr_path(repo, pr))
render_hook(lv, "toggle_state", %{})
assert PullRequests.get_pull_request!(repo, pr.number).state == "closed"
end
test "reopening is recorded in the history", %{conn: conn} do
{user, repo} = repository_fixture()
pr = pr_with_branches(repo, user) |> close!()
{:ok, lv, _html} = live(log_in_user(conn, user), pr_path(repo, pr))
lv |> element("button", "Reopen") |> render_click()
assert [%{kind: "reopened", actor: %{id: actor_id}}] = Events.list_for(pr)
assert actor_id == user.id
{:ok, _hist, html} = live(log_in_user(conn, user), pr_path(repo, pr) <> "/history")
assert html =~ "reopened this."
end
test "a merged PR offers no reopen and refuses one", %{conn: conn} do
{user, repo} = repository_fixture()
pr = pr_with_branches(repo, user)
{:ok, merged} = pr |> Ecto.Changeset.change(state: "merged") |> GitGud.Repo.update()
{:ok, lv, html} = live(log_in_user(conn, user), pr_path(repo, merged))
refute html =~ "Reopen"
render_hook(lv, "toggle_state", %{})
assert PullRequests.get_pull_request!(repo, pr.number).state == "merged"
end
test "set_state/2 refuses to reopen a merged PR at the context level" do
{user, repo} = repository_fixture()
pr = pr_with_branches(repo, user)
{:ok, merged} = pr |> Ecto.Changeset.change(state: "merged") |> GitGud.Repo.update()
assert {:error, :merged} = PullRequests.set_state(merged, "open")
end
test "an open PR still closes, and only for the author or an admin", %{conn: conn} do
{_owner, repo} = repository_fixture(%{visibility: "public"})
author = user_fixture()
pr = pr_with_branches(repo, author)
outsider = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, outsider), pr_path(repo, pr))
refute has_element?(lv, "button[phx-click=toggle_state]")
render_hook(lv, "toggle_state", %{})
assert PullRequests.get_pull_request!(repo, pr.number).state == "open"
{:ok, lv, _html} = live(log_in_user(conn, author), pr_path(repo, pr))
lv |> element("button", "Close") |> render_click()
assert PullRequests.get_pull_request!(repo, pr.number).state == "closed"
end
end
neiam /gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Packages
⭐
Log in to mark this repository.
5.4 KiB · text
History
6280797