feat: add test files

drew created

Change summary

config/config_test.go | 66 +++++++++++++++++++++++++++++++++++++++++++++
sender/sender_test.go | 45 ++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+)

Detailed changes

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)
+			}
+		})
+	}
+}

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 <unique-part@domain>. 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 <random_part>@<from_address>.
+	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)
+	}
+}