Social Annotations in the Atmosphere
15
fork

Configure Feed

Select the types of activity you want to include in your feed.

Testing Guide#

Running Tests#

Integration Tests#

cd server
go test ./internal/service -v

Manual Testing Checklist#

Setup#

  • Enter Nix shell: nix develop (from repo root)
  • Download dependencies: cd server && go mod download
  • Start server: cd server && go run cmd/server/main.go
  • Verify server starts: Should see "Server starting on :8080"
  • Health check: curl http://localhost:8080/health
  • Expected: {"status":"healthy"}
  • Verify DB created: ls -lh db/annotations.db

Extension → Backend Flow#

Create Annotation#

  • Load extension in browser
  • Navigate to test page: https://example.com
  • Select text and create annotation
  • Extension should call POST http://localhost:8080/api/annotations/index
  • Check server logs: Should see "Indexing annotation: at://..."
  • Check server logs: Should see "Successfully indexed annotation"

Verify Database#

sqlite3 server/db/annotations.db "SELECT uri, target_url, exact_text FROM annotations;"
  • Verify record exists
  • Verify target_url is normalized (no fragment)
  • Verify exact_text contains selected text

Query Flow#

Create Multiple Annotations#

  • Create 3 annotations on https://example.com/test
  • Create 2 annotations on https://other.com/page

Query by URL#

curl "http://localhost:8080/api/annotations?url=https://example.com/test"
  • Returns JSON with annotations array
  • count field shows 3
  • Annotations sorted by createdAt DESC (newest first)
  • Each annotation has uri, cid, authorDid, targetUrl, selectors, etc.

Query with Limit#

curl "http://localhost:8080/api/annotations?url=https://example.com/test&limit=2"
  • Returns only 2 annotations
  • Returns most recent 2

Edge Cases#

Upsert (Duplicate Prevention)#

  • Create annotation, note the URI
  • Call index endpoint again with same URI but different CID
curl -X POST http://localhost:8080/api/annotations/index \
  -H "Content-Type: application/json" \
  -d '{"uri":"at://did:plc:test/col/rkey","cid":"new-cid"}'
  • Query database: Should have only 1 record (upserted)
  • CID should be updated to "new-cid"

Delete Annotation#

# Get URI from query
curl "http://localhost:8080/api/annotations?url=https://example.com/test"

# Delete one (URI as query parameter)
curl -X DELETE "http://localhost:8080/api/annotations?uri=at://did:plc:test/col/rkey"
  • Response: {"success":true,"uri":"..."}
  • Query again: Count decreased by 1
  • Database: Record removed

URL Normalization#

  • Create annotation on https://example.com/page#section

  • Query with https://example.com/page (no fragment)

  • Should return the annotation (URLs normalized)

  • Create annotation on https://example.com/page/

  • Query with https://example.com/page (no trailing slash)

  • Should return the annotation

Error Handling#

Invalid Requests#

# Missing URI
curl -X POST http://localhost:8080/api/annotations/index \
  -H "Content-Type: application/json" \
  -d '{"cid":"test"}'
  • Response: 400 Bad Request
  • Body: "uri is required"
# Missing URL parameter
curl "http://localhost:8080/api/annotations"
  • Response: 400 Bad Request
  • Body: "url parameter is required"
# Invalid URL
curl "http://localhost:8080/api/annotations?url=not-a-url"
  • Response: 500 Internal Server Error (or handle gracefully)

ATProto Fetch Failures#

  • Create index request with fake DID
curl -X POST http://localhost:8080/api/annotations/index \
  -H "Content-Type: application/json" \
  -d '{"uri":"at://did:plc:fake123/col/rkey","cid":"test"}'
  • Response: 500 Internal Server Error
  • Server logs: "Failed to fetch record: ..."
  • Database: No record inserted

Performance#

Bulk Insert Test#

Create test script scripts/bulk-insert.sh:

#!/bin/bash
for i in {1..1000}; do
  curl -X POST http://localhost:8080/api/annotations/index \
    -H "Content-Type: application/json" \
    -d "{\"uri\":\"at://did:plc:test/col/rkey$i\",\"cid\":\"cid$i\"}" \
    -s -o /dev/null &
done
wait
  • Run script: bash scripts/bulk-insert.sh
  • Check database size: ls -lh db/annotations.db
  • Query performance:
time curl "http://localhost:8080/api/annotations?url=https://example.com/test"
  • Should complete in <100ms

Database Inspection#

# Count total annotations
sqlite3 server/db/annotations.db "SELECT COUNT(*) FROM annotations;"

# Check index usage
sqlite3 server/db/annotations.db "EXPLAIN QUERY PLAN SELECT * FROM annotations WHERE target_url = 'https://example.com';"

# View all records
sqlite3 server/db/annotations.db "SELECT uri, target_url, created_at FROM annotations ORDER BY created_at DESC LIMIT 10;"

Environment Variables#

Custom Database Path#

DB_PATH=/tmp/test-annotations.db go run cmd/server/main.go
  • Verify database created at /tmp/test-annotations.db

Custom Port#

PORT=3000 go run cmd/server/main.go
  • Server starts on port 3000
  • Health check: curl http://localhost:3000/health

CORS Testing#

Browser Request#

Open browser console on https://example.com:

fetch('http://localhost:8080/api/annotations?url=https://example.com')
  .then(r => r.json())
  .then(console.log)
  • Request succeeds (CORS enabled)
  • Response contains annotations

Clean Up#

# Stop server (Ctrl+C)

# Remove database
rm -rf server/db

# Remove test data
rm /tmp/test-annotations.db