120 lines
3.0 KiB
Go
120 lines
3.0 KiB
Go
package user
|
|
|
|
import "testing"
|
|
|
|
func TestSanitizeForUsername(t *testing.T) {
|
|
cases := []struct {
|
|
in, want string
|
|
}{
|
|
{"alice", "alice"},
|
|
{"Alice", "alice"},
|
|
{" Alice ", "alice"},
|
|
{"Alice Bob", "alice_bob"},
|
|
{"alice bob", "alice_bob"},
|
|
{"Alice!@#Bob", "alice_bob"},
|
|
{"-alice", "alice"},
|
|
{"_alice", "alice"},
|
|
{"alice_", "alice"},
|
|
{"alice--bob", "alice-bob"},
|
|
{"alice__bob", "alice_bob"},
|
|
{" ", ""},
|
|
{"", ""},
|
|
{"!!!", ""},
|
|
{"日本語", ""},
|
|
{"alice日本", "alice"},
|
|
{"thisusernameiswaytoolongtobevalid12345", "thisusernameiswaytoolongtobeva"},
|
|
}
|
|
for _, tc := range cases {
|
|
got := SanitizeForUsername(tc.in)
|
|
if got != tc.want {
|
|
t.Errorf("SanitizeForUsername(%q) = %q, want %q", tc.in, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSanitizeForUsernamePassesValidate(t *testing.T) {
|
|
inputs := []string{"Alice Bob", " S0me User! ", "alice--bob"}
|
|
for _, in := range inputs {
|
|
s := SanitizeForUsername(in)
|
|
if s == "" {
|
|
t.Fatalf("unexpected empty sanitize for %q", in)
|
|
}
|
|
if err := ValidateUsername(s, nil); err != nil {
|
|
t.Errorf("sanitized %q -> %q failed ValidateUsername: %v", in, s, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCandidateFromMetadataPrecedence(t *testing.T) {
|
|
const domain = "azzamo.net"
|
|
reserved := []string{"admin"}
|
|
|
|
cases := []struct {
|
|
desc string
|
|
name, dn, dnAlt, username, nip05, dom string
|
|
want string
|
|
}{
|
|
{
|
|
desc: "nip05 local part wins when domain matches",
|
|
name: "alice", nip05: "preferred@azzamo.net", dom: domain,
|
|
want: "preferred",
|
|
},
|
|
{
|
|
desc: "nip05 ignored when domain differs",
|
|
name: "alice", nip05: "preferred@other.example", dom: domain,
|
|
want: "alice",
|
|
},
|
|
{
|
|
desc: "name takes precedence over display_name",
|
|
name: "alice", dn: "Bob Builder", dom: domain,
|
|
want: "alice",
|
|
},
|
|
{
|
|
desc: "falls back to display_name when name empty",
|
|
dn: "Bob Builder", dom: domain,
|
|
want: "bob_builder",
|
|
},
|
|
{
|
|
desc: "falls back to camelCase displayName when others empty",
|
|
dnAlt: "Bob B", dom: domain,
|
|
want: "bob_b",
|
|
},
|
|
{
|
|
desc: "falls back to deprecated username last",
|
|
username: "legacy_user", dom: domain,
|
|
want: "legacy_user",
|
|
},
|
|
{
|
|
desc: "skips fields that sanitize to empty",
|
|
name: "!!!", dn: "Real Name", dom: domain,
|
|
want: "real_name",
|
|
},
|
|
{
|
|
desc: "skips reserved words and falls through",
|
|
name: "admin", dn: "Real Name", dom: domain,
|
|
want: "real_name",
|
|
},
|
|
{
|
|
desc: "no usable field returns empty",
|
|
name: "!!!", dom: domain,
|
|
want: "",
|
|
},
|
|
{
|
|
desc: "bare nip05 with no @ is ignored",
|
|
nip05: "alice", name: "fallback", dom: domain,
|
|
want: "fallback",
|
|
},
|
|
{
|
|
desc: "empty service domain ignores nip05",
|
|
name: "alice", nip05: "preferred@azzamo.net",
|
|
want: "alice",
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
got := CandidateFromMetadata(tc.name, tc.dn, tc.dnAlt, tc.username, tc.nip05, tc.dom, reserved)
|
|
if got != tc.want {
|
|
t.Errorf("%s: got %q want %q", tc.desc, got, tc.want)
|
|
}
|
|
}
|
|
}
|