Files
knowledge-governance/internal/httpapi/monitor_tasks_test.go
T
姚章浩 1c80b07f2c
build / build (push) Successful in 1m59s
fix(ui): 修复F12-F16入口与追溯缺陷
Dockerfile 运行阶段补齐 dws_dingtalk_scan(F12),并新增 runtime-scripts 门禁
做脚本依赖闭包正负例;就绪探测每次解析当前端点/绑定/凭据并区分 404、未配置、
不可达(F13);路由写入来源路径与父目录,历史空值仅按同连接同 item 的意图读时
补齐(F14);目标筛选显示短 ID 与当前绑定/历史并提供快捷筛选(F15);刷新终态
移除后台运行、展示失败时间/旧快照/脱敏原因/作业 ID 与重试(F16)。

验证:make verify 17 项全过(identity 本地按设计 skipped);一次性 schema 的
Monitor 目录/路由集成用例通过;8088 部署与真实 UI 验收仍由父会话执行。
2026-11-05 10:38:26 +08:00

91 lines
3.3 KiB
Go

package httpapi
import (
"context"
"encoding/json"
postgresstore "knowledge-governance/internal/platform/postgres"
"net/http/httptest"
"testing"
)
type monitorTasksTestStore struct {
fakeJobStore
filter postgresstore.MonitorTaskFilter
}
func (s *monitorTasksTestStore) ListMonitorTasks(_ context.Context, f postgresstore.MonitorTaskFilter) (postgresstore.MonitorTaskPage, error) {
s.filter = f
return postgresstore.MonitorTaskPage{Items: []postgresstore.MonitorTask{}, Total: 145, Limit: f.Limit, Offset: f.Offset}, nil
}
func TestMonitorTasksRoute(t *testing.T) {
s := &monitorTasksTestStore{}
req := httptest.NewRequest("GET", "/api/v1/monitor/tasks?status=active&limit=20&offset=40", nil)
req = req.WithContext(context.WithValue(req.Context(), sessionKey{}, sessionIdentity{Username: "tester", Role: roleViewer}))
w := httptest.NewRecorder()
h, err := NewHandler(Config{Store: s})
if err != nil {
t.Fatal(err)
}
h.ServeHTTP(w, req)
if w.Code != 200 {
t.Fatalf("status %d: %s", w.Code, w.Body.String())
}
if s.filter.Status != "active" || s.filter.Offset != 40 {
t.Fatalf("filter %#v", s.filter)
}
for _, query := range []string{"status=garbage", "stage=internal&scope=internal", "limit=101", "offset=-1", "since=bad"} {
r := httptest.NewRequest("GET", "/api/v1/monitor/tasks?"+query, nil).WithContext(req.Context())
rr := httptest.NewRecorder()
h.ServeHTTP(rr, r)
if rr.Code != 400 {
t.Fatalf("invalid %s: %d", query, rr.Code)
}
}
unauth := httptest.NewRecorder()
h.ServeHTTP(unauth, httptest.NewRequest("GET", "/api/v1/monitor/tasks", nil))
if unauth.Code != 401 {
t.Fatalf("unauthenticated %d", unauth.Code)
}
removal := httptest.NewRecorder()
h.ServeHTTP(removal, httptest.NewRequest("POST", "/api/v1/test-publications/example/removal-retry", nil).WithContext(req.Context()))
if removal.Code != 403 {
t.Fatalf("viewer removal %d", removal.Code)
}
}
// F15:筛选里的“当前绑定”必须来自持久化绑定(与业务同一真源),不是 env 旧值,
// 也不能让前端拿本页数据猜全局。
func TestMonitorTasksReportsEffectiveTargetBindings(t *testing.T) {
store := &monitorTasksTestStore{}
handler, err := NewHandler(Config{
Store: store,
InternalRoutingKnowledgeBaseID: "env-old-internal",
ExternalRoutingKnowledgeBaseID: "env-old-external",
RoutingBindings: &bindingStoreFake{internal: "current-internal", external: "current-external"},
})
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest("GET", "/api/v1/monitor/tasks?limit=20", nil)
req = req.WithContext(context.WithValue(req.Context(), sessionKey{}, sessionIdentity{Username: "tester", Role: roleViewer}))
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, req)
if recorder.Code != 200 {
t.Fatalf("status %d: %s", recorder.Code, recorder.Body.String())
}
var payload struct {
Data struct {
Bindings struct {
Internal string `json:"internal"`
External string `json:"external"`
} `json:"bindings"`
} `json:"data"`
}
if err := json.Unmarshal(recorder.Body.Bytes(), &payload); err != nil {
t.Fatal(err)
}
if payload.Data.Bindings.Internal != "current-internal" || payload.Data.Bindings.External != "current-external" {
t.Fatalf("bindings = %#v, want the persisted current bindings", payload.Data.Bindings)
}
}