package infra import ( "bytes" "io" "mime/multipart" "net/http" "net/http/httptest" "strings" "testing" ) // buildMultipart construye un multipart body con los archivos dados (field, filename, contenido). func buildMultipart(t *testing.T, files []struct{ field, filename, content string }) (string, *bytes.Buffer) { t.Helper() var body bytes.Buffer w := multipart.NewWriter(&body) for _, f := range files { part, err := w.CreateFormFile(f.field, f.filename) if err != nil { t.Fatalf("CreateFormFile: %v", err) } if _, err := part.Write([]byte(f.content)); err != nil { t.Fatalf("Write part: %v", err) } } if err := w.Close(); err != nil { t.Fatalf("Close writer: %v", err) } return w.FormDataContentType(), &body } func newMultipartReq(t *testing.T, contentType string, body *bytes.Buffer) *http.Request { t.Helper() req := httptest.NewRequest("POST", "/upload", body) req.Header.Set("Content-Type", contentType) return req } func TestUploadParse(t *testing.T) { t.Run("extrae un archivo del multipart", func(t *testing.T) { ct, body := buildMultipart(t, []struct{ field, filename, content string }{ {"file", "a.txt", "hello"}, }) req := newMultipartReq(t, ct, body) got, err := UploadParse(req, 1<<20) if err != nil { t.Fatalf("UploadParse: %v", err) } if len(got) != 1 { t.Fatalf("got %d files, want 1", len(got)) } if got[0].Filename != "a.txt" { t.Errorf("got Filename %q", got[0].Filename) } if got[0].Size != 5 { t.Errorf("got Size %d, want 5", got[0].Size) } buf, _ := io.ReadAll(got[0].Content) if string(buf) != "hello" { t.Errorf("got content %q, want hello", buf) } }) t.Run("extrae multiples archivos", func(t *testing.T) { ct, body := buildMultipart(t, []struct{ field, filename, content string }{ {"a", "1.txt", "uno"}, {"b", "2.txt", "dos"}, }) req := newMultipartReq(t, ct, body) got, err := UploadParse(req, 1<<20) if err != nil { t.Fatalf("UploadParse: %v", err) } if len(got) != 2 { t.Fatalf("got %d files, want 2", len(got)) } }) t.Run("rechaza content-type no multipart", func(t *testing.T) { req := httptest.NewRequest("POST", "/upload", strings.NewReader("x")) req.Header.Set("Content-Type", "application/json") _, err := UploadParse(req, 1<<20) if err == nil || !strings.Contains(err.Error(), "no es multipart") { t.Errorf("got %v, want error de content-type", err) } }) t.Run("respeta maxSize", func(t *testing.T) { ct, body := buildMultipart(t, []struct{ field, filename, content string }{ {"file", "big.bin", strings.Repeat("x", 1024)}, }) req := newMultipartReq(t, ct, body) _, err := UploadParse(req, 100) // demasiado pequeno if err == nil { t.Errorf("got nil err, want max bytes error") } }) }