mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-11-12 21:44:22 +08:00
3c7b347d7b
* perf(nodes): paginate node lists and fetch details directly * fix(nodes): preserve Unicode search and page transition state * fix(nodes): validate search using the UTF-8 byte limit
87 lines
3.5 KiB
Go
87 lines
3.5 KiB
Go
// Copyright 2026 Arctel.net
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package integration
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/Rain-kl/Wavelet/internal/apps/openflare/node"
|
|
"github.com/Rain-kl/Wavelet/internal/shared/response"
|
|
"github.com/Rain-kl/Wavelet/internal/testhelper"
|
|
"github.com/gin-contrib/sessions"
|
|
"github.com/gin-contrib/sessions/cookie"
|
|
)
|
|
|
|
func TestNodePageAPI(t *testing.T) {
|
|
_, seed, cleanup := setupCoreChainTest(t)
|
|
engine := testhelper.NewTestGinEngine(sessions.Sessions("node-page-test", cookie.NewStore([]byte("node-page-test-session-secret"))))
|
|
mountOpenFlareTestRoutes(engine)
|
|
t.Cleanup(cleanup)
|
|
headers := adminAuthHeaders(seed.Token)
|
|
created := performJSONRequest(t, engine, http.MethodPost, apiPath("/nodes"), node.Input{Name: "Searchable Edge"}, headers)
|
|
if created.Code != http.StatusOK {
|
|
t.Fatalf("create node status=%d body=%s", created.Code, created.Body.String())
|
|
}
|
|
var createdEnvelope struct {
|
|
Data node.View `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(created.Body.Bytes(), &createdEnvelope); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, path := range []string{"/nodes/page", fmt.Sprintf("/nodes/%d", createdEnvelope.Data.ID)} {
|
|
unauthorized := performJSONRequest(t, engine, http.MethodGet, apiPath(path), nil, nil)
|
|
var denied response.Any
|
|
if err := json.Unmarshal(unauthorized.Body.Bytes(), &denied); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if unauthorized.Code != http.StatusUnauthorized || denied.Data != nil || denied.ErrorMsg == "" {
|
|
t.Errorf("GET %s withoutauth status=%d body=%s,want401 withoutdata", path, unauthorized.Code, unauthorized.Body.String())
|
|
}
|
|
}
|
|
page := performJSONRequest(t, engine, http.MethodGet, apiPath("/nodes/page?search=searchable&status=pending&node_type=edge_node"), nil, headers)
|
|
var envelope struct {
|
|
ErrorMsg string `json:"error_msg"`
|
|
Data node.ListResult `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(page.Body.Bytes(), &envelope); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if page.Code != http.StatusOK || envelope.ErrorMsg != "" || envelope.Data.Total != 1 || len(envelope.Data.Results) != 1 {
|
|
t.Fatalf("GET page status=%d body=%s,wantone", page.Code, page.Body.String())
|
|
}
|
|
detail := performJSONRequest(t, engine, http.MethodGet, apiPath(fmt.Sprintf("/nodes/%d", createdEnvelope.Data.ID)), nil, headers)
|
|
if detail.Code != http.StatusOK {
|
|
t.Errorf("GET detail status=%d body=%s,want200", detail.Code, detail.Body.String())
|
|
}
|
|
missing := performJSONRequest(t, engine, http.MethodGet, apiPath("/nodes/99999"), nil, headers)
|
|
if missing.Code != http.StatusNotFound {
|
|
t.Errorf("GET missing node status=%d,want404", missing.Code)
|
|
}
|
|
invalid := []string{"page=-1", "page=no", "page=9223372036854775807&page_size=100", "page_size=-1", "page_size=no", "status=healthy", "node_type=relay", "search=" + strings.Repeat("x", 257)}
|
|
for _, query := range invalid {
|
|
bad := performJSONRequest(t, engine, http.MethodGet, apiPath("/nodes/page?"+query), nil, headers)
|
|
var body response.Any
|
|
if err := json.Unmarshal(bad.Body.Bytes(), &body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if bad.Code != http.StatusBadRequest || body.Data != nil || body.ErrorMsg == "" {
|
|
t.Errorf("GET page?%s status=%d body=%s,want400 null data", query, bad.Code, bad.Body.String())
|
|
}
|
|
}
|
|
legacy := performJSONRequest(t, engine, http.MethodGet, apiPath("/nodes"), nil, headers)
|
|
var old struct {
|
|
Data []node.View `json:"data"`
|
|
}
|
|
if err := json.Unmarshal(legacy.Body.Bytes(), &old); err != nil {
|
|
t.Fatalf("legacy array JSON: %v", err)
|
|
}
|
|
if len(old.Data) != 1 {
|
|
t.Errorf("legacy len=%d,want1", len(old.Data))
|
|
}
|
|
}
|