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}