Skip to content

Commit

Permalink
feat: add bulk subscriber api
Browse files Browse the repository at this point in the history
  • Loading branch information
mahendraHegde committed Sep 25, 2023
1 parent 29a0e27 commit c2f46a4
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 6 deletions.
30 changes: 24 additions & 6 deletions lib/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,18 @@ type TriggerTopicRecipientsTypeSingle struct {
}

type SubscriberPayload struct {
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
Email string `json:"email,omitempty"`
Phone string `json:"phone,omitempty"`
Avatar string `json:"avatar,omitempty"`
Data map[string]interface{} `json:"data,omitempty"`
FirstName string `json:"firstName,omitempty"`
LastName string `json:"lastName,omitempty"`
Email string `json:"email,omitempty"`
Phone string `json:"phone,omitempty"`
Avatar string `json:"avatar,omitempty"`
Locale string `json:"locale,omitempty"`
Data map[string]interface{} `json:"data,omitempty"`
SubscriberId string `json:"subscriberId"`
}

type SubscriberBulkPayload struct {
Subscribers []SubscriberPayload `json:"subscribers"`
}

type TriggerRecipientsType interface {
Expand Down Expand Up @@ -93,6 +99,18 @@ type SubscriberResponse struct {
Data interface{} `json:"data"`
}

type SubscriberBulkCreateResponse struct {
Data struct {
Updated []struct {
SubscriberId string `json:"subscriberId"`
} `json:"updated"`
Created []struct {
SubscriberId string `json:"subscriberId"`
} `json:"created"`
Failed []interface{} `json:"failed"`
} `json:"data"`
}

type Template struct {
ID string `json:"_id"`
Name string `json:"name"`
Expand Down
21 changes: 21 additions & 0 deletions lib/subscribers.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

type ISubscribers interface {
Identify(ctx context.Context, subscriberID string, data interface{}) (SubscriberResponse, error)
CreateBulk(ctx context.Context, subscribers SubscriberBulkPayload) (SubscriberBulkCreateResponse, error)
Get(ctx context.Context, subscriberID string) (SubscriberResponse, error)
Update(ctx context.Context, subscriberID string, data interface{}) (SubscriberResponse, error)
Delete(ctx context.Context, subscriberID string) (SubscriberResponse, error)
Expand Down Expand Up @@ -49,6 +50,26 @@ func (s *SubscriberService) Identify(ctx context.Context, subscriberID string, d
return resp, nil
}

func (s *SubscriberService) CreateBulk(ctx context.Context, subscribers SubscriberBulkPayload) (SubscriberBulkCreateResponse, error) {
var resp SubscriberBulkCreateResponse
URL := s.client.config.BackendURL.JoinPath("subscribers", "bulk")
jsonBody, err := json.Marshal(subscribers)
if err != nil {
return resp, err
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, URL.String(), bytes.NewBuffer(jsonBody))
if err != nil {
return resp, err
}

_, err = s.client.sendRequest(req, &resp)
if err != nil {
return resp, err
}

return resp, nil
}

func (s *SubscriberService) Get(ctx context.Context, subscriberID string) (SubscriberResponse, error) {
var resp SubscriberResponse
URL := s.client.config.BackendURL.JoinPath("subscribers", subscriberID)
Expand Down
57 changes: 57 additions & 0 deletions lib/subscribers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,63 @@ func TestSubscriberService_Identify_Success(t *testing.T) {
})
}

func TestSubscriberService_BulkCreate_Success(t *testing.T) {
var (
subscriberBulkPayload lib.SubscriberBulkPayload
receivedBody lib.SubscriberBulkPayload
expectedRequest lib.SubscriberBulkPayload
expectedResponse lib.SubscriberBulkCreateResponse
)

subscriberService := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if err := json.NewDecoder(req.Body).Decode(&receivedBody); err != nil {
log.Printf("error in unmarshalling %+v", err)
w.WriteHeader(http.StatusBadRequest)
return
}

t.Run("Header must contain ApiKey", func(t *testing.T) {
authKey := req.Header.Get("Authorization")
assert.True(t, strings.Contains(authKey, novuApiKey))
assert.True(t, strings.HasPrefix(authKey, "ApiKey"))
})

t.Run("URL and request method is as expected", func(t *testing.T) {
expectedURL := "/v1/subscribers/bulk"
assert.Equal(t, http.MethodPost, req.Method)
assert.Equal(t, expectedURL, req.RequestURI)
})

t.Run("Request is as expected", func(t *testing.T) {
fileToStruct(filepath.Join("../testdata", "subscriber_bulk.json"), &expectedRequest)
assert.Equal(t, expectedRequest, receivedBody)
})

var resp lib.SubscriberResponse
fileToStruct(filepath.Join("../testdata", "subscriber_bulk_response.json"), &resp)

w.WriteHeader(http.StatusOK)
bb, _ := json.Marshal(resp)
w.Write(bb)
}))

defer subscriberService.Close()

ctx := context.Background()
fileToStruct(filepath.Join("../testdata", "subscriber_bulk.json"), &subscriberBulkPayload)

c := lib.NewAPIClient(novuApiKey, &lib.Config{BackendURL: lib.MustParseURL(subscriberService.URL)})

resp, err := c.SubscriberApi.CreateBulk(ctx, subscriberBulkPayload)
require.Nil(t, err)
assert.NotNil(t, resp)

t.Run("Response is as expected", func(t *testing.T) {
fileToStruct(filepath.Join("../testdata", "subscriber_bulk_response.json"), &expectedResponse)
assert.Equal(t, expectedResponse, resp)
})
}

func TestSubscriberService_Update_Success(t *testing.T) {
var (
updateSubscriber lib.SubscriberPayload
Expand Down
1 change: 1 addition & 0 deletions testdata/identify_subscriber.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"last_name": "Souza",
"email": "[email protected]",
"phone": "(86) 5889-7095",
"subscriberId":"62b51a44da1af31d109f5da7",
"avatar": "https://randomuser.me/api/portraits/women/39.jpg",
"location": {
"street": {
Expand Down
23 changes: 23 additions & 0 deletions testdata/subscriber_bulk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"subscribers": [
{
"title": "Mrs",
"first_name": "Junilvana",
"last_name": "Souza",
"email": "[email protected]",
"phone": "(86) 5889-7095",
"subscriberId": "62b51a44da1af31d109f5da7",
"avatar": "https://randomuser.me/api/portraits/women/39.jpg",
"location": {
"street": {
"number": 97,
"name": "Rua Santo Antônio"
},
"city": "Itapipoca",
"state": "Mato Grosso",
"country": "Brazil",
"postcode": 92448
}
}
]
}
10 changes: 10 additions & 0 deletions testdata/subscriber_bulk_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"data": {
"updated": [
],
"created": [{
"subscriberId":"62b51a44da1af31d109f5da7"
}],
"failed": []
}
}

0 comments on commit c2f46a4

Please sign in to comment.