package api_test import ( "net/http" "net/http/httptest" "strings" "testing" "git.golem15.com/golem15/summercms/modules/bouncer" "git.golem15.com/jakub/sm-bm-plugin/controllers/api" "gorm.io/gorm" ) // pinnedFirstQueries runs GET /materials?course=7&type=notatka as user on a // dry-run database and returns its count and page queries. func pinnedFirstQueries(t *testing.T, user uint) (string, string) { t.Helper() db, rec := dryDB(t) h := &api.Handlers{DB: func() *gorm.DB { return db }} req := httptest.NewRequest(http.MethodGet, "/materials?course=7&type=notatka", nil) req = req.WithContext(bouncer.WithUser(req.Context(), &bouncer.Principal{ID: user})) w := httptest.NewRecorder() h.Materials(w, req) if w.Code != http.StatusOK { t.Fatalf("status %d: %s", w.Code, w.Body.String()) } var count, page string for _, q := range rec.queries() { switch { case strings.HasPrefix(q, "SELECT count(*)"): count = q case strings.HasPrefix(q, "SELECT") && strings.Contains(q, `FROM "jz_bm_materials"`): page = q } } if count == "" || page == "" { t.Fatalf("queries = %q, want a count and a page", rec.queries()) } return count, page } // TestMaterialsPinnedFirstTrace checks the plain list's order: the caller's // own pins first, then newest first with id as the tie-breaker, inside the // same filters, while the count ignores pins. func TestMaterialsPinnedFirstTrace(t *testing.T) { count, page := pinnedFirstQueries(t, 5) for name, q := range map[string]string{"count": count, "page": page} { for _, want := range []string{"jz_bm_materials.course_id = 7", "jz_bm_materials.type = 'notatka'", "jz_bm_materials.is_private = FALSE"} { if !strings.Contains(q, want) { t.Errorf("%s query lacks %q:\n%s", name, want, q) } } } if want := "p.user_id = 5) DESC NULLS LAST, jz_bm_materials.published_at DESC, jz_bm_materials.id DESC"; !strings.Contains(page, want) { t.Errorf("page query is not pinned first for user 5, want %q:\n%s", want, page) } if strings.Contains(count, "jz_bm_material_pins") { t.Errorf("count query reads pins:\n%s", count) } _, other := pinnedFirstQueries(t, 6) if !strings.Contains(other, "p.user_id = 6)") || strings.Contains(other, "p.user_id = 5") { t.Errorf("page query of user 6 does not use only their pins:\n%s", other) } }