From 0d7a4be43b059153ad1f486eda11e9a2b69b1946 Mon Sep 17 00:00:00 2001 From: Ambrose Chua Date: Sun, 29 Sep 2019 23:53:18 +0800 Subject: [PATCH] Increase integration test coverage to 30% --- Makefile | 2 + contact.go | 26 ++++++------ contact_test.go | 102 ++++++++++++++++++++++++++++++++++++++++------ testutils_test.go | 5 ++- user_test.go | 3 +- 5 files changed, 109 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index b63e37b..ba7b3c1 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,8 @@ test_integration: test_integration_prepare test_integration_prepare: $(GORUN) scripts/testutils.go isrunning || $(DOCKERCOMPOSE) -f $(DOCKERCOMPOSE_INTEGRATION_CONFIG) up -d $(GORUN) scripts/testutils.go wait +test_integration_sql_shell: + $(DOCKERCOMPOSE) -f $(DOCKERCOMPOSE_INTEGRATION_CONFIG) exec pg psql -d core test_integration_cleanup: $(DOCKERCOMPOSE) -f $(DOCKERCOMPOSE_INTEGRATION_CONFIG) down diff --git a/contact.go b/contact.go index 0e35363..b9f4b2b 100644 --- a/contact.go +++ b/contact.go @@ -11,17 +11,17 @@ import ( func (h *Handler) CreateContact(w http.ResponseWriter, r *http.Request, p httprouter.Params) { // Parse userID := r.Context().Value("user").(string) - contact := PhoneNumber{} + contactPhone := PhoneNumber{} decoder := json.NewDecoder(r.Body) - err := decoder.Decode(&contact) + err := decoder.Decode(&contactPhone) if err != nil { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } // Validate - phone, err := ParsePhone(contact.PhoneNumber) - if err != nil || len(contact.PhoneNumber) < 1 { + phone, err := ParsePhone(contactPhone.PhoneNumber) + if err != nil || len(contactPhone.PhoneNumber) < 1 { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } @@ -30,14 +30,14 @@ func (h *Handler) CreateContact(w http.ResponseWriter, r *http.Request, p httpro id := "u-" + RandomHex() // Create contact if not exists, returning the id regardless - var contactId string + contact := User{} err = h.db.QueryRow(` INSERT INTO "user" (id, username, bio, profile_pic, first_name, last_name, phone_number) VALUES ($1, '', '', '', '', '', $2) ON CONFLICT(phone_number) DO UPDATE SET phone_number=EXCLUDED.phone_number - RETURNING id - `, id, phone).Scan(&contactId) + RETURNING id, username, bio, profile_pic, first_name, last_name, phone_number + `, id, phone).Scan(&contact.ID, &contact.Username, &contact.Bio, &contact.ProfilePic, &contact.FirstName, &contact.LastName, &contact.PhoneNumber) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) log.Print(err) @@ -47,7 +47,7 @@ func (h *Handler) CreateContact(w http.ResponseWriter, r *http.Request, p httpro // Insert _, err = h.db.Exec(` INSERT INTO contact ("user", contact) VALUES ($1, $2) - `, userID, contactId) + `, userID, contact.ID) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) log.Print(err) @@ -56,8 +56,8 @@ func (h *Handler) CreateContact(w http.ResponseWriter, r *http.Request, p httpro // Respond w.WriteHeader(200) - //w.Header().Set("Content-Type", "application/json") - //json.NewEncoder(w).Encode(contact) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(contact) } func (h *Handler) GetContacts(w http.ResponseWriter, r *http.Request, p httprouter.Params) { @@ -82,13 +82,13 @@ func (h *Handler) GetContacts(w http.ResponseWriter, r *http.Request, p httprout // Scan for rows.Next() { - var id, username, bio, profilePic, firstName, lastName, phone string - if err := rows.Scan(&id, &username, &bio, &profilePic, &firstName, &lastName, &phone); err != nil { + contact := User{} + if err := rows.Scan(&contact.ID, &contact.Username, &contact.Bio, &contact.ProfilePic, &contact.FirstName, &contact.LastName, &contact.PhoneNumber); err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) log.Print(err) return } - contacts = append(contacts, User{id, &username, bio, profilePic, firstName, lastName, phone}) + contacts = append(contacts, contact) } // Respond diff --git a/contact_test.go b/contact_test.go index 5a1e46e..702a5d0 100644 --- a/contact_test.go +++ b/contact_test.go @@ -9,7 +9,8 @@ import ( "net/http" "net/http/httptest" "testing" - // "github.com/google/go-cmp/cmp" + + "github.com/google/go-cmp/cmp" ) func TestContact(t *testing.T) { @@ -21,9 +22,10 @@ func TestContact(t *testing.T) { users := setupUsers(t, db, r) t.Run("Create", testCreateContact(db, r, users)) + t.Run("Get", testGetContacts(db, r, users)) } -func setupUsers(t *testing.T, db *sql.DB, router http.Handler) { +func setupUsers(t *testing.T, db *sql.DB, router http.Handler) []User { users := []User{ User{ @@ -53,8 +55,8 @@ func setupUsers(t *testing.T, db *sql.DB, router http.Handler) { router.ServeHTTP(w, r) assertCode(t, w, 200) - got := new(User) - json.NewDecoder(w.Body).Decode(got) + got := User{} + json.NewDecoder(w.Body).Decode(&got) resultUsers = append(resultUsers, got) } @@ -63,7 +65,7 @@ func setupUsers(t *testing.T, db *sql.DB, router http.Handler) { } -func testCreateContact(db *sql.DB, router http.Handler) func(t *testing.T) { +func testCreateContact(db *sql.DB, router http.Handler, users []User) func(t *testing.T) { return func(t *testing.T) { // Setup @@ -72,24 +74,98 @@ func testCreateContact(db *sql.DB, router http.Handler) func(t *testing.T) { FirstName: "ContactOwner", LastName: "User", } - b, _ := json.Marshal(mockUser) + bs, _ := json.Marshal(mockUser) + + ws := httptest.NewRecorder() + rs := httptest.NewRequest("POST", "/user", bytes.NewBuffer(bs)) + router.ServeHTTP(ws, rs) + + createdUser := new(User) + json.NewDecoder(ws.Body).Decode(createdUser) // Test + b := []byte(`{"phone_number": "` + users[0].PhoneNumber + `"}`) + w := httptest.NewRecorder() - r := httptest.NewRequest("POST", "/user", bytes.NewBuffer(b)) + r := httptest.NewRequest("POST", "/user/contact", bytes.NewBuffer(b)) + claim, _ := json.Marshal(&RawClient{UserId: createdUser.ID, ClientId: "test"}) + r.Header.Add("X-User-Claim", string(claim)) router.ServeHTTP(w, r) assertCode(t, w, 200) // Assert - got, want := new(User), mockUser - wantPhone, _ := ParsePhone(want.PhoneNumber) - json.NewDecoder(w.Body).Decode(got) - if got.FirstName != want.FirstName || got.LastName != want.LastName || got.PhoneNumber != wantPhone { - t.Error("Wanted a User with same FirstName, LastName, PhoneNumber. Got something else") + got, want := User{}, users[0] + json.NewDecoder(w.Body).Decode(&got) + if diff := cmp.Diff(got, want); len(diff) != 0 { + t.Error(diff) } - assertDB(t, db, `SELECT * FROM "user" WHERE phone_number = '+65 9999 9999' AND first_name = 'Test' AND last_name = 'User 1'`) + assertDB(t, db, `SELECT * FROM contact WHERE "user" = $1 AND contact = $2`, createdUser.ID, users[0].ID) + + } +} + +func testGetContacts(db *sql.DB, router http.Handler, users []User) func(t *testing.T) { + return func(t *testing.T) { + + // Setup + mockUser := &User{ + PhoneNumber: "+65 9999 1002", + FirstName: "ContactOwner", + LastName: "User", + } + bs, _ := json.Marshal(mockUser) + + ws := httptest.NewRecorder() + rs := httptest.NewRequest("POST", "/user", bytes.NewBuffer(bs)) + router.ServeHTTP(ws, rs) + + createdUser := new(User) + json.NewDecoder(ws.Body).Decode(createdUser) + + b := []byte(`{"phone_number": "` + users[0].PhoneNumber + `"}`) + + w := httptest.NewRecorder() + r := httptest.NewRequest("POST", "/user/contact", bytes.NewBuffer(b)) + claim, _ := json.Marshal(&RawClient{UserId: createdUser.ID, ClientId: "test"}) + r.Header.Add("X-User-Claim", string(claim)) + + router.ServeHTTP(w, r) + assertCode(t, w, 200) + + b = []byte(`{"phone_number": "` + users[1].PhoneNumber + `"}`) + + w = httptest.NewRecorder() + r = httptest.NewRequest("POST", "/user/contact", bytes.NewBuffer(b)) + r.Header.Add("X-User-Claim", string(claim)) + + router.ServeHTTP(w, r) + assertCode(t, w, 200) + + b = []byte(`{"phone_number": "` + users[2].PhoneNumber + `"}`) + + w = httptest.NewRecorder() + r = httptest.NewRequest("POST", "/user/contact", bytes.NewBuffer(b)) + r.Header.Add("X-User-Claim", string(claim)) + + router.ServeHTTP(w, r) + assertCode(t, w, 200) + + // Test + w = httptest.NewRecorder() + r = httptest.NewRequest("GET", "/user/contact", nil) + r.Header.Add("X-User-Claim", string(claim)) + + router.ServeHTTP(w, r) + assertCode(t, w, 200) + + // Assert + got, want := []User{}, users + json.NewDecoder(w.Body).Decode(&got) + if diff := cmp.Diff(got, want); len(diff) != 0 { + t.Error(diff) + } } } diff --git a/testutils_test.go b/testutils_test.go index 9065efe..b018b04 100644 --- a/testutils_test.go +++ b/testutils_test.go @@ -12,10 +12,11 @@ func assertCode(t *testing.T, w *httptest.ResponseRecorder, code int) { } } -func assertDB(t *testing.T, db *sql.DB, query string) { - rows, err := db.Query(query) +func assertDB(t *testing.T, db *sql.DB, query string, args ...interface{}) { + rows, err := db.Query(query, args...) if err != nil { t.Errorf("Error during query %s: %s", query, err) + return } defer rows.Close() if rows.Next() != true { diff --git a/user_test.go b/user_test.go index 62802dd..5f69bfb 100644 --- a/user_test.go +++ b/user_test.go @@ -6,10 +6,11 @@ import ( "bytes" "database/sql" "encoding/json" - "github.com/google/go-cmp/cmp" "net/http" "net/http/httptest" "testing" + + "github.com/google/go-cmp/cmp" ) func TestUser(t *testing.T) {