package handlers import ( "context" "net/http" "net/http/httptest" "runtime" "strings" "testing" "time" "github.com/stormlightlabs/noteleaf/internal/articles" "github.com/stormlightlabs/noteleaf/internal/models" "github.com/stormlightlabs/noteleaf/internal/repo" "github.com/stormlightlabs/noteleaf/internal/shared" ) func TestArticleHandler(t *testing.T) { t.Run("NewArticleHandler", func(t *testing.T) { t.Run("creates handler successfully", func(t *testing.T) { helper := NewArticleTestHelper(t) if helper.ArticleHandler == nil { t.Fatal("Handler should not be nil") } if helper.db == nil { t.Error("Handler database should not be nil") } if helper.config == nil { t.Error("Handler config should not be nil") } if helper.repos == nil { t.Error("Handler repos should not be nil") } if helper.parser == nil { t.Error("Handler parser should not be nil") } }) t.Run("handles database initialization error", func(t *testing.T) { envHelper := NewEnvironmentTestHelper() defer envHelper.RestoreEnv() if runtime.GOOS == "windows" { envHelper.UnsetEnv("APPDATA") } else { envHelper.UnsetEnv("XDG_CONFIG_HOME") envHelper.UnsetEnv("HOME") } _, err := NewArticleHandler() shared.AssertErrorContains(t, err, "failed to initialize database", "NewArticleHandler should fail when database initialization fails") }) }) t.Run("Add", func(t *testing.T) { t.Run("adds article successfully", func(t *testing.T) { helper := NewArticleTestHelper(t) ctx := context.Background() server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(`
This is test content for the article.
Content
")) })) defer server.Close() err := helper.Add(ctx, server.URL+"/unsupported") shared.AssertErrorContains(t, err, "failed to parse article", "Add should fail with unsupported domain") }) t.Run("handles HTTP error", func(t *testing.T) { helper := NewArticleTestHelper(t) ctx := context.Background() server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) })) defer server.Close() err := helper.Add(ctx, server.URL+"/404") shared.AssertErrorContains(t, err, "failed to parse article", "Add should fail with HTTP error") }) t.Run("handles storage directory error", func(t *testing.T) { helper := NewArticleTestHelper(t) ctx := context.Background() envHelper := NewEnvironmentTestHelper() defer envHelper.RestoreEnv() // Unset all environment variables that could provide a storage directory envHelper.UnsetEnv("NOTELEAF_DATA_DIR") envHelper.UnsetEnv("NOTELEAF_CONFIG") if runtime.GOOS == "windows" { envHelper.UnsetEnv("USERPROFILE") envHelper.UnsetEnv("HOMEDRIVE") envHelper.UnsetEnv("HOMEPATH") envHelper.UnsetEnv("LOCALAPPDATA") } else { envHelper.UnsetEnv("HOME") envHelper.UnsetEnv("XDG_DATA_HOME") } err := helper.Add(ctx, "https://example.com/test-article") shared.AssertErrorContains(t, err, "failed to get article storage dir", "Add should fail when storage directory cannot be determined") }) t.Run("handles database save error", func(t *testing.T) { helper := NewArticleTestHelper(t) ctx := context.Background() server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(`Integration test content.