+1
-1
package.json
+1
-1
package.json
+39
-35
test/e2e.sh
+39
-35
test/e2e.sh
···
7
7
8
8
# Helper for colored output
9
9
pass() { echo "✓ $1"; }
10
-
fail() { echo "✗ $1" >&2; cleanup; exit 1; }
10
+
fail() {
11
+
echo "✗ $1" >&2
12
+
cleanup
13
+
exit 1
14
+
}
11
15
12
16
# Cleanup function
13
17
cleanup() {
···
21
25
22
26
# Start wrangler dev
23
27
echo "Starting wrangler dev..."
24
-
npx wrangler dev --port 8787 > /dev/null 2>&1 &
28
+
npx wrangler dev --port 8787 >/dev/null 2>&1 &
25
29
WRANGLER_PID=$!
26
30
27
31
# Wait for server to be ready
28
32
for i in {1..30}; do
29
-
if curl -sf "$BASE/" > /dev/null 2>&1; then
33
+
if curl -sf "$BASE/" >/dev/null 2>&1; then
30
34
break
31
35
fi
32
36
sleep 0.5
33
37
done
34
38
35
39
# Verify server is up
36
-
curl -sf "$BASE/" > /dev/null || fail "Server failed to start"
40
+
curl -sf "$BASE/" >/dev/null || fail "Server failed to start"
37
41
pass "Server started"
38
42
39
43
# Initialize PDS
40
44
PRIVKEY=$(openssl rand -hex 32)
41
45
curl -sf -X POST "$BASE/init?did=$DID" \
42
46
-H "Content-Type: application/json" \
43
-
-d "{\"did\":\"$DID\",\"privateKey\":\"$PRIVKEY\",\"handle\":\"test.local\"}" > /dev/null \
44
-
&& pass "PDS initialized" || fail "PDS init"
47
+
-d "{\"did\":\"$DID\",\"privateKey\":\"$PRIVKEY\",\"handle\":\"test.local\"}" >/dev/null &&
48
+
pass "PDS initialized" || fail "PDS init"
45
49
46
50
echo
47
51
echo "Running tests..."
···
51
55
curl -sf "$BASE/" | grep -q "PDS" && pass "Root returns ASCII art" || fail "Root"
52
56
53
57
# 2. describeServer works
54
-
curl -sf "$BASE/xrpc/com.atproto.server.describeServer" | jq -e '.did' > /dev/null \
55
-
&& pass "describeServer" || fail "describeServer"
58
+
curl -sf "$BASE/xrpc/com.atproto.server.describeServer" | jq -e '.did' >/dev/null &&
59
+
pass "describeServer" || fail "describeServer"
56
60
57
61
# 3. resolveHandle works
58
-
curl -sf "$BASE/xrpc/com.atproto.identity.resolveHandle?handle=test.local" \
59
-
| jq -e '.did' > /dev/null && pass "resolveHandle" || fail "resolveHandle"
62
+
curl -sf "$BASE/xrpc/com.atproto.identity.resolveHandle?handle=test.local" |
63
+
jq -e '.did' >/dev/null && pass "resolveHandle" || fail "resolveHandle"
60
64
61
65
# 4. createSession returns tokens
62
66
SESSION=$(curl -sf -X POST "$BASE/xrpc/com.atproto.server.createSession" \
···
67
71
68
72
# 5. getSession works with token
69
73
curl -sf "$BASE/xrpc/com.atproto.server.getSession" \
70
-
-H "Authorization: Bearer $TOKEN" | jq -e '.did' > /dev/null \
71
-
&& pass "getSession with valid token" || fail "getSession"
74
+
-H "Authorization: Bearer $TOKEN" | jq -e '.did' >/dev/null &&
75
+
pass "getSession with valid token" || fail "getSession"
72
76
73
77
# 6. Protected endpoint rejects without auth
74
78
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$BASE/xrpc/com.atproto.repo.createRecord" \
···
78
82
79
83
# 7. getPreferences works (returns empty array initially)
80
84
curl -sf "$BASE/xrpc/app.bsky.actor.getPreferences" \
81
-
-H "Authorization: Bearer $TOKEN" | jq -e '.preferences' > /dev/null \
82
-
&& pass "getPreferences" || fail "getPreferences"
85
+
-H "Authorization: Bearer $TOKEN" | jq -e '.preferences' >/dev/null &&
86
+
pass "getPreferences" || fail "getPreferences"
83
87
84
88
# 8. putPreferences works
85
89
curl -sf -X POST "$BASE/xrpc/app.bsky.actor.putPreferences" \
86
90
-H "Authorization: Bearer $TOKEN" \
87
91
-H "Content-Type: application/json" \
88
-
-d '{"preferences":[{"$type":"app.bsky.actor.defs#savedFeedsPrefV2"}]}' > /dev/null \
89
-
&& pass "putPreferences" || fail "putPreferences"
92
+
-d '{"preferences":[{"$type":"app.bsky.actor.defs#savedFeedsPrefV2"}]}' >/dev/null &&
93
+
pass "putPreferences" || fail "putPreferences"
90
94
91
95
# 9. createRecord works with auth
92
96
RECORD=$(curl -sf -X POST "$BASE/xrpc/com.atproto.repo.createRecord" \
···
98
102
99
103
# 10. getRecord retrieves it
100
104
RKEY=$(echo "$URI" | sed 's|.*/||')
101
-
curl -sf "$BASE/xrpc/com.atproto.repo.getRecord?repo=$DID&collection=app.bsky.feed.post&rkey=$RKEY" \
102
-
| jq -e '.value.text' > /dev/null && pass "getRecord" || fail "getRecord"
105
+
curl -sf "$BASE/xrpc/com.atproto.repo.getRecord?repo=$DID&collection=app.bsky.feed.post&rkey=$RKEY" |
106
+
jq -e '.value.text' >/dev/null && pass "getRecord" || fail "getRecord"
103
107
104
108
# 11. putRecord updates the record
105
109
curl -sf -X POST "$BASE/xrpc/com.atproto.repo.putRecord" \
106
110
-H "Authorization: Bearer $TOKEN" \
107
111
-H "Content-Type: application/json" \
108
-
-d "{\"repo\":\"$DID\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"$RKEY\",\"record\":{\"text\":\"updated\",\"createdAt\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}}" \
109
-
| jq -e '.uri' > /dev/null && pass "putRecord" || fail "putRecord"
112
+
-d "{\"repo\":\"$DID\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"$RKEY\",\"record\":{\"text\":\"updated\",\"createdAt\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}}" |
113
+
jq -e '.uri' >/dev/null && pass "putRecord" || fail "putRecord"
110
114
111
115
# 12. listRecords shows the record
112
-
curl -sf "$BASE/xrpc/com.atproto.repo.listRecords?repo=$DID&collection=app.bsky.feed.post" \
113
-
| jq -e '.records | length > 0' > /dev/null && pass "listRecords" || fail "listRecords"
116
+
curl -sf "$BASE/xrpc/com.atproto.repo.listRecords?repo=$DID&collection=app.bsky.feed.post" |
117
+
jq -e '.records | length > 0' >/dev/null && pass "listRecords" || fail "listRecords"
114
118
115
119
# 13. describeRepo returns repo info
116
-
curl -sf "$BASE/xrpc/com.atproto.repo.describeRepo?repo=$DID" \
117
-
| jq -e '.did' > /dev/null && pass "describeRepo" || fail "describeRepo"
120
+
curl -sf "$BASE/xrpc/com.atproto.repo.describeRepo?repo=$DID" |
121
+
jq -e '.did' >/dev/null && pass "describeRepo" || fail "describeRepo"
118
122
119
123
# 14. applyWrites batch operation (create then delete a record)
120
124
APPLY_RESULT=$(curl -sf -X POST "$BASE/xrpc/com.atproto.repo.applyWrites" \
121
125
-H "Authorization: Bearer $TOKEN" \
122
126
-H "Content-Type: application/json" \
123
127
-d "{\"repo\":\"$DID\",\"writes\":[{\"\$type\":\"com.atproto.repo.applyWrites#create\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"applytest\",\"value\":{\"text\":\"batch\",\"createdAt\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}}]}")
124
-
echo "$APPLY_RESULT" | jq -e '.results' > /dev/null && pass "applyWrites create" || fail "applyWrites create"
128
+
echo "$APPLY_RESULT" | jq -e '.results' >/dev/null && pass "applyWrites create" || fail "applyWrites create"
125
129
126
130
# 15. applyWrites delete
127
131
curl -sf -X POST "$BASE/xrpc/com.atproto.repo.applyWrites" \
128
132
-H "Authorization: Bearer $TOKEN" \
129
133
-H "Content-Type: application/json" \
130
-
-d "{\"repo\":\"$DID\",\"writes\":[{\"\$type\":\"com.atproto.repo.applyWrites#delete\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"applytest\"}]}" \
131
-
| jq -e '.results' > /dev/null && pass "applyWrites delete" || fail "applyWrites delete"
134
+
-d "{\"repo\":\"$DID\",\"writes\":[{\"\$type\":\"com.atproto.repo.applyWrites#delete\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"applytest\"}]}" |
135
+
jq -e '.results' >/dev/null && pass "applyWrites delete" || fail "applyWrites delete"
132
136
133
137
# 16. sync.getLatestCommit returns head
134
-
curl -sf "$BASE/xrpc/com.atproto.sync.getLatestCommit?did=$DID" \
135
-
| jq -e '.cid' > /dev/null && pass "sync.getLatestCommit" || fail "sync.getLatestCommit"
138
+
curl -sf "$BASE/xrpc/com.atproto.sync.getLatestCommit?did=$DID" |
139
+
jq -e '.cid' >/dev/null && pass "sync.getLatestCommit" || fail "sync.getLatestCommit"
136
140
137
141
# 17. sync.getRepoStatus returns status
138
-
curl -sf "$BASE/xrpc/com.atproto.sync.getRepoStatus?did=$DID" \
139
-
| jq -e '.did' > /dev/null && pass "sync.getRepoStatus" || fail "sync.getRepoStatus"
142
+
curl -sf "$BASE/xrpc/com.atproto.sync.getRepoStatus?did=$DID" |
143
+
jq -e '.did' >/dev/null && pass "sync.getRepoStatus" || fail "sync.getRepoStatus"
140
144
141
145
# 18. sync.getRepo returns CAR file
142
146
REPO_SIZE=$(curl -sf "$BASE/xrpc/com.atproto.sync.getRepo?did=$DID" | wc -c)
···
147
151
[ "$RECORD_SIZE" -gt 50 ] && pass "sync.getRecord" || fail "sync.getRecord"
148
152
149
153
# 20. sync.listRepos lists repos
150
-
curl -sf "$BASE/xrpc/com.atproto.sync.listRepos" \
151
-
| jq -e '.repos | length > 0' > /dev/null && pass "sync.listRepos" || fail "sync.listRepos"
154
+
curl -sf "$BASE/xrpc/com.atproto.sync.listRepos" |
155
+
jq -e '.repos | length > 0' >/dev/null && pass "sync.listRepos" || fail "sync.listRepos"
152
156
153
157
# Error handling tests
154
158
echo
···
175
179
curl -sf -X POST "$BASE/xrpc/com.atproto.repo.deleteRecord" \
176
180
-H "Authorization: Bearer $TOKEN" \
177
181
-H "Content-Type: application/json" \
178
-
-d "{\"repo\":\"$DID\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"$RKEY\"}" > /dev/null \
179
-
&& pass "deleteRecord (cleanup)" || fail "deleteRecord"
182
+
-d "{\"repo\":\"$DID\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"$RKEY\"}" >/dev/null &&
183
+
pass "deleteRecord (cleanup)" || fail "deleteRecord"
180
184
181
185
echo
182
186
echo "All tests passed!"