config_test.go

  1package config
  2
  3import (
  4	"reflect"
  5	"testing"
  6)
  7
  8// TestSaveAndLoadConfig verifies that the config can be saved to and loaded from a file correctly.
  9func TestSaveAndLoadConfig(t *testing.T) {
 10	// Create a temporary directory for the test to avoid interfering with actual user config.
 11	tempDir := t.TempDir()
 12
 13	// Temporarily override the user home directory to our temp directory.
 14	// This ensures that our config file is written to a predictable, temporary location.
 15	t.Setenv("HOME", tempDir)
 16
 17	// Define a sample configuration to save with multiple accounts.
 18	expectedConfig := &Config{
 19		Accounts: []Account{
 20			{
 21				ID:              "test-id-1",
 22				Name:            "Test User",
 23				Email:           "test@example.com",
 24				Password:        "supersecret",
 25				ServiceProvider: "gmail",
 26			},
 27			{
 28				ID:              "test-id-2",
 29				Name:            "Custom User",
 30				Email:           "custom@example.com",
 31				Password:        "customsecret",
 32				ServiceProvider: "custom",
 33				IMAPServer:      "imap.custom.com",
 34				IMAPPort:        993,
 35				SMTPServer:      "smtp.custom.com",
 36				SMTPPort:        587,
 37			},
 38		},
 39	}
 40
 41	// Attempt to save the configuration.
 42	err := SaveConfig(expectedConfig)
 43	if err != nil {
 44		t.Fatalf("SaveConfig() failed: %v", err)
 45	}
 46
 47	// Attempt to load the configuration back.
 48	loadedConfig, err := LoadConfig()
 49	if err != nil {
 50		t.Fatalf("LoadConfig() failed: %v", err)
 51	}
 52
 53	// Compare the loaded configuration with the original one.
 54	// reflect.DeepEqual is used for a deep comparison of the structs.
 55	if !reflect.DeepEqual(loadedConfig, expectedConfig) {
 56		t.Errorf("Loaded config does not match expected config.\nGot:  %+v\nWant: %+v", loadedConfig, expectedConfig)
 57	}
 58}
 59
 60// TestAccountGetIMAPServer tests the logic that determines the IMAP server address.
 61func TestAccountGetIMAPServer(t *testing.T) {
 62	testCases := []struct {
 63		name    string
 64		account Account
 65		want    string
 66	}{
 67		{"Gmail", Account{ServiceProvider: "gmail"}, "imap.gmail.com"},
 68		{"iCloud", Account{ServiceProvider: "icloud"}, "imap.mail.me.com"},
 69		{"Custom", Account{ServiceProvider: "custom", IMAPServer: "imap.custom.com"}, "imap.custom.com"},
 70		{"Unsupported", Account{ServiceProvider: "yahoo"}, ""},
 71		{"Empty", Account{ServiceProvider: ""}, ""},
 72	}
 73
 74	for _, tc := range testCases {
 75		t.Run(tc.name, func(t *testing.T) {
 76			got := tc.account.GetIMAPServer()
 77			if got != tc.want {
 78				t.Errorf("GetIMAPServer() = %q, want %q", got, tc.want)
 79			}
 80		})
 81	}
 82}
 83
 84// TestAccountGetSMTPServer tests the logic that determines the SMTP server address.
 85func TestAccountGetSMTPServer(t *testing.T) {
 86	testCases := []struct {
 87		name    string
 88		account Account
 89		want    string
 90	}{
 91		{"Gmail", Account{ServiceProvider: "gmail"}, "smtp.gmail.com"},
 92		{"iCloud", Account{ServiceProvider: "icloud"}, "smtp.mail.me.com"},
 93		{"Custom", Account{ServiceProvider: "custom", SMTPServer: "smtp.custom.com"}, "smtp.custom.com"},
 94		{"Unsupported", Account{ServiceProvider: "yahoo"}, ""},
 95		{"Empty", Account{ServiceProvider: ""}, ""},
 96	}
 97
 98	for _, tc := range testCases {
 99		t.Run(tc.name, func(t *testing.T) {
100			got := tc.account.GetSMTPServer()
101			if got != tc.want {
102				t.Errorf("GetSMTPServer() = %q, want %q", got, tc.want)
103			}
104		})
105	}
106}
107
108// TestConfigAddRemoveAccount tests adding and removing accounts from config.
109func TestConfigAddRemoveAccount(t *testing.T) {
110	cfg := &Config{}
111
112	// Add an account
113	account := Account{
114		Name:            "Test",
115		Email:           "test@example.com",
116		ServiceProvider: "gmail",
117	}
118	cfg.AddAccount(account)
119
120	if len(cfg.Accounts) != 1 {
121		t.Fatalf("Expected 1 account, got %d", len(cfg.Accounts))
122	}
123
124	// Check that ID was auto-generated
125	if cfg.Accounts[0].ID == "" {
126		t.Error("Expected account ID to be auto-generated")
127	}
128
129	// Remove the account
130	accountID := cfg.Accounts[0].ID
131	removed := cfg.RemoveAccount(accountID)
132	if !removed {
133		t.Error("RemoveAccount should return true when account exists")
134	}
135
136	if len(cfg.Accounts) != 0 {
137		t.Fatalf("Expected 0 accounts after removal, got %d", len(cfg.Accounts))
138	}
139
140	// Try to remove non-existent account
141	removed = cfg.RemoveAccount("non-existent")
142	if removed {
143		t.Error("RemoveAccount should return false for non-existent account")
144	}
145}
146
147// TestConfigGetAccountByID tests retrieving accounts by ID.
148func TestConfigGetAccountByID(t *testing.T) {
149	cfg := &Config{
150		Accounts: []Account{
151			{ID: "id-1", Email: "test1@example.com"},
152			{ID: "id-2", Email: "test2@example.com"},
153		},
154	}
155
156	account := cfg.GetAccountByID("id-1")
157	if account == nil {
158		t.Fatal("Expected to find account with id-1")
159	}
160	if account.Email != "test1@example.com" {
161		t.Errorf("Expected email test1@example.com, got %s", account.Email)
162	}
163
164	// Non-existent ID
165	account = cfg.GetAccountByID("non-existent")
166	if account != nil {
167		t.Error("Expected nil for non-existent account ID")
168	}
169}
170
171// TestConfigGetAccountByEmail tests retrieving accounts by email.
172func TestConfigGetAccountByEmail(t *testing.T) {
173	cfg := &Config{
174		Accounts: []Account{
175			{ID: "id-1", Email: "test1@example.com"},
176			{ID: "id-2", Email: "test2@example.com"},
177		},
178	}
179
180	account := cfg.GetAccountByEmail("test2@example.com")
181	if account == nil {
182		t.Fatal("Expected to find account with test2@example.com")
183	}
184	if account.ID != "id-2" {
185		t.Errorf("Expected ID id-2, got %s", account.ID)
186	}
187
188	// Non-existent email
189	account = cfg.GetAccountByEmail("nonexistent@example.com")
190	if account != nil {
191		t.Error("Expected nil for non-existent account email")
192	}
193}
194
195// TestConfigHasAccounts tests the HasAccounts method.
196func TestConfigHasAccounts(t *testing.T) {
197	cfg := &Config{}
198	if cfg.HasAccounts() {
199		t.Error("Expected HasAccounts to return false for empty config")
200	}
201
202	cfg.AddAccount(Account{Email: "test@example.com"})
203	if !cfg.HasAccounts() {
204		t.Error("Expected HasAccounts to return true after adding account")
205	}
206}
207
208// TestAccountGetPorts tests the port retrieval methods.
209func TestAccountGetPorts(t *testing.T) {
210	// Gmail account should use default ports
211	gmailAccount := Account{ServiceProvider: "gmail"}
212	if gmailAccount.GetIMAPPort() != 993 {
213		t.Errorf("Expected Gmail IMAP port 993, got %d", gmailAccount.GetIMAPPort())
214	}
215	if gmailAccount.GetSMTPPort() != 587 {
216		t.Errorf("Expected Gmail SMTP port 587, got %d", gmailAccount.GetSMTPPort())
217	}
218
219	// Custom account with custom ports
220	customAccount := Account{
221		ServiceProvider: "custom",
222		IMAPPort:        1993,
223		SMTPPort:        1587,
224	}
225	if customAccount.GetIMAPPort() != 1993 {
226		t.Errorf("Expected custom IMAP port 1993, got %d", customAccount.GetIMAPPort())
227	}
228	if customAccount.GetSMTPPort() != 1587 {
229		t.Errorf("Expected custom SMTP port 1587, got %d", customAccount.GetSMTPPort())
230	}
231
232	// Custom account with default ports (0 means use default)
233	customDefaultAccount := Account{ServiceProvider: "custom"}
234	if customDefaultAccount.GetIMAPPort() != 993 {
235		t.Errorf("Expected default IMAP port 993 for custom with no port, got %d", customDefaultAccount.GetIMAPPort())
236	}
237	if customDefaultAccount.GetSMTPPort() != 587 {
238		t.Errorf("Expected default SMTP port 587 for custom with no port, got %d", customDefaultAccount.GetSMTPPort())
239	}
240}