feat: file_save_disk, file_delete, file_serve, upload_parse, upload_handler, thumbnail_generate (issue 0014 fase 3)
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package infra
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// buildPNGMultipart crea un multipart con un campo "file" cuyo contenido tiene
|
||||
// los magic bytes de PNG (suficientes para que FileValidateType los reconozca).
|
||||
func buildPNGMultipart(t *testing.T, filename string, body string) (string, *bytes.Buffer) {
|
||||
t.Helper()
|
||||
var buf bytes.Buffer
|
||||
w := multipart.NewWriter(&buf)
|
||||
part, err := w.CreateFormFile("file", filename)
|
||||
if err != nil {
|
||||
t.Fatalf("CreateFormFile: %v", err)
|
||||
}
|
||||
// Magic bytes PNG: 89 50 4E 47 0D 0A 1A 0A
|
||||
part.Write([]byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A})
|
||||
part.Write([]byte(body))
|
||||
w.Close()
|
||||
return w.FormDataContentType(), &buf
|
||||
}
|
||||
|
||||
func TestUploadHandler(t *testing.T) {
|
||||
t.Run("acepta upload con imagen y responde JSON", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
cfg := StorageConfig{
|
||||
BaseDir: dir,
|
||||
MaxFileSize: 1 << 20,
|
||||
AllowedTypes: []string{"image/png"},
|
||||
}
|
||||
ct, body := buildPNGMultipart(t, "foto.png", "data extra")
|
||||
|
||||
req := httptest.NewRequest("POST", "/upload", body)
|
||||
req.Header.Set("Content-Type", ct)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
UploadHandler(cfg).ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("got %d, body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
var resp struct {
|
||||
Files []UploadedFile `json:"files"`
|
||||
}
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if len(resp.Files) != 1 {
|
||||
t.Fatalf("got %d files, want 1", len(resp.Files))
|
||||
}
|
||||
if resp.Files[0].ContentType != "image/png" {
|
||||
t.Errorf("got ContentType %q", resp.Files[0].ContentType)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("rechaza tipo no permitido con 415", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
cfg := StorageConfig{
|
||||
BaseDir: dir,
|
||||
MaxFileSize: 1 << 20,
|
||||
AllowedTypes: []string{"application/pdf"}, // PNG no en lista
|
||||
}
|
||||
ct, body := buildPNGMultipart(t, "foto.png", "x")
|
||||
|
||||
req := httptest.NewRequest("POST", "/upload", body)
|
||||
req.Header.Set("Content-Type", ct)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
UploadHandler(cfg).ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusUnsupportedMediaType {
|
||||
t.Errorf("got %d, want 415", rec.Code)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("rechaza body que excede MaxFileSize con 400", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
cfg := StorageConfig{
|
||||
BaseDir: dir,
|
||||
MaxFileSize: 10, // muy pequeno
|
||||
AllowedTypes: []string{"image/png"},
|
||||
}
|
||||
ct, body := buildPNGMultipart(t, "foto.png", "muchos bytes extra para superar 10")
|
||||
|
||||
req := httptest.NewRequest("POST", "/upload", body)
|
||||
req.Header.Set("Content-Type", ct)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
UploadHandler(cfg).ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusBadRequest {
|
||||
t.Errorf("got %d, want 400", rec.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user