package e2e
import (
"os"
"path/filepath"
"strings"
"testing"
)
// TestRepoFacts covers the repository summary: counts, license, languages,
// and contributors resolved to accounts where the email is verified.
func TestRepoFacts(t *testing.T) {
inst := startInstance(t)
aliceKey := inst.newKey(t, "alice")
inst.admin(t, "admin", "user", "create", "alice",
"--key", aliceKey+".pub", "--email", "alice@example.test", "--verified")
if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
t.Fatalf("repo create: %s", errOut)
}
work := t.TempDir()
env := inst.gitEnv(aliceKey)
aliceEnv := append(append([]string{}, env...),
"GIT_AUTHOR_NAME=Alice", "GIT_AUTHOR_EMAIL=alice@example.test")
mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
dir := filepath.Join(work, "w")
os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\n\nfunc main() {}\n"), 0o644)
os.WriteFile(filepath.Join(dir, "run.sh"), []byte("#!/bin/sh\necho hi\n"), 0o644)
os.WriteFile(filepath.Join(dir, "LICENSE"), []byte(zeroBSD), 0o644)
mustGit(t, dir, env, "checkout", "-q", "-b", "main")
mustGit(t, dir, env, "add", ".")
mustGit(t, dir, aliceEnv, "commit", "-q", "-m", "one")
// A second commit by someone with no account here.
os.WriteFile(filepath.Join(dir, "extra.go"), []byte("package main\n"), 0o644)
mustGit(t, dir, env, "add", ".")
mustGit(t, dir, env, "commit", "-q", "-m", "two")
mustGit(t, dir, env, "push", "-q", "origin", "main")
mustGit(t, dir, env, "tag", "v0.1.0")
mustGit(t, dir, env, "push", "-q", "origin", "v0.1.0")
status, body := inst.get(t, "/alice/app")
if status != 200 {
t.Fatalf("repo home: %d", status)
}
for _, want := range []string{
"2 commit", // both commits counted
"1 branch",
"1 tag",
"0BSD", // license detected and surfaced
"Go", // language census
"Shell", // and it is not single-language
"2 contributors",
} {
if !strings.Contains(body, want) {
t.Errorf("repo home missing %q", want)
}
}
// The contributor with a verified email links to their profile; the
// other is named without inventing an account for them.
if !strings.Contains(body, `href="/alice"`) {
t.Error("verified contributor not linked to their profile")
}
if strings.Contains(body, `href="/t"`) {
t.Error("unknown contributor linked to a profile that does not exist")
}
// Subdirectory listings are about the directory, not the repository.
mustGit(t, dir, env, "rm", "-q", "extra.go")
os.MkdirAll(filepath.Join(dir, "sub"), 0o755)
os.WriteFile(filepath.Join(dir, "sub", "x.go"), []byte("package sub\n"), 0o644)
mustGit(t, dir, env, "add", "-A")
mustGit(t, dir, env, "commit", "-q", "-m", "sub")
mustGit(t, dir, env, "push", "-q", "origin", "main")
if _, body := inst.get(t, "/alice/app/tree/main/sub"); strings.Contains(body, "contributor") {
t.Error("facts bar rendered on a subdirectory listing")
}
// A repository with no commits has no facts to state, and must still
// render — the empty case renders through the same page type.
if _, _, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/empty"); code != 0 {
t.Fatal("repo create failed")
}
if status, body := inst.get(t, "/alice/empty"); status != 200 {
t.Fatalf("empty repo home: %d", status)
} else if strings.Contains(body, "contributor") {
t.Error("empty repository claims contributors")
}
}
const zeroBSD = `Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
`