package server import ( "bytes" "context" "encoding/json" "mime/multipart" "net/http" "net/http/httptest" "path/filepath" "testing" ) func TestArtifactUploadCreatesReadableArtifactForSourceArtifactID(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) } sessionToken, _, ok, err := server.store.createSession("sk-upload-user") if err != nil { t.Fatalf("createSession: %v", err) } if !ok { t.Fatal("expected session creation to succeed") } current, exists, err := server.store.session(sessionToken) if err != nil { t.Fatalf("load session: %v", err) } if !exists { t.Fatal("expected stored session") } imageBytes := tinyPNG(t) var body bytes.Buffer writer := multipart.NewWriter(&body) if err := writer.WriteField("role", "source"); err != nil { t.Fatalf("write role field: %v", err) } if err := writer.WriteField("metadata_json", `{"origin":"chat-upload"}`); err != nil { t.Fatalf("write metadata field: %v", err) } part, err := writer.CreateFormFile("file", "chat-upload.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/artifacts/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 artifact `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 artifact id, got %#v", envelope.Data) } if envelope.Data.ContentType != "image/png" { t.Fatalf("expected image/png, got %q", envelope.Data.ContentType) } editRef, err := server.resolveImageToImageReference(context.Background(), &job{ UserID: current.User.ID, UpstreamKey: current.UpstreamKey, SkillID: "popiskill-image-img2img-basic-v1", }, map[string]any{ "source_artifact_id": envelope.Data.ID, }) if err != nil { t.Fatalf("resolveImageToImageReference: %v", err) } if editRef.ContentType != "image/png" { t.Fatalf("expected resolved content type image/png, got %q", editRef.ContentType) } if !bytes.Equal(editRef.Content, imageBytes) { t.Fatal("expected resolved reference content to match uploaded bytes") } }