defmodule GitGud.RepositoriesCommitterStatsTest do
use GitGud.DataCase, async: false
alias GitGud.Repo
alias GitGud.Repositories
alias GitGud.Repositories.GitCommit
alias GitGud.Repositories.GitCommitDiffstat
import GitGud.ForgeFixtures
defp insert_commit(rid, sha_hex, attrs) do
base = %{
repository_id: rid,
sha: hex(sha_hex),
tree_sha: hex(String.duplicate("0", 40)),
parent_shas: [],
author_name: "Alice",
author_email: "alice@example",
authored_at: ~U[2026-01-01 00:00:00Z],
committer_name: "Alice",
committer_email: "alice@example",
committed_at: ~U[2026-01-01 00:00:00Z],
message: "msg"
}
Repo.insert_all(GitCommit, [Map.merge(base, attrs)])
end
defp insert_diffstat(rid, sha_hex, insertions, deletions) do
Repo.insert_all(GitCommitDiffstat, [
%{
repository_id: rid,
sha: hex(sha_hex),
files_changed: 1,
insertions: insertions,
deletions: deletions,
paths: []
}
])
end
defp hex(s), do: Base.decode16!(s, case: :mixed)
setup do
{_user, repo} = repository_fixture()
{:ok, repo: repo}
end
test "groups by author_email, sorted by commits desc", %{repo: repo} do
insert_commit(repo.id, String.duplicate("1", 40), %{
author_email: "alice@example",
author_name: "Alice",
authored_at: ~U[2026-01-01 10:00:00Z]
})
insert_commit(repo.id, String.duplicate("2", 40), %{
author_email: "alice@example",
author_name: "Alice",
authored_at: ~U[2026-01-02 10:00:00Z]
})
insert_commit(repo.id, String.duplicate("3", 40), %{
author_email: "bob@example",
author_name: "Bob",
authored_at: ~U[2026-01-03 10:00:00Z]
})
assert [alice, bob] = Repositories.committer_stats(repo)
assert alice.email == "alice@example"
assert alice.commits == 2
assert bob.email == "bob@example"
assert bob.commits == 1
end
test "sums insertions + deletions via diffstats join", %{repo: repo} do
sha1 = String.duplicate("1", 40)
sha2 = String.duplicate("2", 40)
insert_commit(repo.id, sha1, %{author_email: "a@e", author_name: "A"})
insert_commit(repo.id, sha2, %{author_email: "a@e", author_name: "A"})
insert_diffstat(repo.id, sha1, 10, 3)
insert_diffstat(repo.id, sha2, 5, 1)
assert [%{insertions: 15, deletions: 4}] = Repositories.committer_stats(repo)
end
test "commits without diffstats still counted (zeros for churn)", %{repo: repo} do
insert_commit(repo.id, String.duplicate("1", 40), %{author_email: "a@e", author_name: "A"})
# No diffstat row.
assert [%{commits: 1, insertions: 0, deletions: 0}] = Repositories.committer_stats(repo)
end
test "first_at / last_at span all of the author's commits", %{repo: repo} do
insert_commit(repo.id, String.duplicate("1", 40), %{
author_email: "a@e",
authored_at: ~U[2026-01-01 00:00:00Z]
})
insert_commit(repo.id, String.duplicate("2", 40), %{
author_email: "a@e",
authored_at: ~U[2026-05-01 00:00:00Z]
})
insert_commit(repo.id, String.duplicate("3", 40), %{
author_email: "a@e",
authored_at: ~U[2026-03-01 00:00:00Z]
})
assert [%{first_at: ~U[2026-01-01 00:00:00Z], last_at: ~U[2026-05-01 00:00:00Z]}] =
Repositories.committer_stats(repo)
end
test "stats are scoped per repository", %{repo: repo} do
{_user2, other} = repository_fixture()
insert_commit(repo.id, String.duplicate("1", 40), %{author_email: "a@e"})
insert_commit(other.id, String.duplicate("2", 40), %{author_email: "b@e"})
assert [%{email: "a@e"}] = Repositories.committer_stats(repo)
assert [%{email: "b@e"}] = Repositories.committer_stats(other)
end
test "empty repo → []", %{repo: repo} do
assert [] = Repositories.committer_stats(repo)
end
end
3.8 KiB · text
5af55d9