- Introduced new endpoints for contact discovery, including scanning, listing, and managing discovered contacts. - Implemented retry logic for handling missing DAV credentials during contact operations. - Added public share functionality for drive API, allowing users to manage public shares, including upload, delete, and rename operations. - Updated Nextcloud configuration to support public share links and improved error handling for public share permissions. - Enhanced logging and validation across contact and drive APIs for better error tracking and user feedback. - Added tests for new contact matching and ranking functionalities to ensure accuracy and reliability.
116 lines
3.0 KiB
Go
116 lines
3.0 KiB
Go
package discovery
|
|
|
|
import "testing"
|
|
|
|
func TestIsNoReplyEmail(t *testing.T) {
|
|
cases := []struct {
|
|
email string
|
|
want bool
|
|
}{
|
|
{"noreply@uber.com", true},
|
|
{"no-reply@zoom.us", true},
|
|
{"user@users.noreply.github.com", true},
|
|
{"alice@corp.com", false},
|
|
{"john.doe@company.com", false},
|
|
}
|
|
for _, tc := range cases {
|
|
if got := isNoReplyEmail(tc.email); got != tc.want {
|
|
t.Fatalf("isNoReplyEmail(%q) = %v, want %v", tc.email, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestClassifyAddressNoReply(t *testing.T) {
|
|
isML, _, _, reason := classifyAddress(&addressAgg{Email: "noreply@github.com"})
|
|
if !isML {
|
|
t.Fatal("expected noreply address to be classified as non-suggestable")
|
|
}
|
|
if !contains(reason, "no-reply") {
|
|
t.Fatalf("expected no-reply in reason, got %q", reason)
|
|
}
|
|
}
|
|
|
|
func TestIsMailingListDomain(t *testing.T) {
|
|
if !isMailingListDomain("sendgrid.net") {
|
|
t.Fatal("expected sendgrid.net to be mailing list")
|
|
}
|
|
if !isMailingListDomain("mail.example.sendgrid.net") {
|
|
t.Fatal("expected subdomain of sendgrid")
|
|
}
|
|
if isMailingListDomain("gmail.com") {
|
|
t.Fatal("gmail.com should not be mailing list")
|
|
}
|
|
}
|
|
|
|
func TestClassifyAddressMailingListRatio(t *testing.T) {
|
|
isML, _, _, _ := classifyAddress(&addressAgg{
|
|
Email: "news@company.com",
|
|
MessageCount: 10,
|
|
ListUnsub: 6,
|
|
})
|
|
if !isML {
|
|
t.Fatal("expected majority list-unsubscribe signals to flag mailing list")
|
|
}
|
|
}
|
|
|
|
func TestClassifyAddressSpamHeavyRatio(t *testing.T) {
|
|
_, _, isSpam, _ := classifyAddress(&addressAgg{
|
|
Email: "spammer@evil.com",
|
|
MessageCount: 4,
|
|
SpamCount: 2,
|
|
})
|
|
if !isSpam {
|
|
t.Fatal("expected 50% spam ratio with min 3 messages")
|
|
}
|
|
}
|
|
|
|
func TestCompanyNamesMatch(t *testing.T) {
|
|
if !companyNamesMatch("Acme Inc", "acme inc") {
|
|
t.Fatal("expected case-insensitive company match")
|
|
}
|
|
if companyNamesMatch("Acme", "Globex") {
|
|
t.Fatal("expected different companies not to match")
|
|
}
|
|
}
|
|
|
|
func TestIsDisposableDomain(t *testing.T) {
|
|
if !isDisposableDomain("yopmail.com") {
|
|
t.Fatal("expected yopmail to be disposable")
|
|
}
|
|
if isDisposableDomain("company.com") {
|
|
t.Fatal("company.com should not be disposable")
|
|
}
|
|
}
|
|
|
|
func TestExtractSignature(t *testing.T) {
|
|
body := "Hello there\n\n--\nJohn Doe\nCEO · Acme Inc\n+33 1 23 45 67 89"
|
|
text, conf := extractSignature(body, "", "john@acme.com", "John Doe")
|
|
if text == "" || conf < 0.5 {
|
|
t.Fatalf("expected signature, got %q conf=%v", text, conf)
|
|
}
|
|
if !contains(text, "John Doe") {
|
|
t.Fatalf("expected name in signature: %q", text)
|
|
}
|
|
}
|
|
|
|
func TestDetectForwardedAddresses(t *testing.T) {
|
|
body := "---------- Forwarded message ---------\nFrom: Alice <alice@example.com>\nSubject: Hi"
|
|
addrs := detectForwardedAddresses(body, "")
|
|
if len(addrs) != 1 || addrs[0] != "alice@example.com" {
|
|
t.Fatalf("unexpected forwarded addrs: %v", addrs)
|
|
}
|
|
}
|
|
|
|
func contains(s, sub string) bool {
|
|
return len(s) >= len(sub) && (s == sub || len(sub) == 0 || indexOf(s, sub) >= 0)
|
|
}
|
|
|
|
func indexOf(s, sub string) int {
|
|
for i := 0; i+len(sub) <= len(s); i++ {
|
|
if s[i:i+len(sub)] == sub {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|