A community based topic aggregation platform built on atproto
1package handlers 2 3import ( 4 "bytes" 5 "encoding/json" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9 10 "Coves/internal/core/repository" 11 "github.com/ipfs/go-cid" 12) 13 14// MockRepositoryService is a mock implementation for testing 15type MockRepositoryService struct { 16 repositories map[string]*repository.Repository 17 records map[string]*repository.Record 18} 19 20func NewMockRepositoryService() *MockRepositoryService { 21 return &MockRepositoryService{ 22 repositories: make(map[string]*repository.Repository), 23 records: make(map[string]*repository.Record), 24 } 25} 26 27func (m *MockRepositoryService) CreateRepository(did string) (*repository.Repository, error) { 28 repo := &repository.Repository{ 29 DID: did, 30 HeadCID: cid.Undef, 31 } 32 m.repositories[did] = repo 33 return repo, nil 34} 35 36func (m *MockRepositoryService) GetRepository(did string) (*repository.Repository, error) { 37 repo, exists := m.repositories[did] 38 if !exists { 39 return nil, nil 40 } 41 return repo, nil 42} 43 44func (m *MockRepositoryService) DeleteRepository(did string) error { 45 delete(m.repositories, did) 46 return nil 47} 48 49func (m *MockRepositoryService) CreateRecord(input repository.CreateRecordInput) (*repository.Record, error) { 50 uri := "at://" + input.DID + "/" + input.Collection + "/" + input.RecordKey 51 record := &repository.Record{ 52 URI: uri, 53 CID: cid.Undef, 54 Collection: input.Collection, 55 RecordKey: input.RecordKey, 56 Value: []byte(`{"test": "data"}`), 57 } 58 m.records[uri] = record 59 return record, nil 60} 61 62func (m *MockRepositoryService) GetRecord(input repository.GetRecordInput) (*repository.Record, error) { 63 uri := "at://" + input.DID + "/" + input.Collection + "/" + input.RecordKey 64 record, exists := m.records[uri] 65 if !exists { 66 return nil, nil 67 } 68 return record, nil 69} 70 71func (m *MockRepositoryService) UpdateRecord(input repository.UpdateRecordInput) (*repository.Record, error) { 72 uri := "at://" + input.DID + "/" + input.Collection + "/" + input.RecordKey 73 record := &repository.Record{ 74 URI: uri, 75 CID: cid.Undef, 76 Collection: input.Collection, 77 RecordKey: input.RecordKey, 78 Value: []byte(`{"test": "updated"}`), 79 } 80 m.records[uri] = record 81 return record, nil 82} 83 84func (m *MockRepositoryService) DeleteRecord(input repository.DeleteRecordInput) error { 85 uri := "at://" + input.DID + "/" + input.Collection + "/" + input.RecordKey 86 delete(m.records, uri) 87 return nil 88} 89 90func (m *MockRepositoryService) ListRecords(did string, collection string, limit int, cursor string) ([]*repository.Record, string, error) { 91 var records []*repository.Record 92 for _, record := range m.records { 93 if record.Collection == collection { 94 records = append(records, record) 95 } 96 } 97 return records, "", nil 98} 99 100func (m *MockRepositoryService) GetCommit(did string, cid cid.Cid) (*repository.Commit, error) { 101 return nil, nil 102} 103 104func (m *MockRepositoryService) ListCommits(did string, limit int, cursor string) ([]*repository.Commit, string, error) { 105 return []*repository.Commit{}, "", nil 106} 107 108func (m *MockRepositoryService) ExportRepository(did string) ([]byte, error) { 109 return []byte("mock-car-data"), nil 110} 111 112func (m *MockRepositoryService) ImportRepository(did string, carData []byte) error { 113 return nil 114} 115 116func TestCreateRecordHandler(t *testing.T) { 117 mockService := NewMockRepositoryService() 118 handler := NewRepositoryHandler(mockService) 119 120 // Create test request 121 reqData := CreateRecordRequest{ 122 Repo: "did:plc:test123", 123 Collection: "app.bsky.feed.post", 124 RKey: "testkey", 125 Record: json.RawMessage(`{"text": "Hello, world!"}`), 126 } 127 128 reqBody, err := json.Marshal(reqData) 129 if err != nil { 130 t.Fatalf("Failed to marshal request: %v", err) 131 } 132 133 req := httptest.NewRequest("POST", "/xrpc/com.atproto.repo.createRecord", bytes.NewReader(reqBody)) 134 req.Header.Set("Content-Type", "application/json") 135 w := httptest.NewRecorder() 136 137 // Call handler 138 handler.CreateRecord(w, req) 139 140 // Check response 141 if w.Code != http.StatusOK { 142 t.Errorf("Expected status 200, got %d", w.Code) 143 } 144 145 var resp CreateRecordResponse 146 if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { 147 t.Fatalf("Failed to decode response: %v", err) 148 } 149 150 expectedURI := "at://did:plc:test123/app.bsky.feed.post/testkey" 151 if resp.URI != expectedURI { 152 t.Errorf("Expected URI %s, got %s", expectedURI, resp.URI) 153 } 154} 155 156func TestGetRecordHandler(t *testing.T) { 157 mockService := NewMockRepositoryService() 158 handler := NewRepositoryHandler(mockService) 159 160 // Create a test record first 161 uri := "at://did:plc:test123/app.bsky.feed.post/testkey" 162 testRecord := &repository.Record{ 163 URI: uri, 164 CID: cid.Undef, 165 Collection: "app.bsky.feed.post", 166 RecordKey: "testkey", 167 Value: []byte(`{"text": "Hello, world!"}`), 168 } 169 mockService.records[uri] = testRecord 170 171 // Create test request 172 req := httptest.NewRequest("GET", "/xrpc/com.atproto.repo.getRecord?repo=did:plc:test123&collection=app.bsky.feed.post&rkey=testkey", nil) 173 w := httptest.NewRecorder() 174 175 // Call handler 176 handler.GetRecord(w, req) 177 178 // Check response 179 if w.Code != http.StatusOK { 180 t.Errorf("Expected status 200, got %d", w.Code) 181 } 182 183 var resp GetRecordResponse 184 if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { 185 t.Fatalf("Failed to decode response: %v", err) 186 } 187 188 if resp.URI != uri { 189 t.Errorf("Expected URI %s, got %s", uri, resp.URI) 190 } 191}