discourse/backend/perspective/service_test.go
2025-03-25 03:52:30 -04:00

226 lines
5.4 KiB
Go

package perspective
import (
"context"
"testing"
"4vif5i.gitea.cloud/numenor-labs/discourse/backend/ipfs"
"github.com/go-redis/redismock/v8"
"github.com/stretchr/testify/assert"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// Setup test dependencies
func setupTestDependencies(t *testing.T) (*PerspectiveService, redismock.ClientMock) {
// Setup mock Redis
client, mock := redismock.NewClientMock()
// Setup in-memory SQLite database
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
if err != nil {
t.Fatalf("Failed to open in-memory database: %v", err)
}
// Create a mock IPFS service
ipfsService := ipfs.NewMockIPFSService()
// Create the service with our mocks
service := NewPerspectiveService(client, db, ipfsService)
return service, mock
}
func TestSubmitPerspective_Success(t *testing.T) {
service, mock := setupTestDependencies(t)
ctx := context.Background()
// Setup Redis mock expectations for unverified user
mock.ExpectExists("user:0x1234:submissions").SetVal(0)
mock.ExpectSet("user:0x1234:submissions", 1, RedisTTL).SetVal("OK")
// Call the service method
ipfsHash, err := service.SubmitPerspective(
ctx,
"issue123",
"This is a test perspective",
"",
"0x1234",
false,
ValidCaptchaToken,
)
// Verify the results
assert.NoError(t, err)
assert.NotEmpty(t, ipfsHash)
// Verify Redis mock expectations were met
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("Redis expectations were not met: %v", err)
}
// Verify perspective was stored in the database
var perspective Perspective
err = service.db.Where("ipfs_hash = ?", ipfsHash).First(&perspective).Error
assert.NoError(t, err)
assert.Equal(t, "issue123", perspective.IssueID)
assert.Equal(t, "0x1234", perspective.UserAddress)
assert.Equal(t, false, perspective.IsVerified)
}
func TestSubmitPerspective_VerifiedUser(t *testing.T) {
service, mock := setupTestDependencies(t)
ctx := context.Background()
// No need to mock Redis for verified user
// Call the service method
ipfsHash, err := service.SubmitPerspective(
ctx,
"issue123",
"This is a test perspective from a verified user",
"",
"0x5678",
true, // Verified user
"", // No captcha needed
)
// Verify the results
assert.NoError(t, err)
assert.NotEmpty(t, ipfsHash)
// Verify Redis mock expectations were met
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("Redis expectations were not met: %v", err)
}
// Verify perspective was stored in the database
var perspective Perspective
err = service.db.Where("ipfs_hash = ?", ipfsHash).First(&perspective).Error
assert.NoError(t, err)
assert.Equal(t, "issue123", perspective.IssueID)
assert.Equal(t, "0x5678", perspective.UserAddress)
assert.Equal(t, true, perspective.IsVerified)
}
func TestSubmitPerspective_RateLimit(t *testing.T) {
service, mock := setupTestDependencies(t)
ctx := context.Background()
// Setup Redis mock expectations for rate-limited user
mock.ExpectGet("user:0x1234:submissions").SetVal("5") // Rate limit reached
// Call the service method
_, err := service.SubmitPerspective(
ctx,
"issue123",
"This is a test perspective that should be rate limited",
"",
"0x1234",
false,
ValidCaptchaToken,
)
// Verify the results
assert.Error(t, err)
assert.Contains(t, err.Error(), "rate limit exceeded")
// Verify Redis mock expectations were met
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("Redis expectations were not met: %v", err)
}
}
func TestSubmitPerspective_InvalidCaptcha(t *testing.T) {
service, _ := setupTestDependencies(t)
ctx := context.Background()
// Call the service method with invalid captcha
_, err := service.SubmitPerspective(
ctx,
"issue123",
"This is a test perspective with invalid captcha",
"",
"0x1234",
false,
"invalid-token",
)
// Verify the results
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid CAPTCHA token")
}
func TestSubmitPerspective_OversizedText(t *testing.T) {
service, _ := setupTestDependencies(t)
ctx := context.Background()
// Generate a text that exceeds the maximum length
oversizedText := ""
for i := 0; i < MaxTextLength+100; i++ {
oversizedText += "a"
}
// Call the service method with oversized text
_, err := service.SubmitPerspective(
ctx,
"issue123",
oversizedText,
"",
"0x1234",
true,
"",
)
// Verify the results
assert.Error(t, err)
assert.Contains(t, err.Error(), "exceeds maximum length")
}
func TestGetPerspectivesByIssue(t *testing.T) {
service, _ := setupTestDependencies(t)
ctx := context.Background()
// Insert test perspectives for the issue
testIssueID := "issue456"
// Create and store a few test perspectives
for i := 0; i < 3; i++ {
ipfsHash, err := service.SubmitPerspective(
ctx,
testIssueID,
"Test perspective",
"",
"0xABCD",
true,
"",
)
assert.NoError(t, err)
assert.NotEmpty(t, ipfsHash)
}
// Also create a perspective for a different issue
_, err := service.SubmitPerspective(
ctx,
"different-issue",
"Different issue perspective",
"",
"0xABCD",
true,
"",
)
assert.NoError(t, err)
// Get perspectives for the test issue
perspectives, err := service.GetPerspectivesByIssue(testIssueID)
// Verify the results
assert.NoError(t, err)
assert.Len(t, perspectives, 3) // Should only find the 3 perspectives for this issue
// Verify each perspective has the correct issue ID
for _, p := range perspectives {
assert.Equal(t, testIssueID, p.IssueID)
}
}