func TestHubInsert(t *testing.T) { // setup database db := testhelpers.SetupDB(t) // insert new user u := &data.User{ Username: "******", Email: "*****@*****.**", EncryptedPassword: "******", } if err := u.Insert(db); err != nil { t.Error("Failed to insert user to db: %v", u) } h := &data.Hub{ Slug: "earthworm", UserID: 1, } if err := h.Insert(db); err != nil { t.Error("Failed to insert h to db: %v", h) } // check if returned values are scanned back to the struct if h.ID == 0 { t.Error("ID must be set") } if h.CreatedAt == nil { t.Error("CreatedAt must be set") } if h.UpdatedAt == nil { t.Error("UpdatedAt must be set") } // check if adding existing hub violates unique constraint h2 := &data.Hub{ Slug: "earthworm", UserID: 1, } err := h2.Insert(db) if err == nil { t.Error("Insert should return an error") } e, ok := err.(*data.Error) if !ok { t.Error("Returned error must be of type `data.Error`") } if e.Code != "unique_violation" { t.Error("Error code must be 'unique violation' but received %s", e.Code) } if e.Desc != "hub exists" { t.Error("Error desc must be 'hub exists' but received %s", e.Desc) } db.Close() }
func TestHubDelete(t *testing.T) { // setup database db := testhelpers.SetupDB(t) // insert new user u := &data.User{ Username: "******", Email: "*****@*****.**", EncryptedPassword: "******", } if err := u.Insert(db); err != nil { t.Error("Failed to insert user to db: %v", u) } h := &data.Hub{ Slug: "earthworm", UserID: 1, } if err := h.Insert(db); err != nil { t.Error("Failed to insert h to db: %v", h) } h1 := &data.Hub{ Slug: "earthworm", } if err := h1.Delete(db); err != nil { t.Error("Failed to get hubs with hub: earthworm") } if h1.Slug != h.Slug { t.Error("Unexpected user record returned: %v", h1) } // check if returned values from Delete are scanned back to the struct if h1.ID == 0 { t.Error("ID must be set") } if h1.CreatedAt == nil { t.Error("CreatedAt must be set") } if h1.UpdatedAt == nil { t.Error("UpdatedAt must be set") } // query for a non-existing hub h2 := &data.Hub{ Slug: "snail", } err := h2.Delete(db) if err == nil { t.Error("Delete should return an error") } //TODO: Add a test case of other errors (eg: db already closed) db.Close() }
func TestHubGet(t *testing.T) { // setup database db := testhelpers.SetupDB(t) // insert new user u := &data.User{ Username: "******", Email: "*****@*****.**", EncryptedPassword: "******", } if err := u.Insert(db); err != nil { t.Error("Failed to insert user to db: %v", u) } // insert new hub h := &data.Hub{ Slug: "earthworm", UserID: 1, } if err := h.Insert(db); err != nil { t.Error("Failed to insert h to db: %v", h) } // query for the inserted hub by hub h1 := &data.Hub{} if err := h1.Get(db, "earthworm"); err != nil { t.Error("Failed to get hubs with hub: earthworm") } if h1.UserID != h.UserID { t.Error("Unexpected user record returned: %v", h1) } // query for a non-existing hub h2 := &data.Hub{} err := h2.Get(db, "snail") if err == nil { t.Error("Get should return an error") } e, ok := err.(*data.Error) if !ok { t.Error("Returned error must be of type `data.Error`") } if e.Code != "record_not_found" { t.Error("Error code must be 'record_not_found' but received %s", e.Code) } if e.Desc != "hub not found" { t.Error("Error desc must be 'hub not found' but received %s", e.Desc) } //TODO: Add a test case of other errors (eg: db already closed) db.Close() }
func TestTokenGet(t *testing.T) { // setup database db := testhelpers.SetupDB(t) // insert new user u := &data.User{ Username: "******", Email: "*****@*****.**", EncryptedPassword: "******", } if err := u.Insert(db); err != nil { t.Error("Failed to insert user to db: %v", u) } // insert a new token for the user tok := &data.Token{ UserID: u.ID, ExpiresIn: (30 * 24 * time.Hour).Nanoseconds(), } if err := tok.Insert(db); err != nil { t.Error("Failed to insert token to db: %v", u) } // query for the inserted token tok1 := &data.Token{} if err := tok1.Get(db, tok.ID); err != nil { t.Error("Failed to find token for id: ", tok.ID) } if tok1.ID != tok.ID { t.Error("Unexpected token returned: %v", tok1) } // query for a non-existing token tok2 := &data.Token{} err := tok2.Get(db, 9999) if err == nil { t.Error("Get should return an error") } e, ok := err.(*data.Error) if !ok { t.Error("Returned error must be of type `data.Error`") } if e.Code != "record_not_found" { t.Error("Error code must be 'record_not_found' but received %s", e.Code) } if e.Desc != "token not found" { t.Error("Error desc must be 'token not found' but received %s", e.Desc) } // TODO: Add a test case of other errors (eg: db already closed) db.Close() }
func TestGetByLogin(t *testing.T) { // setup database db := testhelpers.SetupDB(t) // insert new user u := &data.User{ Username: "******", Email: "*****@*****.**", EncryptedPassword: "******", } if err := u.Insert(db); err != nil { t.Error("Failed to insert user to db: %v", u) } // query for the inserted user by username u1 := &data.User{} if err := u1.GetByLogin(db, "chucknorris"); err != nil { t.Error("Failed to get user with username: chucknorris") } if u1.ID != u.ID { t.Error("Unexpected user record returned: %v", u1) } // query for the inserted user by email u2 := &data.User{} if err := u2.GetByLogin(db, "*****@*****.**"); err != nil { t.Error("Failed to get user with email: [email protected]") } if u2.ID != u.ID { t.Error("Unexpected user record returned: %v", u2) } // query for a non-existing user u3 := &data.User{} err := u3.GetByLogin(db, "jackiechan") e, ok := err.(*data.Error) if !ok { t.Error("Returned error must be of type `data.Error`") } if e.Code != "record_not_found" { t.Error("Error code must be 'record_not_found' but received %s", e.Code) } if e.Desc != "user not found" { t.Error("Error desc must be 'user not found' but received %s", e.Desc) } // TODO: Add a test case of other errors (eg: db already closed) db.Close() }
func TestTokenInsert(t *testing.T) { // setup database db := testhelpers.SetupDB(t) // insert new user u := &data.User{ Username: "******", Email: "*****@*****.**", EncryptedPassword: "******", } if err := u.Insert(db); err != nil { t.Error("Failed to insert user to db: %v", u) } // insert a new token for the user tok := &data.Token{ UserID: u.ID, ExpiresIn: (30 * 24 * time.Hour).Nanoseconds(), } if err := tok.Insert(db); err != nil { t.Error("Failed to insert token to db: %v", u) } // check if returned values are scanned back to the struct if tok.ID == 0 { t.Error("ID must be set") } if tok.CreatedAt == nil { t.Error("CreatedAt must be set") } // RevokedAt should be nil if tok.RevokedAt != nil { t.Error("RevokedAt must be nil") } // insert a token for non-existing user tok2 := &data.Token{ UserID: 9999, ExpiresIn: (30 * 24 * time.Hour).Nanoseconds(), } if err := tok2.Insert(db); err == nil { t.Error("Token insert must fail if user does not exist") } db.Close() }
func TestAddHub(t *testing.T) { // setup DB db := testhelpers.SetupDB(t) defer db.Close() // setup server ts, err := setupServerHub(db, []byte("secret")) if err != nil { t.Fatal(err) } defer ts.Close() // create a user u := &data.User{ Username: "******", Email: "*****@*****.**", } if err := u.EncryptPassword("password"); err != nil { t.Fatal(err) } if err = u.Insert(db); err != nil { t.Fatal(err) } // create a token for the user tok := data.Token{ UserID: u.ID, ExpiresIn: (30 * 24 * time.Hour).Nanoseconds(), // 30 days } if err := tok.Insert(db); err != nil { t.Fatal(err) } // get the encoded JSON Web Token jwt, err := tok.EncodeJWT([]byte("secret")) if err != nil { t.Fatal(err) } hub := data.Hub{ Slug: "1234", UserID: u.ID, } if err := hub.Insert(db); err != nil { t.Fatal(err) } type testCase struct { path string statusCode int body string } // test when valid params are provided spath := "?slug=abcd&access_token=" + jwt res, err := http.Get(ts.URL + "/api/v0/hub" + spath) if err != nil { t.Fatal(err) } if res.StatusCode != http.StatusOK { t.Errorf("%s - Expected status code %v, Got %v", spath, http.StatusOK, res.StatusCode) } b, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { t.Fatal(err) } h := data.Hub{} if err := json.Unmarshal(b, &h); err != nil { t.Errorf("%s - Expected response body to be %+v, Got %s", spath, h, b) } tCases := []testCase{ // when slug param is missing {"?access_token=" + jwt, http.StatusBadRequest, `{"error":"invalid_request","error_description":"slug required"}`}, // when access_token param is missing {"?slug=abcd", http.StatusUnauthorized, `{"error":"invalid_token","error_description":"no token present in request"}`}, // when trying to add existing hub {"?slug=1234&access_token=" + jwt, http.StatusBadRequest, `{"error":"unique_violation","error_description":"hub exists"}`}, } for _, tc := range tCases { res, err := http.Get(ts.URL + "/api/v0/hub" + tc.path) if err != nil { t.Fatal(err) } if res.StatusCode != tc.statusCode { t.Errorf("%s - Expected status code %v, Got %v", tc.path, tc.statusCode, res.StatusCode) } b, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { t.Fatal(err) } if body := string(b); body != tc.body { t.Errorf("%s - Expected response body to be %v, Got %v", tc.path, tc.body, body) } } }
func TestShowHub(t *testing.T) { // setup DB db := testhelpers.SetupDB(t) defer db.Close() // setup server ts, err := setupServerHub(db, []byte("secret")) if err != nil { t.Fatal(err) } defer ts.Close() // create a user u := &data.User{ Username: "******", Email: "*****@*****.**", } if err := u.EncryptPassword("password"); err != nil { t.Fatal(err) } if err = u.Insert(db); err != nil { t.Fatal(err) } // create a token for the user tok := data.Token{ UserID: u.ID, ExpiresIn: (30 * 24 * time.Hour).Nanoseconds(), // 30 days } if err := tok.Insert(db); err != nil { t.Fatal(err) } // get the encoded JSON Web Token jwt, err := tok.EncodeJWT([]byte("secret")) if err != nil { t.Fatal(err) } hub := data.Hub{ Slug: "abcd", UserID: u.ID, } if err := hub.Insert(db); err != nil { t.Fatal(err) } type testCase struct { path string statusCode int body string } tCases := []testCase{ // when valid params are provided {"?access_token=" + jwt, http.StatusOK, `{"hub":["abcd"]}`}, // when access_token param is missing {"?" + jwt, http.StatusUnauthorized, `{"error":"invalid_token","error_description":"no token present in request"}`}, } for _, tc := range tCases { res, err := http.Post(ts.URL+"/api/v0/hub"+tc.path, "", nil) if err != nil { t.Fatal(err) } if res.StatusCode != tc.statusCode { t.Errorf("%s - Expected status code %v, Got %v", tc.path, tc.statusCode, res.StatusCode) } b, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { t.Fatal(err) } if body := string(b); body != tc.body { t.Errorf("%s - Expected response body to be %v, Got %v", tc.path, tc.body, body) } } }
func TestAuthToken(t *testing.T) { // setup DB db := testhelpers.SetupDB(t) defer db.Close() // setup server ts, err := setupServer(db, []byte("secret")) if err != nil { t.Fatal(err) } defer ts.Close() // create a user u := &data.User{ Username: "******", Email: "*****@*****.**", } if err := u.EncryptPassword("password"); err != nil { t.Fatal(err) } if err = u.Insert(db); err != nil { t.Fatal(err) } // create a token for the user tok := data.Token{ UserID: u.ID, ExpiresIn: (30 * 24 * time.Hour).Nanoseconds(), // 30 days } if err := tok.Insert(db); err != nil { t.Fatal(err) } // get the encoded JSON Web Token jwt, err := tok.EncodeJWT([]byte("secret")) if err != nil { t.Fatal(err) } type testCase struct { path string statusCode int body string } tCases := []testCase{ // when access token not provided {"hub", http.StatusUnauthorized, `{"error":"invalid_token","error_description":"no token present in request"}`}, // when access token is invalid {"hub?access_token=invalid", http.StatusUnauthorized, `{"error":"invalid_token","error_description":"token contains an invalid number of segments"}`}, // // when access token is not properly scoped // // fixme currently valid scopes are ["user", "hub", "app"] // {"admin?access_token=" + jwt, http.statusforbidden, `{"error":"invalid_scope","error_description":"token is not valid for this scope"}`}, // when a valid token is provided {"hub?access_token=" + jwt, http.StatusOK, `{"status":"ok"}`}, // when access token is revoked // TODO } for _, tc := range tCases { res, err := http.Get(ts.URL + path.Join("/api/v0", tc.path)) if err != nil { t.Fatal(err) } if res.StatusCode != tc.statusCode { t.Errorf("%s - Expected status code %v, Got %v", tc.path, tc.statusCode, res.StatusCode) } b, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { t.Fatal(err) } if body := string(b); body != tc.body { t.Errorf("%s - Expected response body to be %v, Got %v", tc.path, tc.body, body) } } }
func TestUserToken(t *testing.T) { // setup DB db := testhelpers.SetupDB(t) defer db.Close() // setup server ts, err := setupServerUser(db, []byte("secret")) if err != nil { t.Fatal(err) } defer ts.Close() // create a user u := &data.User{ Username: "******", Email: "*****@*****.**", } if err := u.EncryptPassword("password"); err != nil { t.Fatal(err) } if err = u.Insert(db); err != nil { t.Fatal(err) } tok := data.Token{ UserID: u.ID, ExpiresIn: (30 * 24 * time.Hour).Nanoseconds(), // 30 days } if err := tok.Insert(db); err != nil { t.Fatal(err) } // // get the encoded JSON Web Token // jwt, err := tok.EncodeJWT([]byte("secret")) // if err != nil { // t.Fatal(err) // } type testCase struct { path string statusCode int body string } tCases := []testCase{ // when valid params are provided // FIXME: find out why signature in jwt is different from response // {"?grant_type=password&login=foo&password=password", http.StatusOK, `{"access_token":` + jwt + `","token_type":"bearer","expires_in":"720h0m0s"}`}, // when grant_type param is invalid/missing {"?login=foo&password=password", http.StatusBadRequest, `{"error":"unsupported_grant_type","error_description":"supports only password grant type"}`}, // when login param is missing {"?grant_type=password&password=password", http.StatusBadRequest, `{"error":"invalid_request","error_description":"login required"}`}, // when password param is missing {"?grant_type=password&login=foo", http.StatusBadRequest, `{"error":"invalid_request","error_description":"password required"}`}, // when password value is incorrect {"?grant_type=password&login=foo&password=abcd", http.StatusBadRequest, `{"error":"invalid_grant","error_description":"failed to authenticate user"}`}, // when login value is incorrect {"?grant_type=password&login=bar&password=password", http.StatusBadRequest, `{"error":"invalid_grant","error_description":"user not found"}`}, } for _, tc := range tCases { res, err := http.Post(ts.URL+"/oauth/token"+tc.path, "", nil) if err != nil { t.Fatal(err) } if res.StatusCode != tc.statusCode { t.Errorf("%s - Expected status code %v, Got %v", tc.path, tc.statusCode, res.StatusCode) } b, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { t.Fatal(err) } if body := string(b); body != tc.body { t.Errorf("%s - Expected response body to be %v, Got %v", tc.path, tc.body, body) } } }
func TestSignup(t *testing.T) { // setup DB db := testhelpers.SetupDB(t) defer db.Close() // setup server ts, err := setupServerUser(db, []byte("secret")) if err != nil { t.Fatal(err) } defer ts.Close() type testCase struct { path string statusCode int body string } // test when valid params are provided spath := "?username=foo&[email protected]&password=password" res, err := http.Post(ts.URL+"/signup"+spath, "", nil) if err != nil { t.Fatal(err) } if res.StatusCode != http.StatusCreated { t.Errorf("%s - Expected status code %v, Got %v", spath, http.StatusCreated, res.StatusCode) } b, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { t.Fatal(err) } u := data.User{} if err := json.Unmarshal(b, &u); err != nil { t.Errorf("%s - Expected response body to be %+v, Got %s", spath, u, b) } //test when invalid params are provided tCases := []testCase{ // when username param is missing {"[email protected]&password=password", http.StatusBadRequest, `{"error":"username_required","error_description":"username required"}`}, // when email param is missing {"?username=foo&password=password", http.StatusBadRequest, `{"error":"email_required","error_description":"email required"}`}, // when password param is missing {"?username=foo&[email protected]", http.StatusBadRequest, `{"error":"password_required","error_description":"password required"}`}, } for _, tc := range tCases { res, err := http.Post(ts.URL+"/signup"+tc.path, "", nil) if err != nil { t.Fatal(err) } if res.StatusCode != tc.statusCode { t.Errorf("%s - Expected status code %v, Got %v", tc.path, tc.statusCode, res.StatusCode) } b, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { t.Fatal(err) } if body := string(b); body != tc.body { t.Errorf("%s - Expected response body to be %v, Got %v", tc.path, tc.body, body) } } }