diff --git a/package.json b/package.json index 637168f..3077042 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "test": "node --test test/*.test.js", "test:e2e": "./test/e2e.sh", "setup": "node scripts/setup.js", - "format": "biome format --write .", + "format": "biome format --write . && shfmt -w -i 2 test/*.sh", "lint": "biome lint .", "check": "biome check ." }, diff --git a/test/e2e.sh b/test/e2e.sh index 065e146..568146e 100755 --- a/test/e2e.sh +++ b/test/e2e.sh @@ -7,7 +7,11 @@ DID="did:plc:c6vxslynzebnlk5kw2orx37o" # Helper for colored output pass() { echo "✓ $1"; } -fail() { echo "✗ $1" >&2; cleanup; exit 1; } +fail() { + echo "✗ $1" >&2 + cleanup + exit 1 +} # Cleanup function cleanup() { @@ -21,27 +25,27 @@ trap cleanup EXIT # Start wrangler dev echo "Starting wrangler dev..." -npx wrangler dev --port 8787 > /dev/null 2>&1 & +npx wrangler dev --port 8787 >/dev/null 2>&1 & WRANGLER_PID=$! # Wait for server to be ready for i in {1..30}; do - if curl -sf "$BASE/" > /dev/null 2>&1; then + if curl -sf "$BASE/" >/dev/null 2>&1; then break fi sleep 0.5 done # Verify server is up -curl -sf "$BASE/" > /dev/null || fail "Server failed to start" +curl -sf "$BASE/" >/dev/null || fail "Server failed to start" pass "Server started" # Initialize PDS PRIVKEY=$(openssl rand -hex 32) curl -sf -X POST "$BASE/init?did=$DID" \ -H "Content-Type: application/json" \ - -d "{\"did\":\"$DID\",\"privateKey\":\"$PRIVKEY\",\"handle\":\"test.local\"}" > /dev/null \ - && pass "PDS initialized" || fail "PDS init" + -d "{\"did\":\"$DID\",\"privateKey\":\"$PRIVKEY\",\"handle\":\"test.local\"}" >/dev/null && + pass "PDS initialized" || fail "PDS init" echo echo "Running tests..." @@ -51,12 +55,12 @@ echo curl -sf "$BASE/" | grep -q "PDS" && pass "Root returns ASCII art" || fail "Root" # 2. describeServer works -curl -sf "$BASE/xrpc/com.atproto.server.describeServer" | jq -e '.did' > /dev/null \ - && pass "describeServer" || fail "describeServer" +curl -sf "$BASE/xrpc/com.atproto.server.describeServer" | jq -e '.did' >/dev/null && + pass "describeServer" || fail "describeServer" # 3. resolveHandle works -curl -sf "$BASE/xrpc/com.atproto.identity.resolveHandle?handle=test.local" \ - | jq -e '.did' > /dev/null && pass "resolveHandle" || fail "resolveHandle" +curl -sf "$BASE/xrpc/com.atproto.identity.resolveHandle?handle=test.local" | + jq -e '.did' >/dev/null && pass "resolveHandle" || fail "resolveHandle" # 4. createSession returns tokens SESSION=$(curl -sf -X POST "$BASE/xrpc/com.atproto.server.createSession" \ @@ -67,8 +71,8 @@ TOKEN=$(echo "$SESSION" | jq -r '.accessJwt') # 5. getSession works with token curl -sf "$BASE/xrpc/com.atproto.server.getSession" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.did' > /dev/null \ - && pass "getSession with valid token" || fail "getSession" + -H "Authorization: Bearer $TOKEN" | jq -e '.did' >/dev/null && + pass "getSession with valid token" || fail "getSession" # 6. Protected endpoint rejects without auth STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$BASE/xrpc/com.atproto.repo.createRecord" \ @@ -78,15 +82,15 @@ STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$BASE/xrpc/com.atproto. # 7. getPreferences works (returns empty array initially) curl -sf "$BASE/xrpc/app.bsky.actor.getPreferences" \ - -H "Authorization: Bearer $TOKEN" | jq -e '.preferences' > /dev/null \ - && pass "getPreferences" || fail "getPreferences" + -H "Authorization: Bearer $TOKEN" | jq -e '.preferences' >/dev/null && + pass "getPreferences" || fail "getPreferences" # 8. putPreferences works curl -sf -X POST "$BASE/xrpc/app.bsky.actor.putPreferences" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ - -d '{"preferences":[{"$type":"app.bsky.actor.defs#savedFeedsPrefV2"}]}' > /dev/null \ - && pass "putPreferences" || fail "putPreferences" + -d '{"preferences":[{"$type":"app.bsky.actor.defs#savedFeedsPrefV2"}]}' >/dev/null && + pass "putPreferences" || fail "putPreferences" # 9. createRecord works with auth RECORD=$(curl -sf -X POST "$BASE/xrpc/com.atproto.repo.createRecord" \ @@ -98,45 +102,45 @@ URI=$(echo "$RECORD" | jq -r '.uri') # 10. getRecord retrieves it RKEY=$(echo "$URI" | sed 's|.*/||') -curl -sf "$BASE/xrpc/com.atproto.repo.getRecord?repo=$DID&collection=app.bsky.feed.post&rkey=$RKEY" \ - | jq -e '.value.text' > /dev/null && pass "getRecord" || fail "getRecord" +curl -sf "$BASE/xrpc/com.atproto.repo.getRecord?repo=$DID&collection=app.bsky.feed.post&rkey=$RKEY" | + jq -e '.value.text' >/dev/null && pass "getRecord" || fail "getRecord" # 11. putRecord updates the record curl -sf -X POST "$BASE/xrpc/com.atproto.repo.putRecord" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ - -d "{\"repo\":\"$DID\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"$RKEY\",\"record\":{\"text\":\"updated\",\"createdAt\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}}" \ - | jq -e '.uri' > /dev/null && pass "putRecord" || fail "putRecord" + -d "{\"repo\":\"$DID\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"$RKEY\",\"record\":{\"text\":\"updated\",\"createdAt\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}}" | + jq -e '.uri' >/dev/null && pass "putRecord" || fail "putRecord" # 12. listRecords shows the record -curl -sf "$BASE/xrpc/com.atproto.repo.listRecords?repo=$DID&collection=app.bsky.feed.post" \ - | jq -e '.records | length > 0' > /dev/null && pass "listRecords" || fail "listRecords" +curl -sf "$BASE/xrpc/com.atproto.repo.listRecords?repo=$DID&collection=app.bsky.feed.post" | + jq -e '.records | length > 0' >/dev/null && pass "listRecords" || fail "listRecords" # 13. describeRepo returns repo info -curl -sf "$BASE/xrpc/com.atproto.repo.describeRepo?repo=$DID" \ - | jq -e '.did' > /dev/null && pass "describeRepo" || fail "describeRepo" +curl -sf "$BASE/xrpc/com.atproto.repo.describeRepo?repo=$DID" | + jq -e '.did' >/dev/null && pass "describeRepo" || fail "describeRepo" # 14. applyWrites batch operation (create then delete a record) APPLY_RESULT=$(curl -sf -X POST "$BASE/xrpc/com.atproto.repo.applyWrites" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -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)\"}}]}") -echo "$APPLY_RESULT" | jq -e '.results' > /dev/null && pass "applyWrites create" || fail "applyWrites create" +echo "$APPLY_RESULT" | jq -e '.results' >/dev/null && pass "applyWrites create" || fail "applyWrites create" # 15. applyWrites delete curl -sf -X POST "$BASE/xrpc/com.atproto.repo.applyWrites" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ - -d "{\"repo\":\"$DID\",\"writes\":[{\"\$type\":\"com.atproto.repo.applyWrites#delete\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"applytest\"}]}" \ - | jq -e '.results' > /dev/null && pass "applyWrites delete" || fail "applyWrites delete" + -d "{\"repo\":\"$DID\",\"writes\":[{\"\$type\":\"com.atproto.repo.applyWrites#delete\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"applytest\"}]}" | + jq -e '.results' >/dev/null && pass "applyWrites delete" || fail "applyWrites delete" # 16. sync.getLatestCommit returns head -curl -sf "$BASE/xrpc/com.atproto.sync.getLatestCommit?did=$DID" \ - | jq -e '.cid' > /dev/null && pass "sync.getLatestCommit" || fail "sync.getLatestCommit" +curl -sf "$BASE/xrpc/com.atproto.sync.getLatestCommit?did=$DID" | + jq -e '.cid' >/dev/null && pass "sync.getLatestCommit" || fail "sync.getLatestCommit" # 17. sync.getRepoStatus returns status -curl -sf "$BASE/xrpc/com.atproto.sync.getRepoStatus?did=$DID" \ - | jq -e '.did' > /dev/null && pass "sync.getRepoStatus" || fail "sync.getRepoStatus" +curl -sf "$BASE/xrpc/com.atproto.sync.getRepoStatus?did=$DID" | + jq -e '.did' >/dev/null && pass "sync.getRepoStatus" || fail "sync.getRepoStatus" # 18. sync.getRepo returns CAR file REPO_SIZE=$(curl -sf "$BASE/xrpc/com.atproto.sync.getRepo?did=$DID" | wc -c) @@ -147,8 +151,8 @@ RECORD_SIZE=$(curl -sf "$BASE/xrpc/com.atproto.sync.getRecord?did=$DID&collectio [ "$RECORD_SIZE" -gt 50 ] && pass "sync.getRecord" || fail "sync.getRecord" # 20. sync.listRepos lists repos -curl -sf "$BASE/xrpc/com.atproto.sync.listRepos" \ - | jq -e '.repos | length > 0' > /dev/null && pass "sync.listRepos" || fail "sync.listRepos" +curl -sf "$BASE/xrpc/com.atproto.sync.listRepos" | + jq -e '.repos | length > 0' >/dev/null && pass "sync.listRepos" || fail "sync.listRepos" # Error handling tests echo @@ -175,8 +179,8 @@ STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/xrpc/com.atproto.repo.get curl -sf -X POST "$BASE/xrpc/com.atproto.repo.deleteRecord" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ - -d "{\"repo\":\"$DID\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"$RKEY\"}" > /dev/null \ - && pass "deleteRecord (cleanup)" || fail "deleteRecord" + -d "{\"repo\":\"$DID\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"$RKEY\"}" >/dev/null && + pass "deleteRecord (cleanup)" || fail "deleteRecord" echo echo "All tests passed!"