170 lines
4.6 KiB
Go
170 lines
4.6 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/topfans/backend/pkg/models"
|
|
"github.com/topfans/backend/gateway/service"
|
|
)
|
|
|
|
// fakeAppDownloadSvc 是 AppDownloadSvc 的 in-memory fake
|
|
type fakeAppDownloadSvc struct {
|
|
configs []models.AppDownloadConfig
|
|
getAllErr error
|
|
syncErr error
|
|
syncCalled bool
|
|
lastSyncReq *service.SyncVersionRequest
|
|
}
|
|
|
|
func (f *fakeAppDownloadSvc) GetAllNativeApp(ctx context.Context) ([]models.AppDownloadConfig, error) {
|
|
if f.getAllErr != nil {
|
|
return nil, f.getAllErr
|
|
}
|
|
return f.configs, nil
|
|
}
|
|
|
|
func (f *fakeAppDownloadSvc) SyncVersion(ctx context.Context, req *service.SyncVersionRequest) error {
|
|
f.syncCalled = true
|
|
f.lastSyncReq = req
|
|
return f.syncErr
|
|
}
|
|
|
|
func setupTestRouter(ctrl *AppDownloadController) *gin.Engine {
|
|
gin.SetMode(gin.TestMode)
|
|
r := gin.New()
|
|
r.GET("/api/v1/app/download-urls", ctrl.GetDownloadUrls)
|
|
r.POST("/api/v1/admin/app/versions/sync", ctrl.SyncVersion)
|
|
return r
|
|
}
|
|
|
|
// ========== GET /api/v1/app/download-urls ==========
|
|
|
|
func TestGetDownloadUrls_Success(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
fakeSvc := &fakeAppDownloadSvc{
|
|
configs: []models.AppDownloadConfig{
|
|
{Platform: "android", Type: "native_app", DownloadURL: "https://app.apk", Version: "1.0.5"},
|
|
{Platform: "ios", Type: "native_app", DownloadURL: "https://apps.apple.com/...", Version: "1.0.5"},
|
|
},
|
|
}
|
|
ctrl := NewAppDownloadController(fakeSvc)
|
|
router := setupTestRouter(ctrl)
|
|
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "/api/v1/app/download-urls", nil)
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
json.Unmarshal(w.Body.Bytes(), &resp)
|
|
assert.Equal(t, float64(0), resp["code"])
|
|
|
|
data := resp["data"].(map[string]interface{})
|
|
assert.NotNil(t, data["android"])
|
|
assert.NotNil(t, data["ios"])
|
|
}
|
|
|
|
func TestGetDownloadUrls_EmptyData(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
fakeSvc := &fakeAppDownloadSvc{configs: []models.AppDownloadConfig{}}
|
|
ctrl := NewAppDownloadController(fakeSvc)
|
|
router := setupTestRouter(ctrl)
|
|
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "/api/v1/app/download-urls", nil)
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
json.Unmarshal(w.Body.Bytes(), &resp)
|
|
assert.Equal(t, float64(0), resp["code"])
|
|
|
|
data := resp["data"].(map[string]interface{})
|
|
assert.Nil(t, data["android"])
|
|
assert.Nil(t, data["ios"])
|
|
}
|
|
|
|
func TestGetDownloadUrls_ServiceError(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
fakeSvc := &fakeAppDownloadSvc{getAllErr: errors.New("db down")}
|
|
ctrl := NewAppDownloadController(fakeSvc)
|
|
router := setupTestRouter(ctrl)
|
|
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("GET", "/api/v1/app/download-urls", nil)
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, 500, w.Code)
|
|
}
|
|
|
|
// ========== POST /api/v1/admin/app/versions/sync ==========
|
|
|
|
func TestSyncVersion_InvalidJSON(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
fakeSvc := &fakeAppDownloadSvc{}
|
|
ctrl := NewAppDownloadController(fakeSvc)
|
|
router := setupTestRouter(ctrl)
|
|
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("POST", "/api/v1/admin/app/versions/sync",
|
|
strings.NewReader(`{"android": "not_an_object"}`))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, 400, w.Code)
|
|
}
|
|
|
|
func TestSyncVersion_MissingRequiredField(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
fakeSvc := &fakeAppDownloadSvc{}
|
|
ctrl := NewAppDownloadController(fakeSvc)
|
|
router := setupTestRouter(ctrl)
|
|
|
|
// 缺少必填字段 url
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("POST", "/api/v1/admin/app/versions/sync",
|
|
strings.NewReader(`{"android": {"version": "1.0.5", "type": "native_app"}}`))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, 400, w.Code)
|
|
}
|
|
|
|
func TestSyncVersion_Success(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
fakeSvc := &fakeAppDownloadSvc{}
|
|
ctrl := NewAppDownloadController(fakeSvc)
|
|
router := setupTestRouter(ctrl)
|
|
|
|
body := `{
|
|
"android": {"url": "https://app.apk", "version": "1.0.5", "type": "native_app"},
|
|
"ios": {"url": "https://apps.apple.com/...", "version": "1.0.5", "type": "native_app"}
|
|
}`
|
|
w := httptest.NewRecorder()
|
|
req, _ := http.NewRequest("POST", "/api/v1/admin/app/versions/sync",
|
|
strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, 200, w.Code)
|
|
assert.True(t, fakeSvc.syncCalled)
|
|
assert.NotNil(t, fakeSvc.lastSyncReq.Android)
|
|
assert.NotNil(t, fakeSvc.lastSyncReq.IOS)
|
|
}
|