diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-09-15 00:06:21 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-09-15 00:06:21 +0900 |
| commit | 834db962958652502aba88362dbe91df2ee618ee (patch) | |
| tree | 9c06fbcab83ad56e2d90f24a8d2cf016c6c1d005 /cmd/mbf/internal/pkgsite/api_test.go | |
| parent | cce7a996b06e516f5afcd41d2d67c2392000b6ab (diff) | |
cmd/mbf: rename pkgsite
This name is less ambiguous than pkgserver.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'cmd/mbf/internal/pkgsite/api_test.go')
| -rw-r--r-- | cmd/mbf/internal/pkgsite/api_test.go | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/cmd/mbf/internal/pkgsite/api_test.go b/cmd/mbf/internal/pkgsite/api_test.go new file mode 100644 index 00000000..d2c21d81 --- /dev/null +++ b/cmd/mbf/internal/pkgsite/api_test.go @@ -0,0 +1,111 @@ +package pkgsite + +import ( + "net/http" + "net/http/httptest" + "strconv" + "testing" + + "hakurei.app/internal/info" + "hakurei.app/internal/rosa" +) + +// prefix is prepended to every API path. +const prefix = "/api/" + apiVersion + "/" + +func TestAPIInfo(t *testing.T) { + t.Parallel() + + w := httptest.NewRecorder() + handleInfo(w, httptest.NewRequestWithContext( + t.Context(), + http.MethodGet, + prefix+"info", + nil, + )) + + resp := w.Result() + checkStatus(t, resp, http.StatusOK) + checkAPIHeader(t, w.Header()) + + checkPayload(t, resp, struct { + Count int `json:"count"` + HakureiVersion string `json:"hakurei_version"` + }{len(rosa.Collect()), info.Version()}) +} + +func TestAPIGet(t *testing.T) { + t.Parallel() + const target = prefix + "get" + + index := newIndex(t) + newRequest := func(suffix string) *httptest.ResponseRecorder { + w := httptest.NewRecorder() + index.handleGet(w, httptest.NewRequestWithContext( + t.Context(), + http.MethodGet, + target+suffix, + nil, + )) + return w + } + + checkValidate := func(t *testing.T, suffix string, vmin, vmax int, wantErr string) { + t.Run("invalid", func(t *testing.T) { + t.Parallel() + + w := newRequest("?" + suffix + "=invalid") + resp := w.Result() + checkError(t, resp, wantErr, http.StatusBadRequest) + }) + + t.Run("min", func(t *testing.T) { + t.Parallel() + + w := newRequest("?" + suffix + "=" + strconv.Itoa(vmin-1)) + resp := w.Result() + checkError(t, resp, wantErr, http.StatusBadRequest) + + w = newRequest("?" + suffix + "=" + strconv.Itoa(vmin)) + resp = w.Result() + checkStatus(t, resp, http.StatusOK) + }) + + t.Run("max", func(t *testing.T) { + t.Parallel() + + w := newRequest("?" + suffix + "=" + strconv.Itoa(vmax+1)) + resp := w.Result() + checkError(t, resp, wantErr, http.StatusBadRequest) + + w = newRequest("?" + suffix + "=" + strconv.Itoa(vmax)) + resp = w.Result() + checkStatus(t, resp, http.StatusOK) + }) + } + + t.Run("limit", func(t *testing.T) { + t.Parallel() + checkValidate( + t, "index=0&sort=0&limit", 1, 100, + "limit must be an integer between 1 and 100", + ) + }) + + count := len(rosa.Collect()) + t.Run("index", func(t *testing.T) { + t.Parallel() + checkValidate( + t, "limit=1&sort=0&index", 0, count-1, + "index must be an integer between 0 and "+strconv.Itoa(count-1), + ) + }) + + t.Run("sort", func(t *testing.T) { + t.Parallel() + checkValidate( + t, "index=0&limit=1&sort", 0, int(sortOrderEnd), + "sort must be an integer between 0 and "+strconv.Itoa(int(sortOrderEnd)), + ) + }) +} |
