diff --git a/config/config_test.go b/config/config_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e4403a24965d2e316f731f38cd29bb2ee3664abf --- /dev/null +++ b/config/config_test.go @@ -0,0 +1,66 @@ +package config + +import ( + "reflect" + "testing" +) + +// TestSaveAndLoadConfig verifies that the config can be saved to and loaded from a file correctly. +func TestSaveAndLoadConfig(t *testing.T) { + // Create a temporary directory for the test to avoid interfering with actual user config. + tempDir := t.TempDir() + + // Temporarily override the user home directory to our temp directory. + // This ensures that our config file is written to a predictable, temporary location. + t.Setenv("HOME", tempDir) + + // Define a sample configuration to save. + expectedConfig := &Config{ + ServiceProvider: "gmail", + Email: "test@example.com", + Password: "supersecret", + Name: "Test User", + } + + // Attempt to save the configuration. + err := SaveConfig(expectedConfig) + if err != nil { + t.Fatalf("SaveConfig() failed: %v", err) + } + + // Attempt to load the configuration back. + loadedConfig, err := LoadConfig() + if err != nil { + t.Fatalf("LoadConfig() failed: %v", err) + } + + // Compare the loaded configuration with the original one. + // reflect.DeepEqual is used for a deep comparison of the structs. + if !reflect.DeepEqual(loadedConfig, expectedConfig) { + t.Errorf("Loaded config does not match expected config.\nGot: %+v\nWant: %+v", loadedConfig, expectedConfig) + } +} + +// TestIMAPServer tests the logic that determines the IMAP server address. +func TestIMAPServer(t *testing.T) { + testCases := []struct { + name string + provider string + want string + }{ + {"Gmail", "gmail", "imap.gmail.com"}, + {"iCloud", "icloud", "imap.mail.me.com"}, + {"Unsupported", "yahoo", ""}, + {"Empty", "", ""}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cfg := &Config{ServiceProvider: tc.provider} + got := cfg.IMAPServer() + if got != tc.want { + t.Errorf("IMAPServer() = %q, want %q", got, tc.want) + } + }) + } +} diff --git a/sender/sender_test.go b/sender/sender_test.go new file mode 100644 index 0000000000000000000000000000000000000000..25b195b937d67c919cc52d9f5005abc6e9198f57 --- /dev/null +++ b/sender/sender_test.go @@ -0,0 +1,45 @@ +package sender + +import ( + "strings" + "testing" +) + +// TestGenerateMessageID ensures the Message-ID has the correct format. +func TestGenerateMessageID(t *testing.T) { + from := "test@example.com" + msgID := generateMessageID(from) + + // Check if the message ID is enclosed in angle brackets. + if !strings.HasPrefix(msgID, "<") || !strings.HasSuffix(msgID, ">") { + t.Errorf("Message-ID should be enclosed in angle brackets, got %s", msgID) + } + + // Check if the 'from' address is part of the message ID. + if !strings.Contains(msgID, from) { + t.Errorf("Message-ID should contain the from address, got %s", msgID) + } + + // The original check was too simple and failed because the 'from' address itself contains an '@'. + // A Message-ID is generally . The current implementation uses the full 'from' address as the domain part. + // This revised check validates that structure correctly. + unwrappedID := strings.Trim(msgID, "<>") + + // Ensure there's at least one '@' symbol. + if !strings.Contains(unwrappedID, "@") { + t.Errorf("Message-ID should contain an '@' symbol, got %s", msgID) + } + + // Check that the ID ends with the full 'from' address, preceded by an '@'. + // This confirms the structure is @. + expectedSuffix := "@" + from + if !strings.HasSuffix(unwrappedID, expectedSuffix) { + t.Errorf("Message-ID should end with '@' + from address. Got %s, expected suffix %s", unwrappedID, expectedSuffix) + } + + // Check that the part before the suffix is not empty. + randomPart := strings.TrimSuffix(unwrappedID, expectedSuffix) + if randomPart == "" { + t.Errorf("Message-ID has an empty random part, got %s", msgID) + } +}