defmodule GitGud.SuggestionTest do
use GitGud.DataCase, async: false
import GitGud.AccountsFixtures
import GitGud.ForgeFixtures
alias GitGud.Git
alias GitGud.PullRequests
alias GitGud.PullRequests.Suggestion
alias GitGud.Repositories
describe "parsing" do
test "pulls the replacement out of a fenced block" do
assert Suggestion.parse("looks off\n\n```suggestion\nnew line\n```") == "new line"
end
test "keeps a multi-line replacement intact" do
assert Suggestion.parse("```suggestion\none\ntwo\n```") == "one\ntwo"
end
test "an empty block means delete the line, not 'no suggestion'" do
assert Suggestion.parse("```suggestion\n```") == ""
assert Suggestion.suggestion?("```suggestion\n```")
end
test "a plain comment has none" do
refute Suggestion.suggestion?("just a remark")
assert Suggestion.parse("just a remark") == nil
end
test "prose is the comment minus the block" do
body = "please rename this\n\n```suggestion\nfoo = 1\n```"
assert Suggestion.prose(body) == "please rename this"
end
end
describe "apply_to/3" do
test "replaces the named line" do
assert {:ok, "a\nX\nc"} = Suggestion.apply_to("a\nb\nc", 2, "X")
end
test "expands one line into several" do
assert {:ok, "a\nX\nY\nc"} = Suggestion.apply_to("a\nb\nc", 2, "X\nY")
end
test "an empty replacement removes the line" do
assert {:ok, "a\nc"} = Suggestion.apply_to("a\nb\nc", 2, "")
end
test "the first and last lines are reachable" do
assert {:ok, "X\nb\nc"} = Suggestion.apply_to("a\nb\nc", 1, "X")
assert {:ok, "a\nb\nX"} = Suggestion.apply_to("a\nb\nc", 3, "X")
end
test "a line past the end is out of range rather than appended" do
assert {:error, :out_of_range} = Suggestion.apply_to("a\nb", 5, "X")
assert {:error, :out_of_range} = Suggestion.apply_to("a\nb", 0, "X")
end
end
describe "apply_suggestion/2" do
setup do
{user, repo} = repository_fixture()
pr = pr_with_branches(repo, user)
{:ok, user: user, repo: repo, pr: pr}
end
defp suggest!(pr, user, line, body) do
{:ok, comment} =
PullRequests.add_comment(pr, user, %{
"body" => body,
"file_path" => "feature.txt",
"line" => line,
"commit_sha" => pr.head_sha
})
comment
end
test "commits the replacement to the source branch", %{user: user, repo: repo, pr: pr} do
comment = suggest!(pr, user, 1, "```suggestion\nreplaced\n```")
assert {:ok, new_sha} = PullRequests.apply_suggestion(comment, user)
assert new_sha != pr.head_sha
# The branch moved to the new commit...
assert {:ok, ^new_sha} = Repositories.resolve(repo, "feature")
# ...and the file says what the reviewer suggested.
{:ok, commit} = Repositories.get_commit(repo, new_sha)
{:ok, entry} = Repositories.get_tree_entry_at(repo, commit.tree_sha, "feature.txt")
{:ok, bytes} = Repositories.get_blob_bytes(repo, entry.sha)
assert bytes =~ "replaced"
end
test "the new commit's parent is the old head", %{user: user, repo: repo, pr: pr} do
comment = suggest!(pr, user, 1, "```suggestion\nchild\n```")
{:ok, new_sha} = PullRequests.apply_suggestion(comment, user)
{:ok, commit} = Repositories.get_commit(repo, new_sha)
assert Git.to_hex(pr.head_sha) in Enum.map(commit.parent_shas || [], &Git.to_hex/1)
end
test "the PR row follows the branch", %{user: user, repo: repo, pr: pr} do
comment = suggest!(pr, user, 1, "```suggestion\nmoved\n```")
{:ok, new_sha} = PullRequests.apply_suggestion(comment, user)
assert PullRequests.get_pull_request!(repo, pr.number).head_sha == new_sha
end
test "someone without write access is refused", %{user: user, pr: pr} do
comment = suggest!(pr, user, 1, "```suggestion\nnope\n```")
outsider = user_fixture()
assert {:error, :forbidden} = PullRequests.apply_suggestion(comment, outsider)
end
test "a plain comment isn't applyable", %{user: user, pr: pr} do
comment = suggest!(pr, user, 1, "just a remark")
assert {:error, :not_a_suggestion} = PullRequests.apply_suggestion(comment, user)
end
test "a suggestion written against an older head is stale", %{user: user, repo: repo, pr: pr} do
comment = suggest!(pr, user, 1, "```suggestion\ntoo late\n```")
# Someone pushes; the line this named may not be that line now.
advance_branch(repo, "feature", user)
assert {:error, :stale} = PullRequests.apply_suggestion(comment, user)
end
test "a line past the end of the file is refused", %{user: user, pr: pr} do
comment = suggest!(pr, user, 999, "```suggestion\nnowhere\n```")
assert {:error, :out_of_range} = PullRequests.apply_suggestion(comment, user)
end
test "a closed PR can't take suggestions", %{user: user, pr: pr} do
comment = suggest!(pr, user, 1, "```suggestion\nclosed\n```")
{:ok, _} = PullRequests.set_state(pr, "closed")
assert {:error, :closed} = PullRequests.apply_suggestion(comment, user)
end
test "applying twice in a row is refused as stale", %{user: user, pr: pr} do
one = suggest!(pr, user, 1, "```suggestion\nfirst\n```")
two = suggest!(pr, user, 1, "```suggestion\nsecond\n```")
assert {:ok, _} = PullRequests.apply_suggestion(one, user)
# The branch moved under it, so the second no longer means what it said.
assert {:error, :stale} = PullRequests.apply_suggestion(two, user)
end
end
end
neiam /gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Packages
⭐
Log in to mark this repository.
5.5 KiB · text
History
51deb4e