chore: send admin email on adding waitlist entry
This commit is contained in:
@@ -76,7 +76,7 @@ func main() {
|
|||||||
GoogleServiceAccountEmail: utils.MustGetEnv("GOOGLE_SERVICE_ACCOUNT_EMAIL"),
|
GoogleServiceAccountEmail: utils.MustGetEnv("GOOGLE_SERVICE_ACCOUNT_EMAIL"),
|
||||||
BucketName: gcsBucket,
|
BucketName: gcsBucket,
|
||||||
})
|
})
|
||||||
waitlistSvc := waitlist.NewService(db.Pool())
|
waitlistSvc := waitlist.NewService(db.Pool(), aeroSvc)
|
||||||
|
|
||||||
// Initialize handler
|
// Initialize handler
|
||||||
h := handler.NewHandler(authSvc, humanSvc, networkSvc, particleSvc, depotSvc, waitlistSvc)
|
h := handler.NewHandler(authSvc, humanSvc, networkSvc, particleSvc, depotSvc, waitlistSvc)
|
||||||
@@ -135,7 +135,7 @@ func main() {
|
|||||||
mux.Handle("POST /waitlist/invite", withAuth(h.InviteWaitlistEntrant))
|
mux.Handle("POST /waitlist/invite", withAuth(h.InviteWaitlistEntrant))
|
||||||
|
|
||||||
// Apply middleware
|
// Apply middleware
|
||||||
// nil allows all origins (required for electron app)
|
// nil allows all origins (required for electron app)
|
||||||
muxWithCors := middleware.CORS(nil)(mux)
|
muxWithCors := middleware.CORS(nil)(mux)
|
||||||
|
|
||||||
addr := fmt.Sprintf("0.0.0.0:%s", port)
|
addr := fmt.Sprintf("0.0.0.0:%s", port)
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ require (
|
|||||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||||
|
go.uber.org/mock v0.6.0 // indirect
|
||||||
golang.org/x/crypto v0.45.0 // indirect
|
golang.org/x/crypto v0.45.0 // indirect
|
||||||
golang.org/x/net v0.47.0 // indirect
|
golang.org/x/net v0.47.0 // indirect
|
||||||
golang.org/x/oauth2 v0.34.0 // indirect
|
golang.org/x/oauth2 v0.34.0 // indirect
|
||||||
|
|||||||
@@ -244,6 +244,8 @@ go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJr
|
|||||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||||
go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os=
|
go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os=
|
||||||
go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo=
|
go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo=
|
||||||
|
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||||
|
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||||
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ func NewHandler(authSvc auth.AuthService, humanSvc human.Service, networkSvc net
|
|||||||
|
|
||||||
type Human struct {
|
type Human struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
EmailPrefix string `json:"email_prefix"`
|
EmailPrefix string `json:"email_prefix"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: /Users/talksik/Documents/code/llink/go/genproto/aero/main_grpc.pb.go
|
||||||
|
//
|
||||||
|
// Generated by this command:
|
||||||
|
//
|
||||||
|
// mockgen -source=/Users/talksik/Documents/code/llink/go/genproto/aero/main_grpc.pb.go -destination=/Users/talksik/Documents/code/llink/go/internal/waitlist/mocks/mock_aero.go -package=mocks
|
||||||
|
//
|
||||||
|
|
||||||
|
// Package mocks is a generated GoMock package.
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
pbaero "github.com/flowy-live/llink/genproto/aero"
|
||||||
|
gomock "go.uber.org/mock/gomock"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockPrimaryClient is a mock of PrimaryClient interface.
|
||||||
|
type MockPrimaryClient struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockPrimaryClientMockRecorder
|
||||||
|
isgomock struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockPrimaryClientMockRecorder is the mock recorder for MockPrimaryClient.
|
||||||
|
type MockPrimaryClientMockRecorder struct {
|
||||||
|
mock *MockPrimaryClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockPrimaryClient creates a new mock instance.
|
||||||
|
func NewMockPrimaryClient(ctrl *gomock.Controller) *MockPrimaryClient {
|
||||||
|
mock := &MockPrimaryClient{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockPrimaryClientMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockPrimaryClient) EXPECT() *MockPrimaryClientMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShootEmail mocks base method.
|
||||||
|
func (m *MockPrimaryClient) ShootEmail(ctx context.Context, in *pbaero.ShootEmailRequest, opts ...grpc.CallOption) (*pbaero.ShootEmailResponse, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{ctx, in}
|
||||||
|
for _, a := range opts {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "ShootEmail", varargs...)
|
||||||
|
ret0, _ := ret[0].(*pbaero.ShootEmailResponse)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShootEmail indicates an expected call of ShootEmail.
|
||||||
|
func (mr *MockPrimaryClientMockRecorder) ShootEmail(ctx, in any, opts ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]any{ctx, in}, opts...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShootEmail", reflect.TypeOf((*MockPrimaryClient)(nil).ShootEmail), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockPrimaryServer is a mock of PrimaryServer interface.
|
||||||
|
type MockPrimaryServer struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockPrimaryServerMockRecorder
|
||||||
|
isgomock struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockPrimaryServerMockRecorder is the mock recorder for MockPrimaryServer.
|
||||||
|
type MockPrimaryServerMockRecorder struct {
|
||||||
|
mock *MockPrimaryServer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockPrimaryServer creates a new mock instance.
|
||||||
|
func NewMockPrimaryServer(ctrl *gomock.Controller) *MockPrimaryServer {
|
||||||
|
mock := &MockPrimaryServer{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockPrimaryServerMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockPrimaryServer) EXPECT() *MockPrimaryServerMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShootEmail mocks base method.
|
||||||
|
func (m *MockPrimaryServer) ShootEmail(arg0 context.Context, arg1 *pbaero.ShootEmailRequest) (*pbaero.ShootEmailResponse, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ShootEmail", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(*pbaero.ShootEmailResponse)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShootEmail indicates an expected call of ShootEmail.
|
||||||
|
func (mr *MockPrimaryServerMockRecorder) ShootEmail(arg0, arg1 any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShootEmail", reflect.TypeOf((*MockPrimaryServer)(nil).ShootEmail), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustEmbedUnimplementedPrimaryServer mocks base method.
|
||||||
|
func (m *MockPrimaryServer) mustEmbedUnimplementedPrimaryServer() {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "mustEmbedUnimplementedPrimaryServer")
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustEmbedUnimplementedPrimaryServer indicates an expected call of mustEmbedUnimplementedPrimaryServer.
|
||||||
|
func (mr *MockPrimaryServerMockRecorder) mustEmbedUnimplementedPrimaryServer() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "mustEmbedUnimplementedPrimaryServer", reflect.TypeOf((*MockPrimaryServer)(nil).mustEmbedUnimplementedPrimaryServer))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockUnsafePrimaryServer is a mock of UnsafePrimaryServer interface.
|
||||||
|
type MockUnsafePrimaryServer struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockUnsafePrimaryServerMockRecorder
|
||||||
|
isgomock struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockUnsafePrimaryServerMockRecorder is the mock recorder for MockUnsafePrimaryServer.
|
||||||
|
type MockUnsafePrimaryServerMockRecorder struct {
|
||||||
|
mock *MockUnsafePrimaryServer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockUnsafePrimaryServer creates a new mock instance.
|
||||||
|
func NewMockUnsafePrimaryServer(ctrl *gomock.Controller) *MockUnsafePrimaryServer {
|
||||||
|
mock := &MockUnsafePrimaryServer{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockUnsafePrimaryServerMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockUnsafePrimaryServer) EXPECT() *MockUnsafePrimaryServerMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustEmbedUnimplementedPrimaryServer mocks base method.
|
||||||
|
func (m *MockUnsafePrimaryServer) mustEmbedUnimplementedPrimaryServer() {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "mustEmbedUnimplementedPrimaryServer")
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustEmbedUnimplementedPrimaryServer indicates an expected call of mustEmbedUnimplementedPrimaryServer.
|
||||||
|
func (mr *MockUnsafePrimaryServerMockRecorder) mustEmbedUnimplementedPrimaryServer() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "mustEmbedUnimplementedPrimaryServer", reflect.TypeOf((*MockUnsafePrimaryServer)(nil).mustEmbedUnimplementedPrimaryServer))
|
||||||
|
}
|
||||||
@@ -3,8 +3,11 @@ package waitlist
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
pbaero "github.com/flowy-live/llink/genproto/aero"
|
||||||
"github.com/flowy-live/llink/internal/utils"
|
"github.com/flowy-live/llink/internal/utils"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
)
|
)
|
||||||
@@ -41,12 +44,14 @@ type Service interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type serviceImpl struct {
|
type serviceImpl struct {
|
||||||
repo repository
|
repo repository
|
||||||
|
aeroSvc pbaero.PrimaryClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(pool *pgxpool.Pool) Service {
|
func NewService(pool *pgxpool.Pool, aeroSvc pbaero.PrimaryClient) Service {
|
||||||
return &serviceImpl{
|
return &serviceImpl{
|
||||||
repo: newRepository(pool),
|
repo: newRepository(pool),
|
||||||
|
aeroSvc: aeroSvc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +73,20 @@ func (s *serviceImpl) AddToWaitlist(ctx context.Context, email string, metadata
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message := fmt.Sprintf("New human added to the llink waitlist: %s", email)
|
||||||
|
_, err = s.aeroSvc.ShootEmail(context.Background(), &pbaero.ShootEmailRequest{
|
||||||
|
ToEmails: []string{"[email protected]"},
|
||||||
|
Subject: "Flowy Llink - New Waitlist Subscriber",
|
||||||
|
TemplateData: &pbaero.ShootEmailRequest_GenericFlowyAdminAlertData{
|
||||||
|
GenericFlowyAdminAlertData: &pbaero.GenericFlowyAdminAlertData{
|
||||||
|
Message: message,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to add to waitlist", "error", err, "email", email)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
pbaero "github.com/flowy-live/llink/genproto/aero"
|
||||||
"github.com/flowy-live/llink/internal/testhelper"
|
"github.com/flowy-live/llink/internal/testhelper"
|
||||||
"github.com/flowy-live/llink/internal/waitlist"
|
"github.com/flowy-live/llink/internal/waitlist"
|
||||||
|
"github.com/flowy-live/llink/internal/waitlist/mocks"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
var dbPool *pgxpool.Pool
|
var dbPool *pgxpool.Pool
|
||||||
@@ -21,9 +24,19 @@ func TestMain(m *testing.M) {
|
|||||||
os.Exit(ret)
|
os.Exit(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newTestService(t *testing.T) waitlist.Service {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
mockAero := mocks.NewMockPrimaryClient(ctrl)
|
||||||
|
mockAero.EXPECT().
|
||||||
|
ShootEmail(gomock.Any(), gomock.Any()).
|
||||||
|
Return(&pbaero.ShootEmailResponse{}, nil).
|
||||||
|
AnyTimes()
|
||||||
|
return waitlist.NewService(dbPool, mockAero)
|
||||||
|
}
|
||||||
|
|
||||||
func TestWaitlistService_AddAndGet(t *testing.T) {
|
func TestWaitlistService_AddAndGet(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
svc := waitlist.NewService(dbPool)
|
svc := newTestService(t)
|
||||||
|
|
||||||
email := "[email protected]"
|
email := "[email protected]"
|
||||||
metadata := map[string]string{"source": "landing-page", "plan": "pro"}
|
metadata := map[string]string{"source": "landing-page", "plan": "pro"}
|
||||||
@@ -48,7 +61,7 @@ func TestWaitlistService_AddAndGet(t *testing.T) {
|
|||||||
|
|
||||||
func TestWaitlistService_AddDuplicate(t *testing.T) {
|
func TestWaitlistService_AddDuplicate(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
svc := waitlist.NewService(dbPool)
|
svc := newTestService(t)
|
||||||
|
|
||||||
email := "[email protected]"
|
email := "[email protected]"
|
||||||
|
|
||||||
@@ -66,7 +79,7 @@ func TestWaitlistService_AddDuplicate(t *testing.T) {
|
|||||||
|
|
||||||
func TestWaitlistService_AddNilMetadata(t *testing.T) {
|
func TestWaitlistService_AddNilMetadata(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
svc := waitlist.NewService(dbPool)
|
svc := newTestService(t)
|
||||||
|
|
||||||
email := "[email protected]"
|
email := "[email protected]"
|
||||||
|
|
||||||
@@ -84,7 +97,7 @@ func TestWaitlistService_AddNilMetadata(t *testing.T) {
|
|||||||
|
|
||||||
func TestWaitlistService_GetEntryNotFound(t *testing.T) {
|
func TestWaitlistService_GetEntryNotFound(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
svc := waitlist.NewService(dbPool)
|
svc := newTestService(t)
|
||||||
|
|
||||||
_, err := svc.GetWaitlistEntryByEmail(ctx, "[email protected]")
|
_, err := svc.GetWaitlistEntryByEmail(ctx, "[email protected]")
|
||||||
assert.ErrorIs(t, err, waitlist.EntryNotFoundError)
|
assert.ErrorIs(t, err, waitlist.EntryNotFoundError)
|
||||||
@@ -92,7 +105,7 @@ func TestWaitlistService_GetEntryNotFound(t *testing.T) {
|
|||||||
|
|
||||||
func TestWaitlistService_MarkInvited(t *testing.T) {
|
func TestWaitlistService_MarkInvited(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
svc := waitlist.NewService(dbPool)
|
svc := newTestService(t)
|
||||||
|
|
||||||
email := "[email protected]"
|
email := "[email protected]"
|
||||||
|
|
||||||
@@ -115,7 +128,7 @@ func TestWaitlistService_MarkInvited(t *testing.T) {
|
|||||||
|
|
||||||
func TestWaitlistService_MarkInvitedNotFound(t *testing.T) {
|
func TestWaitlistService_MarkInvitedNotFound(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
svc := waitlist.NewService(dbPool)
|
svc := newTestService(t)
|
||||||
|
|
||||||
err := svc.MarkWaitlistEntryInvited(ctx, "[email protected]")
|
err := svc.MarkWaitlistEntryInvited(ctx, "[email protected]")
|
||||||
assert.ErrorIs(t, err, waitlist.EntryNotFoundError)
|
assert.ErrorIs(t, err, waitlist.EntryNotFoundError)
|
||||||
@@ -123,7 +136,7 @@ func TestWaitlistService_MarkInvitedNotFound(t *testing.T) {
|
|||||||
|
|
||||||
func TestWaitlistService_GetWaitlistFilters(t *testing.T) {
|
func TestWaitlistService_GetWaitlistFilters(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
svc := waitlist.NewService(dbPool)
|
svc := newTestService(t)
|
||||||
|
|
||||||
uninvitedEmail := "[email protected]"
|
uninvitedEmail := "[email protected]"
|
||||||
invitedEmail := "[email protected]"
|
invitedEmail := "[email protected]"
|
||||||
@@ -166,7 +179,7 @@ func TestWaitlistService_GetWaitlistFilters(t *testing.T) {
|
|||||||
|
|
||||||
func TestWaitlistService_EmailNormalization(t *testing.T) {
|
func TestWaitlistService_EmailNormalization(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
svc := waitlist.NewService(dbPool)
|
svc := newTestService(t)
|
||||||
|
|
||||||
// Add with uppercase email
|
// Add with uppercase email
|
||||||
err := svc.AddToWaitlist(ctx, "[email protected]", nil)
|
err := svc.AddToWaitlist(ctx, "[email protected]", nil)
|
||||||
@@ -188,7 +201,7 @@ func TestWaitlistService_EmailNormalization(t *testing.T) {
|
|||||||
|
|
||||||
func TestWaitlistService_InvalidEmail(t *testing.T) {
|
func TestWaitlistService_InvalidEmail(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
svc := waitlist.NewService(dbPool)
|
svc := newTestService(t)
|
||||||
|
|
||||||
err := svc.AddToWaitlist(ctx, "not-an-email", nil)
|
err := svc.AddToWaitlist(ctx, "not-an-email", nil)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|||||||
Reference in New Issue
Block a user