// SPDX-License-Identifier: AGPL-3.0-or-later
package web
import (
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"bnema.dev/ermite/internal/domain"
)
const (
sshFP = "SHA256:abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG"
gpgFP = "0123456789ABCDEF0123456789ABCDEF01234567"
)
func verification(f domain.SignatureFormat, s domain.SignatureStatus, fp, title string) domain.CommitVerification {
return domain.CommitVerification{Format: f, Status: s, Fingerprint: fp, KeyTitle: title}
}
func TestSignatureBadge(t *testing.T) {
t.Parallel()
for _, tt := range []struct {
name string
v domain.CommitVerification
long bool
nilBadge bool
proto, label string
class, title string
}{
{name: "unchecked", v: domain.CommitVerification{}, nilBadge: true},
{name: "unchecked long", v: domain.CommitVerification{}, long: true, nilBadge: true},
{name: "unsigned in a list", v: verification("", domain.StatusUnsigned, "", ""), nilBadge: true},
{name: "unsigned on the page", v: verification("", domain.StatusUnsigned, "", ""), long: true, label: "unsigned", class: "sig-none"},
{name: "verified ssh", v: verification(domain.FormatSSH, domain.StatusVerified, sshFP, "laptop"),
proto: "SSH", label: "Verified", class: "sig-ok", title: "Signed with SSH key " + sshFP + " (laptop) — verified for the committer email"},
{name: "verified gpg", v: verification(domain.FormatGPG, domain.StatusVerified, gpgFP, ""),
proto: "GPG", label: "Verified", class: "sig-ok", title: "Signed with GPG key " + gpgFP + " — verified for the committer email"},
{name: "unknown key", v: verification(domain.FormatGPG, domain.StatusUnknownKey, gpgFP, ""),
proto: "GPG", label: "Unverified", class: "sig-warn", title: "Signed with an unknown GPG key " + gpgFP},
{name: "email mismatch", v: verification(domain.FormatSSH, domain.StatusEmailMismatch, sshFP, "laptop"),
proto: "SSH", label: "Unverified", class: "sig-warn", title: "this key is not trusted for the committer email"},
{name: "expired", v: verification(domain.FormatGPG, domain.StatusExpired, gpgFP, ""),
proto: "GPG", label: "Unverified", class: "sig-warn", title: "expired"},
{name: "revoked", v: verification(domain.FormatGPG, domain.StatusRevoked, gpgFP, ""),
proto: "GPG", label: "Unverified", class: "sig-warn", title: "revoked"},
{name: "bad signature", v: verification(domain.FormatSSH, domain.StatusBadSignature, "", ""),
proto: "SSH", label: "Bad signature", class: "sig-bad", title: "The signature does not match the commit"},
{name: "x509", v: verification(domain.FormatX509, domain.StatusUnsupported, "", ""),
proto: "X.509", label: "Unverified", class: "sig-warn", title: "X.509 signatures are not checked"},
} {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
b := signatureBadge(tt.v, tt.long)
if tt.nilBadge {
assert.Nil(t, b)
return
}
require.NotNil(t, b)
assert.Equal(t, tt.proto, b.Proto)
assert.Equal(t, tt.label, b.Label)
assert.Equal(t, tt.class, b.Class)
assert.Contains(t, b.Title, tt.title)
})
}
}
func rowOf(v domain.CommitVerification) CommitRow {
id := objectID(&testing.T{}, "0123456789abcdef0123456789abcdef01234567")
return commitRow("demo", domain.Commit{
ID: id, Summary: "s", Verification: v,
Author: domain.Signature{Name: "A"}, Committer: domain.Signature{Time: time.Unix(1, 0)},
}, time.Unix(100, 0))
}
func TestCommitRowsShowTheSignatureBadge(t *testing.T) {
t.Parallel()
for _, tt := range []struct {
name string
v domain.CommitVerification
want []string
none bool
}{
{name: "ssh verified", v: verification(domain.FormatSSH, domain.StatusVerified, sshFP, "laptop"),
want: []string{`class="pill sig sig-ok"`, `SSH Verified`, `title="Signed with SSH key ` + sshFP}},
{name: "gpg verified", v: verification(domain.FormatGPG, domain.StatusVerified, gpgFP, ""),
want: []string{`class="pill sig sig-ok"`, `GPG Verified`}},
{name: "unknown key", v: verification(domain.FormatGPG, domain.StatusUnknownKey, gpgFP, ""),
want: []string{`class="pill sig sig-warn"`, `GPG Unverified`, `unknown GPG key`}},
{name: "bad signature", v: verification(domain.FormatSSH, domain.StatusBadSignature, "", ""),
want: []string{`class="pill sig sig-bad"`, `SSH Bad signature`}},
{name: "unsigned", v: verification("", domain.StatusUnsigned, "", ""), none: true},
{name: "unchecked", v: domain.CommitVerification{}, none: true},
} {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := renderToString(t, CommitRows([]CommitRow{rowOf(tt.v)}))
if tt.none {
assert.NotContains(t, got, "sig")
assert.NotContains(t, got, "unsigned")
return
}
for _, w := range tt.want {
assert.Contains(t, got, w)
}
})
}
}
func TestCommitPageShowsTheSignature(t *testing.T) {
t.Parallel()
page := func(v domain.CommitVerification) string {
return renderToString(t, Commit(Layout{Repo: "demo"}, CommitPage{
SHA: "0123456789abcdef0123456789abcdef01234567", Short: "0123456", Subject: "s",
Sig: signatureBadge(v, true), Verification: v,
}))
}
got := page(verification(domain.FormatSSH, domain.StatusVerified, sshFP, "my "))
assert.Contains(t, got, "signature")
assert.Contains(t, got, `SSH Verified`)
assert.Contains(t, got, ""+sshFP+"")
assert.Contains(t, got, "my <laptop>")
got = page(verification(domain.FormatGPG, domain.StatusUnknownKey, gpgFP, ""))
assert.Contains(t, got, `sig-warn`)
assert.Contains(t, got, ""+gpgFP+"")
assert.Contains(t, got, `Signed with an unknown GPG key `+gpgFP+``, "the reason is text, not only a tooltip")
got = page(verification("", domain.StatusUnsigned, "", ""))
assert.Contains(t, got, "signature")
assert.Contains(t, got, "sig-none")
assert.Contains(t, got, "unsigned")
assert.NotContains(t, got, "")
assert.NotContains(t, got, "sig-why")
got = page(domain.CommitVerification{})
assert.NotContains(t, got, "signature")
}
func TestMergeRequestCommitsShowTheSignatureBadge(t *testing.T) {
t.Parallel()
signed := signatureBadge(verification(domain.FormatGPG, domain.StatusVerified, gpgFP, ""), false)
got := renderToString(t, mrRail(MRPage{Commits: []MRCommit{
{Short: "aaaaaaa", Href: "/r/commit/a", Subject: "signed", Sig: signed},
{Short: "bbbbbbb", Href: "/r/commit/b", Subject: "unsigned"},
}}))
assert.Equal(t, 1, strings.Count(got, `class="pill sig sig-ok"`), "only the signed commit has a pill")
assert.Contains(t, got, `GPG Verified`)
}