package test import ( "RenewCMS/api/pkg/apperr" "RenewCMS/internal/domain/user" "encoding/json" "net/http" "net/http/httptest" "reflect" "testing" ) const mediaGetEditorID = 9 func newMediaGetEnv(t *testing.T) *siteEnv { t.Helper() e := newSiteEnvWithMain(t) e.users.users[mediaGetEditorID] = user.User{ID: mediaGetEditorID, Username: "editor", Email: "editor@example.com", IsVerified: true, Role: user.Role("editor")} e.seedImageRecord(5) return e } func (e *siteEnv) seedImageRecord(id uint32) { e.seedImage(id) img := e.images.images[id] img.Size, img.Width, img.Height, img.SHA256 = 2048, 800, 600, hashA e.images.images[id] = img e.seedSpring(1, ``, true) } func TestMediaGetOne(t *testing.T) { t.Run("Who can read one image", func(t *testing.T) { cases := []struct { credentials string send func(e *siteEnv) *httptest.ResponseRecorder status int }{ {"the owner's jwt cookie", func(e *siteEnv) *httptest.ResponseRecorder { return e.as(t, apiKeyOwnerId, http.MethodGet, "/v1/media/5", "") }, http.StatusOK}, {"a verified admin's jwt cookie", func(e *siteEnv) *httptest.ResponseRecorder { return e.as(t, apiKeyDevId, http.MethodGet, "/v1/media/5", "") }, http.StatusOK}, {"a verified account with another role", func(e *siteEnv) *httptest.ResponseRecorder { return e.as(t, mediaGetEditorID, http.MethodGet, "/v1/media/5", "") }, http.StatusOK}, {"a valid API key", func(e *siteEnv) *httptest.ResponseRecorder { raw, _ := e.issueKey(apiKeyDevId, "Deploy bot") return e.asKey(t, raw, http.MethodGet, "/v1/media/5", "") }, http.StatusOK}, {"an unverified account's jwt cookie", func(e *siteEnv) *httptest.ResponseRecorder { return e.as(t, apiKeyQuinnId, http.MethodGet, "/v1/media/5", "") }, http.StatusForbidden}, {"no credentials", func(e *siteEnv) *httptest.ResponseRecorder { return e.anonymous(t, http.MethodGet, "/v1/media/5", "") }, http.StatusUnauthorized}, } for _, c := range cases { t.Run(c.credentials, func(t *testing.T) { e := newMediaGetEnv(t) if rec := c.send(e); rec.Code != c.status { t.Errorf("status = %d, expected %d", rec.Code, c.status) } }) } }) t.Run("The item has the shape of the list", func(t *testing.T) { e := newMediaGetEnv(t) single := e.owner(t, http.MethodGet, "/v1/media/5", "") listed := e.owner(t, http.MethodGet, "/v1/media/", "") var one map[string]any var page struct { Items []map[string]any `json:"items"` } if err := json.Unmarshal(single.Body.Bytes(), &one); err != nil { t.Fatalf("decode item: %v", err) } if err := json.Unmarshal(listed.Body.Bytes(), &page); err != nil { t.Fatalf("decode list: %v", err) } var expected map[string]any for _, item := range page.Items { if item["id"] == 5.0 { expected = item } } if expected == nil || !reflect.DeepEqual(one, expected) { t.Fatalf("item %v, list element %v", one, expected) } if one["used_in"] != 1.0 || one["size"] != 2048.0 { t.Errorf("item = %v", one) } }) t.Run("A missing image is not found", func(t *testing.T) { e := newMediaGetEnv(t) rec := e.owner(t, http.MethodGet, "/v1/media/999", "") expectSiteStatusAndBody(t, rec, http.StatusNotFound, apperr.ImageNotFoundErrorMessage) }) t.Run("A malformed id is refused", func(t *testing.T) { for _, id := range []string{"abc", "-1", "4294967296", "1.5"} { e := newMediaGetEnv(t) rec := e.owner(t, http.MethodGet, "/v1/media/"+id, "") expectSiteStatusAndBody(t, rec, http.StatusBadRequest, apperr.IdUint32ErrorMessage) } }) t.Run("Reading one image records nothing", func(t *testing.T) { e := newMediaGetEnv(t) e.owner(t, http.MethodGet, "/v1/media/5", "") e.noEvent(t) }) t.Run("The route does not shadow the usage route", func(t *testing.T) { e := newMediaGetEnv(t) rec := e.owner(t, http.MethodGet, "/v1/media/5/usage", "") if rec.Code != http.StatusOK || rec.Body.String() == "" { t.Fatalf("status %d", rec.Code) } }) }