diff --git a/cmd/server/tests/media_note_length_test.go b/cmd/server/tests/media_note_length_test.go new file mode 100644 index 0000000..3447af9 --- /dev/null +++ b/cmd/server/tests/media_note_length_test.go @@ -0,0 +1,54 @@ +package main + +import ( + "bytes" + "encoding/json" + "io" + "net/http" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestMediaNoteLengthLimits verifies the note content validator cap +// (internal/handlers/media.go): content up to 100,000 chars is accepted, +// longer content is rejected with 400. +func TestMediaNoteLengthLimits(t *testing.T) { + setup := setupTestServer(t) + + token := setup.Token + mediaItemID := createTestMediaItemID(t, setup) + + postNote := func(content string) int { + payload := map[string]interface{}{ + "content": content, + "position": "page:1", + } + body, _ := json.Marshal(payload) + req, _ := http.NewRequest("POST", setup.Server.URL+"/api/media-items/"+mediaItemID+"/notes", bytes.NewBuffer(body)) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", "Bearer "+token) + + client := &http.Client{} + resp, err := client.Do(req) + require.NoError(t, err) + defer func(Body io.ReadCloser) { + _ = Body.Close() + }(resp.Body) + return resp.StatusCode + } + + t.Run("50k-char note accepted", func(t *testing.T) { + assert.Equal(t, http.StatusCreated, postNote(strings.Repeat("a", 50000))) + }) + + t.Run("100k-char note accepted at boundary", func(t *testing.T) { + assert.Equal(t, http.StatusCreated, postNote(strings.Repeat("b", 100000))) + }) + + t.Run("over-limit note rejected", func(t *testing.T) { + assert.Equal(t, http.StatusBadRequest, postNote(strings.Repeat("c", 100001))) + }) +} diff --git a/internal/handlers/media.go b/internal/handlers/media.go index e2aa501..60a3cc0 100644 --- a/internal/handlers/media.go +++ b/internal/handlers/media.go @@ -102,13 +102,13 @@ type UpdateMediaItemRequest struct { // CreateMediaNoteRequest represents the request for creating a media note type CreateMediaNoteRequest struct { - Content string `json:"content" validate:"required,min=1,max=10000"` + Content string `json:"content" validate:"required,min=1,max=100000"` Position string `json:"position"` } // UpdateMediaNoteRequest represents the request for updating a media note type UpdateMediaNoteRequest struct { - Content string `json:"content" validate:"required,min=1,max=10000"` + Content string `json:"content" validate:"required,min=1,max=100000"` Position string `json:"position"` } @@ -120,7 +120,7 @@ type CreateMediaHighlightRequest struct { EpubcfiStart string `json:"epubcfi_start" validate:"max=2000"` EpubcfiEnd string `json:"epubcfi_end" validate:"max=2000"` Color string `json:"color" validate:"omitempty,len=7"` - NoteText string `json:"note_text" validate:"max=10000"` + NoteText string `json:"note_text" validate:"max=100000"` NoteID string `json:"note_id"` PercentageStart float64 `json:"percentage_start"` PercentageEnd float64 `json:"percentage_end"` @@ -135,7 +135,7 @@ type UpdateMediaHighlightRequest struct { EpubcfiStart string `json:"epubcfi_start" validate:"max=2000"` EpubcfiEnd string `json:"epubcfi_end" validate:"max=2000"` Color string `json:"color" validate:"omitempty,len=7"` - NoteText string `json:"note_text" validate:"max=10000"` + NoteText string `json:"note_text" validate:"max=100000"` NoteID string `json:"note_id"` PercentageStart float64 `json:"percentage_start"` PercentageEnd float64 `json:"percentage_end"` @@ -146,7 +146,7 @@ type UpdateMediaHighlightRequest struct { type CreateMediaBookmarkRequest struct { Title string `json:"title" validate:"required,min=1,max=255"` Position string `json:"position" validate:"max=100"` - Notes string `json:"notes" validate:"max=10000"` + Notes string `json:"notes" validate:"max=100000"` CfiPosition string `json:"cfi_position" validate:"max=255"` PageNumber int32 `json:"page_number"` ChapterNumber int32 `json:"chapter_number"` @@ -160,7 +160,7 @@ type CreateMediaBookmarkRequest struct { // UpdateMediaBookmarkRequest represents the request for updating a media bookmark type UpdateMediaBookmarkRequest struct { Title string `json:"title" validate:"required,min=1,max=255"` - Notes string `json:"notes" validate:"max=10000"` + Notes string `json:"notes" validate:"max=100000"` Position string `json:"position" validate:"max=100"` }