This repository has no description
5.1 kB
156 lines
1package reporesolver
2
3import (
4 "context"
5 "net/http"
6 "net/http/httptest"
7 "testing"
8
9 "github.com/bluesky-social/indigo/atproto/identity"
10 "github.com/bluesky-social/indigo/atproto/syntax"
11 "github.com/go-chi/chi/v5"
12 "tangled.org/core/appview/models"
13)
14
15func TestExtractCurrentDir(t *testing.T) {
16 tests := []struct {
17 path string
18 want string
19 }{
20 {"/@user/repo/blob/main/docs/README.md", "docs"},
21 {"/@user/repo/blob/main/README.md", "."},
22 {"/@user/repo/tree/main/docs", "docs"},
23 {"/@user/repo/tree/main/docs/", "docs"},
24 {"/@user/repo/tree/main", "."},
25 }
26
27 for _, tt := range tests {
28 if got := extractCurrentDir(tt.path); got != tt.want {
29 t.Errorf("extractCurrentDir(%q) = %q, want %q", tt.path, got, tt.want)
30 }
31 }
32}
33
34func TestCanonicalRepoPath(t *testing.T) {
35 cases := []struct {
36 name string
37 handle string
38 repo *models.Repo
39 want string
40 }{
41 {"name preferred", "boltless.dev", &models.Repo{Name: "anemone", Rkey: "3kabc"}, "boltless.dev/anemone"},
42 {"name equals rkey", "boltless.dev", &models.Repo{Name: "clam", Rkey: "clam"}, "boltless.dev/clam"},
43 {"empty name uses rkey", "akshay.dev", &models.Repo{Rkey: "limpet"}, "akshay.dev/limpet"},
44 }
45 for _, c := range cases {
46 t.Run(c.name, func(t *testing.T) {
47 if got := CanonicalRepoPath(c.handle, c.repo); got != c.want {
48 t.Errorf("CanonicalRepoPath = %q, want %q", got, c.want)
49 }
50 })
51 }
52}
53
54func TestCanonicalRedirectTargetKeepsTheTailEscaped(t *testing.T) {
55 cases := []struct {
56 name string
57 path string
58 want string
59 }{
60 {"plain tail", "/boltless.dev/limpet/tree/main", "/akshay.dev/anemone/tree/main"},
61 {"space in a blob path", "/boltless.dev/limpet/blob/main/a%20b.txt", "/akshay.dev/anemone/blob/main/a%20b.txt"},
62 {"escaped slash in a ref", "/boltless.dev/limpet/archive/refs%2Fheads%2Fmain", "/akshay.dev/anemone/archive/refs%2Fheads%2Fmain"},
63 {"hash in a filename", "/boltless.dev/limpet/raw/main/c%23.cs", "/akshay.dev/anemone/raw/main/c%23.cs"},
64 {"repo root", "/boltless.dev/limpet", "/akshay.dev/anemone"},
65 }
66
67 for _, c := range cases {
68 t.Run(c.name, func(t *testing.T) {
69 req := httptest.NewRequest("GET", c.path, nil)
70 if got := CanonicalRedirectTarget(req, "akshay.dev/anemone"); got != c.want {
71 t.Errorf("CanonicalRedirectTarget = %q, want %q", got, c.want)
72 }
73 })
74 }
75}
76
77func reqWithChiParams(user, repo string) *http.Request {
78 r := httptest.NewRequest("GET", "/", nil)
79 rctx := chi.NewRouteContext()
80 rctx.URLParams.Add("user", user)
81 rctx.URLParams.Add("repo", repo)
82 return r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
83}
84
85func TestGetBaseRepoPath_DoesNotVoluntaryRedirectToRepoDid(t *testing.T) {
86 r := reqWithChiParams("@boltless.dev", "anemone")
87 repo := &models.Repo{
88 Did: "did:plc:boltless",
89 Name: "anemone",
90 Rkey: "3kabcxyz",
91 RepoDid: "did:plc:anemone",
92 }
93 got := GetBaseRepoPath(r, repo)
94 want := "@boltless.dev/anemone"
95 if got != want {
96 t.Errorf("GetBaseRepoPath = %q, want %q", got, want)
97 }
98}
99
100func TestGetBaseRepoPath_HonorsUrlParams(t *testing.T) {
101 r := reqWithChiParams("did:plc:akshay", "limpet")
102 repo := &models.Repo{Did: "did:plc:akshay", Name: "limpet", Rkey: "limpet"}
103 if got, want := GetBaseRepoPath(r, repo), "did:plc:akshay/limpet"; got != want {
104 t.Errorf("GetBaseRepoPath = %q, want %q", got, want)
105 }
106}
107
108func TestGetBaseRepoPath_NoParamsPrefersName(t *testing.T) {
109 r := httptest.NewRequest("GET", "/", nil)
110 repo := &models.Repo{Did: "did:plc:akshay", Name: "scallop", Rkey: "3koldtid"}
111 got := GetBaseRepoPath(r, repo)
112 want := "did:plc:akshay/scallop"
113 if got != want {
114 t.Errorf("GetBaseRepoPath = %q, want %q", got, want)
115 }
116}
117
118func TestGetBaseRepoPath_NoParamsNoNameFallsToRepoIdentifier(t *testing.T) {
119 r := httptest.NewRequest("GET", "/", nil)
120 repo := &models.Repo{Did: "did:plc:akshay", Rkey: "3koldtid", RepoDid: "did:plc:scallop"}
121 if got, want := GetBaseRepoPath(r, repo), "did:plc:scallop"; got != want {
122 t.Errorf("GetBaseRepoPath = %q, want %q", got, want)
123 }
124}
125
126func reqWithResolvedId(handle, did string) *http.Request {
127 r := reqWithChiParams(did, "3koldtid")
128 id := identity.Identity{
129 DID: syntax.DID(did),
130 Handle: syntax.Handle(handle),
131 }
132 return r.WithContext(context.WithValue(r.Context(), "resolvedId", id))
133}
134
135func TestGetBaseRepoPath_PrefersResolvedHandleOverChiDid(t *testing.T) {
136 r := reqWithResolvedId("boltless.dev", "did:plc:boltless")
137 repo := &models.Repo{Did: "did:plc:boltless", Name: "anemone", Rkey: "3kabcxyz"}
138 got := GetBaseRepoPath(r, repo)
139 want := "boltless.dev/anemone"
140 if got != want {
141 t.Errorf("GetBaseRepoPath = %q, want %q", got, want)
142 }
143}
144
145func TestGetBaseRepoPath_InvalidHandleFallsThroughToChi(t *testing.T) {
146 r := reqWithChiParams("did:plc:boltless", "limpet")
147 id := identity.Identity{
148 DID: syntax.DID("did:plc:boltless"),
149 Handle: syntax.HandleInvalid,
150 }
151 r = r.WithContext(context.WithValue(r.Context(), "resolvedId", id))
152 repo := &models.Repo{Did: "did:plc:boltless", Name: "limpet", Rkey: "limpet"}
153 if got, want := GetBaseRepoPath(r, repo), "did:plc:boltless/limpet"; got != want {
154 t.Errorf("GetBaseRepoPath = %q, want %q", got, want)
155 }
156}