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}