A community based topic aggregation platform built on atproto
1package integration
2
3import (
4 "Coves/internal/core/users"
5 "bytes"
6 "context"
7 "database/sql"
8 "encoding/json"
9 "fmt"
10 "io"
11 "net/http"
12 "strings"
13 "testing"
14)
15
16// createTestUser creates a test user in the database for use in integration tests
17// Returns the created user or fails the test
18func createTestUser(t *testing.T, db *sql.DB, handle, did string) *users.User {
19 t.Helper()
20
21 ctx := context.Background()
22
23 // Create user directly in DB for speed
24 query := `
25 INSERT INTO users (did, handle, pds_url, created_at, updated_at)
26 VALUES ($1, $2, $3, NOW(), NOW())
27 RETURNING did, handle, pds_url, created_at, updated_at
28 `
29
30 user := &users.User{}
31 err := db.QueryRowContext(ctx, query, did, handle, "http://localhost:3001").Scan(
32 &user.DID,
33 &user.Handle,
34 &user.PDSURL,
35 &user.CreatedAt,
36 &user.UpdatedAt,
37 )
38 if err != nil {
39 t.Fatalf("Failed to create test user: %v", err)
40 }
41
42 return user
43}
44
45// contains checks if string s contains substring substr
46// Helper for error message assertions
47func contains(s, substr string) bool {
48 return strings.Contains(s, substr)
49}
50
51// authenticateWithPDS authenticates with PDS to get access token and DID
52// Used for setting up test environments that need PDS credentials
53func authenticateWithPDS(pdsURL, handle, password string) (string, string, error) {
54 // Call com.atproto.server.createSession
55 sessionReq := map[string]string{
56 "identifier": handle,
57 "password": password,
58 }
59
60 reqBody, marshalErr := json.Marshal(sessionReq)
61 if marshalErr != nil {
62 return "", "", fmt.Errorf("failed to marshal session request: %w", marshalErr)
63 }
64 resp, err := http.Post(
65 pdsURL+"/xrpc/com.atproto.server.createSession",
66 "application/json",
67 bytes.NewBuffer(reqBody),
68 )
69 if err != nil {
70 return "", "", fmt.Errorf("failed to create session: %w", err)
71 }
72 defer func() { _ = resp.Body.Close() }()
73
74 if resp.StatusCode != http.StatusOK {
75 body, readErr := io.ReadAll(resp.Body)
76 if readErr != nil {
77 return "", "", fmt.Errorf("PDS auth failed (status %d, failed to read body: %w)", resp.StatusCode, readErr)
78 }
79 return "", "", fmt.Errorf("PDS auth failed (status %d): %s", resp.StatusCode, string(body))
80 }
81
82 var sessionResp struct {
83 AccessJwt string `json:"accessJwt"`
84 DID string `json:"did"`
85 }
86
87 if err := json.NewDecoder(resp.Body).Decode(&sessionResp); err != nil {
88 return "", "", fmt.Errorf("failed to decode session response: %w", err)
89 }
90
91 return sessionResp.AccessJwt, sessionResp.DID, nil
92}