- remove backend-old (Medusa), saveinmed-frontend (Next.js/Appwrite) and marketplace dirs - split Go usecases by domain and move notifications/payments to infrastructure - reorganize frontend pages into auth, dashboard and marketplace modules - add Makefile, docker-compose.yml and architecture docs
114 lines
3 KiB
Go
114 lines
3 KiB
Go
package notifications
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"github.com/gofrs/uuid/v5"
|
|
"github.com/saveinmed/backend-go/internal/domain"
|
|
)
|
|
|
|
type roundTripperFunc func(*http.Request) (*http.Response, error)
|
|
|
|
func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
return f(req)
|
|
}
|
|
|
|
func TestRegisterAndUnregisterToken(t *testing.T) {
|
|
svc := NewFCMService("")
|
|
ctx := context.Background()
|
|
userID := uuid.Must(uuid.NewV7())
|
|
|
|
if err := svc.RegisterToken(ctx, userID, ""); err == nil {
|
|
t.Fatal("expected error for empty token")
|
|
}
|
|
|
|
if err := svc.RegisterToken(ctx, userID, "token-1"); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if err := svc.RegisterToken(ctx, userID, "token-1"); err != nil {
|
|
t.Fatalf("unexpected error on duplicate token: %v", err)
|
|
}
|
|
|
|
if len(svc.tokens[userID]) != 1 {
|
|
t.Fatalf("expected 1 token, got %d", len(svc.tokens[userID]))
|
|
}
|
|
|
|
if err := svc.UnregisterToken(ctx, userID, "token-1"); err != nil {
|
|
t.Fatalf("unexpected error unregistering: %v", err)
|
|
}
|
|
|
|
if len(svc.tokens[userID]) != 0 {
|
|
t.Fatalf("expected no tokens after unregister, got %d", len(svc.tokens[userID]))
|
|
}
|
|
}
|
|
|
|
func TestSendPushSkipsWhenNoTokens(t *testing.T) {
|
|
svc := NewFCMService("")
|
|
ctx := context.Background()
|
|
|
|
if err := svc.SendPush(ctx, uuid.Must(uuid.NewV7()), "title", "body", nil); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSendToFCMWithServerKey(t *testing.T) {
|
|
svc := NewFCMService("server-key")
|
|
ctx := context.Background()
|
|
|
|
var capturedAuth string
|
|
svc.httpClient = &http.Client{
|
|
Transport: roundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
|
capturedAuth = req.Header.Get("Authorization")
|
|
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString("ok"))}, nil
|
|
}),
|
|
}
|
|
|
|
err := svc.sendToFCM(ctx, FCMMessage{
|
|
To: "token",
|
|
Notification: &FCMNotification{
|
|
Title: "Hello",
|
|
Body: "World",
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if capturedAuth != "key=server-key" {
|
|
t.Fatalf("expected auth header to include server key, got %q", capturedAuth)
|
|
}
|
|
}
|
|
|
|
func TestSendToFCMRejectsNonOK(t *testing.T) {
|
|
svc := NewFCMService("server-key")
|
|
ctx := context.Background()
|
|
|
|
svc.httpClient = &http.Client{
|
|
Transport: roundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
|
return &http.Response{StatusCode: http.StatusBadRequest, Body: io.NopCloser(bytes.NewBufferString("bad"))}, nil
|
|
}),
|
|
}
|
|
|
|
if err := svc.sendToFCM(ctx, FCMMessage{To: "token"}); err == nil {
|
|
t.Fatal("expected error for non-OK response")
|
|
}
|
|
}
|
|
|
|
func TestNotifyOrderStatusChangedUsesDefaultEmoji(t *testing.T) {
|
|
svc := NewFCMService("")
|
|
ctx := context.Background()
|
|
buyerID := uuid.Must(uuid.NewV7())
|
|
|
|
_ = svc.RegisterToken(ctx, buyerID, "token-1")
|
|
|
|
order := &domain.Order{ID: uuid.Must(uuid.NewV7()), Status: domain.OrderStatus("Em análise")}
|
|
buyer := &domain.User{ID: buyerID}
|
|
|
|
if err := svc.NotifyOrderStatusChanged(ctx, order, buyer); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|