Change summary
config/cache.go | 9 +++++++--
config/config_test.go | 28 ++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 2 deletions(-)
Detailed changes
@@ -148,13 +148,17 @@ func LoadContactsCache() (*ContactsCache, error) {
return &cache, nil
}
+func normalizeContactEmail(email string) string {
+ return strings.ToLower(strings.Trim(strings.TrimSpace(email), ","))
+}
+
// AddContact adds or updates a contact in the cache.
func AddContact(name, email string) error {
if email == "" {
return nil
}
- email = strings.ToLower(strings.Trim(strings.TrimSpace(email), ","))
+ email = normalizeContactEmail(email)
name = strings.TrimSpace(name)
cache, err := LoadContactsCache()
@@ -166,7 +170,8 @@ func AddContact(name, email string) error {
found := false
for i, c := range cache.Contacts {
if strings.EqualFold(c.Email, email) {
- // Update existing contact
+ // Normalize the stored email to a canonical lowercase form.
+ cache.Contacts[i].Email = email
cache.Contacts[i].UseCount++
cache.Contacts[i].LastUsed = time.Now()
// Update name if we have a better one
@@ -201,6 +201,34 @@ func TestConfigGetAccountByEmail(t *testing.T) {
}
}
+func TestAddContactNormalizesEmailAndDeduplicates(t *testing.T) {
+ t.Setenv("HOME", t.TempDir())
+
+ if err := AddContact("Alice", "Alice@Example.com"); err != nil {
+ t.Fatalf("AddContact() failed: %v", err)
+ }
+ if err := AddContact("", "alice@example.com"); err != nil {
+ t.Fatalf("AddContact() failed: %v", err)
+ }
+
+ cache, err := LoadContactsCache()
+ if err != nil {
+ t.Fatalf("LoadContactsCache() failed: %v", err)
+ }
+
+ if len(cache.Contacts) != 1 {
+ t.Fatalf("Expected 1 contact after deduplication, got %d", len(cache.Contacts))
+ }
+
+ contact := cache.Contacts[0]
+ if contact.Email != "alice@example.com" {
+ t.Errorf("Expected normalized email alice@example.com, got %s", contact.Email)
+ }
+ if contact.UseCount != 2 {
+ t.Errorf("Expected UseCount 2 after duplicate add, got %d", contact.UseCount)
+ }
+}
+
// TestConfigHasAccounts tests the HasAccounts method.
func TestConfigHasAccounts(t *testing.T) {
cfg := &Config{}