2019-06-26 20:21:00 -08:00
|
|
|
package tests
|
|
|
|
|
|
|
|
import (
|
2019-06-27 04:48:18 -08:00
|
|
|
"context"
|
2019-06-26 20:21:00 -08:00
|
|
|
"encoding/json"
|
2019-06-27 04:48:18 -08:00
|
|
|
"fmt"
|
2019-06-26 20:21:00 -08:00
|
|
|
"net/http"
|
|
|
|
"testing"
|
2019-06-27 04:48:18 -08:00
|
|
|
"time"
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-07-13 12:16:28 -08:00
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/account"
|
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
|
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/tests"
|
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
|
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/signup"
|
|
|
|
"geeks-accelerator/oss/saas-starter-kit/internal/user"
|
2019-06-26 20:21:00 -08:00
|
|
|
"github.com/pborman/uuid"
|
|
|
|
)
|
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
type mockSignup struct {
|
|
|
|
account *account.Account
|
|
|
|
user mockUser
|
|
|
|
token user.Token
|
|
|
|
claims auth.Claims
|
|
|
|
context context.Context
|
|
|
|
}
|
|
|
|
|
2019-06-26 20:21:00 -08:00
|
|
|
func mockSignupRequest() signup.SignupRequest {
|
|
|
|
return signup.SignupRequest{
|
|
|
|
Account: signup.SignupAccount{
|
|
|
|
Name: uuid.NewRandom().String(),
|
|
|
|
Address1: "103 East Main St",
|
|
|
|
Address2: "Unit 546",
|
|
|
|
City: "Valdez",
|
|
|
|
Region: "AK",
|
|
|
|
Country: "USA",
|
|
|
|
Zipcode: "99686",
|
|
|
|
},
|
|
|
|
User: signup.SignupUser{
|
|
|
|
Name: "Lee Brown",
|
|
|
|
Email: uuid.NewRandom().String() + "@geeksinthewoods.com",
|
|
|
|
Password: "akTechFr0n!ier",
|
|
|
|
PasswordConfirm: "akTechFr0n!ier",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
func newMockSignup() mockSignup {
|
|
|
|
req := mockSignupRequest()
|
|
|
|
now := time.Now().UTC().AddDate(-1, -1, -1)
|
|
|
|
s, err := signup.Signup(tests.Context(), auth.Claims{}, test.MasterDB, req, now)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
expires := time.Now().UTC().Sub(s.User.CreatedAt) + time.Hour
|
|
|
|
tkn, err := user.Authenticate(tests.Context(), test.MasterDB, authenticator, req.User.Email, req.User.Password, expires, now)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
claims, err := authenticator.ParseClaims(tkn.AccessToken)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
// Add claims to the context for the user.
|
|
|
|
ctx := context.WithValue(tests.Context(), auth.Key, claims)
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
return mockSignup{
|
|
|
|
account: s.Account,
|
|
|
|
user: mockUser{s.User, req.User.Password},
|
|
|
|
claims: claims,
|
|
|
|
token: tkn,
|
|
|
|
context: ctx,
|
|
|
|
}
|
|
|
|
}
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
// TestSignup validates the signup endpoint.
|
|
|
|
func TestSignup(t *testing.T) {
|
|
|
|
defer tests.Recover(t)
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
ctx := tests.Context()
|
|
|
|
|
|
|
|
// Test signup.
|
|
|
|
{
|
|
|
|
expectedStatus := http.StatusCreated
|
|
|
|
|
|
|
|
req := mockSignupRequest()
|
|
|
|
rt := requestTest{
|
|
|
|
fmt.Sprintf("Signup %d w/no authorization", expectedStatus),
|
|
|
|
http.MethodPost,
|
|
|
|
"/v1/signup",
|
|
|
|
req,
|
|
|
|
user.Token{},
|
|
|
|
auth.Claims{},
|
|
|
|
expectedStatus,
|
|
|
|
nil,
|
|
|
|
}
|
|
|
|
t.Logf("\tTest: %s - %s %s", rt.name, rt.method, rt.url)
|
|
|
|
|
|
|
|
w, ok := executeRequestTest(t, rt, ctx)
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("\t%s\tExecute request failed.", tests.Failed)
|
|
|
|
}
|
|
|
|
t.Logf("\t%s\tReceived valid status code of %d.", tests.Success, w.Code)
|
|
|
|
|
|
|
|
var actual signup.SignupResponse
|
|
|
|
if err := json.Unmarshal(w.Body.Bytes(), &actual); err != nil {
|
|
|
|
t.Logf("\t\tGot error : %+v", err)
|
|
|
|
t.Fatalf("\t%s\tDecode response body failed.", tests.Failed)
|
|
|
|
}
|
|
|
|
|
|
|
|
expectedMap := map[string]interface{}{
|
|
|
|
"user": map[string]interface{}{
|
|
|
|
"id": actual.User.ID,
|
|
|
|
"name": req.User.Name,
|
|
|
|
"email": req.User.Email,
|
|
|
|
"timezone": actual.User.Timezone,
|
|
|
|
"created_at": web.NewTimeResponse(ctx, actual.User.CreatedAt.Value),
|
|
|
|
"updated_at": web.NewTimeResponse(ctx, actual.User.UpdatedAt.Value),
|
|
|
|
},
|
|
|
|
"account": map[string]interface{}{
|
|
|
|
"updated_at": web.NewTimeResponse(ctx, actual.Account.UpdatedAt.Value),
|
|
|
|
"id": actual.Account.ID,
|
|
|
|
"address2": req.Account.Address2,
|
|
|
|
"region": req.Account.Region,
|
|
|
|
"zipcode": req.Account.Zipcode,
|
|
|
|
"timezone": actual.Account.Timezone,
|
|
|
|
"created_at": web.NewTimeResponse(ctx, actual.Account.CreatedAt.Value),
|
|
|
|
"country": req.Account.Country,
|
|
|
|
"billing_user_id": &actual.Account.BillingUserID,
|
|
|
|
"name": req.Account.Name,
|
|
|
|
"address1": req.Account.Address1,
|
|
|
|
"city": req.Account.City,
|
|
|
|
"status": map[string]interface{}{
|
|
|
|
"value": "active",
|
|
|
|
"title": "Active",
|
|
|
|
"options": []map[string]interface{}{{"selected": false, "title": "[Active Pending Disabled]", "value": "[active pending disabled]"}},
|
|
|
|
},
|
|
|
|
"signup_user_id": &actual.Account.SignupUserID,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var expected signup.SignupResponse
|
|
|
|
if err := decodeMapToStruct(expectedMap, &expected); err != nil {
|
|
|
|
t.Logf("\t\tGot error : %+v\nActual results to format expected : \n", err)
|
|
|
|
printResultMap(ctx, w.Body.Bytes()) // used to help format expectedMap
|
|
|
|
t.Fatalf("\t%s\tDecode expected failed.", tests.Failed)
|
|
|
|
}
|
|
|
|
|
|
|
|
if diff := cmpDiff(t, actual, expected); diff {
|
|
|
|
if len(expectedMap) == 0 {
|
|
|
|
printResultMap(ctx, w.Body.Bytes()) // used to help format expectedMap
|
2019-06-26 20:21:00 -08:00
|
|
|
}
|
2019-06-27 04:48:18 -08:00
|
|
|
t.Fatalf("\t%s\tReceived expected result.", tests.Failed)
|
|
|
|
}
|
|
|
|
t.Logf("\t%s\tReceived expected result.", tests.Success)
|
|
|
|
}
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
// Test signup w/empty request.
|
|
|
|
{
|
|
|
|
expectedStatus := http.StatusBadRequest
|
|
|
|
|
|
|
|
rt := requestTest{
|
|
|
|
fmt.Sprintf("Signup %d w/empty request", expectedStatus),
|
|
|
|
http.MethodPost,
|
|
|
|
"/v1/signup",
|
|
|
|
nil,
|
|
|
|
user.Token{},
|
|
|
|
auth.Claims{},
|
|
|
|
expectedStatus,
|
|
|
|
nil,
|
|
|
|
}
|
|
|
|
t.Logf("\tTest: %s - %s %s", rt.name, rt.method, rt.url)
|
|
|
|
|
|
|
|
w, ok := executeRequestTest(t, rt, ctx)
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("\t%s\tExecute request failed.", tests.Failed)
|
|
|
|
}
|
|
|
|
t.Logf("\t%s\tReceived valid status code of %d.", tests.Success, w.Code)
|
|
|
|
|
|
|
|
var actual web.ErrorResponse
|
|
|
|
if err := json.Unmarshal(w.Body.Bytes(), &actual); err != nil {
|
|
|
|
t.Logf("\t\tGot error : %+v", err)
|
|
|
|
t.Fatalf("\t%s\tDecode response body failed.", tests.Failed)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := web.ErrorResponse{
|
|
|
|
Error: "decode request body failed: EOF",
|
|
|
|
}
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
if diff := cmpDiff(t, actual, expected); diff {
|
|
|
|
t.Fatalf("\t%s\tReceived expected error.", tests.Failed)
|
|
|
|
}
|
|
|
|
t.Logf("\t%s\tReceived expected error.", tests.Success)
|
|
|
|
}
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
// Test signup w/validation errors.
|
|
|
|
{
|
|
|
|
expectedStatus := http.StatusBadRequest
|
|
|
|
|
|
|
|
req := mockSignupRequest()
|
|
|
|
req.User.Email = ""
|
|
|
|
req.Account.Name = ""
|
|
|
|
rt := requestTest{
|
|
|
|
fmt.Sprintf("Signup %d w/validation errors", expectedStatus),
|
|
|
|
http.MethodPost,
|
|
|
|
"/v1/signup",
|
|
|
|
req,
|
|
|
|
user.Token{},
|
|
|
|
auth.Claims{},
|
|
|
|
expectedStatus,
|
|
|
|
nil,
|
|
|
|
}
|
|
|
|
t.Logf("\tTest: %s - %s %s", rt.name, rt.method, rt.url)
|
|
|
|
|
|
|
|
w, ok := executeRequestTest(t, rt, ctx)
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("\t%s\tExecute request failed.", tests.Failed)
|
|
|
|
}
|
|
|
|
t.Logf("\t%s\tReceived valid status code of %d.", tests.Success, w.Code)
|
|
|
|
|
|
|
|
var actual web.ErrorResponse
|
|
|
|
if err := json.Unmarshal(w.Body.Bytes(), &actual); err != nil {
|
|
|
|
t.Logf("\t\tGot error : %+v", err)
|
|
|
|
t.Fatalf("\t%s\tDecode response body failed.", tests.Failed)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := web.ErrorResponse{
|
2019-06-26 20:21:00 -08:00
|
|
|
Error: "field validation error",
|
|
|
|
Fields: []web.FieldError{
|
|
|
|
{Field: "name", Error: "Key: 'SignupRequest.account.name' Error:Field validation for 'name' failed on the 'required' tag"},
|
|
|
|
{Field: "email", Error: "Key: 'SignupRequest.user.email' Error:Field validation for 'email' failed on the 'required' tag"},
|
|
|
|
},
|
2019-06-27 04:48:18 -08:00
|
|
|
}
|
2019-06-26 20:21:00 -08:00
|
|
|
|
2019-06-27 04:48:18 -08:00
|
|
|
if diff := cmpDiff(t, actual, expected); diff {
|
|
|
|
t.Fatalf("\t%s\tReceived expected error.", tests.Failed)
|
|
|
|
}
|
|
|
|
t.Logf("\t%s\tReceived expected error.", tests.Success)
|
|
|
|
}
|
2019-06-26 20:21:00 -08:00
|
|
|
}
|