仰望星辰工作室

clearlove2.1

clearlove2.1/ internal/plugin/router_test.go 2.9 KB · 85 行 原始文件
1package plugin
2
3import (
4 "io/fs"
5 "net/http"
6 "net/http/httptest"
7 "strings"
8 "testing"
9)
10
11// stubView 模拟 handlers 注入的视图能力
12type stubView struct{ uid, aid int64 }
13
14func (s stubView) RenderTemplate(fsys fs.FS, name string, data any) (string, error) {
15 return "<rendered:" + name + ">", nil
16}
17func (s stubView) CSRF(r *http.Request) string { return "tok" }
18func (s stubView) UserID(r *http.Request) int64 { return s.uid }
19func (s stubView) AdminID(r *http.Request) int64 { return s.aid }
20func (s stubView) AdminPerm(r *http.Request, p string) bool { return true }
21
22// TestAppRouter 覆盖插件路由分发:鉴权、返回值约定、后台页面
23func TestAppRouter(t *testing.T) {
24 dataDir := setupAppEnv(t)
25 writeAppPlugin(t, dataDir, "demo", demoManifest, demoScript)
26
27 SetEnabled("demo", true)
28 if err := LoadApp("demo"); err != nil {
29 t.Fatalf("加载失败: %v", err)
30 }
31 defer func() {
32 UnloadApp("demo")
33 SetEnabled("demo", false)
34 SetViewProvider(nil)
35 }()
36
37 api := AppHandler()
38 admin := AdminAppHandler()
39
40 // 1) 公开路由:未登录也可访问(auth=none)
41 SetViewProvider(stubView{})
42 w := httptest.NewRecorder()
43 api.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/x/demo/", nil))
44 if w.Code != http.StatusOK || !strings.Contains(w.Body.String(), "hi") {
45 t.Fatalf("公开路由异常: code=%d body=%q", w.Code, w.Body.String())
46 }
47
48 // 2) 需要登录的路由:未登录应跳转登录页
49 w2 := httptest.NewRecorder()
50 api.ServeHTTP(w2, httptest.NewRequest(http.MethodPost, "/x/demo/do", nil))
51 if w2.Code != http.StatusFound || !strings.Contains(w2.Header().Get("Location"), "/login") {
52 t.Fatalf("未登录未拦截: code=%d location=%q", w2.Code, w2.Header().Get("Location"))
53 }
54
55 // 3) 已登录:返回 JSON
56 SetViewProvider(stubView{uid: 7})
57 w3 := httptest.NewRecorder()
58 api.ServeHTTP(w3, httptest.NewRequest(http.MethodPost, "/x/demo/do", nil))
59 if w3.Code != http.StatusOK || !strings.Contains(w3.Body.String(), `"ok"`) {
60 t.Fatalf("JSON 响应异常: code=%d body=%q", w3.Code, w3.Body.String())
61 }
62
63 // 4) 未知 slug → 404
64 w4 := httptest.NewRecorder()
65 api.ServeHTTP(w4, httptest.NewRequest(http.MethodGet, "/x/nope/", nil))
66 if w4.Code != http.StatusNotFound {
67 t.Fatalf("未知插件应 404,实际 %d", w4.Code)
68 }
69
70 // 5) 后台页面:未登录跳登录页
71 SetViewProvider(stubView{})
72 w5 := httptest.NewRecorder()
73 admin.ServeHTTP(w5, httptest.NewRequest(http.MethodGet, "/admin/plugins/demo/", nil))
74 if w5.Code != http.StatusFound {
75 t.Fatalf("后台页面未拦截: %d", w5.Code)
76 }
77
78 // 6) 后台页面:管理员可访问
79 SetViewProvider(stubView{aid: 1})
80 w6 := httptest.NewRecorder()
81 admin.ServeHTTP(w6, httptest.NewRequest(http.MethodGet, "/admin/plugins/demo/", nil))
82 if w6.Code != http.StatusOK || !strings.Contains(w6.Body.String(), "admin") {
83 t.Fatalf("后台页面异常: code=%d body=%q", w6.Code, w6.Body.String())
84 }
85}