69 lines
2.8 KiB
Go
69 lines
2.8 KiB
Go
package http
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/cookiejar"
|
|
"testing"
|
|
)
|
|
|
|
func TestRevocationAndForeignRelations(t *testing.T) {
|
|
srv := testServer(t)
|
|
newClient := func() apiClient { jar, _ := cookiejar.New(nil); return apiClient{t, &http.Client{Jar: jar}, srv.URL} }
|
|
a, b := newClient(), newClient()
|
|
account := func(c apiClient, email string) string {
|
|
body := map[string]any{"email": email, "password": "test-password"}
|
|
c.request("POST", "/api/signup", body, 201)
|
|
c.request("POST", "/api/auth/login", body, 200)
|
|
// Review CR-03: the id comes from the authenticated session, not the
|
|
// uniform signup body.
|
|
return meID(c)
|
|
}
|
|
account(a, "owner@computer.test")
|
|
bid := account(b, "recipient@computer.test")
|
|
tag := a.request("POST", "/api/tags", map[string]any{"name": "Shared"}, 201)["id"].(string)
|
|
id := a.request("POST", "/api/bookmarks", map[string]any{"url": "https://127.0.0.1/test", "tagIds": []string{tag}, "dueDate": "2026-10-07"}, 201)["id"].(string)
|
|
a.request("POST", "/api/bookmarks/"+id+"/share", map[string]any{"userIds": []string{bid}}, 200)
|
|
b.request("GET", "/api/bookmarks/"+id, nil, 200)
|
|
b.request("DELETE", "/api/bookmarks/"+id+"/share/"+bid, nil, 404)
|
|
a.request("DELETE", "/api/bookmarks/"+id+"/share/"+bid, nil, 200)
|
|
b.request("GET", "/api/bookmarks/"+id, nil, 404)
|
|
a.request("PUT", "/api/tags/"+tag, map[string]any{"shareUserIds": []string{bid}}, 200)
|
|
b.request("GET", "/api/bookmarks/"+id, nil, 200)
|
|
a.request("DELETE", "/api/tags/"+tag+"/share/"+bid, nil, 200)
|
|
b.request("GET", "/api/bookmarks/"+id, nil, 404)
|
|
// Unsharing a tag must remove every discovery surface, not just the
|
|
// detail path (review recheck): list and search share the single
|
|
// BookmarkVisible predicate, so prove it holds end-to-end.
|
|
for _, q := range []string{"", "?search=127.0.0.1"} {
|
|
var list []map[string]any
|
|
res, e := b.c.Get(srv.URL + "/api/bookmarks" + q)
|
|
if e != nil {
|
|
t.Fatal(e)
|
|
}
|
|
json.NewDecoder(res.Body).Decode(&list)
|
|
res.Body.Close()
|
|
for _, item := range list {
|
|
if item["id"] == id {
|
|
t.Fatalf("revoked bookmark still visible in list %q", q)
|
|
}
|
|
}
|
|
}
|
|
a.request("POST", "/api/shared-dates", map[string]any{"date": "2026-10-07", "recipientIds": []string{bid}}, 201)
|
|
response, e := a.c.Get(srv.URL + "/api/shared-dates")
|
|
if e != nil {
|
|
t.Fatal(e)
|
|
}
|
|
var dates []map[string]any
|
|
if e = json.NewDecoder(response.Body).Decode(&dates); e != nil {
|
|
t.Fatal(e)
|
|
}
|
|
response.Body.Close()
|
|
b.request("GET", "/api/bookmarks/"+id, nil, 200)
|
|
a.request("DELETE", "/api/shared-dates/"+dates[0]["id"].(string), nil, 200)
|
|
b.request("GET", "/api/bookmarks/"+id, nil, 404)
|
|
foreign := b.request("POST", "/api/kanban/columns", map[string]any{"label": "Private"}, 201)["id"].(string)
|
|
putBookmark(a, id, map[string]any{"kanbanColumnId": foreign}, 400)
|
|
putBookmark(a, id, map[string]any{"dueDate": map[string]any{}}, 400)
|
|
}
|