package api import ( "bytes" "encoding/json" "mime/multipart" "net/http/httptest" "strings" "testing" ) func multipartBody(t *testing.T, fields map[string]string, fileField, fileName, fileContent string) (*bytes.Buffer, string) { t.Helper() var buf bytes.Buffer w := multipart.NewWriter(&buf) for k, v := range fields { w.WriteField(k, v) } if fileField != "" { fw, _ := w.CreateFormFile(fileField, fileName) fw.Write([]byte(fileContent)) } w.Close() return &buf, w.FormDataContentType() } func TestCreateAndGetCan(t *testing.T) { s := testServer(t) h := s.routes() body, ct := multipartBody(t, map[string]string{ "title": "My can", "json_items": `[{"title":"a.txt","content":"AAA"},{"title":"b.txt","content":"BBB"}]`, "expires_in": "1h", }, "files", "pic.txt", "file data") req := httptest.NewRequest("POST", "/api/pastes/can", body) req.Header.Set("Content-Type", ct) rec := httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != 201 { t.Fatalf("create can: got %d: %s", rec.Code, rec.Body.String()) } var created struct { ID string `json:"id"` Items int `json:"items"` } json.Unmarshal(rec.Body.Bytes(), &created) if created.Items != 3 { t.Fatalf("expected 3 items, got %d", created.Items) } // get can req = httptest.NewRequest("GET", "/api/cans/"+created.ID, nil) rec = httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != 200 { t.Fatalf("get can: got %d", rec.Code) } var can struct { Items []struct{ ID string `json:"id"` } `json:"items"` } json.Unmarshal(rec.Body.Bytes(), &can) if len(can.Items) != 3 { t.Fatalf("expected 3 items in get, got %d", len(can.Items)) } // fetch item req = httptest.NewRequest("GET", "/api/cans/"+created.ID+"/items/"+can.Items[0].ID, nil) rec = httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != 200 { t.Fatalf("item fetch: got %d", rec.Code) } } func TestEmptyCanRejected(t *testing.T) { s := testServer(t) h := s.routes() body, ct := multipartBody(t, map[string]string{"title": "empty"}, "", "", "") req := httptest.NewRequest("POST", "/api/pastes/can", body) req.Header.Set("Content-Type", ct) rec := httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != 400 { t.Fatalf("expected 400 for empty can, got %d", rec.Code) } } func TestCanPasswordInheritedByItems(t *testing.T) { s := testServer(t) h := s.routes() body, ct := multipartBody(t, map[string]string{ "title": "locked", "password": "pw123", "json_items": `[{"title":"s.txt","content":"sec"}]`, }, "", "", "") req := httptest.NewRequest("POST", "/api/pastes/can", body) req.Header.Set("Content-Type", ct) rec := httptest.NewRecorder() h.ServeHTTP(rec, req) var created struct{ ID string `json:"id"` } json.Unmarshal(rec.Body.Bytes(), &created) // can without pw -> 401 req = httptest.NewRequest("GET", "/api/cans/"+created.ID, nil) rec = httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != 401 { t.Fatalf("expected 401, got %d", rec.Code) } // get item id with pw req = httptest.NewRequest("GET", "/api/cans/"+created.ID+"?password=pw123", nil) rec = httptest.NewRecorder() h.ServeHTTP(rec, req) var can struct { Items []struct{ ID string `json:"id"` } `json:"items"` } json.Unmarshal(rec.Body.Bytes(), &can) itemID := can.Items[0].ID // item without pw -> 401 req = httptest.NewRequest("GET", "/api/cans/"+created.ID+"/items/"+itemID, nil) rec = httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != 401 { t.Fatalf("item expected 401, got %d", rec.Code) } // item with pw -> 200 req = httptest.NewRequest("GET", "/api/cans/"+created.ID+"/items/"+itemID+"?password=pw123", nil) rec = httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != 200 { t.Fatalf("item expected 200, got %d", rec.Code) } if !strings.Contains(rec.Body.String(), "sec") { t.Fatalf("item content mismatch: %s", rec.Body.String()) } }