66 lines
2.2 KiB
Go
66 lines
2.2 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"rawmark/internal/events"
|
|
"rawmark/internal/vault"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestTreeIconAuthAndBroadcast(t *testing.T) {
|
|
f := newFixture(t)
|
|
f.write("a.md", "正文")
|
|
payload := `{"path":"a.md","icon":{"kind":"emoji","value":"📚"}}`
|
|
check := func(client *http.Client, headers map[string]string, want int) {
|
|
t.Helper()
|
|
res := f.do(client, "PUT", "/api/v1/tree-icon", payload, headers)
|
|
res.Body.Close()
|
|
if res.StatusCode != want {
|
|
t.Fatalf("设置图标状态: %d,期望 %d", res.StatusCode, want)
|
|
}
|
|
}
|
|
check(newClient(), nil, 401)
|
|
for _, scope := range []string{"read", "write"} {
|
|
token := decode[struct{ Token string }](t, f.do(f.admin, "POST", "/api/v1/tokens", `{"name":"icons","scope":"`+scope+`"}`, nil))
|
|
want := 200
|
|
if scope == "read" {
|
|
want = 403
|
|
}
|
|
check(newClient(), map[string]string{"Authorization": "Bearer " + token.Token}, want)
|
|
}
|
|
ch, cancel := f.hub.Subscribe()
|
|
defer cancel()
|
|
check(f.admin, nil, 200)
|
|
select {
|
|
case msg := <-ch:
|
|
var batch []events.Event
|
|
if err := json.Unmarshal(msg, &batch); err != nil || len(batch) != 1 || batch[0].Type != "tree" {
|
|
t.Fatalf("图标广播不符: %s %v", msg, err)
|
|
}
|
|
case <-time.After(time.Second):
|
|
t.Fatal("缺少 tree 广播")
|
|
}
|
|
tree := decode[struct{ Entries []vault.Entry }](t, f.do(f.admin, "GET", "/api/v1/tree", "", nil))
|
|
if len(tree.Entries) != 1 || tree.Entries[0].Icon == nil || tree.Entries[0].Icon.Value != "📚" {
|
|
t.Fatalf("目录属性不符: %+v", tree)
|
|
}
|
|
res := f.do(f.admin, "PUT", "/api/v1/tree-icon", `{"path":"a.md","icon":null}`, nil)
|
|
res.Body.Close()
|
|
if res.StatusCode != 200 {
|
|
t.Fatal(res.StatusCode)
|
|
}
|
|
tree = decode[struct{ Entries []vault.Entry }](t, f.do(f.admin, "GET", "/api/v1/tree", "", nil))
|
|
if tree.Entries[0].Icon != nil {
|
|
t.Fatal("恢复默认后不应返回覆盖属性")
|
|
}
|
|
for _, body := range []string{`{"path":"a.md"}`, `{"path":"a.md","icon":"📚"}`, `{"path":"a.md","icon":{"kind":"builtin","value":"fake"}}`, `{"path":"../a.md","icon":null}`} {
|
|
res := f.do(f.admin, "PUT", "/api/v1/tree-icon", body, nil)
|
|
res.Body.Close()
|
|
if res.StatusCode != 400 {
|
|
t.Fatal(res.StatusCode)
|
|
}
|
|
}
|
|
}
|