package classes import "testing" // TestHandle: generator charset is a subset of MentionParser, uniqueness // uses the smallest free integer suffix, and short names fall back to user{id}. func TestHandle(t *testing.T) { t.Parallel() g := HandleGenerator{} if got := g.Slug("Paweł"); got != "pawel" { t.Fatalf("slug Paweł = %q, want pawel", got) } if got := g.Slug("John Doe"); got != "johndoe" { t.Fatalf("slug John Doe = %q, want johndoe", got) } if got := g.Slug("Zoë"); got != "zoe" { t.Fatalf("slug Zoë = %q, want zoe", got) } handle := g.Generate("James", func(string) bool { return false }, nil) if handle != "james" { t.Fatalf("generate James = %q, want james", handle) } if !validHandle(handle) { t.Fatalf("generated %q is outside [a-z0-9._-]{2,255}", handle) } taken := map[string]struct{}{} isTaken := func(c string) bool { _, ok := taken[c] return ok } first := g.Generate("James", isTaken, nil) taken[first] = struct{}{} second := g.Generate("James", isTaken, nil) taken[second] = struct{}{} third := g.Generate("James", isTaken, nil) if first != "james" || second != "james1" || third != "james2" { t.Fatalf("suffixes = %q %q %q, want james james1 james2", first, second, third) } id := uint(42) if got := g.Generate("", func(string) bool { return false }, &id); got != "user42" { t.Fatalf("empty name = %q, want user42", got) } if got := g.Generate("x", func(string) bool { return false }, &id); got != "user42" { t.Fatalf("short name = %q, want user42", got) } if got := g.Generate("???", func(string) bool { return false }, &id); got != "user42" { t.Fatalf("punctuation name = %q, want user42", got) } if got := g.Generate("", func(string) bool { return false }, nil); got != "user" { t.Fatalf("no id = %q, want user", got) } names := []string{"James", "Paweł", "John Doe", "???", "a", "Zoë", " ", "....", "O'Brien"} for _, name := range names { got := g.Generate(name, func(string) bool { return false }, &id) if !validHandle(got) { t.Errorf("generated %q for %q is outside the MentionParser subset", got, name) } } } func validHandle(s string) bool { if len(s) < 2 || len(s) > 255 { return false } for _, r := range s { switch { case r >= 'a' && r <= 'z', r >= '0' && r <= '9', r == '.', r == '_', r == '-': default: return false } } return true }