defmodule GitGudWeb.PrLive.ReviewTest do
@moduledoc """
The approval UI: leaving a review, changing your mind, and the way
both land in the PR's history.
"""
use GitGudWeb.ConnCase, async: false
import Phoenix.LiveViewTest
import GitGud.AccountsFixtures
import GitGud.ForgeFixtures
alias GitGud.Events
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}/reviews"
end
defp submit_review(lv, state, body \\ "") do
lv
|> form("#review-form", %{"pr_review" => %{"state" => state, "body" => body}})
|> render_submit()
end
test "a reviewer can leave a verdict", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
html = submit_review(lv, "approved", "Looks good")
assert html =~ "approved"
assert html =~ "Looks good"
end
test "submitting again changes the standing verdict", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
_ = submit_review(lv, "approved", "Fine by me")
html = submit_review(lv, "changes_requested", "Actually, hold on")
# Only the latest counts as this reviewer's verdict.
reloaded = PullRequests.get_pull_request!(repo, pr.number)
assert [latest] = PullRequests.latest_reviews(reloaded)
assert latest.state == "changes_requested"
# But both rows survive as the log.
assert length(reloaded.reviews) == 2
assert html =~ "Show all 2 reviews"
end
test "the form says what you already left and offers to update it", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
assert html =~ "Submit review"
refute html =~ "Update review"
html = submit_review(lv, "changes_requested", "Needs work")
assert html =~ "You requested changes"
assert html =~ "Update review"
end
test "two reviewers each keep their own verdict", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
one = user_fixture()
two = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, one), pr_path(repo, pr))
_ = submit_review(lv, "approved")
{:ok, lv2, _html} = live(log_in_user(conn, two), pr_path(repo, pr))
_ = submit_review(lv2, "changes_requested")
reloaded = PullRequests.get_pull_request!(repo, pr.number)
states = reloaded |> PullRequests.latest_reviews() |> Enum.map(& &1.state) |> Enum.sort()
assert states == ["approved", "changes_requested"]
end
test "anonymous visitors get no review form", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
{:ok, lv, _html} = live(conn, pr_path(repo, pr))
refute has_element?(lv, "#review-form")
end
test "an anonymous submission is refused rather than crashing", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
{:ok, lv, _html} = live(conn, pr_path(repo, pr))
render_hook(lv, "add_review", %{"pr_review" => %{"state" => "approved"}})
assert PullRequests.get_pull_request!(repo, pr.number).reviews == []
end
test "a first review is recorded in the history", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
_ = submit_review(lv, "approved")
assert [event] = Events.list_for(pr)
assert event.kind == "reviewed"
assert event.data["to"] == "approved"
assert event.data["from"] == nil
hist = String.replace_suffix(pr_path(repo, pr), "/reviews", "/history")
{:ok, _hist, html} = live(log_in_user(conn, reviewer), hist)
assert html =~ "reviewed:"
assert html =~ "approved"
end
test "changing a review records the transition", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
_ = submit_review(lv, "approved")
_ = submit_review(lv, "changes_requested")
assert [_first, second] = Events.list_for(pr)
assert second.data["from"] == "approved"
assert second.data["to"] == "changes_requested"
hist = String.replace_suffix(pr_path(repo, pr), "/reviews", "/history")
{:ok, _hist, html} = live(log_in_user(conn, reviewer), hist)
assert html =~ "changed their review from"
assert html =~ "changes requested"
end
test "review events interleave with everything else", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
_ = submit_review(lv, "approved")
conv = String.replace_suffix(pr_path(repo, pr), "/reviews", "")
{:ok, owner_lv, _html} = live(log_in_user(conn, owner), conv)
_ = owner_lv |> element("button", "Close") |> render_click()
kinds = pr |> Events.list_for() |> Enum.map(& &1.kind)
assert kinds == ["reviewed", "closed"]
end
test "re-submitting the same verdict adds nothing", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
_ = submit_review(lv, "approved", "Looks good")
_ = submit_review(lv, "approved", "Looks good")
_ = submit_review(lv, "approved", "Looks good")
assert length(PullRequests.get_pull_request!(repo, pr.number).reviews) == 1
assert length(Events.list_for(pr)) == 1
end
test "whitespace-only differences don't count as a change", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
_ = submit_review(lv, "approved", "Fine")
_ = submit_review(lv, "approved", " Fine ")
assert length(PullRequests.get_pull_request!(repo, pr.number).reviews) == 1
end
test "changing the body alone is a real change", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
_ = submit_review(lv, "approved", "First thought")
_ = submit_review(lv, "approved", "Second thought")
assert length(PullRequests.get_pull_request!(repo, pr.number).reviews) == 2
end
test "another reviewer's identical verdict is still their own", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
one = user_fixture()
two = user_fixture()
{:ok, lv1, _html} = live(log_in_user(conn, one), pr_path(repo, pr))
_ = submit_review(lv1, "approved", "LGTM")
{:ok, lv2, _html} = live(log_in_user(conn, two), pr_path(repo, pr))
_ = submit_review(lv2, "approved", "LGTM")
assert length(PullRequests.get_pull_request!(repo, pr.number).reviews) == 2
end
test "the full log stays hidden while every reviewer has one review", %{conn: conn} do
{owner, repo} = repository_fixture(%{visibility: "public"})
pr = pr_with_branches(repo, owner)
reviewer = user_fixture()
{:ok, lv, _html} = live(log_in_user(conn, reviewer), pr_path(repo, pr))
html = submit_review(lv, "approved")
refute html =~ "Show all"
end
end
neiam /gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Packages
⭐
Log in to mark this repository.
8.1 KiB · text
History
6280797