Files

90 lines
2.8 KiB
Go

package handler
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/warmbly/warmbly/internal/api/middleware"
"github.com/warmbly/warmbly/internal/app/contact"
"github.com/warmbly/warmbly/internal/errx"
"github.com/warmbly/warmbly/internal/models"
)
type recordingContacts struct {
contact.ContactService
added []models.AddContact
}
func (r *recordingContacts) Add(_ context.Context, _ string, _ uuid.UUID, in []models.AddContact) ([]models.Contact, *errx.Error) {
r.added = in
out := make([]models.Contact, len(in))
return out, nil
}
func postContacts(t *testing.T, body string) (*httptest.ResponseRecorder, *recordingContacts) {
t.Helper()
gin.SetMode(gin.TestMode)
svc := &recordingContacts{}
h := &Handler{ContactService: svc}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodPost, "/v1/contacts", strings.NewReader(body))
c.Request.Header.Set("Content-Type", "application/json")
c.Set(middleware.OrganizationIDKey, uuid.New())
h.AddContacts(c)
return w, svc
}
// The CLIs create one contact by sending a bare object, so it has to be accepted alongside the array (issue #650).
func TestAddContactsAcceptsOneObjectOrAnArray(t *testing.T) {
for _, body := range []string{
`{"email":"jane@example.com","first_name":"Jane"}`,
` [{"email":"jane@example.com","first_name":"Jane"}]`,
} {
w, svc := postContacts(t, body)
if w.Code != http.StatusOK {
t.Fatalf("%s: status %d, body %s", body, w.Code, w.Body.String())
}
if len(svc.added) != 1 || svc.added[0].Email != "jane@example.com" || svc.added[0].FirstName != "Jane" {
t.Fatalf("%s: service got %+v", body, svc.added)
}
var out []json.RawMessage
if err := json.Unmarshal(w.Body.Bytes(), &out); err != nil || len(out) != 1 {
t.Fatalf("%s: response is not a one-item array: %s", body, w.Body.String())
}
}
}
func TestAddContactsNamesWhatIsWrongWithTheBody(t *testing.T) {
cases := map[string]string{
``: "request body is empty",
`[]`: "no contacts provided",
`{"email":5}`: `Field "email" must be a JSON string, not a JSON number`,
`"jane@example.com"`: "must be a JSON array, not a JSON string",
`{"email":"a@b.co",}`: "not valid JSON",
}
for body, want := range cases {
w, svc := postContacts(t, body)
if w.Code != http.StatusBadRequest {
t.Fatalf("%q: status %d, want 400", body, w.Code)
}
if svc.added != nil {
t.Fatalf("%q: reached the service", body)
}
var resp struct {
Message string `json:"message"`
}
_ = json.Unmarshal(w.Body.Bytes(), &resp)
if !strings.Contains(resp.Message, want) {
t.Errorf("%q: message %q does not say %q", body, resp.Message, want)
}
}
}