gohorsejobs/backend/internal/services/credentials_service_test.go
Tiago Yamamoto 6cd8c02252 feat: add test coverage and handler improvements
- Add new test files for handlers (storage, payment, settings)
- Add new test files for services (chat, email, storage, settings, admin)
- Add integration tests for services
- Update handler implementations with bug fixes
- Add coverage reports and test documentation
2026-01-02 08:50:29 -03:00

153 lines
3.9 KiB
Go

package services_test
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"os"
"regexp"
"testing"
"time"
"github.com/DATA-DOG/go-sqlmock"
"github.com/rede5/gohorsejobs/backend/internal/services"
"github.com/stretchr/testify/assert"
)
// Helper to generate a valid RSA private key for testing
func generateTestRSAKey() (string, *rsa.PublicKey, error) {
key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return "", nil, err
}
keyBytes := x509.MarshalPKCS1PrivateKey(key)
pemBlock := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: keyBytes,
}
pemBytes := pem.EncodeToMemory(pemBlock)
return base64.StdEncoding.EncodeToString(pemBytes), &key.PublicKey, nil
}
func TestSaveCredentials(t *testing.T) {
db, mock, err := sqlmock.New()
assert.NoError(t, err)
defer db.Close()
service := services.NewCredentialsService(db)
ctx := context.Background()
mock.ExpectExec(regexp.QuoteMeta(`INSERT INTO external_services_credentials`)).
WithArgs("stripe", "encrypted_data", "admin").
WillReturnResult(sqlmock.NewResult(1, 1))
err = service.SaveCredentials(ctx, "stripe", "encrypted_data", "admin")
assert.NoError(t, err)
}
func TestGetDecryptedKey(t *testing.T) {
// Setup RSA Key
privKeyStr, pubKey, err := generateTestRSAKey()
assert.NoError(t, err)
os.Setenv("RSA_PRIVATE_KEY_BASE64", privKeyStr)
defer os.Unsetenv("RSA_PRIVATE_KEY_BASE64")
db, mock, err := sqlmock.New()
assert.NoError(t, err)
defer db.Close()
service := services.NewCredentialsService(db)
ctx := context.Background()
// Encrypt a secret
secret := "my-secret-key"
encryptedBytes, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
pubKey,
[]byte(secret),
nil,
)
assert.NoError(t, err)
encryptedPayload := base64.StdEncoding.EncodeToString(encryptedBytes)
// Mock DB return
mock.ExpectQuery(regexp.QuoteMeta(`SELECT encrypted_payload FROM external_services_credentials`)).
WithArgs("stripe").
WillReturnRows(sqlmock.NewRows([]string{"encrypted_payload"}).AddRow(encryptedPayload))
// Execute
decrypted, err := service.GetDecryptedKey(ctx, "stripe")
assert.NoError(t, err)
assert.Equal(t, secret, decrypted)
}
func TestListConfiguredServices(t *testing.T) {
db, mock, err := sqlmock.New()
assert.NoError(t, err)
defer db.Close()
service := services.NewCredentialsService(db)
ctx := context.Background()
mock.ExpectQuery(regexp.QuoteMeta(`SELECT service_name, updated_at, COALESCE(updated_by::text, '')`)).
WillReturnRows(sqlmock.NewRows([]string{"service_name", "updated_at", "updated_by"}).
AddRow("stripe", time.Now().Format(time.RFC3339), "admin").
AddRow("appwrite", time.Now().Format(time.RFC3339), "system"))
servicesList, err := service.ListConfiguredServices(ctx)
assert.NoError(t, err)
assert.NotEmpty(t, servicesList)
// Verify mapped correctly
foundStripe := false
for _, s := range servicesList {
if s.ServiceName == "stripe" {
assert.True(t, s.IsConfigured)
foundStripe = true
}
if s.ServiceName == "firebase" {
assert.False(t, s.IsConfigured)
}
}
assert.True(t, foundStripe)
}
func TestDeleteCredentials(t *testing.T) {
db, mock, err := sqlmock.New()
assert.NoError(t, err)
defer db.Close()
service := services.NewCredentialsService(db)
ctx := context.Background()
mock.ExpectExec(regexp.QuoteMeta(`DELETE FROM external_services_credentials`)).
WithArgs("stripe").
WillReturnResult(sqlmock.NewResult(1, 1))
err = service.DeleteCredentials(ctx, "stripe")
assert.NoError(t, err)
}
func TestEncryptPayload(t *testing.T) {
// Setup RSA Key
privKeyStr, _, err := generateTestRSAKey()
assert.NoError(t, err)
os.Setenv("RSA_PRIVATE_KEY_BASE64", privKeyStr)
defer os.Unsetenv("RSA_PRIVATE_KEY_BASE64")
service := services.NewCredentialsService(nil)
// Encrypt
payload := "test-payload-123"
encrypted, err := service.EncryptPayload(payload)
assert.NoError(t, err)
assert.NotEmpty(t, encrypted)
assert.NotEqual(t, payload, encrypted)
}