From 5a6895ecdc95b7ffe677cfb8a55b3395bc3a6ccf Mon Sep 17 00:00:00 2001 From: LordMathis Date: Thu, 10 Jul 2025 22:02:03 +0200 Subject: [PATCH] Enhance integration tests with file upload functionality and support for multipart requests --- server/internal/db/testdb.go | 2 +- .../file_handlers_integration_test.go | 31 ++++++++++++ server/internal/handlers/integration_test.go | 47 ++++++++++++++++++- 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/server/internal/db/testdb.go b/server/internal/db/testdb.go index 201d3fe..0c5334b 100644 --- a/server/internal/db/testdb.go +++ b/server/internal/db/testdb.go @@ -1,4 +1,4 @@ -//go:build test +//go:build test || integration package db diff --git a/server/internal/handlers/file_handlers_integration_test.go b/server/internal/handlers/file_handlers_integration_test.go index ea94e31..edef78b 100644 --- a/server/internal/handlers/file_handlers_integration_test.go +++ b/server/internal/handlers/file_handlers_integration_test.go @@ -239,5 +239,36 @@ func testFileHandlers(t *testing.T, dbConfig DatabaseConfig) { }) } }) + + t.Run("upload file", func(t *testing.T) { + t.Run("successful upload", func(t *testing.T) { + fileName := "uploaded-test.txt" + fileContent := "This is an uploaded file" + + rr := h.makeUploadRequest(t, baseURL+"/_op/upload/uploads", fileName, fileContent, h.RegularTestUser) + require.Equal(t, http.StatusOK, rr.Code) + + // Verify response structure + var response struct { + FilePath string `json:"filePath"` + Size int64 `json:"size"` + UpdatedAt string `json:"updatedAt"` + } + err := json.NewDecoder(rr.Body).Decode(&response) + require.NoError(t, err) + assert.Equal(t, "uploads/"+fileName, response.FilePath) + assert.Equal(t, int64(len(fileContent)), response.Size) + + // Verify file was saved + rr = h.makeRequest(t, http.MethodGet, baseURL+"/uploads/"+fileName, nil, h.RegularTestUser) + require.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, fileContent, rr.Body.String()) + }) + + t.Run("upload without file", func(t *testing.T) { + rr := h.makeUploadRequest(t, baseURL+"/_op/upload/test", "", "", h.RegularTestUser) + assert.Equal(t, http.StatusBadRequest, rr.Code) + }) + }) }) } diff --git a/server/internal/handlers/integration_test.go b/server/internal/handlers/integration_test.go index 7e9894c..2e0acc5 100644 --- a/server/internal/handlers/integration_test.go +++ b/server/internal/handlers/integration_test.go @@ -6,6 +6,7 @@ import ( "bytes" "encoding/json" "io" + "mime/multipart" "net/http" "net/http/httptest" "os" @@ -303,11 +304,19 @@ func (h *testHarness) makeRequest(t *testing.T, method, path string, body any, t return h.executeRequest(req) } -// makeRequestRawWithHeaders adds support for custom headers with raw body -func (h *testHarness) makeRequestRaw(t *testing.T, method, path string, body io.Reader, testUser *testUser) *httptest.ResponseRecorder { +// makeRequestRaw adds support for raw body requests with optional headers +func (h *testHarness) makeRequestRaw(t *testing.T, method, path string, body io.Reader, testUser *testUser, headers ...map[string]string) *httptest.ResponseRecorder { t.Helper() req := h.newRequestRaw(t, method, path, body) + + // Set custom headers if provided + if len(headers) > 0 { + for key, value := range headers[0] { + req.Header.Set(key, value) + } + } + h.addAuthCookies(t, req, testUser) needsCSRF := method != http.MethodGet && method != http.MethodHead && method != http.MethodOptions @@ -318,3 +327,37 @@ func (h *testHarness) makeRequestRaw(t *testing.T, method, path string, body io. return h.executeRequest(req) } + +// makeUploadRequest creates a multipart form request for file uploads +// If fileName is empty, creates an empty multipart form without a file +func (h *testHarness) makeUploadRequest(t *testing.T, path, fileName, fileContent string, testUser *testUser) *httptest.ResponseRecorder { + t.Helper() + + // Create multipart form + var buf bytes.Buffer + writer := multipart.NewWriter(&buf) + + // Only add file part if fileName is not empty + if fileName != "" { + part, err := writer.CreateFormFile("file", fileName) + if err != nil { + t.Fatalf("Failed to create form file: %v", err) + } + + _, err = part.Write([]byte(fileContent)) + if err != nil { + t.Fatalf("Failed to write file content: %v", err) + } + } + + err := writer.Close() + if err != nil { + t.Fatalf("Failed to close multipart writer: %v", err) + } + + headers := map[string]string{ + "Content-Type": writer.FormDataContentType(), + } + + return h.makeRequestRaw(t, http.MethodPost, path, &buf, testUser, headers) +}