Files
gochat/internal/service/shopify_integration_service_test.go
T
2026-06-04 15:44:48 +08:00

170 lines
5.9 KiB
Go

package service
import (
"context"
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"github.com/gochat/gochat/internal/model"
"github.com/gochat/gochat/internal/repository"
)
func setupShopifyIntegrationServiceTestDB(t *testing.T) *gorm.DB {
t.Helper()
db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
require.NoError(t, err, "failed to open SQLite test database")
require.NoError(t, db.AutoMigrate(
&model.Account{},
&model.IntegrationHook{},
&model.IntegrationApp{},
), "failed to auto-migrate models")
t.Cleanup(func() {
sqlDB, _ := db.DB()
sqlDB.Close()
})
return db
}
func setupShopifyIntegrationService(t *testing.T) (*ShopifyIntegrationService, *gorm.DB) {
t.Helper()
db := setupShopifyIntegrationServiceTestDB(t)
hookRepo := repository.NewIntegrationHookRepo(db)
svc := NewShopifyIntegrationService(hookRepo)
return svc, db
}
func seedShopifyAccount(db *gorm.DB, t *testing.T) uint {
t.Helper()
account := &model.Account{Name: "Test Account"}
require.NoError(t, db.Create(account).Error, "failed to seed account")
return account.ID
}
// ========================================
// ShopifyIntegrationService — Auth tests
// ========================================
func TestShopifyIntegrationService_Auth_CreateNew(t *testing.T) {
svc, db := setupShopifyIntegrationService(t)
accountID := seedShopifyAccount(db, t)
ctx := context.Background()
req := CreateShopifyAuthRequest{
ShopDomain: "my-store.myshopify.com",
AccessToken: "shpat_abc123",
}
hook, err := svc.Auth(ctx, accountID, req)
require.NoError(t, err, "Auth should succeed for new integration")
require.NotNil(t, hook, "Auth should return a hook")
assert.Equal(t, accountID, hook.AccountID, "hook should belong to the account")
assert.Equal(t, model.HookTypeShopify, hook.HookType, "hook type should be shopify")
assert.Equal(t, model.HookStatusActive, hook.Status, "hook status should be active")
assert.Equal(t, "https://my-store.myshopify.com/admin/api/webhooks.json", hook.URL, "hook URL should be constructed from shop domain")
// Verify settings were stored correctly
var settings model.ShopifySettings
require.NoError(t, json.Unmarshal(hook.Settings, &settings), "settings should be valid JSON")
assert.Equal(t, "my-store.myshopify.com", settings.ShopDomain, "settings shop_domain should match request")
assert.Equal(t, "shpat_abc123", settings.AccessToken, "settings access_token should match request")
// Verify the hook was persisted
hooks, err := svc.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeShopify)
require.NoError(t, err)
assert.Len(t, hooks, 1, "one Shopify hook should exist for the account")
}
func TestShopifyIntegrationService_Auth_UpdateExisting(t *testing.T) {
svc, db := setupShopifyIntegrationService(t)
accountID := seedShopifyAccount(db, t)
ctx := context.Background()
// Create initial integration
initialReq := CreateShopifyAuthRequest{
ShopDomain: "old-store.myshopify.com",
AccessToken: "shpat_old_token",
}
initialHook, err := svc.Auth(ctx, accountID, initialReq)
require.NoError(t, err, "initial Auth should succeed")
require.NotNil(t, initialHook)
// Update with new credentials
updateReq := CreateShopifyAuthRequest{
ShopDomain: "new-store.myshopify.com",
AccessToken: "shpat_new_token",
}
updatedHook, err := svc.Auth(ctx, accountID, updateReq)
require.NoError(t, err, "Auth update should succeed")
require.NotNil(t, updatedHook)
// Should return the same hook (updated, not a new one)
assert.Equal(t, initialHook.ID, updatedHook.ID, "update should return the same hook ID")
assert.Equal(t, "https://new-store.myshopify.com/admin/api/webhooks.json", updatedHook.URL, "URL should reflect updated shop domain")
// Verify updated settings
var settings model.ShopifySettings
require.NoError(t, json.Unmarshal(updatedHook.Settings, &settings), "settings should be valid JSON")
assert.Equal(t, "new-store.myshopify.com", settings.ShopDomain, "shop_domain should be updated")
assert.Equal(t, "shpat_new_token", settings.AccessToken, "access_token should be updated")
// Verify only one hook exists (no duplicates)
hooks, err := svc.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeShopify)
require.NoError(t, err)
assert.Len(t, hooks, 1, "still only one Shopify hook should exist after update")
}
// ========================================
// ShopifyIntegrationService — Delete tests
// ========================================
func TestShopifyIntegrationService_Delete_Success(t *testing.T) {
svc, db := setupShopifyIntegrationService(t)
accountID := seedShopifyAccount(db, t)
ctx := context.Background()
// Create an integration first
req := CreateShopifyAuthRequest{
ShopDomain: "my-store.myshopify.com",
AccessToken: "shpat_abc123",
}
_, err := svc.Auth(ctx, accountID, req)
require.NoError(t, err, "Auth should succeed before delete")
// Verify hook exists before delete
hooks, err := svc.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeShopify)
require.NoError(t, err)
assert.Len(t, hooks, 1, "hook should exist before delete")
// Delete the integration
err = svc.Delete(ctx, accountID)
require.NoError(t, err, "Delete should succeed")
// Verify hook no longer exists
hooks, err = svc.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeShopify)
require.NoError(t, err)
assert.Len(t, hooks, 0, "no Shopify hooks should remain after delete")
}
func TestShopifyIntegrationService_Delete_NotFound(t *testing.T) {
svc, db := setupShopifyIntegrationService(t)
accountID := seedShopifyAccount(db, t)
ctx := context.Background()
// Delete without any integration configured
err := svc.Delete(ctx, accountID)
assert.Error(t, err, "Delete should fail when no Shopify integration exists")
assert.Contains(t, err.Error(), "not found", "error should indicate integration not found")
}