package main import ( "bytes" "io" "net/http" "net/http/httptest" "os" "path/filepath" "testing" "github.com/evanreichard/markdown-editor/internal/api" "github.com/evanreichard/markdown-editor/internal/logger" "github.com/gorilla/mux" "github.com/stretchr/testify/assert" ) func setupTestDir() (string, error) { tmpDir := filepath.Join(os.TempDir(), "markdown-editor-test-"+randomString(10)) if err := os.MkdirAll(tmpDir, 0755); err != nil { return "", err } return tmpDir, nil } func cleanupTestDir(dir string) { os.RemoveAll(dir) } func randomString(n int) string { const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" b := make([]byte, n) for i := range b { b[i] = letters[i%len(letters)] } return string(b) } func TestCRUDOperations(t *testing.T) { dataDir, err := setupTestDir() if err != nil { t.Fatalf("Failed to create test dir: %v", err) } defer cleanupTestDir(dataDir) log := logger.NewLogger() handler := api.NewAPIHandler(dataDir, log) router := mux.NewRouter() router.Handle("/api/{filename:.+\\.md}", handler) testContent := "# Test Content\n\nThis is a test." // Test POST (Create) req := httptest.NewRequest("POST", "/api/test.md", bytes.NewBufferString(testContent)) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusCreated, w.Code) // Test GET (Read) req = httptest.NewRequest("GET", "/api/test.md", nil) w = httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) body, _ := io.ReadAll(w.Body) assert.Equal(t, testContent, string(body)) // Test PUT (Update) updatedContent := "# Updated Content\n\nThis has been updated." req = httptest.NewRequest("PUT", "/api/test.md", bytes.NewBufferString(updatedContent)) w = httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) // Verify update req = httptest.NewRequest("GET", "/api/test.md", nil) w = httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) body, _ = io.ReadAll(w.Body) assert.Equal(t, updatedContent, string(body)) // Test DELETE req = httptest.NewRequest("DELETE", "/api/test.md", nil) w = httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusNoContent, w.Code) // Verify deletion req = httptest.NewRequest("GET", "/api/test.md", nil) w = httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusNotFound, w.Code) } func TestStaticAssetServing(t *testing.T) { dataDir, err := setupTestDir() if err != nil { t.Fatalf("Failed to create test dir: %v", err) } defer cleanupTestDir(dataDir) // Test that FileServer can serve files fs := http.FileServer(http.Dir(dataDir)) // Create a test HTML file testHTML := `Test

Hello

` testPath := filepath.Join(dataDir, "index.html") if err := os.WriteFile(testPath, []byte(testHTML), 0644); err != nil { t.Fatalf("Failed to create test HTML: %v", err) } // Verify file was created content, err := os.ReadFile(testPath) if err != nil { t.Fatalf("Failed to read test HTML: %v", err) } assert.Equal(t, testHTML, string(content)) // Test serving static file - just verify it doesn't error req := httptest.NewRequest("GET", "/index.html/", nil) w := httptest.NewRecorder() fs.ServeHTTP(w, req) // FileServer may redirect, but we just verify it doesn't panic assert.NotEqual(t, http.StatusNotFound, w.Code) }