Skip to content

Commit

Permalink
Added wrapper method for ease of use
Browse files Browse the repository at this point in the history
  • Loading branch information
mrz1836 committed May 12, 2021
1 parent 2206196 commit 7de0134
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 2 deletions.
3 changes: 1 addition & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,7 @@ func (c *Client) request(httpMethod string, requestURL string,
// Set the body if (PUT || POST)
if httpMethod != http.MethodGet && httpMethod != http.MethodDelete {
var j []byte
j, err = json.Marshal(data)
if err != nil {
if j, err = json.Marshal(data); err != nil {
return
}
req = req.SetBody(string(j))
Expand Down
33 changes: 33 additions & 0 deletions events.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package customerio

import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
Expand All @@ -23,6 +25,10 @@ func (c *Client) NewEvent(customerIDOrEmail string, eventName string, timestamp
if timestamp.IsZero() {
timestamp = time.Now().UTC()
}
if len(data) > 56000 {
return errors.New("event body size limited to 56000")
}

_, err := c.request(
http.MethodPost,
fmt.Sprintf("%s/api/v1/customers/%s/events", c.options.trackURL, url.PathEscape(customerIDOrEmail)),
Expand All @@ -47,6 +53,9 @@ func (c *Client) NewAnonymousEvent(eventName string, timestamp time.Time, data m
if timestamp.IsZero() {
timestamp = time.Now().UTC()
}
if len(data) > 56000 {
return errors.New("event body size limited to 56000")
}
_, err := c.request(
http.MethodPost,
fmt.Sprintf("%s/api/v1/events", c.options.trackURL),
Expand All @@ -59,3 +68,27 @@ func (c *Client) NewAnonymousEvent(eventName string, timestamp time.Time, data m
)
return err
}

// NewEventUsingInterface is a wrapper for NewEvent() which can take a custom struct vs map[string]interface{}
// See: https://customer.io/docs/api/#tag/Track-Events
// AKA: Track()
// Only use "email" if the workspace is setup to use email instead of ID
// Use "timestamp" to send events in the past. If not set, it will use Now().UTC()
func (c *Client) NewEventUsingInterface(customerIDOrEmail string, eventName string, timestamp time.Time,
data interface{}) error {

// Marshall struct into JSON string
var mapInterface map[string]interface{}
d, err := json.Marshal(data)
if err != nil {
return err
}

// Convert to string to map[string]interface
if err = json.Unmarshal(d, &mapInterface); err != nil {
return err
}

// Fire main method
return c.NewEvent(customerIDOrEmail, eventName, timestamp, mapInterface)
}
122 changes: 122 additions & 0 deletions events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,128 @@ func BenchmarkClient_NewAnonymousEvent(b *testing.B) {
}
}

// TestClient_NewEventUsingInterface will test the method NewEventUsingInterface()
func TestClient_NewEventUsingInterface(t *testing.T) {
// t.Parallel() (Cannot run in parallel - issues with overriding the mock client)

t.Run("successful response", func(t *testing.T) {
client, err := newTestClient()
assert.NoError(t, err)
assert.NotNil(t, client)

mockNewEvent(http.StatusOK, testCustomerID)

someData := struct {
FieldName string `json:"field_name"`
IntField int `json:"int_field"`
TimestampField int64 `json:"timestamp_field"`
}{
FieldName: "some_value",
IntField: 123,
TimestampField: time.Now().UTC().Unix(),
}

err = client.NewEventUsingInterface(
testCustomerID, testEventName, time.Now().UTC(), someData,
)
assert.NoError(t, err)
})

t.Run("missing customer id", func(t *testing.T) {
client, err := newTestClient()
assert.NoError(t, err)
assert.NotNil(t, client)

mockNewEvent(http.StatusOK, testCustomerID+"456")

someData := struct {
FieldName string `json:"field_name"`
IntField int `json:"int_field"`
TimestampField int64 `json:"timestamp_field"`
}{
FieldName: "some_value",
IntField: 123,
TimestampField: time.Now().UTC().Unix(),
}

err = client.NewEventUsingInterface(
"", testEventName, time.Now().UTC(), someData,
)
assert.Error(t, err)
checkParamError(t, err, "customerIDOrEmail")
})

t.Run("missing event name", func(t *testing.T) {
client, err := newTestClient()
assert.NoError(t, err)
assert.NotNil(t, client)

mockNewEvent(http.StatusOK, testCustomerID)

someData := struct {
FieldName string `json:"field_name"`
IntField int `json:"int_field"`
TimestampField int64 `json:"timestamp_field"`
}{
FieldName: "some_value",
IntField: 123,
TimestampField: time.Now().UTC().Unix(),
}

err = client.NewEventUsingInterface(
testCustomerID, "", time.Now().UTC(), someData,
)
assert.Error(t, err)
checkParamError(t, err, "eventName")
})

t.Run("no time set", func(t *testing.T) {
client, err := newTestClient()
assert.NoError(t, err)
assert.NotNil(t, client)

mockNewEvent(http.StatusOK, testCustomerID)

someData := struct {
FieldName string `json:"field_name"`
IntField int `json:"int_field"`
TimestampField int64 `json:"timestamp_field"`
}{
FieldName: "some_value",
IntField: 123,
TimestampField: time.Now().UTC().Unix(),
}

err = client.NewEventUsingInterface(
testCustomerID, testEventName, time.Time{}, someData,
)
assert.NoError(t, err)
})

t.Run("customerIo error", func(t *testing.T) {
client, err := newTestClient()
assert.NoError(t, err)
assert.NotNil(t, client)

mockNewEvent(http.StatusUnprocessableEntity, testCustomerID)

someData := struct {
FieldName string `json:"field_name"`
IntField int `json:"int_field"`
TimestampField int64 `json:"timestamp_field"`
}{
FieldName: "some_value",
IntField: 123,
TimestampField: time.Now().UTC().Unix(),
}

err = client.NewEventUsingInterface(
testCustomerID, testEventName, time.Now().UTC(), someData,
)
assert.Error(t, err)
})
}

// mockNewEvent is used for mocking the response
func mockNewEvent(statusCode int, customerID string) {
httpmock.Reset()
Expand Down
39 changes: 39 additions & 0 deletions examples/new_event_using_interface/new_event_using_interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"log"
"os"
"time"

"github.com/mrz1836/go-customerio"
)

func main() {

// Load the client (with Tracking API enabled)
client, err := customerio.NewClient(
customerio.WithTrackingKey(os.Getenv("TRACKING_SITE_ID"), os.Getenv("TRACKING_API_KEY")),
)
if err != nil {
log.Fatalln(err)
}

someData := struct {
FieldName string `json:"field_name"`
IntField int `json:"int_field"`
TimestampField int64 `json:"timestamp_field"`
}{
FieldName: "some_value",
IntField: 123,
TimestampField: time.Now().UTC().Unix(),
}

// New event
err = client.NewEventUsingInterface(
"123", "order_completed", time.Now().UTC(), someData,
)
if err != nil {
log.Fatalln(err)
}
log.Println("Event Created Successfully!")
}

0 comments on commit 7de0134

Please sign in to comment.