140 lines
4.5 KiB
Go
140 lines
4.5 KiB
Go
package luckygift_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"hyapp-luck-gateway/internal/config"
|
|
"hyapp-luck-gateway/internal/integration/luckygiftclient"
|
|
"hyapp-luck-gateway/internal/modules/luckygift"
|
|
"hyapp-luck-gateway/internal/router"
|
|
)
|
|
|
|
type fakeClient struct {
|
|
got luckygiftclient.SendCommand
|
|
calls int
|
|
}
|
|
|
|
func (f *fakeClient) SendLuckyGift(_ context.Context, cmd luckygiftclient.SendCommand) (luckygiftclient.SendResult, error) {
|
|
f.calls++
|
|
f.got = cmd
|
|
return luckygiftclient.SendResult{DrawID: "draw-1", RequestID: cmd.RequestID, AppCode: cmd.AppCode, RewardStatus: "granted"}, nil
|
|
}
|
|
|
|
func TestSendAcceptsAllowedAppAndComputesAmount(t *testing.T) {
|
|
client := &fakeClient{}
|
|
handler := testRouter(client, "aslan,yumi")
|
|
body := []byte(`{"app_code":"Aslan","request_id":"req-1","external_user_id":"u-1001","gift_count":3,"unit_amount":7,"currency":"COIN","metadata":{"gift":"rose"}}`)
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/lucky-gifts/send", bytes.NewReader(body))
|
|
rec := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
if client.calls != 1 {
|
|
t.Fatalf("client calls=%d", client.calls)
|
|
}
|
|
if client.got.AppCode != "aslan" || client.got.RequestID != "req-1" || client.got.TotalAmount != 21 || client.got.GiftCount != 3 {
|
|
t.Fatalf("unexpected command: %+v", client.got)
|
|
}
|
|
}
|
|
|
|
func TestSendRejectsPoolAndPaidAtOverrides(t *testing.T) {
|
|
client := &fakeClient{}
|
|
handler := testRouter(client, "aslan")
|
|
body := []byte(`{"app_code":"aslan","request_id":"req-1","external_user_id":"u-1001","pool_id":"pool-1","paid_at_ms":1700000000000,"gift_count":1,"unit_amount":7}`)
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/lucky-gifts/send", bytes.NewReader(body))
|
|
rec := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusBadRequest {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
if client.calls != 0 {
|
|
t.Fatalf("client should not be called, calls=%d", client.calls)
|
|
}
|
|
}
|
|
|
|
func TestSendRejectsDisallowedAppBeforeClientCall(t *testing.T) {
|
|
client := &fakeClient{}
|
|
handler := testRouter(client, "aslan,yumi")
|
|
body := []byte(`{"app_code":"hyapp","request_id":"req-1","external_user_id":"u-1001","gift_count":1,"unit_amount":9}`)
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/lucky-gifts/send", bytes.NewReader(body))
|
|
rec := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusForbidden {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
if client.calls != 0 {
|
|
t.Fatalf("client should not be called, calls=%d", client.calls)
|
|
}
|
|
}
|
|
|
|
func TestSendRejectsInvalidAmount(t *testing.T) {
|
|
client := &fakeClient{}
|
|
handler := testRouter(client, "aslan")
|
|
body, _ := json.Marshal(map[string]any{
|
|
"app_code": "aslan",
|
|
"request_id": "req-1",
|
|
"external_user_id": "u-1",
|
|
"gift_count": 0,
|
|
"unit_amount": 10,
|
|
})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/lucky-gifts/send", bytes.NewReader(body))
|
|
rec := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusBadRequest {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
if client.calls != 0 {
|
|
t.Fatalf("client should not be called, calls=%d", client.calls)
|
|
}
|
|
}
|
|
|
|
func TestSendRejectsTooLongExternalFields(t *testing.T) {
|
|
client := &fakeClient{}
|
|
handler := testRouter(client, "aslan")
|
|
body, _ := json.Marshal(map[string]any{
|
|
"app_code": "aslan",
|
|
"request_id": "req-1",
|
|
"external_user_id": strings.Repeat("u", 129),
|
|
"gift_count": 1,
|
|
"unit_amount": 10,
|
|
})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/lucky-gifts/send", bytes.NewReader(body))
|
|
rec := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusBadRequest {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
if client.calls != 0 {
|
|
t.Fatalf("client should not be called, calls=%d", client.calls)
|
|
}
|
|
}
|
|
|
|
func testRouter(client *fakeClient, allowedApps string) http.Handler {
|
|
cfg := config.Config{AllowedApps: parseAllowedAppsForTest(allowedApps)}
|
|
return router.New(cfg, router.Handlers{LuckyGift: luckygift.New(client, time.Second, cfg.AllowedApps)})
|
|
}
|
|
|
|
func parseAllowedAppsForTest(raw string) map[string]struct{} {
|
|
out := map[string]struct{}{}
|
|
for _, app := range strings.Split(raw, ",") {
|
|
app = strings.ToLower(strings.TrimSpace(app))
|
|
if app != "" {
|
|
out[app] = struct{}{}
|
|
}
|
|
}
|
|
return out
|
|
}
|