package server import ( "bytes" "encoding/json" "io" "mime/multipart" "net/http" "net/http/httptest" "path/filepath" "testing" ) func TestMediaUploadGetAndContent(t *testing.T) { cfg := Config{ SQLitePath: filepath.Join(t.TempDir(), "popiart.db"), SkillhubDir: makeEmptySkillhub(t), SessionSecret: "test-secret", } server, err := NewWithConfig(cfg) if err != nil { t.Fatalf("NewWithConfig: %v", err) } srv := httptest.NewServer(server.Handler()) defer srv.Close() server.cfg.PublicBaseURL = srv.URL sessionToken, _, ok, err := server.store.createSession("sk-media-user") if err != nil { t.Fatalf("createSession: %v", err) } if !ok { t.Fatal("expected session creation to succeed") } imageBytes := tinyPNG(t) var body bytes.Buffer writer := multipart.NewWriter(&body) if err := writer.WriteField("project_id", "proj_media_demo"); err != nil { t.Fatalf("write project_id field: %v", err) } if err := writer.WriteField("visibility", "public"); err != nil { t.Fatalf("write visibility field: %v", err) } part, err := writer.CreateFormFile("file", "poster.png") if err != nil { t.Fatalf("create form file: %v", err) } if _, err := part.Write(imageBytes); err != nil { t.Fatalf("write form file: %v", err) } if err := writer.Close(); err != nil { t.Fatalf("close multipart writer: %v", err) } req := httptest.NewRequest(http.MethodPost, "/v1/media/upload", &body) req.Header.Set("Authorization", "Bearer "+sessionToken) req.Header.Set("Content-Type", writer.FormDataContentType()) rec := httptest.NewRecorder() server.Handler().ServeHTTP(rec, req) if rec.Code != http.StatusCreated { t.Fatalf("expected status 201, got %d body=%s", rec.Code, rec.Body.String()) } var envelope struct { OK bool `json:"ok"` Data media `json:"data"` } if err := json.Unmarshal(rec.Body.Bytes(), &envelope); err != nil { t.Fatalf("decode upload response: %v body=%s", err, rec.Body.String()) } if !envelope.OK { t.Fatalf("expected ok upload response, got %s", rec.Body.String()) } if envelope.Data.ID == "" { t.Fatalf("expected media id, got %#v", envelope.Data) } if envelope.Data.URL == "" { t.Fatalf("expected stable url, got %#v", envelope.Data) } getReq := httptest.NewRequest(http.MethodGet, "/v1/media/"+envelope.Data.ID, nil) getReq.Header.Set("Authorization", "Bearer "+sessionToken) getRec := httptest.NewRecorder() server.Handler().ServeHTTP(getRec, getReq) if getRec.Code != http.StatusOK { t.Fatalf("expected media get 200, got %d body=%s", getRec.Code, getRec.Body.String()) } contentResp, err := http.Get(envelope.Data.URL) if err != nil { t.Fatalf("GET media content: %v", err) } defer contentResp.Body.Close() if contentResp.StatusCode != http.StatusOK { t.Fatalf("expected media content 200, got %d", contentResp.StatusCode) } content, err := io.ReadAll(contentResp.Body) if err != nil { t.Fatalf("read content body: %v", err) } if !bytes.Equal(content, imageBytes) { t.Fatal("expected media content bytes to match uploaded file") } }