A community based topic aggregation platform built on atproto

test: update tests for lexicon migration and selfLabels structure

Updates all tests to use new social.coves.community.post namespace and
structured com.atproto.label.defs#selfLabels format.

Changes:
- Update test data to match new lexicon schema (author field, facets, etc)
- Update integration tests to use SelfLabels{Values: []SelfLabel{...}}
- Update vote_repo_test to use new namespace
- Update post creation tests for label validation
- Update E2E tests for community post namespace

All lexicon validation tests passing (64 pass, 2 skip for defs files).
All integration tests passing with JSONB label storage.

+165 -127
+11 -11
internal/db/postgres/vote_repo_test.go
··· 67 67 CID: "bafyreigtest123", 68 68 RKey: "3k1234567890", 69 69 VoterDID: voterDID, 70 - SubjectURI: "at://did:plc:community/social.coves.post.record/abc123", 70 + SubjectURI: "at://did:plc:community/social.coves.community.post/abc123", 71 71 SubjectCID: "bafyreigpost123", 72 72 Direction: "up", 73 73 CreatedAt: time.Now(), ··· 95 95 CID: "bafyreigtest456", 96 96 RKey: "3k9876543210", 97 97 VoterDID: voterDID, 98 - SubjectURI: "at://did:plc:community/social.coves.post.record/xyz789", 98 + SubjectURI: "at://did:plc:community/social.coves.community.post/xyz789", 99 99 SubjectCID: "bafyreigpost456", 100 100 Direction: "down", 101 101 CreatedAt: time.Now(), ··· 136 136 CID: "bafyreignovoter", 137 137 RKey: "3k1111111111", 138 138 VoterDID: "did:plc:nonexistentvoter", 139 - SubjectURI: "at://did:plc:community/social.coves.post.record/test123", 139 + SubjectURI: "at://did:plc:community/social.coves.community.post/test123", 140 140 SubjectCID: "bafyreigpost789", 141 141 Direction: "up", 142 142 CreatedAt: time.Now(), ··· 168 168 CID: "bafyreigtest789", 169 169 RKey: "3k5555555555", 170 170 VoterDID: voterDID, 171 - SubjectURI: "at://did:plc:community/social.coves.post.record/post123", 171 + SubjectURI: "at://did:plc:community/social.coves.community.post/post123", 172 172 SubjectCID: "bafyreigpost999", 173 173 Direction: "up", 174 174 CreatedAt: time.Now(), ··· 207 207 voterDID := "did:plc:testvoter999" 208 208 createTestUser(t, db, "testvoter999.test", voterDID) 209 209 210 - subjectURI := "at://did:plc:community/social.coves.post.record/subject123" 210 + subjectURI := "at://did:plc:community/social.coves.community.post/subject123" 211 211 212 212 // Create vote 213 213 vote := &votes.Vote{ ··· 238 238 repo := NewVoteRepository(db) 239 239 ctx := context.Background() 240 240 241 - _, err := repo.GetByVoterAndSubject(ctx, "did:plc:nobody", "at://did:plc:community/social.coves.post.record/nopost") 241 + _, err := repo.GetByVoterAndSubject(ctx, "did:plc:nobody", "at://did:plc:community/social.coves.community.post/nopost") 242 242 assert.ErrorIs(t, err, votes.ErrVoteNotFound) 243 243 } 244 244 ··· 259 259 CID: "bafyreigdelete", 260 260 RKey: "3k7777777777", 261 261 VoterDID: voterDID, 262 - SubjectURI: "at://did:plc:community/social.coves.post.record/deletetest", 262 + SubjectURI: "at://did:plc:community/social.coves.community.post/deletetest", 263 263 SubjectCID: "bafyreigdeletepost", 264 264 Direction: "up", 265 265 CreatedAt: time.Now(), ··· 297 297 CID: "bafyreigdelete2", 298 298 RKey: "3k8888888888", 299 299 VoterDID: voterDID, 300 - SubjectURI: "at://did:plc:community/social.coves.post.record/deletetest2", 300 + SubjectURI: "at://did:plc:community/social.coves.community.post/deletetest2", 301 301 SubjectCID: "bafyreigdeletepost2", 302 302 Direction: "down", 303 303 CreatedAt: time.Now(), ··· 327 327 createTestUser(t, db, "testvoterlist1.test", voterDID1) 328 328 createTestUser(t, db, "testvoterlist2.test", voterDID2) 329 329 330 - subjectURI := "at://did:plc:community/social.coves.post.record/listtest" 330 + subjectURI := "at://did:plc:community/social.coves.community.post/listtest" 331 331 332 332 // Create multiple votes on same subject 333 333 vote1 := &votes.Vote{ ··· 377 377 CID: "bafyreigvoter1", 378 378 RKey: "3k0000000001", 379 379 VoterDID: voterDID, 380 - SubjectURI: "at://did:plc:community/social.coves.post.record/post1", 380 + SubjectURI: "at://did:plc:community/social.coves.community.post/post1", 381 381 SubjectCID: "bafyreigp1", 382 382 Direction: "up", 383 383 CreatedAt: time.Now(), ··· 387 387 CID: "bafyreigvoter2", 388 388 RKey: "3k0000000002", 389 389 VoterDID: voterDID, 390 - SubjectURI: "at://did:plc:community/social.coves.post.record/post2", 390 + SubjectURI: "at://did:plc:community/social.coves.community.post/post2", 391 391 SubjectCID: "bafyreigp2", 392 392 Direction: "down", 393 393 CreatedAt: time.Now(),
+8 -8
tests/integration/aggregator_e2e_test.go
··· 332 332 reqJSON, err := json.Marshal(reqBody) 333 333 require.NoError(t, err) 334 334 335 - req := httptest.NewRequest("POST", "/xrpc/social.coves.post.create", bytes.NewReader(reqJSON)) 335 + req := httptest.NewRequest("POST", "/xrpc/social.coves.community.post.create", bytes.NewReader(reqJSON)) 336 336 req.Header.Set("Content-Type", "application/json") 337 337 338 338 // Create JWT for aggregator (not a user) ··· 360 360 Kind: "commit", 361 361 Commit: &jetstream.CommitEvent{ 362 362 Operation: "create", 363 - Collection: "social.coves.post.record", 363 + Collection: "social.coves.community.post", 364 364 RKey: rkey, 365 365 CID: response.CID, 366 366 Record: map[string]interface{}{ 367 - "$type": "social.coves.post.record", 367 + "$type": "social.coves.community.post", 368 368 "community": communityDID, 369 369 "author": aggregatorDID, // Aggregator is the author 370 370 "title": title, ··· 422 422 reqJSON, err := json.Marshal(reqBody) 423 423 require.NoError(t, err) 424 424 425 - req := httptest.NewRequest("POST", "/xrpc/social.coves.post.create", bytes.NewReader(reqJSON)) 425 + req := httptest.NewRequest("POST", "/xrpc/social.coves.community.post.create", bytes.NewReader(reqJSON)) 426 426 req.Header.Set("Content-Type", "application/json") 427 427 req.Header.Set("Authorization", "Bearer "+createSimpleTestJWT(aggregatorDID)) 428 428 ··· 444 444 reqJSON, err := json.Marshal(reqBody) 445 445 require.NoError(t, err) 446 446 447 - req := httptest.NewRequest("POST", "/xrpc/social.coves.post.create", bytes.NewReader(reqJSON)) 447 + req := httptest.NewRequest("POST", "/xrpc/social.coves.community.post.create", bytes.NewReader(reqJSON)) 448 448 req.Header.Set("Content-Type", "application/json") 449 449 req.Header.Set("Authorization", "Bearer "+createSimpleTestJWT(aggregatorDID)) 450 450 ··· 465 465 reqJSON, err = json.Marshal(reqBody) 466 466 require.NoError(t, err) 467 467 468 - req = httptest.NewRequest("POST", "/xrpc/social.coves.post.create", bytes.NewReader(reqJSON)) 468 + req = httptest.NewRequest("POST", "/xrpc/social.coves.community.post.create", bytes.NewReader(reqJSON)) 469 469 req.Header.Set("Content-Type", "application/json") 470 470 req.Header.Set("Authorization", "Bearer "+createSimpleTestJWT(aggregatorDID)) 471 471 ··· 657 657 reqJSON, err := json.Marshal(reqBody) 658 658 require.NoError(t, err) 659 659 660 - req := httptest.NewRequest("POST", "/xrpc/social.coves.post.create", bytes.NewReader(reqJSON)) 660 + req := httptest.NewRequest("POST", "/xrpc/social.coves.community.post.create", bytes.NewReader(reqJSON)) 661 661 req.Header.Set("Content-Type", "application/json") 662 662 req.Header.Set("Authorization", "Bearer "+createSimpleTestJWT(unauthorizedAggDID)) 663 663 ··· 781 781 reqJSON, err := json.Marshal(reqBody) 782 782 require.NoError(t, err) 783 783 784 - req := httptest.NewRequest("POST", "/xrpc/social.coves.post.create", bytes.NewReader(reqJSON)) 784 + req := httptest.NewRequest("POST", "/xrpc/social.coves.community.post.create", bytes.NewReader(reqJSON)) 785 785 req.Header.Set("Content-Type", "application/json") 786 786 req.Header.Set("Authorization", "Bearer "+createSimpleTestJWT(aggregatorDID)) 787 787
+4 -4
tests/integration/aggregator_test.go
··· 544 544 }) 545 545 546 546 t.Run("records aggregator post for rate limiting", func(t *testing.T) { 547 - postURI := fmt.Sprintf("at://%s/social.coves.post.record/post1", communityDID) 547 + postURI := fmt.Sprintf("at://%s/social.coves.community.post/post1", communityDID) 548 548 549 549 err := aggRepo.RecordAggregatorPost(ctx, aggregatorDID, communityDID, postURI, "bafy123") 550 550 if err != nil { ··· 627 627 t.Run("allows posts within rate limit", func(t *testing.T) { 628 628 // Create 9 posts (under the 10/hour limit) 629 629 for i := 0; i < 9; i++ { 630 - postURI := fmt.Sprintf("at://%s/social.coves.post.record/post%d", communityDID, i) 630 + postURI := fmt.Sprintf("at://%s/social.coves.community.post/post%d", communityDID, i) 631 631 if err := aggRepo.RecordAggregatorPost(ctx, aggregatorDID, communityDID, postURI, "bafy123"); err != nil { 632 632 t.Fatalf("Failed to record post %d: %v", i, err) 633 633 } ··· 642 642 643 643 t.Run("enforces rate limit at 10 posts/hour", func(t *testing.T) { 644 644 // Add one more post to hit the limit (total = 10) 645 - postURI := fmt.Sprintf("at://%s/social.coves.post.record/post10", communityDID) 645 + postURI := fmt.Sprintf("at://%s/social.coves.community.post/post10", communityDID) 646 646 if err := aggRepo.RecordAggregatorPost(ctx, aggregatorDID, communityDID, postURI, "bafy123"); err != nil { 647 647 t.Fatalf("Failed to record 10th post: %v", err) 648 648 } ··· 801 801 802 802 // Record 5 posts 803 803 for i := 0; i < 5; i++ { 804 - postURI := fmt.Sprintf("at://%s/social.coves.post.record/triggerpost%d", communityDID, i) 804 + postURI := fmt.Sprintf("at://%s/social.coves.community.post/triggerpost%d", communityDID, i) 805 805 if err := aggRepo.RecordAggregatorPost(ctx, aggregatorDID, communityDID, postURI, "bafy123"); err != nil { 806 806 t.Fatalf("Failed to record post %d: %v", i, err) 807 807 }
+1 -1
tests/integration/feed_test.go
··· 81 81 assert.NotNil(t, feedPost.Post.Record, "Post %d should have Record field", i) 82 82 record, ok := feedPost.Post.Record.(map[string]interface{}) 83 83 require.True(t, ok, "Record should be a map") 84 - assert.Equal(t, "social.coves.post.record", record["$type"], "Record should have correct $type") 84 + assert.Equal(t, "social.coves.community.post", record["$type"], "Record should have correct $type") 85 85 assert.NotEmpty(t, record["community"], "Record should have community") 86 86 assert.NotEmpty(t, record["author"], "Record should have author") 87 87 assert.NotEmpty(t, record["createdAt"], "Record should have createdAt")
+1 -1
tests/integration/helpers.go
··· 274 274 275 275 // Generate URI 276 276 rkey := fmt.Sprintf("post-%d", time.Now().UnixNano()) 277 - uri := fmt.Sprintf("at://%s/social.coves.post.record/%s", communityDID, rkey) 277 + uri := fmt.Sprintf("at://%s/social.coves.community.post/%s", communityDID, rkey) 278 278 279 279 // Insert post 280 280 _, err := db.ExecContext(ctx, `
+41 -21
tests/integration/post_creation_test.go
··· 1 1 package integration 2 2 3 3 import ( 4 + "Coves/internal/api/middleware" 4 5 "Coves/internal/atproto/identity" 5 6 "Coves/internal/core/communities" 6 7 "Coves/internal/core/posts" ··· 97 98 98 99 // This will fail at token refresh step (expected for unit test) 99 100 // We're using a fake token that can't be parsed 100 - _, err := postService.CreatePost(ctx, req) 101 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 102 + _, err := postService.CreatePost(authCtx, req) 101 103 102 104 // For now, we expect an error because token is fake 103 105 // In a full E2E test with real PDS, this would succeed ··· 123 125 124 126 // Should resolve handle to DID and proceed 125 127 // Will still fail at token refresh (expected with fake token) 126 - _, err := postService.CreatePost(ctx, req) 128 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 129 + _, err := postService.CreatePost(authCtx, req) 127 130 require.Error(t, err) 128 131 // Should fail at token refresh, not community resolution 129 132 assert.Contains(t, err.Error(), "failed to refresh community credentials") ··· 152 155 153 156 // Should resolve handle to DID and proceed 154 157 // Will still fail at token refresh (expected with fake token) 155 - _, err := postService.CreatePost(ctx, req) 158 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 159 + _, err := postService.CreatePost(authCtx, req) 156 160 require.Error(t, err) 157 161 // Should fail at token refresh, not community resolution 158 162 assert.Contains(t, err.Error(), "failed to refresh community credentials") ··· 167 171 AuthorDID: testUserDID, 168 172 } 169 173 170 - _, err := postService.CreatePost(ctx, req) 174 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 175 + _, err := postService.CreatePost(authCtx, req) 171 176 require.Error(t, err) 172 177 assert.True(t, posts.IsValidationError(err)) 173 178 }) ··· 181 186 AuthorDID: testUserDID, 182 187 } 183 188 184 - _, err := postService.CreatePost(ctx, req) 189 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 190 + _, err := postService.CreatePost(authCtx, req) 185 191 require.Error(t, err) 186 192 // Should fail with community not found (wrapped in error) 187 193 assert.Contains(t, err.Error(), "community not found") ··· 196 202 AuthorDID: "", // Missing! 197 203 } 198 204 199 - _, err := postService.CreatePost(ctx, req) 205 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 206 + _, err := postService.CreatePost(authCtx, req) 200 207 require.Error(t, err) 201 208 assert.True(t, posts.IsValidationError(err)) 202 209 assert.Contains(t, err.Error(), "authorDid") ··· 211 218 AuthorDID: testUserDID, 212 219 } 213 220 214 - _, err := postService.CreatePost(ctx, req) 221 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 222 + _, err := postService.CreatePost(authCtx, req) 215 223 require.Error(t, err) 216 224 assert.Equal(t, posts.ErrCommunityNotFound, err) 217 225 }) ··· 226 234 AuthorDID: testUserDID, 227 235 } 228 236 229 - _, err := postService.CreatePost(ctx, req) 237 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 238 + _, err := postService.CreatePost(authCtx, req) 230 239 require.Error(t, err) 231 240 assert.True(t, posts.IsValidationError(err)) 232 241 assert.Contains(t, err.Error(), "too long") ··· 236 245 content := "Post with invalid label" 237 246 238 247 req := posts.CreatePostRequest{ 239 - Community: testCommunity.DID, 240 - Content: &content, 241 - ContentLabels: []string{"invalid_label"}, // Not in known values! 242 - AuthorDID: testUserDID, 248 + Community: testCommunity.DID, 249 + Content: &content, 250 + Labels: &posts.SelfLabels{ 251 + Values: []posts.SelfLabel{ 252 + {Val: "invalid_label"}, // Not in known values! 253 + }, 254 + }, 255 + AuthorDID: testUserDID, 243 256 } 244 257 245 - _, err := postService.CreatePost(ctx, req) 258 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 259 + _, err := postService.CreatePost(authCtx, req) 246 260 require.Error(t, err) 247 261 assert.True(t, posts.IsValidationError(err)) 248 262 assert.Contains(t, err.Error(), "unknown content label") ··· 252 266 content := "Post with valid labels" 253 267 254 268 req := posts.CreatePostRequest{ 255 - Community: testCommunity.DID, 256 - Content: &content, 257 - ContentLabels: []string{"nsfw", "spoiler"}, 258 - AuthorDID: testUserDID, 269 + Community: testCommunity.DID, 270 + Content: &content, 271 + Labels: &posts.SelfLabels{ 272 + Values: []posts.SelfLabel{ 273 + {Val: "nsfw"}, 274 + {Val: "spoiler"}, 275 + }, 276 + }, 277 + AuthorDID: testUserDID, 259 278 } 260 279 261 280 // Will fail at token refresh (expected with fake token) 262 - _, err := postService.CreatePost(ctx, req) 281 + authCtx := middleware.SetTestUserDID(ctx, testUserDID) 282 + _, err := postService.CreatePost(authCtx, req) 263 283 require.Error(t, err) 264 284 // Should fail at token refresh, not validation 265 285 assert.Contains(t, err.Error(), "failed to refresh community credentials") ··· 316 336 title := "Test Title" 317 337 318 338 post := &posts.Post{ 319 - URI: "at://" + testCommunityDID + "/social.coves.post.record/test123", 339 + URI: "at://" + testCommunityDID + "/social.coves.community.post/test123", 320 340 CID: "bafy2test123", 321 341 RKey: "test123", 322 342 AuthorDID: testUserDID, ··· 335 355 content := "Duplicate post" 336 356 337 357 post1 := &posts.Post{ 338 - URI: "at://" + testCommunityDID + "/social.coves.post.record/duplicate", 358 + URI: "at://" + testCommunityDID + "/social.coves.community.post/duplicate", 339 359 CID: "bafy2duplicate1", 340 360 RKey: "duplicate", 341 361 AuthorDID: testUserDID, ··· 348 368 349 369 // Try to insert again with same URI 350 370 post2 := &posts.Post{ 351 - URI: "at://" + testCommunityDID + "/social.coves.post.record/duplicate", 371 + URI: "at://" + testCommunityDID + "/social.coves.community.post/duplicate", 352 372 CID: "bafy2duplicate2", 353 373 RKey: "duplicate", 354 374 AuthorDID: testUserDID,
+15 -15
tests/integration/post_e2e_test.go
··· 33 33 // XRPC endpoint → AppView Service → PDS write → Jetstream consumer → DB indexing 34 34 // 35 35 // This is a TRUE E2E test that simulates what happens in production: 36 - // 1. Client calls POST /xrpc/social.coves.post.create with auth token 36 + // 1. Client calls POST /xrpc/social.coves.community.post.create with auth token 37 37 // 2. Handler validates and calls PostService.CreatePost() 38 38 // 3. Service writes post to community's PDS repository 39 39 // 4. PDS broadcasts event to firehose/Jetstream ··· 116 116 Kind: "commit", 117 117 Commit: &jetstream.CommitEvent{ 118 118 Operation: "create", 119 - Collection: "social.coves.post.record", 119 + Collection: "social.coves.community.post", 120 120 RKey: rkey, 121 121 CID: "bafy2bzaceabc123def456", // Fake CID 122 122 Record: map[string]interface{}{ 123 - "$type": "social.coves.post.record", 123 + "$type": "social.coves.community.post", 124 124 "community": community.DID, 125 125 "author": author.DID, 126 126 "title": *postReq.Title, ··· 138 138 } 139 139 140 140 // STEP 4: Verify post was indexed in AppView database 141 - expectedURI := fmt.Sprintf("at://%s/social.coves.post.record/%s", community.DID, rkey) 141 + expectedURI := fmt.Sprintf("at://%s/social.coves.community.post/%s", community.DID, rkey) 142 142 indexedPost, err := postRepo.GetByURI(ctx, expectedURI) 143 143 if err != nil { 144 144 t.Fatalf("Post not indexed in AppView: %v", err) ··· 187 187 Kind: "commit", 188 188 Commit: &jetstream.CommitEvent{ 189 189 Operation: "create", 190 - Collection: "social.coves.post.record", 190 + Collection: "social.coves.community.post", 191 191 RKey: generateTID(), 192 192 CID: "bafy2bzacefake", 193 193 Record: map[string]interface{}{ 194 - "$type": "social.coves.post.record", 194 + "$type": "social.coves.community.post", 195 195 "community": community.DID, // Claims to be for this community 196 196 "author": author.DID, 197 197 "title": "Fake Post", ··· 227 227 Kind: "commit", 228 228 Commit: &jetstream.CommitEvent{ 229 229 Operation: "create", 230 - Collection: "social.coves.post.record", 230 + Collection: "social.coves.community.post", 231 231 RKey: rkey, 232 232 CID: "bafy2bzaceidempotent", 233 233 Record: map[string]interface{}{ 234 - "$type": "social.coves.post.record", 234 + "$type": "social.coves.community.post", 235 235 "community": community.DID, 236 236 "author": author.DID, 237 237 "title": "Duplicate Test", ··· 256 256 } 257 257 258 258 // Verify only one post in database 259 - uri := fmt.Sprintf("at://%s/social.coves.post.record/%s", community.DID, rkey) 259 + uri := fmt.Sprintf("at://%s/social.coves.community.post/%s", community.DID, rkey) 260 260 post, err := postRepo.GetByURI(ctx, uri) 261 261 if err != nil { 262 262 t.Fatalf("Post not found: %v", err) ··· 281 281 Kind: "commit", 282 282 Commit: &jetstream.CommitEvent{ 283 283 Operation: "create", 284 - Collection: "social.coves.post.record", 284 + Collection: "social.coves.community.post", 285 285 RKey: generateTID(), 286 286 CID: "bafy2bzaceorphaned", 287 287 Record: map[string]interface{}{ 288 - "$type": "social.coves.post.record", 288 + "$type": "social.coves.community.post", 289 289 "community": unknownCommunityDID, 290 290 "author": author.DID, 291 291 "title": "Orphaned Post", ··· 313 313 } 314 314 315 315 // TestPostCreation_E2E_LivePDS tests the COMPLETE end-to-end flow with a live PDS: 316 - // 1. HTTP POST to /xrpc/social.coves.post.create (with auth) 316 + // 1. HTTP POST to /xrpc/social.coves.community.post.create (with auth) 317 317 // 2. Handler → Service → Write to community's PDS repository 318 318 // 3. PDS → Jetstream firehose event 319 319 // 4. Jetstream consumer → Index in AppView database ··· 472 472 require.NoError(t, err) 473 473 474 474 // Create HTTP request 475 - req := httptest.NewRequest("POST", "/xrpc/social.coves.post.create", bytes.NewReader(reqJSON)) 475 + req := httptest.NewRequest("POST", "/xrpc/social.coves.community.post.create", bytes.NewReader(reqJSON)) 476 476 req.Header.Set("Content-Type", "application/json") 477 477 478 478 // Create a simple JWT for testing (Phase 1: no signature verification) ··· 511 511 pdsHostname = strings.Split(pdsHostname, ":")[0] // Remove port 512 512 513 513 // Build Jetstream URL with filters for post records 514 - jetstreamURL := fmt.Sprintf("ws://%s:6008/subscribe?wantedCollections=social.coves.post.record", 514 + jetstreamURL := fmt.Sprintf("ws://%s:6008/subscribe?wantedCollections=social.coves.community.post", 515 515 pdsHostname) 516 516 517 517 t.Logf(" Jetstream URL: %s", jetstreamURL) ··· 653 653 654 654 // Check if this is a post event for the target DID 655 655 if event.Did == targetDID && event.Kind == "commit" && 656 - event.Commit != nil && event.Commit.Collection == "social.coves.post.record" { 656 + event.Commit != nil && event.Commit.Collection == "social.coves.community.post" { 657 657 // Process the event through the consumer 658 658 if err := consumer.HandleEvent(ctx, &event); err != nil { 659 659 return fmt.Errorf("failed to process event: %w", err)
+13 -13
tests/integration/post_handler_test.go
··· 55 55 } 56 56 57 57 body, _ := json.Marshal(payload) 58 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 58 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 59 59 60 60 // Mock authenticated user context 61 61 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") ··· 82 82 } 83 83 84 84 body, _ := json.Marshal(payload) 85 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 85 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 86 86 87 87 // No auth context set 88 88 rec := httptest.NewRecorder() ··· 108 108 } 109 109 110 110 body, _ := json.Marshal(payload) 111 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 111 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 112 112 113 113 // Mock authenticated user context 114 114 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") ··· 131 131 // Invalid JSON 132 132 invalidJSON := []byte(`{"community": "did:plc:test123", "content": `) 133 133 134 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(invalidJSON)) 134 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(invalidJSON)) 135 135 136 136 // Mock authenticated user context 137 137 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") ··· 157 157 } 158 158 159 159 body, _ := json.Marshal(payload) 160 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 160 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 161 161 162 162 // Mock authenticated user context 163 163 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") ··· 192 192 } 193 193 194 194 body, _ := json.Marshal(payload) 195 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 195 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 196 196 197 197 // Mock authenticated user context 198 198 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") ··· 231 231 } 232 232 233 233 body, _ := json.Marshal(payload) 234 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 234 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 235 235 236 236 // Mock authenticated user context 237 237 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") ··· 269 269 } 270 270 271 271 body, _ := json.Marshal(payload) 272 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 272 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 273 273 274 274 // Mock authenticated user context 275 275 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") ··· 307 307 } 308 308 309 309 body, _ := json.Marshal(payload) 310 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 310 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 311 311 312 312 // Mock authenticated user context 313 313 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") ··· 345 345 } 346 346 347 347 body, _ := json.Marshal(payload) 348 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 348 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 349 349 350 350 // Mock authenticated user context 351 351 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") ··· 373 373 374 374 for _, method := range methods { 375 375 t.Run(method, func(t *testing.T) { 376 - req := httptest.NewRequest(method, "/xrpc/social.coves.post.create", nil) 376 + req := httptest.NewRequest(method, "/xrpc/social.coves.community.post.create", nil) 377 377 rec := httptest.NewRecorder() 378 378 379 379 handler.HandleCreate(rec, req) ··· 422 422 } 423 423 424 424 body, _ := json.Marshal(payload) 425 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 425 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 426 426 427 427 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") 428 428 req = req.WithContext(ctx) ··· 452 452 } 453 453 454 454 body, _ := json.Marshal(payload) 455 - req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.post.create", bytes.NewReader(body)) 455 + req := httptest.NewRequest(http.MethodPost, "/xrpc/social.coves.community.post.create", bytes.NewReader(body)) 456 456 457 457 ctx := middleware.SetTestUserDID(req.Context(), "did:plc:alice") 458 458 req = req.WithContext(ctx)
+1 -1
tests/integration/timeline_test.go
··· 100 100 assert.NotNil(t, feedPost.Post.Record, "Post %d should have Record field", i) 101 101 record, ok := feedPost.Post.Record.(map[string]interface{}) 102 102 require.True(t, ok, "Record should be a map") 103 - assert.Equal(t, "social.coves.post.record", record["$type"], "Record should have correct $type") 103 + assert.Equal(t, "social.coves.community.post", record["$type"], "Record should have correct $type") 104 104 assert.NotEmpty(t, record["community"], "Record should have community") 105 105 assert.NotEmpty(t, record["author"], "Record should have author") 106 106 assert.NotEmpty(t, record["createdAt"], "Record should have createdAt")
+1 -1
tests/lexicon-test-data/actor/saved-invalid-type.json
··· 1 1 { 2 2 "$type": "social.coves.actor.saved", 3 - "subject": "at://did:plc:exampleuser/social.coves.post.record/3k7a3dmb5bk2c", 3 + "subject": "at://$1/social.coves.community.post/3k7a3dmb5bk2c", 4 4 "type": "article", 5 5 "createdAt": "2025-01-09T14:30:00Z" 6 6 }
+1 -1
tests/lexicon-test-data/actor/saved-valid.json
··· 1 1 { 2 2 "$type": "social.coves.actor.saved", 3 - "subject": "at://did:plc:exampleuser/social.coves.post.record/3k7a3dmb5bk2c", 3 + "subject": "at://$1/social.coves.community.post/3k7a3dmb5bk2c", 4 4 "type": "post", 5 5 "createdAt": "2025-01-09T14:30:00Z", 6 6 "note": "Great tutorial on Go concurrency patterns"
+12 -3
tests/lexicon-test-data/interaction/comment-invalid-content.json
··· 1 1 { 2 - "$type": "social.coves.interaction.comment", 3 - "post": "at://did:plc:author123/social.coves.post.record/3k7a3dmb5bk2c", 2 + "$type": "social.coves.feed.comment", 3 + "reply": { 4 + "root": { 5 + "uri": "at://did:plc:test123/social.coves.community.post/3k7a3dmb5bk2c", 6 + "cid": "bafyreigj3fwnwjuzr35k2kuzmb5dixxczrzjhqkr5srlqplsh6gq3bj3si" 7 + }, 8 + "parent": { 9 + "uri": "at://did:plc:test123/social.coves.community.post/3k7a3dmb5bk2c", 10 + "cid": "bafyreigj3fwnwjuzr35k2kuzmb5dixxczrzjhqkr5srlqplsh6gq3bj3si" 11 + } 12 + }, 4 13 "createdAt": "2025-01-09T16:45:00Z" 5 - } 14 + }
+12 -7
tests/lexicon-test-data/interaction/comment-valid-sticker.json
··· 1 1 { 2 - "$type": "social.coves.interaction.comment", 3 - "subject": "at://did:plc:author123/social.coves.post.record/3k7a3dmb5bk2c", 4 - "content": { 5 - "$type": "social.coves.interaction.comment#stickerContent", 6 - "stickerId": "thumbs-up", 7 - "stickerPackId": "default-pack" 2 + "$type": "social.coves.feed.comment", 3 + "reply": { 4 + "root": { 5 + "uri": "at://did:plc:test123/social.coves.community.post/3k7a3dmb5bk2c", 6 + "cid": "bafyreigj3fwnwjuzr35k2kuzmb5dixxczrzjhqkr5srlqplsh6gq3bj3si" 7 + }, 8 + "parent": { 9 + "uri": "at://did:plc:test123/social.coves.community.post/3k7a3dmb5bk2c", 10 + "cid": "bafyreigj3fwnwjuzr35k2kuzmb5dixxczrzjhqkr5srlqplsh6gq3bj3si" 11 + } 8 12 }, 13 + "content": "👍", 9 14 "createdAt": "2025-01-09T16:50:00Z" 10 - } 15 + }
+26 -20
tests/lexicon-test-data/interaction/comment-valid-text.json
··· 1 1 { 2 - "$type": "social.coves.interaction.comment", 3 - "subject": "at://did:plc:author123/social.coves.post.record/3k7a3dmb5bk2c", 4 - "content": { 5 - "$type": "social.coves.interaction.comment#textContent", 6 - "text": "Great post! I especially liked the part about @alice.example.com's contribution to the project.", 7 - "facets": [ 8 - { 9 - "index": { 10 - "byteStart": 46, 11 - "byteEnd": 64 12 - }, 13 - "features": [ 14 - { 15 - "$type": "social.coves.richtext.facet#mention", 16 - "did": "did:plc:aliceuser123" 17 - } 18 - ] 19 - } 20 - ] 2 + "$type": "social.coves.feed.comment", 3 + "reply": { 4 + "root": { 5 + "uri": "at://did:plc:test123/social.coves.community.post/3k7a3dmb5bk2c", 6 + "cid": "bafyreigj3fwnwjuzr35k2kuzmb5dixxczrzjhqkr5srlqplsh6gq3bj3si" 7 + }, 8 + "parent": { 9 + "uri": "at://did:plc:test123/social.coves.community.post/3k7a3dmb5bk2c", 10 + "cid": "bafyreigj3fwnwjuzr35k2kuzmb5dixxczrzjhqkr5srlqplsh6gq3bj3si" 11 + } 21 12 }, 13 + "content": "Great post! I especially liked the part about @alice.example.com's contribution to the project.", 14 + "facets": [ 15 + { 16 + "index": { 17 + "byteStart": 46, 18 + "byteEnd": 64 19 + }, 20 + "features": [ 21 + { 22 + "$type": "social.coves.richtext.facet#mention", 23 + "did": "did:plc:aliceuser123" 24 + } 25 + ] 26 + } 27 + ], 22 28 "createdAt": "2025-01-09T16:30:00Z" 23 - } 29 + }
+1 -1
tests/lexicon-test-data/moderation/tribunal-vote-invalid-decision.json
··· 1 1 { 2 2 "$type": "social.coves.moderation.tribunalVote", 3 3 "tribunal": "at://did:plc:community123/social.coves.moderation.tribunal/3k7a3dmb5bk2c", 4 - "subject": "at://did:plc:user123/social.coves.post.record/3k7a2clb4bj2b", 4 + "subject": "at://$1/social.coves.community.post/3k7a2clb4bj2b", 5 5 "decision": "maybe", 6 6 "createdAt": "2025-01-09T18:00:00Z" 7 7 }
+1 -1
tests/lexicon-test-data/moderation/tribunal-vote-valid.json
··· 1 1 { 2 2 "$type": "social.coves.moderation.tribunalVote", 3 3 "tribunal": "at://did:plc:community123/social.coves.moderation.tribunal/3k7a3dmb5bk2c", 4 - "subject": "at://did:plc:spammer123/social.coves.post.record/3k7a2clb4bj2b", 4 + "subject": "at://$1/social.coves.community.post/3k7a2clb4bj2b", 5 5 "decision": "remove", 6 6 "reasoning": "The moderator's action was justified based on clear violation of Rule 2 (No Spam). The user posted the same promotional content across multiple communities within a short timeframe.", 7 7 "precedents": [
+5 -5
tests/lexicon-test-data/post/post-invalid-enum-type.json
··· 1 1 { 2 - "$type": "social.coves.post.record", 2 + "$type": "social.coves.community.post", 3 3 "community": "did:plc:programming123", 4 + "author": "did:plc:testauthor123", 4 5 "postType": "invalid-type", 5 6 "title": "This has an invalid post type", 6 - "text": "The postType field has an invalid value", 7 + "content": "The postType field is not defined in the schema and should be rejected", 7 8 "tags": [], 8 - "language": "en", 9 - "contentWarnings": [], 9 + "langs": ["en"], 10 10 "createdAt": "2025-01-09T14:30:00Z" 11 - } 11 + }
+5 -6
tests/lexicon-test-data/post/post-invalid-missing-community.json
··· 1 1 { 2 - "$type": "social.coves.post.record", 3 - "postType": "text", 2 + "$type": "social.coves.community.post", 3 + "author": "did:plc:testauthor123", 4 4 "title": "Test Post", 5 - "text": "This post is missing the required community field", 5 + "content": "This post is missing the required community field", 6 6 "tags": ["test"], 7 - "language": "en", 8 - "contentWarnings": [], 7 + "langs": ["en"], 9 8 "createdAt": "2025-01-09T14:30:00Z" 10 - } 9 + }
+6 -7
tests/lexicon-test-data/post/post-valid-text.json
··· 1 1 { 2 - "$type": "social.coves.post.record", 2 + "$type": "social.coves.community.post", 3 3 "community": "did:plc:programming123", 4 - "postType": "text", 4 + "author": "did:plc:testauthor123", 5 5 "title": "Best practices for error handling in Go", 6 - "text": "I've been working with Go for a while now and wanted to share some thoughts on error handling patterns...", 7 - "textFacets": [ 6 + "content": "I've been working with Go for a while now and wanted to share some thoughts on error handling patterns...", 7 + "facets": [ 8 8 { 9 9 "index": { 10 10 "byteStart": 20, ··· 18 18 } 19 19 ], 20 20 "tags": ["golang", "error-handling", "best-practices"], 21 - "language": "en", 22 - "contentWarnings": [], 21 + "langs": ["en"], 23 22 "createdAt": "2025-01-09T14:30:00Z" 24 - } 23 + }