Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions subuser.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,85 @@ func (c *Client) DeleteSubuser(ctx context.Context, username string) error {
}
return nil
}

type OutputGetCreditsForSubuser struct {
Type string `json:"type,omitempty"`
ResetFrequency string `json:"reset_frequency,omitempty"`
Remain int `json:"remain,omitempty"`
Total int `json:"total,omitempty"`
Used int `json:"used,omitempty"`
}

// see: https://www.twilio.com/docs/sendgrid/api-reference/subusers-api/get-credits-for-subuser
func (c *Client) GetCreditsForSubuser(ctx context.Context, username string) (*OutputGetCreditsForSubuser, error) {
path := fmt.Sprintf("/subusers/%s/credits", username)

req, err := c.NewRequest("GET", path, nil)
if err != nil {
return nil, err
}

r := new(OutputGetCreditsForSubuser)
if err := c.Do(ctx, req, &r); err != nil {
return nil, err
}
return r, nil
}

type InputUpdateCreditsForSubuser struct {
Type string `json:"type,omitempty"`
ResetFrequency string `json:"reset_frequency,omitempty"`
Total int `json:"total,omitempty"`
}

type OutputUpdateCreditsForSubuser struct {
Type string `json:"type,omitempty"`
ResetFrequency string `json:"reset_frequency,omitempty"`
Remain int `json:"remain,omitempty"`
Total int `json:"total,omitempty"`
Used int `json:"used,omitempty"`
}

// see: https://www.twilio.com/docs/sendgrid/api-reference/subusers-api/update-credits-for-subuser
func (c *Client) UpdateCreditsForSubuser(ctx context.Context, username string, input *InputUpdateCreditsForSubuser) (*OutputUpdateCreditsForSubuser, error) {
path := fmt.Sprintf("/subusers/%s/credits", username)

req, err := c.NewRequest("PUT", path, input)
if err != nil {
return nil, err
}

r := new(OutputUpdateCreditsForSubuser)
if err := c.Do(ctx, req, &r); err != nil {
return nil, err
}
return r, nil
}

type InputUpdateRemainingCreditsForSubuser struct {
AllocationUpdate int `json:"allocation_update,omitempty"`
}

type OutputUpdateRemainingCreditsForSubuser struct {
Type string `json:"type,omitempty"`
ResetFrequency string `json:"reset_frequency,omitempty"`
Remain int `json:"remain,omitempty"`
Total int `json:"total,omitempty"`
Used int `json:"used,omitempty"`
}

// see: https://www.twilio.com/docs/sendgrid/api-reference/subusers-api/update-remaining-credits-for-subuser
func (c *Client) UpdateRemainingCreditsForSubuser(ctx context.Context, username string, input *InputUpdateRemainingCreditsForSubuser) (*OutputUpdateRemainingCreditsForSubuser, error) {
path := fmt.Sprintf("/subusers/%s/credits/remaining", username)

req, err := c.NewRequest("PATCH", path, input)
if err != nil {
return nil, err
}

r := new(OutputUpdateRemainingCreditsForSubuser)
if err := c.Do(ctx, req, &r); err != nil {
return nil, err
}
return r, nil
}
219 changes: 219 additions & 0 deletions subuser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,3 +675,222 @@ func TestDeleteSubuser_NewRequestError(t *testing.T) {

client.baseURL = originalBaseURL
}

func TestGetCreditsForSubuser(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/subusers/dummy/credits", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
if _, err := fmt.Fprint(w, `{
"type": "recurring",
"reset_frequency": "daily",
"remain": 500,
"total": 1000,
"used": 500
}`); err != nil {
t.Fatal(err)
}
})

expected, err := client.GetCreditsForSubuser(context.TODO(), "dummy")
if err != nil {
t.Errorf("Unexpected error: %s", err)
return
}

want := &OutputGetCreditsForSubuser{
Type: "recurring",
ResetFrequency: "daily",
Remain: 500,
Total: 1000,
Used: 500,
}
if !reflect.DeepEqual(want, expected) {
t.Fatal(ErrIncorrectResponse)
}
}

func TestGetCreditsForSubuser_Failed(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/subusers/dummy/credits", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
})

_, err := client.GetCreditsForSubuser(context.TODO(), "dummy")
if err == nil {
t.Fatal("expected an error but got none")
}
}

func TestGetCreditsForSubuser_NewRequestError(t *testing.T) {
client, _, _, teardown := setup()
defer teardown()

originalBaseURL := client.baseURL
invalidURL, _ := url.Parse("https://api.example.com/v3/")
client.baseURL = invalidURL

_, err := client.GetCreditsForSubuser(context.TODO(), "dummy")
if err == nil {
t.Error("Expected error for invalid baseURL")
}
if err != nil && !strings.Contains(err.Error(), "trailing slash") {
t.Errorf("Expected error message to contain 'trailing slash', got %v", err.Error())
}

client.baseURL = originalBaseURL
}

func TestUpdateCreditsForSubuser(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/subusers/dummy/credits", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
if _, err := fmt.Fprint(w, `{
"type": "recurring",
"reset_frequency": "daily",
"remain": 500,
"total": 1000,
"used": 500
}`); err != nil {
t.Fatal(err)
}
})

input := &InputUpdateCreditsForSubuser{
Type: "recurring",
}

expected, err := client.UpdateCreditsForSubuser(context.TODO(), "dummy", input)
if err != nil {
t.Errorf("Unexpected error: %s", err)
return
}

want := &OutputUpdateCreditsForSubuser{
Type: "recurring",
ResetFrequency: "daily",
Remain: 500,
Total: 1000,
Used: 500,
}
if !reflect.DeepEqual(want, expected) {
t.Fatal(ErrIncorrectResponse)
}
}

func TestUpdateCreditsForSubuser_Failed(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/subusers/dummy/credits", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
})

input := &InputUpdateCreditsForSubuser{
Type: "recurring",
}
_, err := client.UpdateCreditsForSubuser(context.TODO(), "dummy", input)
if err == nil {
t.Fatal("expected an error but got none")
}
}

func TestUpdateCreditsForSubuser_NewRequestError(t *testing.T) {
client, _, _, teardown := setup()
defer teardown()

originalBaseURL := client.baseURL
invalidURL, _ := url.Parse("https://api.example.com/v3/")
client.baseURL = invalidURL

input := &InputUpdateCreditsForSubuser{
Type: "recurring",
}
_, err := client.UpdateCreditsForSubuser(context.TODO(), "dummy", input)
if err == nil {
t.Error("Expected error for invalid baseURL")
}
if err != nil && !strings.Contains(err.Error(), "trailing slash") {
t.Errorf("Expected error message to contain 'trailing slash', got %v", err.Error())
}

client.baseURL = originalBaseURL
}

func TestUpdateRemainingCreditsForSubuser(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/subusers/dummy/credits/remaining", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PATCH")
if _, err := fmt.Fprint(w, `{
"type": "recurring",
"reset_frequency": "daily",
"remain": 600,
"total": 1000,
"used": 400
}`); err != nil {
t.Fatal(err)
}
})

expected, err := client.UpdateRemainingCreditsForSubuser(context.TODO(), "dummy", &InputUpdateRemainingCreditsForSubuser{
AllocationUpdate: 100,
})
if err != nil {
t.Errorf("Unexpected error: %s", err)
return
}
want := &OutputUpdateRemainingCreditsForSubuser{
Type: "recurring",
ResetFrequency: "daily",
Remain: 600,
Total: 1000,
Used: 400,
}
if !reflect.DeepEqual(want, expected) {
t.Fatal(ErrIncorrectResponse)
}
}

func TestUpdateRemainingCreditsForSubuser_Failed(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/subusers/dummy/credits/remaining", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
})

_, err := client.UpdateRemainingCreditsForSubuser(context.TODO(), "dummy", &InputUpdateRemainingCreditsForSubuser{
AllocationUpdate: 100,
})
if err == nil {
t.Fatal("expected an error but got none")
}
}

func TestUpdateRemainingCreditsForSubuser_NewRequestError(t *testing.T) {
client, _, _, teardown := setup()
defer teardown()

originalBaseURL := client.baseURL
invalidURL, _ := url.Parse("https://api.example.com/v3/")
client.baseURL = invalidURL

_, err := client.UpdateRemainingCreditsForSubuser(context.TODO(), "dummy", &InputUpdateRemainingCreditsForSubuser{
AllocationUpdate: 100,
})
if err == nil {
t.Error("Expected error for invalid baseURL")
}
if err != nil && !strings.Contains(err.Error(), "trailing slash") {
t.Errorf("Expected error message to contain 'trailing slash', got %v", err.Error())
}

client.baseURL = originalBaseURL
}
Loading