Compare commits

...

25 Commits

Author SHA1 Message Date
c3be0b8e54 Adds put plan route
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
2021-02-07 15:27:12 -06:00
8ca7858069 Adds update plan method
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
2021-02-07 15:11:44 -06:00
5e030a5bc3 Uses plan description instead of date 2021-02-02 15:58:18 -06:00
b47abbfc0b Adds put route tests for current plans
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
2021-01-31 14:29:53 -06:00
4905d18222 Adds tests for post current plan 2021-01-31 14:24:05 -06:00
eb8838ab75 Add store/postgres tests for current plan 2021-01-31 13:57:54 -06:00
6ad0112683 Adds tests for inmemory store 2021-01-31 12:26:39 -06:00
b9cea2347c Adds error store tests 2021-01-31 12:18:58 -06:00
e420bf303a Adds tests for model code 2021-01-31 12:15:30 -06:00
92ddd9e0fe Current plan beats primary plan 2021-01-31 11:54:41 -06:00
8c17aa9d6d Adds current plan implementation 2021-01-31 11:42:47 -06:00
d37c53c60b Add put test unauthorized
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
2021-01-30 12:44:47 -06:00
2465b0a73a Adds user id to actions 2021-01-30 12:40:58 -06:00
12515c2a1e Merge pull request 'auth' (#3) from auth into master
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
Reviewed-on: #3
2021-01-25 22:31:49 +00:00
6dd91f5a1b Adds tests for auth route
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
gitea-deepak/gogmagog/pipeline/pr-master This commit looks good
2021-01-25 16:23:42 -06:00
249fabbd7a Adds tests for register route 2021-01-25 15:18:56 -06:00
c9675b1573 Adds last currentUser route tests
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
2021-01-25 15:00:07 -06:00
63a9e2ff58 Adds tests for context errors 2021-01-25 14:58:06 -06:00
28325c8d7b Adds current user tests. 2021-01-25 14:51:28 -06:00
93a5e9c1ba Adds middleware set userid on context method. 2021-01-25 14:50:54 -06:00
4d093ed99a Adds plan route unauthorised tests
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
2021-01-25 14:34:17 -06:00
77e6e6bc04 Adds test for context methods 2021-01-25 14:25:12 -06:00
c28939d2b8 Adds middleware testing methods
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
2021-01-25 13:33:52 -06:00
cfe5d89b22 Adds test for token encode/decode 2021-01-25 12:51:19 -06:00
f84c9b6ea2 Adds error store test for missing store 2021-01-25 12:30:38 -06:00
45 changed files with 3122 additions and 247 deletions

View File

@@ -8,6 +8,7 @@ import (
type Action struct {
ActionID int64 `json:"action_id"`
ActionDescription string `json:"action_description"`
UserID int64 `json:"user_id"`
EstimatedChunks int `json:"estimated_chunks"`
CompletedChunks int `json:"completed_chunks"`
CompletedOn *time.Time `json:"completed_on,omitempty"`
@@ -17,22 +18,22 @@ type Action struct {
}
// Actions returns all actions from the model.
func (m *Model) Actions() ([]*Action, error) {
return m.SelectActions()
func (m *Model) Actions(userID int) ([]*Action, error) {
return m.SelectActions(userID)
}
// Action returns a single action from its ID
func (m *Model) Action(id int) (*Action, error) {
act, err := m.SelectActionByID(id)
func (m *Model) Action(id int, userID int) (*Action, error) {
act, err := m.SelectActionByID(id, userID)
return act, wrapNotFound(err)
}
// AddAction inserts a given action into the store, returning the generated ActionID. The provided ActionID is ignored.
func (m *Model) AddAction(action *Action) (int, error) {
return m.InsertAction(action)
func (m *Model) AddAction(action *Action, userID int) (int, error) {
return m.InsertAction(action, userID)
}
// SaveAction saves and updates an action.
func (m *Model) SaveAction(action *Action) error {
return m.UpdateAction(action)
func (m *Model) SaveAction(action *Action, userID int) error {
return m.UpdateAction(action, userID)
}

23
models/current_plan.go Normal file
View File

@@ -0,0 +1,23 @@
package models
// CurrentPlan represents the primary plan ID for a particular user ID.
type CurrentPlan struct {
UserID int64 `json:"user_id"`
PlanID int64 `json:"plan_id"`
}
// CurrentPlan returns the primary plan for a provided user ID in the given model.
func (m *Model) CurrentPlan(userID int) (*CurrentPlan, error) {
pp, err := m.SelectCurrentPlan(userID)
return pp, wrapNotFound(err)
}
// AddCurrentPlan inserts a given primary plan into the store, returning nothing.
func (m *Model) AddCurrentPlan(pp *CurrentPlan, userID int) error {
return m.InsertCurrentPlan(pp, userID)
}
// SaveCurrentPlan saves and updates a primary plan.
func (m *Model) SaveCurrentPlan(pp *CurrentPlan, userID int) error {
return m.UpdateCurrentPlan(pp, userID)
}

View File

@@ -0,0 +1,45 @@
package models_test
import (
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/store"
"github.com/stretchr/testify/assert"
"testing"
)
func TestModelCurrentPlan(t *testing.T) {
assert := assert.New(t)
a1 := &models.Action{ActionID: 3}
userID := 3
p := &models.Plan{PlanID: 6}
str, _ := store.GetInMemoryStore()
str.InsertAction(a1, userID)
str.InsertPlan(p, userID)
str.InsertPlan(p, userID)
m := models.New(str)
_, err := m.CurrentPlan(userID)
assert.NotNil(err)
assert.True(models.IsNotFoundError(err))
err = m.AddCurrentPlan(&models.CurrentPlan{PlanID: 1}, userID)
assert.Nil(err)
pp, err := m.CurrentPlan(userID)
assert.Nil(err)
assert.EqualValues(1, pp.PlanID)
assert.EqualValues(userID, pp.UserID)
err = m.AddCurrentPlan(&models.CurrentPlan{PlanID: 2}, userID)
assert.NotNil(err)
err = m.SaveCurrentPlan(&models.CurrentPlan{PlanID: 2}, userID)
assert.Nil(err)
pp, err = m.CurrentPlan(userID)
assert.Nil(err)
assert.EqualValues(2, pp.PlanID)
assert.EqualValues(userID, pp.UserID)
}

View File

@@ -37,7 +37,7 @@ func TestErrorModelWrapping(t *testing.T) {
_, err := m.Plan(0, 0)
assert.True(models.IsNotFoundError(err))
_, err = m.Action(0)
_, err = m.Action(0, 0)
assert.True(models.IsNotFoundError(err))
}
func TestErrorModelInvalidLogin(t *testing.T) {

View File

@@ -7,16 +7,20 @@ import (
// Store represents the backing store.
type Store interface {
ConnectionLive() error
SelectActions() ([]*Action, error)
SelectActionByID(id int) (*Action, error)
InsertAction(action *Action) (int, error)
UpdateAction(action *Action) error
SelectActions(userID int) ([]*Action, error)
SelectActionByID(id int, userID int) (*Action, error)
InsertAction(action *Action, userID int) (int, error)
UpdateAction(action *Action, userID int) error
SelectPlans(userID int) ([]*Plan, error)
SelectPlanByID(id int, userID int) (*Plan, error)
InsertPlan(plan *Plan, userID int) (int, error)
SelectActionsByPlanID(plan *Plan) ([]*Action, error)
UpdatePlan(plan *Plan, userID int) error
SelectActionsByPlanID(plan *Plan, userID int) ([]*Action, error)
SelectUserByUsername(username string) (*User, error)
InsertUser(user *User) (int, error)
SelectCurrentPlan(userID int) (*CurrentPlan, error)
InsertCurrentPlan(currentPlan *CurrentPlan, userID int) error
UpdateCurrentPlan(currentPlan *CurrentPlan, userID int) error
}
// Model represents a current model item.

View File

@@ -15,23 +15,23 @@ func TestModelActions(t *testing.T) {
p := &models.Plan{PlanID: 6}
str, _ := store.GetInMemoryStore()
str.InsertAction(a1)
str.InsertAction(a1, userID)
str.InsertPlan(p, userID)
m := models.New(str)
actions, err := m.Actions()
actions, err := m.Actions(userID)
assert.Nil(err)
assert.Equal(1, len(actions))
firstAction, err := m.Action(1)
firstAction, err := m.Action(1, userID)
assert.Nil(err)
assert.EqualValues(1, firstAction.ActionID)
actionID, err := m.AddAction(a2)
actionID, err := m.AddAction(a2, userID)
assert.Nil(err)
assert.EqualValues(2, actionID)
err = m.SaveAction(a1)
err = m.SaveAction(a1, userID)
assert.Nil(err)
}
@@ -44,8 +44,8 @@ func TestModelPlanMethods(t *testing.T) {
str, _ := store.GetInMemoryStore()
str.InsertPlan(p, userID)
str.InsertAction(a1)
str.InsertAction(a2)
str.InsertAction(a1, userID)
str.InsertAction(a2, userID)
m := models.New(str)
plans, err := m.Plans(userID)
@@ -56,7 +56,13 @@ func TestModelPlanMethods(t *testing.T) {
assert.Nil(err)
assert.EqualValues(1, firstPlan.PlanID)
actions, err := m.GetActions(firstPlan)
p2 := &models.Plan{PlanDescription: "testing", PlanID: 1}
m.SavePlan(p2, userID)
p2, err = m.Plan(1, userID)
assert.Nil(err)
assert.Equal("testing", p2.PlanDescription)
actions, err := m.GetActions(firstPlan, userID)
assert.Nil(err)
assert.Equal(1, len(actions))

View File

@@ -1,14 +1,10 @@
package models
import (
"time"
)
// Plan represents a single day's agenda of actions.
type Plan struct {
PlanID int64 `json:"plan_id"`
PlanDate *time.Time `json:"plan_date"`
UserID int64 `json:"user_id"`
PlanID int64 `json:"plan_id"`
PlanDescription string `json:"plan_description"`
UserID int64 `json:"user_id"`
}
// Plans returns all plans in the model.
@@ -27,7 +23,12 @@ func (m *Model) AddPlan(plan *Plan, userID int) (int, error) {
return m.InsertPlan(plan, userID)
}
// GetActions returns the actions associated with a particular plan.
func (m *Model) GetActions(plan *Plan) ([]*Action, error) {
return m.SelectActionsByPlanID(plan)
// SavePlan saves and updates a plan.
func (m *Model) SavePlan(plan *Plan, userID int) error {
return m.UpdatePlan(plan, userID)
}
// GetActions returns the actions associated with a particular plan.
func (m *Model) GetActions(plan *Plan, userID int) ([]*Action, error) {
return m.SelectActionsByPlanID(plan, userID)
}

View File

@@ -20,8 +20,8 @@ func TestModelUsers(t *testing.T) {
user1 := &models.User{Username: username, DisplayName: "Ted Est", Password: []byte("$2y$05$6SVV35GX4cB4PDPhRaDD/exsL.HV8QtMMr60YL6dLyqtX4l58q.cy")}
str, _ := store.GetInMemoryStore()
str.InsertPlan(p, 3)
str.InsertAction(a1)
str.InsertAction(a2)
str.InsertAction(a1, 3)
str.InsertAction(a2, 3)
str.InsertUser(user1)
m := models.New(str)

View File

@@ -3,6 +3,7 @@ package routes
import (
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/go-chi/chi"
"io"
"net/http"
@@ -21,13 +22,19 @@ func NewActionRouter(m *models.Model) http.Handler {
func getActionsFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, userErr := tokens.GetUserID(r.Context())
if userErr != nil {
unauthorizedHandler(w, r)
return
}
var (
actions []*models.Action
err error
)
planIDString := r.URL.Query().Get("plan_id")
if planIDString == "" {
actions, err = m.Actions()
actions, err = m.Actions(userID)
} else {
planID, convErr := strconv.ParseInt(planIDString, 10, 64)
if convErr != nil {
@@ -35,7 +42,7 @@ func getActionsFunc(m *models.Model) http.HandlerFunc {
err = nil
} else {
plan := &models.Plan{PlanID: planID}
actions, err = m.GetActions(plan)
actions, err = m.GetActions(plan, userID)
}
}
if err != nil {
@@ -51,12 +58,20 @@ func getActionsFunc(m *models.Model) http.HandlerFunc {
func getActionByIDFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, userErr := tokens.GetUserID(r.Context())
if userErr != nil {
unauthorizedHandler(w, r)
return
}
id, err := strconv.Atoi(chi.URLParam(r, "actionid"))
if err != nil {
notFoundHandler(w, r)
return
}
action, err := m.Action(id)
action, err := m.Action(id, userID)
if err != nil {
if models.IsNotFoundError(err) {
notFoundHandler(w, r)
@@ -81,11 +96,17 @@ type createActionResponse struct {
func postActionFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, err := tokens.GetUserID(r.Context())
if err != nil {
unauthorizedHandler(w, r)
return
}
r.Body = http.MaxBytesReader(w, r.Body, 1024)
dec := json.NewDecoder(r.Body)
dec.DisallowUnknownFields()
var a models.Action
err := dec.Decode(&a)
err = dec.Decode(&a)
if err != nil {
badRequestError(w, err)
return
@@ -103,12 +124,12 @@ func postActionFunc(m *models.Model) http.HandlerFunc {
CompletedOn: a.CompletedOn,
PlanID: a.PlanID,
}
id, err := m.AddAction(action)
id, err := m.AddAction(action, userID)
if err != nil {
serverError(w, err)
return
}
action, err = m.Action(id)
action, err = m.Action(id, userID)
if err != nil {
serverError(w, err)
return
@@ -134,6 +155,13 @@ type updateActionResponse struct {
func putActionFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, err := tokens.GetUserID(r.Context())
if err != nil {
unauthorizedHandler(w, r)
return
}
id, err := strconv.Atoi(chi.URLParam(r, "actionid"))
if err != nil {
notFoundHandler(w, r)
@@ -162,12 +190,12 @@ func putActionFunc(m *models.Model) http.HandlerFunc {
PlanID: a.PlanID,
ActionID: int64(id),
}
err = m.SaveAction(action)
err = m.SaveAction(action, userID)
if err != nil {
serverError(w, err)
return
}
action, err = m.Action(id)
action, err = m.Action(id, userID)
if err != nil {
serverError(w, err)
return

View File

@@ -16,7 +16,7 @@ func TestEmptyActions(t *testing.T) {
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
rr := httptest.NewRecorder()
@@ -41,10 +41,10 @@ func TestOneAction(t *testing.T) {
completedDate, _ := time.Parse("2006-01-02", "2021-01-03")
a1 := &models.Action{ActionID: 3, ActionDescription: "testing", CompletedChunks: 1, CompletedOn: &completedDate, CreatedAt: &createdDate, UpdatedAt: &updatedDate, EstimatedChunks: 3, PlanID: 0}
m := getEmptyModel()
m.AddAction(a1)
m.AddAction(a1, 3)
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
rr := httptest.NewRecorder()
@@ -59,6 +59,7 @@ func TestOneAction(t *testing.T) {
{
"action_id": 1,
"action_description": "testing",
"user_id": 3,
"estimated_chunks": 3,
"completed_chunks": 1,
"completed_on": "2021-01-03T00:00:00Z",
@@ -79,7 +80,7 @@ func TestErrorAction(t *testing.T) {
m := getErrorModel("Model always errors")
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
rr := httptest.NewRecorder()
@@ -101,7 +102,7 @@ func TestEmptyActionErrorWriter(t *testing.T) {
m := getEmptyModel()
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
rr := NewBadWriter()
@@ -121,9 +122,9 @@ func TestOneActionByID(t *testing.T) {
updatedDate, _ := time.Parse("2006-01-02", "2021-01-02")
a := &models.Action{ActionID: 6, ActionDescription: "howdy", CompletedOn: nil, CreatedAt: &createdDate, UpdatedAt: &updatedDate, CompletedChunks: 0, EstimatedChunks: 54, PlanID: 3}
m := getEmptyModel()
m.InsertAction(a)
m.InsertAction(a, 3)
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/1", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/1", nil)
rr := httptest.NewRecorder()
@@ -137,6 +138,7 @@ func TestOneActionByID(t *testing.T) {
expected := `{
"action_id": 1,
"action_description": "howdy",
"user_id": 3,
"estimated_chunks": 54,
"completed_chunks": 0,
"updated_at": "2021-01-02T00:00:00Z",
@@ -155,7 +157,7 @@ func TestErrorActionByID(t *testing.T) {
m := getErrorModel("Model always errors")
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/5", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/5", nil)
rr := httptest.NewRecorder()
@@ -176,10 +178,10 @@ func TestEmptyActionErrorWriterByID(t *testing.T) {
a := &models.Action{ActionID: 6}
m := getEmptyModel()
m.AddAction(a)
m.AddAction(a, 3)
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/1", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/1", nil)
rr := NewBadWriter()
@@ -199,7 +201,7 @@ func TestNotFoundActionByIDText(t *testing.T) {
m := getEmptyModel()
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/wo", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/wo", nil)
rr := httptest.NewRecorder()
@@ -218,7 +220,7 @@ func TestNotFoundActionByIDEmpty(t *testing.T) {
m := getEmptyModel()
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/1", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/1", nil)
rr := httptest.NewRecorder()
@@ -238,9 +240,9 @@ func TestActionsByPlanID(t *testing.T) {
updatedDate, _ := time.Parse("2006-01-02", "2021-01-02")
a := &models.Action{ActionID: 1, ActionDescription: "howdy", CompletedOn: nil, CreatedAt: &createdDate, UpdatedAt: &updatedDate, CompletedChunks: 0, EstimatedChunks: 54, PlanID: 6}
m := getEmptyModel()
m.AddAction(a)
m.AddAction(a, 3)
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/?plan_id=6", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/?plan_id=6", nil)
rr := httptest.NewRecorder()
@@ -255,6 +257,7 @@ func TestActionsByPlanID(t *testing.T) {
{
"action_id": 1,
"action_description": "howdy",
"user_id": 3,
"estimated_chunks": 54,
"completed_chunks": 0,
"updated_at": "2021-01-02T00:00:00Z",
@@ -274,9 +277,9 @@ func TestActionsByPlanIDInvalidID(t *testing.T) {
updatedDate, _ := time.Parse("2006-01-02", "2021-01-02")
a := &models.Action{ActionID: 6, ActionDescription: "howdy", CompletedOn: nil, CreatedAt: &createdDate, UpdatedAt: &updatedDate, CompletedChunks: 0, EstimatedChunks: 54, PlanID: 3}
m := getEmptyModel()
m.AddAction(a)
m.AddAction(a, 3)
router := routes.NewActionRouter(m)
req, _ := http.NewRequest("GET", "/?plan_id=aoeu", nil)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/?plan_id=aoeu", nil)
rr := httptest.NewRecorder()

View File

@@ -0,0 +1,119 @@
package routes_test
import (
"bytes"
"context"
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/routes"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestEmptyActionEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewActionRouter(m)
req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestOneActionEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
planDescription := "2006-01-02"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription, UserID: 3}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewActionRouter(m)
req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestOneActionByIDEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription, UserID: 3}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewActionRouter(m)
req, _ := http.NewRequestWithContext(context.Background(), "GET", "/1", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestPureJSONActionEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewActionRouter(m)
data := []byte(`{
"plan_description": "2021-01-01T00:00:00Z",
"plan_id": 1,
"user_id": 3
}`)
req, _ := http.NewRequestWithContext(context.Background(), "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestPutActionEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
a := &models.Action{PlanID: 6}
m := getEmptyModel()
m.AddAction(a, 3)
router := routes.NewActionRouter(m)
data, _ := json.Marshal(a)
req, _ := http.NewRequestWithContext(context.Background(), "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}

View File

@@ -9,7 +9,8 @@ import (
"net/http"
)
func newAuthRouter(m *models.Model, tok tokens.Toker) http.Handler {
// NewAuthRouter returns a new auth router.
func NewAuthRouter(m *models.Model, tok tokens.Toker) http.Handler {
router := chi.NewRouter()
router.Post("/register", postUserFunc(m))
router.Post("/tokens", createTokenFunc(m, tok))

202
routes/auth_login_test.go Normal file
View File

@@ -0,0 +1,202 @@
package routes_test
import (
"bytes"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/routes"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestLoginAuth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "pass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusOK, status)
expected := `{
"token": "{\"ID\":1,\"Username\":\"testing_username\"}"
}`
assert.JSONEq(expected, rr.Body.String())
contentType := rr.Header().Get("Content-Type")
assert.Equal("application/json", contentType)
}
func TestLoginBadCreds(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_use
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
}
func TestLoginBadRequestTwoBodies(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "pass"
}{
"username": "testing_username",
"password": "pass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
}
func TestLoginAuthWrongPass(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "badpass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestLoginErrorModel(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel("error")
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "badpass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}
func TestLoginBadWriter(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "pass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := NewBadWriter()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}
//
// func TestRegisterBadWriter(t *testing.T) {
// // set up
// assert := assert.New(t)
// m := getEmptyModel()
// toker := tokens.New("secret")
// data := []byte(`{
// "username": "test",
// "password": "pass",
// "display_name": "My Display Name"
// }`)
// req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
//
// rr := NewBadWriter()
//
// // function under test
// router := routes.NewAuthRouter(m, toker)
// router.ServeHTTP(rr, req)
//
// // check results
// status := rr.Code
// assert.Equal(http.StatusInternalServerError, status)
//
// }

View File

@@ -0,0 +1,139 @@
package routes_test
import (
"bytes"
"gitea.deepak.science/deepak/gogmagog/routes"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestRegisterAuth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.New("secret")
data := []byte(`{
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusCreated, status)
expected := `{
"username": "test"
}`
assert.JSONEq(expected, rr.Body.String())
contentType := rr.Header().Get("Content-Type")
assert.Equal("application/json", contentType)
}
func TestRegisterBadRequestAuth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.New("secret")
data := []byte(`{
"username": y Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
}
func TestRegisterBadRequestTwoBodies(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.New("secret")
data := []byte(`{
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}, {
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
}
func TestRegisterErrorModel(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel("here's an error")
toker := tokens.New("secret")
data := []byte(`{
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}
func TestRegisterBadWriter(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.New("secret")
data := []byte(`{
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := NewBadWriter()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}

View File

@@ -33,6 +33,10 @@ func getMeFunc(m *models.Model) http.HandlerFunc {
user, err := m.UserByUsername(username, userID)
if err != nil {
if models.IsNotFoundError(err) {
notFoundHandler(w, r)
return
}
serverError(w, err)
return
}

158
routes/currentUser_test.go Normal file
View File

@@ -0,0 +1,158 @@
package routes_test
import (
"context"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/routes"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestEmptyCurrentUser(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewCurrentUserRouter(m)
req, _ := http.NewRequestWithContext(tokens.GetContextForUserValues(3, "testing"), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusNotFound, status)
}
func TestSingleUser(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
idToUse := 1
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
router := routes.NewCurrentUserRouter(m)
req, _ := http.NewRequestWithContext(tokens.GetContextForUserValues(idToUse, username), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusOK, status)
expected := `{
"user_id": 1,
"username": "testing_username",
"display_name": "testing_name"
}`
assert.JSONEq(expected, rr.Body.String())
contentType := rr.Header().Get("Content-Type")
assert.Equal("application/json", contentType)
}
func TestSingleUserEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
router := routes.NewCurrentUserRouter(m)
req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestSingleUserContextNoUserID(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
idToUse := 1
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
router := routes.NewCurrentUserRouter(m)
req, _ := http.NewRequestWithContext(tokens.SetUserID(context.Background(), idToUse), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestErrorUserContextNoUserID(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel("Here's an error.")
idToUse := 1
router := routes.NewCurrentUserRouter(m)
req, _ := http.NewRequestWithContext(tokens.GetContextForUserValues(idToUse, "username"), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}
func TestSingleUserErrorWriter(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
idToUse := 1
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
router := routes.NewCurrentUserRouter(m)
req, _ := http.NewRequestWithContext(tokens.GetContextForUserValues(idToUse, username), "GET", "/", nil)
rr := NewBadWriter()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}

160
routes/current_plan.go Normal file
View File

@@ -0,0 +1,160 @@
package routes
import (
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/go-chi/chi"
"io"
"net/http"
)
// NewCurrentPlanRouter returns a new primary plan router
func NewCurrentPlanRouter(m *models.Model) http.Handler {
router := chi.NewRouter()
router.Get("/", getCurrentPlanFunc(m))
router.Post("/", postCurrentPlanFunc(m))
router.Put("/", putCurrentPlanFunc(m))
return router
}
func getCurrentPlanFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, userErr := tokens.GetUserID(r.Context())
if userErr != nil {
unauthorizedHandler(w, r)
return
}
pp, err := m.CurrentPlan(userID)
if err != nil {
if models.IsNotFoundError(err) {
notFoundHandler(w, r)
return
}
serverError(w, err)
return
}
w.Header().Add("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(pp); err != nil {
serverError(w, err)
}
}
}
type createCurrentPlanResponse struct {
CreatedCurrentPlan *models.CurrentPlan `json:"created_current_plan"`
}
func postCurrentPlanFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, err := tokens.GetUserID(r.Context())
if err != nil {
unauthorizedHandler(w, r)
return
}
r.Body = http.MaxBytesReader(w, r.Body, 1024)
dec := json.NewDecoder(r.Body)
dec.DisallowUnknownFields()
var pp models.CurrentPlan
err = dec.Decode(&pp)
if err != nil {
badRequestError(w, err)
return
}
err = dec.Decode(&struct{}{})
if err != io.EOF {
badRequestError(w, err)
return
}
newPP := &models.CurrentPlan{
PlanID: pp.PlanID,
UserID: int64(userID),
}
err = m.AddCurrentPlan(newPP, userID)
if err != nil {
serverError(w, err)
return
}
finishedPP, err := m.CurrentPlan(userID)
if err != nil {
serverError(w, err)
return
}
response := &createCurrentPlanResponse{
CreatedCurrentPlan: finishedPP,
}
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
if err := json.NewEncoder(w).Encode(response); err != nil {
serverError(w, err)
}
}
}
type updateCurrentPlanResponse struct {
UpdatedCurrentPlan *models.CurrentPlan `json:"updated_current_plan"`
}
func putCurrentPlanFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, err := tokens.GetUserID(r.Context())
if err != nil {
unauthorizedHandler(w, r)
return
}
_, err = m.CurrentPlan(userID)
if models.IsNotFoundError(err) {
notFoundHandler(w, r)
return
}
r.Body = http.MaxBytesReader(w, r.Body, 1024)
dec := json.NewDecoder(r.Body)
dec.DisallowUnknownFields()
var pp models.CurrentPlan
err = dec.Decode(&pp)
if err != nil {
badRequestError(w, err)
return
}
err = dec.Decode(&struct{}{})
if err != io.EOF {
badRequestError(w, err)
return
}
newPP := &models.CurrentPlan{
PlanID: pp.PlanID,
UserID: int64(userID),
}
err = m.SaveCurrentPlan(newPP, userID)
if err != nil {
serverError(w, err)
return
}
newPP, err = m.CurrentPlan(userID)
if err != nil {
serverError(w, err)
return
}
response := &updateCurrentPlanResponse{
UpdatedCurrentPlan: newPP,
}
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
serverError(w, err)
}
}
}

View File

@@ -0,0 +1,228 @@
package routes_test
import (
"bytes"
"context"
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/routes"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestPostSinglePlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewCurrentPlanRouter(m)
plan := &models.Plan{}
m.AddPlan(plan, 3)
pp := &models.CurrentPlan{PlanID: 1}
data, _ := json.Marshal(pp)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusCreated, status)
}
func TestPostCurrentPlanUnauth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
pp := &models.CurrentPlan{PlanID: 1}
data, _ := json.Marshal(pp)
req, _ := http.NewRequestWithContext(context.Background(), "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestExtraFieldJSONCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
data := []byte(`{
"plan_id": 5,
"sabotage": "omg"
}`)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
expected := `Bad Request`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestEmptyBodyJSONCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
data := []byte(``)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
expected := `Bad Request`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestTwoBodyCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
data := []byte(`{
"plan_id": 5
}, {
"plan_id": 7
}`)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
expected := `Bad Request`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestErrorCreateCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel("error model")
plan := &models.Plan{}
m.AddPlan(plan, 3)
data := []byte(`{
"plan_id": 5
}`)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
expected := `Internal Server Error`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestErrorOnRetrieveCreateCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorOnGetModel("error model")
plan := &models.Plan{}
m.AddPlan(plan, 3)
data := []byte(`{
"plan_id": 5
}`)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
expected := `Internal Server Error`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestErrorWriterCreateCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
data := []byte(`{
"plan_id": 5
}`)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := NewBadWriter()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}

View File

@@ -0,0 +1,269 @@
package routes_test
import (
"bytes"
"context"
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/routes"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestPutSinglePlanNotFound(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewCurrentPlanRouter(m)
plan := &models.Plan{}
m.AddPlan(plan, 3)
m.AddPlan(plan, 3)
pp := &models.CurrentPlan{PlanID: 1}
data, _ := json.Marshal(pp)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusNotFound, status)
}
func TestPutSinglePlanNonDup(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewCurrentPlanRouter(m)
plan := &models.Plan{}
m.AddPlan(plan, 3)
m.AddPlan(plan, 3)
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 1}, 3)
pp := &models.CurrentPlan{PlanID: 2}
data, _ := json.Marshal(pp)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusOK, status)
}
func TestPutCurrentPlanUnauth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
m.AddPlan(plan, 3)
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 1}, 3)
pp := &models.CurrentPlan{PlanID: 1}
data, _ := json.Marshal(pp)
req, _ := http.NewRequestWithContext(context.Background(), "PUT", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestExtraFieldJSONPutCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
m.AddPlan(plan, 3)
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 1}, 3)
data := []byte(`{
"plan_id": 5,
"sabotage": "omg"
}`)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
expected := `Bad Request`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestEmptyBodyJSONPutCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
m.AddPlan(plan, 3)
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 1}, 3)
data := []byte(``)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
expected := `Bad Request`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestTwoBodyPutCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
m.AddPlan(plan, 3)
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 1}, 3)
data := []byte(`{
"plan_id": 5
}, {
"plan_id": 7
}`)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
expected := `Bad Request`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestErrorPutCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel("error model")
plan := &models.Plan{}
m.AddPlan(plan, 3)
m.AddPlan(plan, 3)
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 1}, 3)
data := []byte(`{
"plan_id": 5
}`)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
expected := `Internal Server Error`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestErrorOnRetrievePutCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorOnGetModel("error model")
plan := &models.Plan{}
m.AddPlan(plan, 3)
m.AddPlan(plan, 3)
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 1}, 3)
data := []byte(`{
"plan_id": 5
}`)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
expected := `Internal Server Error`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestErrorWriterPutCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
plan := &models.Plan{}
m.AddPlan(plan, 3)
m.AddPlan(plan, 3)
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 1}, 3)
data := []byte(`{
"plan_id": 5
}`)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := NewBadWriter()
router := routes.NewCurrentPlanRouter(m)
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}

117
routes/current_plan_test.go Normal file
View File

@@ -0,0 +1,117 @@
package routes_test
import (
"context"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/routes"
// "gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestEmptyCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewCurrentPlanRouter(m)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusNotFound, status)
}
func TestEmptyCurrentPlanUnauth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewCurrentPlanRouter(m)
req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestErrorCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel("Model always errors")
router := routes.NewCurrentPlanRouter(m)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
// We pass in the date as a time.time so it makes sense that it comes back with a midnight timestamp.
expected := `Internal Server Error`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestEmptyCurrentPlanErrorWriter(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 3}, 3)
router := routes.NewCurrentPlanRouter(m)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
rr := NewBadWriter()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}
func TestSingleCurrentPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
m.AddCurrentPlan(&models.CurrentPlan{PlanID: 3}, 3)
router := routes.NewCurrentPlanRouter(m)
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusOK, status)
// We pass in the date as a time.time so it makes sense that it comes back with a midnight timestamp.
expected := `{
"plan_id": 3,
"user_id": 3
}`
assert.JSONEq(expected, rr.Body.String())
contentType := rr.Header().Get("Content-Type")
assert.Equal("application/json", contentType)
}

218
routes/plan_put_test.go Normal file
View File

@@ -0,0 +1,218 @@
package routes_test
import (
"bytes"
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/routes"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestPureJSONPutPlan(t *testing.T) {
// set up
assert := assert.New(t)
p := &models.Plan{
PlanID: 1,
PlanDescription: "hn",
}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)
data := []byte(`{
"plan_id": 1,
"plan_description": "testing"
}`)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusOK, status)
expected := `{
"updated_plan": {
"plan_description": "testing",
"plan_id": 1,
"user_id": 3
},
"id": 1
}`
assert.JSONEq(expected, rr.Body.String())
contentType := rr.Header().Get("Content-Type")
assert.Equal("application/json", contentType)
}
func TestExtraFieldPlanPutJSON(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
p := &models.Plan{
PlanID: 1,
PlanDescription: "hn",
}
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)
data := []byte(`{
"plan_id": 1,
"plan_description": "testing",
"sabotage": "omg"
}`)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
expected := `Bad Request`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestEmptyBodyPlanPut(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewPlanRouter(m)
data := []byte(``)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
expected := `Bad Request`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestTwoBodyPlanPut(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewPlanRouter(m)
data := []byte(`{
"plan_id": 5
}, {
"plan_id": 6
}`)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
expected := `Bad Request`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestBadPlanIDPut(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewPlanRouter(m)
data := []byte(`{
"plan_id": 5
}, {
"plan_id": 6
}`)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/text", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusNotFound, status)
expected := `Not Found`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestErrorUpdatePlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel("Model always errors")
router := routes.NewPlanRouter(m)
p := &models.Plan{PlanID: 6}
data, _ := json.Marshal(p)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
expected := `Internal Server Error`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestErrorOnRetrieveUpdatePlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorOnGetModel("Model always errors")
router := routes.NewPlanRouter(m)
p := &models.Plan{PlanID: 6}
data, _ := json.Marshal(p)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
expected := `Internal Server Error`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
func TestErrorWriterUpdatePlan(t *testing.T) {
// set up
assert := assert.New(t)
p := &models.Plan{PlanID: 6}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)
data, _ := json.Marshal(p)
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := NewBadWriter()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}

View File

@@ -6,7 +6,6 @@ import (
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/go-chi/chi"
"io"
"log"
"net/http"
"strconv"
)
@@ -17,6 +16,7 @@ func NewPlanRouter(m *models.Model) http.Handler {
router.Get("/", getAllPlansFunc(m))
router.Post("/", postPlanFunc(m))
router.Get("/{planid}", getPlanByIDFunc(m))
router.Put("/{planid}", putPlanFunc(m))
return router
}
@@ -24,7 +24,6 @@ func getAllPlansFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, err := tokens.GetUserID(r.Context())
if err != nil {
log.Print(err)
unauthorizedHandler(w, r)
return
}
@@ -45,7 +44,6 @@ func getPlanByIDFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, err := tokens.GetUserID(r.Context())
if err != nil {
log.Print(err)
unauthorizedHandler(w, r)
return
}
@@ -82,7 +80,6 @@ func postPlanFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, err := tokens.GetUserID(r.Context())
if err != nil {
log.Print(err)
unauthorizedHandler(w, r)
return
}
@@ -103,7 +100,7 @@ func postPlanFunc(m *models.Model) http.HandlerFunc {
}
// Map the fields we allow to be set to the plan to be created.
plan := &models.Plan{PlanDate: p.PlanDate, UserID: p.UserID}
plan := &models.Plan{PlanDescription: p.PlanDescription, UserID: p.UserID}
id, err := m.AddPlan(plan, userID)
if err != nil {
serverError(w, err)
@@ -127,3 +124,65 @@ func postPlanFunc(m *models.Model) http.HandlerFunc {
}
}
type updatePlanResponse struct {
UpdatedPlan *models.Plan `json:"updated_plan"`
ID int64 `json:"id"`
}
func putPlanFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID, err := tokens.GetUserID(r.Context())
if err != nil {
unauthorizedHandler(w, r)
return
}
id, err := strconv.Atoi(chi.URLParam(r, "planid"))
if err != nil {
notFoundHandler(w, r)
return
}
r.Body = http.MaxBytesReader(w, r.Body, 1024)
dec := json.NewDecoder(r.Body)
dec.DisallowUnknownFields()
var p models.Plan
err = dec.Decode(&p)
if err != nil {
badRequestError(w, err)
return
}
err = dec.Decode(&struct{}{})
if err != io.EOF {
badRequestError(w, err)
return
}
plan := &models.Plan{
PlanDescription: p.PlanDescription,
PlanID: int64(id),
}
err = m.SavePlan(plan, userID)
if err != nil {
serverError(w, err)
return
}
plan, err = m.Plan(id, userID)
if err != nil {
serverError(w, err)
return
}
response := &updatePlanResponse{
UpdatedPlan: plan,
ID: int64(id),
}
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
serverError(w, err)
}
}
}

View File

@@ -9,7 +9,6 @@ import (
"net/http/httptest"
"strings"
"testing"
"time"
)
var sampleContext = tokens.GetContextForUserValues(3, "testing")
@@ -39,8 +38,8 @@ func TestEmptyPlans(t *testing.T) {
func TestOnePlan(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
p := &models.Plan{PlanID: 6, PlanDate: &planDate, UserID: 3}
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription, UserID: 3}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)
@@ -58,7 +57,7 @@ func TestOnePlan(t *testing.T) {
expected := `[
{
"plan_id": 1,
"plan_date": "2021-01-01T00:00:00Z",
"plan_description": "2021-01-01",
"user_id": 3
}
]`
@@ -84,7 +83,6 @@ func TestErrorPlan(t *testing.T) {
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
// We pass in the date as a time.time so it makes sense that it comes back with a midnight timestamp.
expected := `Internal Server Error`
assert.Equal(expected, strings.TrimSpace(rr.Body.String()))
}
@@ -112,8 +110,8 @@ func TestEmptyPlanErrorWriter(t *testing.T) {
func TestOnePlanByID(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
p := &models.Plan{PlanID: 6, PlanDate: &planDate, UserID: 3}
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription, UserID: 3}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)
@@ -127,10 +125,10 @@ func TestOnePlanByID(t *testing.T) {
// check results
status := rr.Code
assert.Equal(http.StatusOK, status)
// We pass in the date as a time.time so it makes sense that it comes back with a midnight timestamp.
expected := `{
"plan_id": 1,
"plan_date": "2021-01-01T00:00:00Z",
"plan_description": "2021-01-01",
"user_id": 3
}`
assert.JSONEq(expected, rr.Body.String())
@@ -163,9 +161,8 @@ func TestErrorPlanByID(t *testing.T) {
func TestEmptyPlanErrorWriterByID(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
p := &models.Plan{PlanID: 1, PlanDate: &planDate}
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 1, PlanDescription: planDescription}
m := getEmptyModel()
m.AddPlan(p, 3)

View File

@@ -0,0 +1,119 @@
package routes_test
import (
"bytes"
"context"
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/routes"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestEmptyPlanEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewPlanRouter(m)
req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestOnePlanEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription, UserID: 3}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)
req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestOnePlanByIDEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription, UserID: 3}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)
req, _ := http.NewRequestWithContext(context.Background(), "GET", "/1", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestPureJSONEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewPlanRouter(m)
data := []byte(`{
"plan_description": "2021-01-01T00:00:00Z",
"plan_id": 1,
"user_id": 3
}`)
req, _ := http.NewRequestWithContext(context.Background(), "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestPutPlanEmptyContext(t *testing.T) {
// set up
assert := assert.New(t)
p := &models.Plan{PlanID: 6, PlanDescription: "sth"}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)
data, _ := json.Marshal(p)
req, _ := http.NewRequestWithContext(context.Background(), "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}

View File

@@ -25,7 +25,7 @@ func TestPureJSONPostAction(t *testing.T) {
ActionDescription: "here's an action",
}
m := getEmptyModel()
m.AddAction(a)
m.AddAction(a, 3)
router := routes.NewActionRouter(m)
data := []byte(`{
"action_description": "here's an action",
@@ -34,7 +34,7 @@ func TestPureJSONPostAction(t *testing.T) {
"completed_on": "2021-01-01T00:00:00Z",
"plan_id": 5
}`)
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -52,7 +52,8 @@ func TestPureJSONPostAction(t *testing.T) {
"completed_chunks": 2,
"completed_on": "2021-01-01T00:00:00Z",
"plan_id": 5,
"action_id": 2
"action_id": 2,
"user_id": 3
},
"id": 2
}`
@@ -64,8 +65,8 @@ func TestPureJSONPostAction(t *testing.T) {
func TestExtraFieldActionPostJSON(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewActionRouter(m)
@@ -74,7 +75,7 @@ func TestExtraFieldActionPostJSON(t *testing.T) {
"plan_id": 5,
"sabotage": "omg"
}`)
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -91,13 +92,13 @@ func TestExtraFieldActionPostJSON(t *testing.T) {
func TestEmptyBodyActionPost(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewActionRouter(m)
data := []byte(``)
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -115,8 +116,8 @@ func TestEmptyBodyActionPost(t *testing.T) {
func TestTwoBodyActionPost(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewActionRouter(m)
@@ -125,7 +126,7 @@ func TestTwoBodyActionPost(t *testing.T) {
}, {
"plan_id": 6
}`)
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -149,7 +150,7 @@ func TestErrorCreateAction(t *testing.T) {
router := routes.NewActionRouter(m)
a := &models.Action{PlanID: 6}
data, _ := json.Marshal(a)
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -174,7 +175,7 @@ func TestErrorOnRetrieveCreateAction(t *testing.T) {
router := routes.NewActionRouter(m)
a := &models.Action{PlanID: 6}
data, _ := json.Marshal(a)
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -195,11 +196,11 @@ func TestErrorWriterCreateAction(t *testing.T) {
a := &models.Action{PlanID: 6}
m := getEmptyModel()
m.AddAction(a)
m.AddAction(a, 3)
router := routes.NewActionRouter(m)
data, _ := json.Marshal(a)
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := NewBadWriter()

View File

@@ -10,15 +10,14 @@ import (
"net/http/httptest"
"strings"
"testing"
"time"
)
func TestCreatePlanRoute(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
planDescription := "2021-01-01"
userID := 3
p := &models.Plan{PlanID: 6, PlanDate: &planDate, UserID: int64(userID)}
p := &models.Plan{PlanID: 6, PlanDescription: planDescription, UserID: int64(userID)}
m := getEmptyModel()
m.AddPlan(p, userID)
router := routes.NewPlanRouter(m)
@@ -37,7 +36,7 @@ func TestCreatePlanRoute(t *testing.T) {
expected := `{
"created_plan": {
"plan_id": 2,
"plan_date": "2021-01-01T00:00:00Z",
"plan_description": "2021-01-01",
"user_id": 3
},
"id": 2
@@ -50,14 +49,14 @@ func TestCreatePlanRoute(t *testing.T) {
func TestPureJSON(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
planDescription := "2021-01-01"
userID := 3
p := &models.Plan{PlanID: 1, PlanDate: &planDate, UserID: int64(userID)}
p := &models.Plan{PlanID: 1, PlanDescription: planDescription, UserID: int64(userID)}
m := getEmptyModel()
m.AddPlan(p, userID)
router := routes.NewPlanRouter(m)
data := []byte(`{
"plan_date": "2021-01-01T00:00:00Z",
"plan_description": "2021-01-01",
"plan_id": 1,
"user_id": 3
}`)
@@ -76,7 +75,7 @@ func TestPureJSON(t *testing.T) {
"created_plan": {
"plan_id": 2,
"user_id": 3,
"plan_date": "2021-01-01T00:00:00Z"
"plan_description": "2021-01-01"
},
"id": 2
}`
@@ -88,14 +87,14 @@ func TestPureJSON(t *testing.T) {
func TestExtraFieldJSON(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
planDescription := "2021-01-01"
userID := 3
p := &models.Plan{PlanID: 6, PlanDate: &planDate, UserID: int64(userID)}
p := &models.Plan{PlanID: 6, PlanDescription: planDescription, UserID: int64(userID)}
m := getEmptyModel()
m.AddPlan(p, userID)
router := routes.NewPlanRouter(m)
data := []byte(`{
"plan_date": "2021-01-01T00:00:00Z",
"plan_description": "2021-01-01",
"plan_id": 5,
"plan_sabotage": "omg"
}`)
@@ -116,9 +115,9 @@ func TestExtraFieldJSON(t *testing.T) {
func TestEmptyBody(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
planDescription := "2021-01-01"
userID := 3
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
p := &models.Plan{PlanID: 6, PlanDescription: planDescription}
m := getEmptyModel()
m.AddPlan(p, userID)
router := routes.NewPlanRouter(m)
@@ -141,16 +140,16 @@ func TestEmptyBody(t *testing.T) {
func TestTwoBody(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)
data := []byte(`{
"plan_date": "2021-01-01T00:00:00Z",
"plan_description": "2021-01-01",
"plan_id": 5
}, {
"plan_date": "2021-01-01T00:00:00Z",
"plan_description": "2021-01-01",
"plan_id": 6
}`)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
@@ -175,8 +174,8 @@ func TestErrorCreatePlan(t *testing.T) {
m := getErrorModel("Model always errors")
router := routes.NewPlanRouter(m)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription}
data, _ := json.Marshal(p)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
@@ -201,8 +200,8 @@ func TestErrorOnRetrieveCreatePlan(t *testing.T) {
m := getErrorOnGetModel("Model always errors")
router := routes.NewPlanRouter(m)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDescription: planDescription}
data, _ := json.Marshal(p)
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
@@ -222,9 +221,9 @@ func TestErrorOnRetrieveCreatePlan(t *testing.T) {
func TestErrorWriterCreatePlan(t *testing.T) {
// set up
assert := assert.New(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
planDescription := "2021-01-01"
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
p := &models.Plan{PlanID: 6, PlanDescription: planDescription}
m := getEmptyModel()
m.AddPlan(p, 3)
router := routes.NewPlanRouter(m)

View File

@@ -25,7 +25,7 @@ func TestPureJSONPutAction(t *testing.T) {
ActionDescription: "hn",
}
m := getEmptyModel()
m.AddAction(a)
m.AddAction(a, 3)
router := routes.NewActionRouter(m)
data := []byte(`{
"action_description": "here's an action",
@@ -34,7 +34,7 @@ func TestPureJSONPutAction(t *testing.T) {
"completed_on": "2021-01-01T00:00:00Z",
"plan_id": 5
}`)
req, _ := http.NewRequest("PUT", "/1", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -52,7 +52,8 @@ func TestPureJSONPutAction(t *testing.T) {
"completed_chunks": 2,
"completed_on": "2021-01-01T00:00:00Z",
"plan_id": 5,
"action_id": 1
"action_id": 1,
"user_id": 3
},
"id": 1
}`
@@ -71,7 +72,7 @@ func TestExtraFieldActionPutJSON(t *testing.T) {
"plan_id": 5,
"sabotage": "omg"
}`)
req, _ := http.NewRequest("PUT", "/1", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -91,7 +92,7 @@ func TestEmptyBodyActionPut(t *testing.T) {
m := getEmptyModel()
router := routes.NewActionRouter(m)
data := []byte(``)
req, _ := http.NewRequest("PUT", "/1", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -116,7 +117,7 @@ func TestTwoBodyActionPut(t *testing.T) {
}, {
"plan_id": 6
}`)
req, _ := http.NewRequest("PUT", "/1", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -141,7 +142,7 @@ func TestBadActionIDPut(t *testing.T) {
}, {
"plan_id": 6
}`)
req, _ := http.NewRequest("PUT", "/text", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/text", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -165,7 +166,7 @@ func TestErrorUpdateAction(t *testing.T) {
router := routes.NewActionRouter(m)
a := &models.Action{PlanID: 6}
data, _ := json.Marshal(a)
req, _ := http.NewRequest("PUT", "/1", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -190,7 +191,7 @@ func TestErrorOnRetrieveUpdateAction(t *testing.T) {
router := routes.NewActionRouter(m)
a := &models.Action{PlanID: 6}
data, _ := json.Marshal(a)
req, _ := http.NewRequest("PUT", "/1", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
@@ -211,11 +212,11 @@ func TestErrorWriterUpdateAction(t *testing.T) {
a := &models.Action{PlanID: 6}
m := getEmptyModel()
m.AddAction(a)
m.AddAction(a, 3)
router := routes.NewActionRouter(m)
data, _ := json.Marshal(a)
req, _ := http.NewRequest("PUT", "/1", bytes.NewBuffer(data))
req, _ := http.NewRequestWithContext(sampleContext, "PUT", "/1", bytes.NewBuffer(data))
req.Header.Set("Content-Type", "application/json")
rr := NewBadWriter()

View File

@@ -18,8 +18,9 @@ func NewRouter(m *models.Model, tok tokens.Toker) http.Handler {
r.Mount("/actions", NewActionRouter(m))
r.Mount("/plans", NewPlanRouter(m))
r.Mount("/me", NewCurrentUserRouter(m))
r.Mount("/currentPlan", NewCurrentPlanRouter(m))
})
router.Mount("/auth", newAuthRouter(m, tok))
router.Mount("/auth", NewAuthRouter(m, tok))
router.Mount("/health", newHealthRouter(m))
router.Get("/ping", ping)
return router

View File

@@ -5,22 +5,22 @@ import (
"gitea.deepak.science/deepak/gogmagog/models"
)
func (e *errorStore) SelectActions() ([]*models.Action, error) {
func (e *errorStore) SelectActions(userID int) ([]*models.Action, error) {
return nil, e.error
}
func (e *errorStore) SelectActionByID(id int) (*models.Action, error) {
func (e *errorStore) SelectActionByID(id int, userID int) (*models.Action, error) {
return nil, e.error
}
func (e *errorStore) InsertAction(action *models.Action) (int, error) {
func (e *errorStore) InsertAction(action *models.Action, userID int) (int, error) {
if e.errorOnInsert {
return 0, e.error
}
return 0, nil
}
func (e *errorStore) UpdateAction(action *models.Action) error {
func (e *errorStore) UpdateAction(action *models.Action, userID int) error {
if e.errorOnInsert {
return e.error
}
@@ -42,7 +42,14 @@ func (e *errorStore) InsertPlan(plan *models.Plan, userID int) (int, error) {
return 0, nil
}
func (e *errorStore) SelectActionsByPlanID(plan *models.Plan) ([]*models.Action, error) {
func (e *errorStore) UpdatePlan(plan *models.Plan, userID int) error {
if e.errorOnInsert {
return e.error
}
return nil
}
func (e *errorStore) SelectActionsByPlanID(plan *models.Plan, userID int) ([]*models.Action, error) {
return nil, e.error
}
@@ -57,6 +64,24 @@ func (e *errorStore) InsertUser(user *models.User) (int, error) {
return 0, nil
}
func (e *errorStore) SelectCurrentPlan(userID int) (*models.CurrentPlan, error) {
return nil, e.error
}
func (e *errorStore) InsertCurrentPlan(currentPlan *models.CurrentPlan, userID int) error {
if e.errorOnInsert {
return e.error
}
return nil
}
func (e *errorStore) UpdateCurrentPlan(currentPlan *models.CurrentPlan, userID int) error {
if e.errorOnInsert {
return e.error
}
return nil
}
func (e *errorStore) ConnectionLive() error {
return e.error
}

View File

@@ -1,6 +1,7 @@
package store_test
import (
"fmt"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/store"
"github.com/stretchr/testify/assert"
@@ -9,29 +10,33 @@ import (
func TestErrorActionMethods(t *testing.T) {
assert := assert.New(t)
userID := 2
str := store.GetErrorStore("error message sample", true)
str2 := store.GetErrorStore("error message sample", false)
str3 := store.GetErrorStoreForError(fmt.Errorf("test error"), false)
_, err := str.InsertAction(&models.Action{})
_, err := str.InsertAction(&models.Action{}, userID)
assert.NotNil(err)
_, err = str2.InsertAction(&models.Action{})
_, err = str2.InsertAction(&models.Action{}, userID)
assert.Nil(err)
_, err = str3.InsertAction(&models.Action{}, userID)
assert.Nil(err)
_, err = str.SelectActionByID(8)
_, err = str.SelectActionByID(8, userID)
assert.NotNil(err)
_, err = str2.SelectActionByID(8)
_, err = str2.SelectActionByID(8, userID)
assert.NotNil(err)
_, err = str.SelectActions()
_, err = str.SelectActions(userID)
assert.NotNil(err)
_, err = str.SelectActionsByPlanID(&models.Plan{})
_, err = str.SelectActionsByPlanID(&models.Plan{}, userID)
assert.NotNil(err)
replacementAction := &models.Action{}
err = str.UpdateAction(replacementAction)
err = str.UpdateAction(replacementAction, userID)
assert.NotNil(err)
err = str2.UpdateAction(replacementAction)
err = str2.UpdateAction(replacementAction, userID)
assert.Nil(err)
}
@@ -49,6 +54,12 @@ func TestErrorPlanMethods(t *testing.T) {
_, err = str2.InsertPlan(&models.Plan{}, 3)
assert.Nil(err)
replacementPlan := &models.Plan{}
err = str.UpdatePlan(replacementPlan, 3)
assert.NotNil(err)
err = str2.UpdatePlan(replacementPlan, 3)
assert.Nil(err)
_, err = str.SelectPlanByID(5, 3)
assert.NotNil(err)
@@ -77,3 +88,25 @@ func TestErrorUserMethods(t *testing.T) {
_, err = str.SelectUserByUsername("snth")
assert.NotNil(err)
}
func TestErrorCurrentPlanMethods(t *testing.T) {
assert := assert.New(t)
str := store.GetErrorStore("error", true)
str2 := store.GetErrorStore("error", false)
cp := &models.CurrentPlan{}
_, err := str.SelectCurrentPlan(1)
assert.NotNil(err)
err = str.InsertCurrentPlan(cp, 1)
assert.NotNil(err)
err = str2.InsertCurrentPlan(cp, 1)
assert.Nil(err)
replace := &models.CurrentPlan{}
err = str.UpdateCurrentPlan(replace, 1)
assert.NotNil(err)
err = str2.UpdateCurrentPlan(replace, 1)
assert.Nil(err)
}

View File

@@ -2,13 +2,15 @@ package store
import (
"database/sql"
"fmt"
"gitea.deepak.science/deepak/gogmagog/models"
)
type inMemoryStore struct {
actions []*models.Action
plans []*models.Plan
users []*models.User
actions []*models.Action
plans []*models.Plan
users []*models.User
currentPlans []*models.CurrentPlan
}
// GetInMemoryStore provides a purely in memory store, for testing purposes only, with no persistence.
@@ -20,38 +22,45 @@ func GetInMemoryStore() (models.Store, error) {
}, nil
}
func (store *inMemoryStore) SelectActions() ([]*models.Action, error) {
return store.actions, nil
}
func (store *inMemoryStore) SelectActionsByPlanID(plan *models.Plan) ([]*models.Action, error) {
func (store *inMemoryStore) SelectActions(userID int) ([]*models.Action, error) {
ret := make([]*models.Action, 0)
for _, action := range store.actions {
if int(plan.PlanID) == int(action.PlanID) {
if int(action.UserID) == userID {
ret = append(ret, action)
}
}
return ret, nil
}
func (store *inMemoryStore) SelectActionByID(id int) (*models.Action, error) {
func (store *inMemoryStore) SelectActionsByPlanID(plan *models.Plan, userID int) ([]*models.Action, error) {
ret := make([]*models.Action, 0)
for _, action := range store.actions {
if id == int(action.ActionID) {
if (int(plan.PlanID) == int(action.PlanID)) && (int(action.UserID) == userID) {
ret = append(ret, action)
}
}
return ret, nil
}
func (store *inMemoryStore) SelectActionByID(id int, userID int) (*models.Action, error) {
for _, action := range store.actions {
if id == int(action.ActionID) && (int(action.UserID) == userID) {
return action, nil
}
}
return nil, sql.ErrNoRows
}
func (store *inMemoryStore) InsertAction(action *models.Action) (int, error) {
func (store *inMemoryStore) InsertAction(action *models.Action, userID int) (int, error) {
id := len(store.actions) + 1
action.ActionID = int64(id)
action.UserID = int64(userID)
store.actions = append(store.actions, action)
return id, nil
}
func (store *inMemoryStore) UpdateAction(action *models.Action) error {
currentAction, err := store.SelectActionByID(int(action.ActionID))
func (store *inMemoryStore) UpdateAction(action *models.Action, userID int) error {
currentAction, err := store.SelectActionByID(int(action.ActionID), userID)
if err != nil {
return err
}
@@ -91,6 +100,48 @@ func (store *inMemoryStore) InsertPlan(plan *models.Plan, userID int) (int, erro
return id, nil
}
func (store *inMemoryStore) UpdatePlan(plan *models.Plan, userID int) error {
currPlan, err := store.SelectPlanByID(int(plan.PlanID), userID)
if err != nil {
return err
}
currPlan.PlanDescription = plan.PlanDescription
return nil
}
func (store *inMemoryStore) SelectCurrentPlan(userID int) (*models.CurrentPlan, error) {
for _, currentPlan := range store.currentPlans {
if userID == int(currentPlan.UserID) {
return currentPlan, nil
}
}
return nil, sql.ErrNoRows
}
func (store *inMemoryStore) InsertCurrentPlan(currentPlan *models.CurrentPlan, userID int) error {
_, err := store.SelectCurrentPlan(userID)
if err == nil {
return fmt.Errorf("Can't insert primary plan")
}
// actually impossible, but at this point it must be a not found error.
// if err != sql.ErrNoRows {
// return err
// }
store.currentPlans = append(store.currentPlans, &models.CurrentPlan{PlanID: int64(currentPlan.PlanID), UserID: int64(userID)})
return nil
}
func (store *inMemoryStore) UpdateCurrentPlan(currentPlan *models.CurrentPlan, userID int) error {
current, err := store.SelectCurrentPlan(userID)
if err != nil {
return err
}
current.PlanID = currentPlan.PlanID
return nil
}
func (store *inMemoryStore) ConnectionLive() error {
return nil
}

View File

@@ -12,42 +12,45 @@ func TestInMemoryActionMethods(t *testing.T) {
str, _ := store.GetInMemoryStore()
sampleplanid := 8
userID := 10
act := &models.Action{}
a2 := &models.Action{PlanID: sampleplanid}
id, _ := str.InsertAction(act)
id, _ := str.InsertAction(act, userID)
assert.EqualValues(1, id)
receivedAction, err := str.SelectActionByID(id)
receivedAction, err := str.SelectActionByID(id, userID)
assert.Nil(err)
assert.EqualValues(act, receivedAction)
_, err = str.SelectActionByID(id, userID+1)
assert.NotNil(err)
allactions, err := str.SelectActions()
allactions, err := str.SelectActions(userID)
assert.Nil(err)
assert.EqualValues(1, len(allactions))
str.InsertAction(a2)
allactions, err = str.SelectActions()
str.InsertAction(a2, userID)
allactions, err = str.SelectActions(userID)
assert.Nil(err)
assert.EqualValues(2, len(allactions))
planactions, err := str.SelectActionsByPlanID(&models.Plan{PlanID: int64(sampleplanid)})
planactions, err := str.SelectActionsByPlanID(&models.Plan{PlanID: int64(sampleplanid)}, userID)
assert.Nil(err)
assert.EqualValues(1, len(planactions))
assert.Equal(a2, planactions[0])
_, err = str.SelectActionByID(151)
_, err = str.SelectActionByID(151, userID)
assert.NotNil(err)
sampleDescription := "snth"
replacementAction := &models.Action{ActionID: 1, ActionDescription: sampleDescription}
err = str.UpdateAction(replacementAction)
err = str.UpdateAction(replacementAction, userID)
assert.Nil(err)
assert.Equal(sampleDescription, act.ActionDescription)
replacementAction = &models.Action{ActionID: 1235122, ActionDescription: sampleDescription}
err = str.UpdateAction(replacementAction)
err = str.UpdateAction(replacementAction, userID)
assert.NotNil(err)
}
@@ -74,6 +77,16 @@ func TestInMemoryPlanMethods(t *testing.T) {
_, err = str.SelectPlanByID(135135, userID)
assert.NotNil(err)
sampleDescription := "snth"
replacePlan := &models.Plan{PlanID: 1, PlanDescription: sampleDescription}
err = str.UpdatePlan(replacePlan, userID)
assert.Nil(err)
assert.Equal(sampleDescription, p.PlanDescription)
replacePlan = &models.Plan{PlanID: 1235122, PlanDescription: sampleDescription}
err = str.UpdatePlan(replacePlan, userID)
assert.NotNil(err)
}
func TestLive(t *testing.T) {
@@ -102,3 +115,37 @@ func TestInMemoryUserMethods(t *testing.T) {
_, err = str.SelectUserByUsername("bad username")
assert.NotNil(err)
}
func TestInMemoryCurrentPlanMethods(t *testing.T) {
assert := assert.New(t)
str, _ := store.GetInMemoryStore()
userID := 10
cp1 := &models.CurrentPlan{PlanID: 1}
cp2 := &models.CurrentPlan{PlanID: 2}
err := str.UpdateCurrentPlan(cp1, userID)
assert.NotNil(err)
err = str.InsertCurrentPlan(cp1, userID)
assert.Nil(err)
receivedCp, err := str.SelectCurrentPlan(userID)
assert.Nil(err)
assert.EqualValues(1, receivedCp.PlanID)
_, err = str.SelectCurrentPlan(userID + 1)
assert.NotNil(err)
str.InsertCurrentPlan(cp2, userID)
assert.NotNil(err)
err = str.UpdateCurrentPlan(cp2, userID)
assert.Nil(err)
receivedCp, err = str.SelectCurrentPlan(userID)
assert.Nil(err)
assert.EqualValues(2, receivedCp.PlanID)
}

View File

@@ -1,4 +1,5 @@
DROP TABLE IF EXISTS actions;
DROP TABLE IF EXISTS user_current_plan;
DROP TABLE IF EXISTS plans;
DROP TABLE IF EXISTS users;

View File

@@ -9,15 +9,23 @@ CREATE TABLE IF NOT EXISTS users(
CREATE TABLE IF NOT EXISTS plans(
plan_id serial PRIMARY KEY,
plan_date DATE NOT NULL,
plan_description VARCHAR (500) NOT NULL,
user_id int REFERENCES users(user_id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
UNIQUE (user_id, plan_id)
);
CREATE TABLE IF NOT EXISTS user_current_plan(
user_id int PRIMARY KEY,
plan_id int,
FOREIGN KEY (user_id, plan_id) REFERENCES plans(user_id, plan_id)
);
CREATE TABLE IF NOT EXISTS actions(
action_id serial PRIMARY KEY,
action_description VARCHAR (500) NOT NULL,
user_id int REFERENCES users(user_id),
estimated_chunks SMALLINT,
completed_chunks SMALLINT,
completed_on TIMESTAMP WITH TIME ZONE,

View File

@@ -17,41 +17,44 @@ func GetPostgresStore(db *sqlx.DB) (models.Store, error) {
return &postgresStore{db: db}, nil
}
func (store *postgresStore) SelectActions() ([]*models.Action, error) {
func (store *postgresStore) SelectActions(userID int) ([]*models.Action, error) {
queryString := store.db.Rebind("SELECT action_id, action_description, user_id, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE user_id = ?")
actions := make([]*models.Action, 0)
err := store.db.Select(&actions, "SELECT action_id, action_description, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions")
err := store.db.Select(&actions, queryString, userID)
if err != nil {
return nil, err
}
return actions, nil
}
func (store *postgresStore) SelectActionsByPlanID(plan *models.Plan) ([]*models.Action, error) {
queryString := store.db.Rebind("SELECT action_id, action_description, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE plan_id = ?")
func (store *postgresStore) SelectActionsByPlanID(plan *models.Plan, userID int) ([]*models.Action, error) {
queryString := store.db.Rebind("SELECT action_id, action_description, user_id, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE plan_id = ? AND user_id = ?")
actions := make([]*models.Action, 0)
err := store.db.Select(&actions, queryString, plan.PlanID)
err := store.db.Select(&actions, queryString, plan.PlanID, userID)
if err != nil {
return nil, err
}
return actions, nil
}
func (store *postgresStore) SelectActionByID(id int) (*models.Action, error) {
func (store *postgresStore) SelectActionByID(id int, userID int) (*models.Action, error) {
queryString := store.db.Rebind("SELECT action_id, action_description, user_id, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE action_id = ? AND user_id = ?")
action := models.Action{}
err := store.db.Get(&action, store.db.Rebind("SELECT action_id, action_description, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE action_id = ?"), id)
err := store.db.Get(&action, queryString, id, userID)
if err != nil {
return nil, err
}
return &action, nil
}
func (store *postgresStore) InsertAction(action *models.Action) (int, error) {
func (store *postgresStore) InsertAction(action *models.Action, userID int) (int, error) {
queryString := store.db.Rebind(
`INSERT INTO actions (action_description,
user_id,
estimated_chunks,
completed_chunks,
completed_on,
plan_id) VALUES (?, ?, ?, ?, ?) RETURNING action_id`,
plan_id) VALUES (?, ?, ?, ?, ?, ?) RETURNING action_id`,
)
tx := store.db.MustBegin()
var id int
@@ -59,6 +62,7 @@ func (store *postgresStore) InsertAction(action *models.Action) (int, error) {
&id,
queryString,
action.ActionDescription,
userID,
action.EstimatedChunks,
action.CompletedChunks,
action.CompletedOn,
@@ -75,16 +79,26 @@ func (store *postgresStore) InsertAction(action *models.Action) (int, error) {
return id, nil
}
func (store *postgresStore) UpdateAction(action *models.Action) error {
func (store *postgresStore) UpdateAction(action *models.Action, userID int) error {
query := `UPDATE actions SET
action_description = :action_description,
estimated_chunks = :estimated_chunks,
completed_chunks = :completed_chunks,
completed_on = :completed_on,
plan_id = :plan_id
WHERE action_id = :action_id`
WHERE action_id = :action_id
AND user_id = :user_id`
tx := store.db.MustBegin()
_, err := store.db.NamedExec(query, action)
actionToUse := &models.Action{
ActionDescription: action.ActionDescription,
EstimatedChunks: action.EstimatedChunks,
CompletedChunks: action.CompletedChunks,
CompletedOn: action.CompletedOn,
PlanID: action.PlanID,
ActionID: action.ActionID,
UserID: int64(userID),
}
_, err := store.db.NamedExec(query, actionToUse)
if err != nil {
tx.Rollback()
return err
@@ -98,7 +112,7 @@ func (store *postgresStore) UpdateAction(action *models.Action) error {
}
func (store *postgresStore) SelectPlans(userID int) ([]*models.Plan, error) {
queryString := store.db.Rebind("SELECT plan_id, plan_date, user_id FROM plans WHERE user_id = ?")
queryString := store.db.Rebind("SELECT plan_id, plan_description, user_id FROM plans WHERE user_id = ?")
plans := make([]*models.Plan, 0)
err := store.db.Select(&plans, queryString, userID)
if err != nil {
@@ -109,7 +123,7 @@ func (store *postgresStore) SelectPlans(userID int) ([]*models.Plan, error) {
func (store *postgresStore) SelectPlanByID(id int, userID int) (*models.Plan, error) {
plan := models.Plan{}
err := store.db.Get(&plan, store.db.Rebind("SELECT plan_id, plan_date, user_id FROM plans WHERE plan_id = ? AND user_id = ?"), id, userID)
err := store.db.Get(&plan, store.db.Rebind("SELECT plan_id, plan_description, user_id FROM plans WHERE plan_id = ? AND user_id = ?"), id, userID)
if err != nil {
return nil, err
}
@@ -117,10 +131,10 @@ func (store *postgresStore) SelectPlanByID(id int, userID int) (*models.Plan, er
}
func (store *postgresStore) InsertPlan(plan *models.Plan, userID int) (int, error) {
queryString := store.db.Rebind("INSERT INTO plans (plan_date, user_id) VALUES (?, ?) RETURNING plan_id")
queryString := store.db.Rebind("INSERT INTO plans (plan_description, user_id) VALUES (?, ?) RETURNING plan_id")
tx := store.db.MustBegin()
var id int
err := tx.Get(&id, queryString, plan.PlanDate, userID)
err := tx.Get(&id, queryString, plan.PlanDescription, userID)
if err != nil {
tx.Rollback()
return -1, err
@@ -132,6 +146,30 @@ func (store *postgresStore) InsertPlan(plan *models.Plan, userID int) (int, erro
return id, nil
}
func (store *postgresStore) UpdatePlan(plan *models.Plan, userID int) error {
query := `UPDATE plans SET
plan_description = :plan_description
WHERE plan_id = :plan_id
AND user_id = :user_id`
tx := store.db.MustBegin()
planToUse := &models.Plan{
PlanDescription: plan.PlanDescription,
PlanID: plan.PlanID,
UserID: int64(userID),
}
_, err := store.db.NamedExec(query, planToUse)
if err != nil {
tx.Rollback()
return err
}
err = tx.Commit()
if err != nil {
return err
}
return nil
}
func (store *postgresStore) ConnectionLive() error {
return store.db.Ping()
}
@@ -160,3 +198,51 @@ func (store *postgresStore) InsertUser(user *models.User) (int, error) {
}
return id, nil
}
func (store *postgresStore) SelectCurrentPlan(userID int) (*models.CurrentPlan, error) {
pp := models.CurrentPlan{}
queryString := store.db.Rebind(`SELECT user_id, plan_id FROM user_current_plan WHERE user_id = ?`)
err := store.db.Get(&pp, queryString, userID)
if err != nil {
return nil, err
}
return &pp, nil
}
func (store *postgresStore) InsertCurrentPlan(currentPlan *models.CurrentPlan, userID int) error {
queryString := store.db.Rebind("INSERT INTO user_current_plan (user_id, plan_id) VALUES (?, ?) RETURNING user_id")
tx := store.db.MustBegin()
var id int
err := tx.Get(&id, queryString, userID, currentPlan.PlanID)
if err != nil {
tx.Rollback()
return err
}
err = tx.Commit()
if err != nil {
return err
}
return nil
}
func (store *postgresStore) UpdateCurrentPlan(currentPlan *models.CurrentPlan, userID int) error {
query := `UPDATE user_current_plan SET
plan_id = :plan_id
WHERE user_id = :user_id`
tx := store.db.MustBegin()
ppToUse := &models.CurrentPlan{
PlanID: currentPlan.PlanID,
UserID: int64(userID),
}
_, err := store.db.NamedExec(query, ppToUse)
if err != nil {
tx.Rollback()
return err
}
err = tx.Commit()
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,217 @@
package store_test
import (
"fmt"
"gitea.deepak.science/deepak/gogmagog/models"
"github.com/DATA-DOG/go-sqlmock"
"github.com/stretchr/testify/assert"
"testing"
)
func TestSelectCurrentPlan(t *testing.T) {
assert := assert.New(t)
planIDToUse := 1
userIDToUse := 2
str, mock := getDbMock(t)
rows := sqlmock.NewRows([]string{"plan_id", "user_id"}).AddRow(planIDToUse, userIDToUse)
mock.ExpectQuery(`^SELECT user_id, plan_id FROM user_current_plan WHERE user_id = \$1`).
WithArgs(userIDToUse).
WillReturnRows(rows)
currPlan, err := str.SelectCurrentPlan(userIDToUse)
assert.Nil(err)
assert.EqualValues(planIDToUse, currPlan.PlanID)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestSelectCurrentPlanErr(t *testing.T) {
assert := assert.New(t)
userIDToUse := 2
str, mock := getDbMock(t)
mock.ExpectQuery(`^SELECT user_id, plan_id FROM user_current_plan WHERE user_id = \$1`).
WithArgs(userIDToUse).
WillReturnError(fmt.Errorf("example error"))
currPlan, err := str.SelectCurrentPlan(userIDToUse)
assert.NotNil(err)
assert.Nil(currPlan)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestInsertCurrentPlan(t *testing.T) {
// setup
assert := assert.New(t)
str, mock := getDbMock(t)
planID := 1
userID := 2
badUserID := 7
cp := &models.CurrentPlan{PlanID: int64(planID), UserID: int64(badUserID)}
rows := sqlmock.NewRows([]string{"userID"}).AddRow(userID)
mock.ExpectBegin()
mock.ExpectQuery(`^INSERT INTO user_current_plan \(user_id, plan_id\) VALUES \(\$1, \$2\) RETURNING user_id$`).
WithArgs(userID, planID).
WillReturnRows(rows)
mock.ExpectCommit()
// function under test
err := str.InsertCurrentPlan(cp, userID)
// check results
assert.Nil(err)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestInsertCurrentPlanErr(t *testing.T) {
// setup
assert := assert.New(t)
str, mock := getDbMock(t)
userID := 2
badUserID := 7
planID := 1
cp := &models.CurrentPlan{PlanID: int64(planID), UserID: int64(badUserID)}
mock.ExpectBegin()
mock.ExpectQuery(`^INSERT INTO user_current_plan \(user_id, plan_id\) VALUES \(\$1, \$2\) RETURNING user_id$`).
WithArgs(userID, planID).
WillReturnError(fmt.Errorf("example error"))
mock.ExpectRollback()
// function under test
err := str.InsertCurrentPlan(cp, userID)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestInsertCurrentPlanCommitErr(t *testing.T) {
// setup
assert := assert.New(t)
str, mock := getDbMock(t)
planID := 1
userID := 2
cp := &models.CurrentPlan{PlanID: int64(planID), UserID: int64(userID)}
rows := sqlmock.NewRows([]string{"user_id"}).AddRow(userID)
mock.ExpectBegin()
mock.ExpectQuery(`^INSERT INTO user_current_plan \(user_id, plan_id\) VALUES \(\$1, \$2\) RETURNING user_id$`).
WithArgs(userID, planID).
WillReturnRows(rows)
mock.ExpectCommit().WillReturnError(fmt.Errorf("another error example"))
// function under test
err := str.InsertCurrentPlan(cp, userID)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestUpdateCurrentPlan(t *testing.T) {
// setup
assert := assert.New(t)
str, mock := getDbMock(t)
userIDToUse := 1
planIDToUse := 2
mock.ExpectBegin()
mock.ExpectExec(`
UPDATE user_current_plan SET
plan_id = \$1
WHERE user_id = \$2`).
WithArgs(planIDToUse, userIDToUse).
WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
// function under test
err := str.UpdateCurrentPlan(&models.CurrentPlan{PlanID: int64(planIDToUse)}, userIDToUse)
// check results
assert.Nil(err)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestUpdateCurrentPlanErr(t *testing.T) {
// setup
assert := assert.New(t)
str, mock := getDbMock(t)
userIDToUse := 1
planIDToUse := 2
mock.ExpectBegin()
mock.ExpectExec(`
UPDATE user_current_plan SET
plan_id = \$1
WHERE user_id = \$2`).
WithArgs(planIDToUse, userIDToUse).
WillReturnError(fmt.Errorf("example error"))
mock.ExpectRollback()
// function under test
err := str.UpdateCurrentPlan(&models.CurrentPlan{PlanID: int64(planIDToUse)}, userIDToUse)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestUpdateCurrentPlanCommitErr(t *testing.T) {
// setup
assert := assert.New(t)
str, mock := getDbMock(t)
userIDToUse := 1
planIDToUse := 2
mock.ExpectBegin()
mock.ExpectExec(`
UPDATE user_current_plan SET
plan_id = \$1
WHERE user_id = \$2`).
WithArgs(planIDToUse, userIDToUse).
WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit().WillReturnError(fmt.Errorf("another error example"))
// function under test
err := str.UpdateCurrentPlan(&models.CurrentPlan{PlanID: int64(planIDToUse)}, userIDToUse)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}

View File

@@ -6,20 +6,19 @@ import (
"github.com/DATA-DOG/go-sqlmock"
"github.com/stretchr/testify/assert"
"testing"
"time"
)
func TestSelectPlans(t *testing.T) {
assert := assert.New(t)
currentTime := time.Now()
planDesc := "testing"
idToUse := 1
userIDToUse := 2
str, mock := getDbMock(t)
rows := sqlmock.NewRows([]string{"plan_id", "plan_date", "user_id"}).AddRow(idToUse, currentTime, userIDToUse)
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans WHERE user_id = \$1`).
rows := sqlmock.NewRows([]string{"plan_id", "plan_description", "user_id"}).AddRow(idToUse, planDesc, userIDToUse)
mock.ExpectQuery(`^SELECT plan_id, plan_description, user_id FROM plans WHERE user_id = \$1`).
WithArgs(userIDToUse).
WillReturnRows(rows)
@@ -28,7 +27,7 @@ func TestSelectPlans(t *testing.T) {
assert.Equal(1, len(plans))
plan := plans[0]
assert.EqualValues(idToUse, plan.PlanID)
assert.Equal(currentTime, *plan.PlanDate)
assert.Equal(planDesc, plan.PlanDescription)
assert.EqualValues(userIDToUse, plan.UserID)
if err := mock.ExpectationsWereMet(); err != nil {
@@ -39,21 +38,21 @@ func TestSelectPlans(t *testing.T) {
func TestSelectPlanByID(t *testing.T) {
assert := assert.New(t)
currentTime := time.Now()
planDesc := "tsaoeu"
idToUse := 1
userIDToUse := 2
str, mock := getDbMock(t)
rows := sqlmock.NewRows([]string{"plan_id", "plan_date", "user_id"}).AddRow(idToUse, currentTime, userIDToUse)
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans WHERE plan_id = \$1 AND user_id = \$2$`).
rows := sqlmock.NewRows([]string{"plan_id", "plan_description", "user_id"}).AddRow(idToUse, planDesc, userIDToUse)
mock.ExpectQuery(`^SELECT plan_id, plan_description, user_id FROM plans WHERE plan_id = \$1 AND user_id = \$2$`).
WithArgs(idToUse, userIDToUse).
WillReturnRows(rows)
plan, err := str.SelectPlanByID(idToUse, userIDToUse)
assert.Nil(err)
assert.EqualValues(idToUse, plan.PlanID)
assert.Equal(currentTime, *plan.PlanDate)
assert.Equal(planDesc, plan.PlanDescription)
assert.EqualValues(userIDToUse, plan.UserID)
if err := mock.ExpectationsWereMet(); err != nil {
@@ -66,19 +65,19 @@ func TestInsertPlan(t *testing.T) {
assert := assert.New(t)
str, mock := getDbMock(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
planDescription := "2021-01-01"
userID := 2
badUserID := 7
plan := &models.Plan{PlanDate: &planDate, UserID: int64(badUserID)}
plan := &models.Plan{PlanDescription: planDescription, UserID: int64(badUserID)}
idToUse := 8
rows := sqlmock.NewRows([]string{"plan_id"}).AddRow(8)
mock.ExpectBegin()
mock.ExpectQuery(`^INSERT INTO plans \(plan_date, user_id\) VALUES \(\$1, \$2\) RETURNING plan_id$`).
WithArgs(planDate, userID).
mock.ExpectQuery(`^INSERT INTO plans \(plan_description, user_id\) VALUES \(\$1, \$2\) RETURNING plan_id$`).
WithArgs(planDescription, userID).
WillReturnRows(rows)
mock.ExpectCommit()
@@ -98,14 +97,14 @@ func TestInsertPlanErr(t *testing.T) {
assert := assert.New(t)
str, mock := getDbMock(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
planDescription := "2021-01-01"
userID := 2
badUserID := 7
plan := &models.Plan{PlanDate: &planDate, UserID: int64(badUserID)}
plan := &models.Plan{PlanDescription: planDescription, UserID: int64(badUserID)}
mock.ExpectBegin()
mock.ExpectQuery(`^INSERT INTO plans \(plan_date, user_id\) VALUES \(\$1, \$2\) RETURNING plan_id$`).
WithArgs(planDate, userID).
mock.ExpectQuery(`^INSERT INTO plans \(plan_description, user_id\) VALUES \(\$1, \$2\) RETURNING plan_id$`).
WithArgs(planDescription, userID).
WillReturnError(fmt.Errorf("example error"))
mock.ExpectRollback()
@@ -124,16 +123,16 @@ func TestInsertPlanCommitErr(t *testing.T) {
assert := assert.New(t)
str, mock := getDbMock(t)
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
planDescription := "2021-01-01"
userID := 2
plan := &models.Plan{PlanDate: &planDate, UserID: int64(userID)}
plan := &models.Plan{PlanDescription: planDescription, UserID: int64(userID)}
idToUse := 8
rows := sqlmock.NewRows([]string{"plan_id"}).AddRow(idToUse)
mock.ExpectBegin()
mock.ExpectQuery(`^INSERT INTO plans \(plan_date, user_id\) VALUES \(\$1, \$2\) RETURNING plan_id$`).
WithArgs(planDate, userID).
mock.ExpectQuery(`^INSERT INTO plans \(plan_description, user_id\) VALUES \(\$1, \$2\) RETURNING plan_id$`).
WithArgs(planDescription, userID).
WillReturnRows(rows)
mock.ExpectCommit().WillReturnError(fmt.Errorf("another error example"))
@@ -154,7 +153,7 @@ func TestErrPlanByID(t *testing.T) {
str, mock := getDbMock(t)
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans WHERE plan_id = \$1 AND user_id = \$2$`).
mock.ExpectQuery(`^SELECT plan_id, plan_description, user_id FROM plans WHERE plan_id = \$1 AND user_id = \$2$`).
WithArgs(idToUse, 8).
WillReturnError(fmt.Errorf("example error"))
@@ -172,7 +171,7 @@ func TestErrPlans(t *testing.T) {
assert := assert.New(t)
str, mock := getDbMock(t)
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans WHERE user_id = \$1$`).
mock.ExpectQuery(`^SELECT plan_id, plan_description, user_id FROM plans WHERE user_id = \$1$`).
WithArgs(8).
WillReturnError(fmt.Errorf("example error"))
// function under test
@@ -184,3 +183,82 @@ func TestErrPlans(t *testing.T) {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestUpdatePlan(t *testing.T) {
// setup
assert := assert.New(t)
str, mock := getDbMock(t)
planDescription := "2021-01-01"
userID := 2
idToUse := 8
plan := &models.Plan{PlanDescription: planDescription, UserID: int64(userID), PlanID: int64(idToUse)}
mock.ExpectBegin()
mock.ExpectExec(`^UPDATE plans SET plan_description = \$1 WHERE plan_id = \$2 AND user_id = \$3$`).
WithArgs(planDescription, idToUse, userID).
WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
// function under test
err := str.UpdatePlan(plan, userID)
// check results
assert.Nil(err)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestUpdatePlanErr(t *testing.T) {
// setup
assert := assert.New(t)
str, mock := getDbMock(t)
planDescription := "2021-01-01"
userID := 2
idToUse := 8
plan := &models.Plan{PlanDescription: planDescription, UserID: int64(userID), PlanID: int64(idToUse)}
mock.ExpectBegin()
mock.ExpectExec(`^UPDATE plans SET plan_description = \$1 WHERE plan_id = \$2 AND user_id = \$3$`).
WithArgs(planDescription, idToUse, userID).
WillReturnError(fmt.Errorf("example error"))
mock.ExpectRollback()
// function under test
err := str.UpdatePlan(plan, userID)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}
func TestUpdatePlanCommitErr(t *testing.T) {
// setup
assert := assert.New(t)
str, mock := getDbMock(t)
planDescription := "2021-01-01"
userID := 2
idToUse := 8
plan := &models.Plan{PlanDescription: planDescription, UserID: int64(userID), PlanID: int64(idToUse)}
mock.ExpectBegin()
mock.ExpectExec(`^UPDATE plans SET plan_description = \$1 WHERE plan_id = \$2 AND user_id = \$3$`).
WithArgs(planDescription, idToUse, userID).
WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit().WillReturnError(fmt.Errorf("another error example"))
// function under test
err := str.UpdatePlan(plan, userID)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
}
}

View File

@@ -34,6 +34,7 @@ func TestSelectActions(t *testing.T) {
idToUse := 1
estChunks := 5
compChunks := 7
userIDToUse := 13
desc := "Howdy, partner."
str, mock := getDbMock(t)
@@ -46,13 +47,16 @@ func TestSelectActions(t *testing.T) {
"completed_on",
"created_at",
"updated_at",
"plan_id"}).
AddRow(idToUse, desc, estChunks, compChunks, completeTime, createTime, updateTime, idToUse).
AddRow(idToUse+1, desc, estChunks, compChunks, completeTime, createTime, updateTime, idToUse)
mock.ExpectQuery("^SELECT action_id, action_description, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions$").WillReturnRows(rows)
"plan_id",
"user_id"}).
AddRow(idToUse, desc, estChunks, compChunks, completeTime, createTime, updateTime, idToUse, userIDToUse).
AddRow(idToUse+1, desc, estChunks, compChunks, completeTime, createTime, updateTime, idToUse, userIDToUse)
mock.ExpectQuery(`^SELECT action_id, action_description, user_id, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE user_id = \$1$`).
WithArgs(userIDToUse).
WillReturnRows(rows)
// function under test
actions, err := str.SelectActions()
actions, err := str.SelectActions(userIDToUse)
// test results
assert.Nil(err)
@@ -66,6 +70,7 @@ func TestSelectActions(t *testing.T) {
assert.Equal(createTime, *action.CreatedAt)
assert.Equal(updateTime, *action.UpdatedAt)
assert.Equal(idToUse, action.PlanID)
assert.EqualValues(userIDToUse, action.UserID)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
@@ -82,6 +87,7 @@ func TestSelectActionsByPlanID(t *testing.T) {
idToUse := 1
estChunks := 5
compChunks := 7
userIDToUse := 13
desc := "Howdy, partner."
str, mock := getDbMock(t)
@@ -89,20 +95,21 @@ func TestSelectActionsByPlanID(t *testing.T) {
rows := sqlmock.NewRows([]string{
"action_id",
"action_description",
"user_id",
"estimated_chunks",
"completed_chunks",
"completed_on",
"created_at",
"updated_at",
"plan_id"}).
AddRow(idToUse, desc, estChunks, compChunks, completeTime, createTime, updateTime, idToUse).
AddRow(idToUse+1, desc, estChunks, compChunks, completeTime, createTime, updateTime, idToUse)
mock.ExpectQuery("^SELECT action_id, action_description, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE plan_id = \\$1$").
WithArgs(idToUse).
AddRow(idToUse, desc, userIDToUse, estChunks, compChunks, completeTime, createTime, updateTime, idToUse).
AddRow(idToUse+1, desc, userIDToUse, estChunks, compChunks, completeTime, createTime, updateTime, idToUse)
mock.ExpectQuery(`^SELECT action_id, action_description, user_id, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE plan_id = \$1 AND user_id = \$2$`).
WithArgs(idToUse, userIDToUse).
WillReturnRows(rows)
// function under test
actions, err := str.SelectActionsByPlanID(&models.Plan{PlanID: int64(idToUse)})
actions, err := str.SelectActionsByPlanID(&models.Plan{PlanID: int64(idToUse)}, userIDToUse)
// test results
assert.Nil(err)
@@ -116,6 +123,7 @@ func TestSelectActionsByPlanID(t *testing.T) {
assert.Equal(createTime, *action.CreatedAt)
assert.Equal(updateTime, *action.UpdatedAt)
assert.Equal(idToUse, action.PlanID)
assert.EqualValues(userIDToUse, action.UserID)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
@@ -127,15 +135,16 @@ func TestSelectActionsByPlanIDErr(t *testing.T) {
assert := assert.New(t)
idToUse := 1
userIDToUse := 13
str, mock := getDbMock(t)
mock.ExpectQuery("^SELECT action_id, action_description, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE plan_id = \\$1$").
WithArgs(idToUse).
mock.ExpectQuery(`^SELECT action_id, action_description, user_id, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE plan_id = \$1 AND user_id = \$2$`).
WithArgs(idToUse, userIDToUse).
WillReturnError(fmt.Errorf("example error"))
// function under test
actions, err := str.SelectActionsByPlanID(&models.Plan{PlanID: int64(idToUse)})
actions, err := str.SelectActionsByPlanID(&models.Plan{PlanID: int64(idToUse)}, userIDToUse)
// test results
assert.NotNil(err)
@@ -156,6 +165,7 @@ func TestSelectActionById(t *testing.T) {
idToUse := 1
estChunks := 5
compChunks := 7
userIDToUse := 13
desc := "Howdy, partner."
str, mock := getDbMock(t)
@@ -163,20 +173,21 @@ func TestSelectActionById(t *testing.T) {
rows := sqlmock.NewRows([]string{
"action_id",
"action_description",
"user_id",
"estimated_chunks",
"completed_chunks",
"completed_on",
"created_at",
"updated_at",
"plan_id"}).
AddRow(idToUse, desc, estChunks, compChunks, completeTime, createTime, updateTime, idToUse)
AddRow(idToUse, desc, userIDToUse, estChunks, compChunks, completeTime, createTime, updateTime, idToUse)
mock.ExpectQuery("^SELECT action_id, action_description, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE action_id = \\$1").
WithArgs(1).
mock.ExpectQuery(`^SELECT action_id, action_description, user_id, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE action_id = \$1 AND user_id = \$2`).
WithArgs(1, userIDToUse).
WillReturnRows(rows)
// function under test
action, err := str.SelectActionByID(1)
action, err := str.SelectActionByID(1, userIDToUse)
// test results
assert.Nil(err)
@@ -189,6 +200,7 @@ func TestSelectActionById(t *testing.T) {
assert.Equal(createTime, *action.CreatedAt)
assert.Equal(updateTime, *action.UpdatedAt)
assert.Equal(idToUse, action.PlanID)
assert.EqualValues(userIDToUse, action.UserID)
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("unfulfilled expectations: %s", err)
@@ -200,9 +212,9 @@ func TestErrActions(t *testing.T) {
assert := assert.New(t)
str, mock := getDbMock(t)
mock.ExpectQuery("^SELECT action_id, action_description, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions$").WillReturnError(fmt.Errorf("example error"))
mock.ExpectQuery(`^SELECT action_id, action_description, user_id, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE user_id = \$1$`).WithArgs(1).WillReturnError(fmt.Errorf("example error"))
// function under test
actions, err := str.SelectActions()
actions, err := str.SelectActions(1)
// test results
assert.Nil(actions)
assert.NotNil(err)
@@ -216,9 +228,11 @@ func TestErrActionByID(t *testing.T) {
assert := assert.New(t)
str, mock := getDbMock(t)
mock.ExpectQuery("^SELECT action_id, action_description, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE action_id = \\$1").WillReturnError(fmt.Errorf("example error"))
userIDToUse := 3
mock.ExpectQuery(`^SELECT action_id, action_description, user_id, estimated_chunks, completed_chunks, completed_on, created_at, updated_at, plan_id FROM actions WHERE action_id = \$1 AND user_id = \$2`).WithArgs(1, userIDToUse).WillReturnError(fmt.Errorf("example error"))
// function under test
action, err := str.SelectActionByID(1)
action, err := str.SelectActionByID(1, userIDToUse)
// test results
assert.Nil(action)
assert.NotNil(err)
@@ -244,6 +258,8 @@ func TestInsertAction(t *testing.T) {
// setup
assert := assert.New(t)
userIDToUse := 7
str, mock := getDbMock(t)
completedOn, _ := time.Parse("2006-01-02", "2021-01-01")
action := &models.Action{
@@ -259,13 +275,13 @@ func TestInsertAction(t *testing.T) {
rows := sqlmock.NewRows([]string{"action_id"}).AddRow(8)
mock.ExpectBegin()
mock.ExpectQuery("^INSERT INTO actions \\(action_description, estimated_chunks, completed_chunks, completed_on, plan_id\\) VALUES \\(\\$1, \\$2, \\$3, \\$4, \\$5\\) RETURNING action_id$").
WithArgs("testing", 3, 6, completedOn, 5).
mock.ExpectQuery(`^INSERT INTO actions \(action_description, user_id, estimated_chunks, completed_chunks, completed_on, plan_id\) VALUES \(\$1, \$2, \$3, \$4, \$5, \$6\) RETURNING action_id$`).
WithArgs("testing", userIDToUse, 3, 6, completedOn, 5).
WillReturnRows(rows)
mock.ExpectCommit()
// function under test
insertedId, err := str.InsertAction(action)
insertedId, err := str.InsertAction(action, userIDToUse)
// check results
assert.Nil(err)
assert.EqualValues(idToUse, insertedId)
@@ -290,13 +306,13 @@ func TestInsertActionErr(t *testing.T) {
}
mock.ExpectBegin()
mock.ExpectQuery("^INSERT INTO actions \\(action_description, estimated_chunks, completed_chunks, completed_on, plan_id\\) VALUES \\(\\$1, \\$2, \\$3, \\$4, \\$5\\) RETURNING action_id$").
WithArgs("testing", 3, 6, completedOn, 5).
mock.ExpectQuery(`^INSERT INTO actions \(action_description, user_id, estimated_chunks, completed_chunks, completed_on, plan_id\) VALUES \(\$1, \$2, \$3, \$4, \$5, \$6\) RETURNING action_id$`).
WithArgs("testing", 7, 3, 6, completedOn, 5).
WillReturnError(fmt.Errorf("example error"))
mock.ExpectRollback()
// function under test
_, err := str.InsertAction(action)
_, err := str.InsertAction(action, 7)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {
@@ -319,17 +335,18 @@ func TestInsertActionCommitErr(t *testing.T) {
ActionDescription: "testing",
}
idToUse := 8
userIDToUse := 11
rows := sqlmock.NewRows([]string{"plan_id"}).AddRow(idToUse)
mock.ExpectBegin()
mock.ExpectQuery("^INSERT INTO actions \\(action_description, estimated_chunks, completed_chunks, completed_on, plan_id\\) VALUES \\(\\$1, \\$2, \\$3, \\$4, \\$5\\) RETURNING action_id$").
WithArgs("testing", 3, 6, completedOn, 5).
mock.ExpectQuery(`^INSERT INTO actions \(action_description, user_id, estimated_chunks, completed_chunks, completed_on, plan_id\) VALUES \(\$1, \$2, \$3, \$4, \$5, \$6\) RETURNING action_id$`).
WithArgs("testing", userIDToUse, 3, 6, completedOn, 5).
WillReturnRows(rows)
mock.ExpectCommit().WillReturnError(fmt.Errorf("another error example"))
// function under test
_, err := str.InsertAction(action)
_, err := str.InsertAction(action, userIDToUse)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {
@@ -352,6 +369,7 @@ func TestUpdateAction(t *testing.T) {
ActionDescription: "testing",
ActionID: 2,
}
userIDToUse := 31
mock.ExpectBegin()
mock.ExpectExec(`
@@ -361,13 +379,14 @@ func TestUpdateAction(t *testing.T) {
completed_chunks = \$3,
completed_on = \$4,
plan_id = \$5
WHERE action_id = \$6`).
WithArgs("testing", 3, 6, completedOn, 5, 2).
WHERE action_id = \$6
AND user_id = \$7`).
WithArgs("testing", 3, 6, completedOn, 5, 2, userIDToUse).
WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
// function under test
err := str.UpdateAction(action)
err := str.UpdateAction(action, userIDToUse)
// check results
assert.Nil(err)
if err := mock.ExpectationsWereMet(); err != nil {
@@ -393,12 +412,12 @@ func TestUpdateActionErr(t *testing.T) {
mock.ExpectBegin()
mock.ExpectExec("UPDATE actions").
WithArgs("testing", 3, 6, completedOn, 5, 2).
WithArgs("testing", 3, 6, completedOn, 5, 2, 31).
WillReturnError(fmt.Errorf("example error"))
mock.ExpectRollback()
// function under test
err := str.UpdateAction(action)
err := str.UpdateAction(action, 31)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {
@@ -424,12 +443,12 @@ func TestUpdateActionCommitErr(t *testing.T) {
mock.ExpectBegin()
mock.ExpectExec("UPDATE actions").
WithArgs("testing", 3, 6, completedOn, 5, 2).
WithArgs("testing", 3, 6, completedOn, 5, 2, 31).
WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit().WillReturnError(fmt.Errorf("another error example"))
// function under test
err := str.UpdateAction(action)
err := str.UpdateAction(action, 31)
// check results
assert.NotNil(err)
if err := mock.ExpectationsWereMet(); err != nil {

View File

@@ -0,0 +1,53 @@
package tokens
import (
"context"
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"log"
"net/http"
)
type deterministicToker struct{}
// GetDeterministicToker returns a zero security toker for testing purposes.
// Do not use in production.
func GetDeterministicToker() Toker {
return &deterministicToker{}
}
func (d *deterministicToker) EncodeUser(user *models.UserNoPassword) string {
tok := &UserToken{ID: user.UserID, Username: user.Username}
ret, _ := json.Marshal(tok)
return string(ret)
}
func (d *deterministicToker) DecodeTokenString(tokenString string) (*UserToken, error) {
var tok UserToken
err := json.Unmarshal([]byte(tokenString), &tok)
return &tok, err
}
func (d *deterministicToker) Authenticator(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tokenString := TokenFromHeader(r)
if tokenString == "" {
log.Print("No valid token found")
unauthorized(w, r)
return
}
userToken, err := d.DecodeTokenString(tokenString)
if err != nil {
log.Printf("Error while verifying token: %s", err)
unauthorized(w, r)
return
}
log.Printf("Got user with ID: [%d]", userToken.ID)
ctx := context.WithValue(r.Context(), userIDCtxKey, userToken.ID)
ctx = context.WithValue(ctx, usernameCtxKey, userToken.Username)
// Authenticated
next.ServeHTTP(w, r.WithContext(ctx))
})
}

View File

@@ -0,0 +1,80 @@
package tokens_test
import (
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"log"
"net/http"
"net/http/httptest"
"testing"
)
var dtMiddlewareURL string = "/"
func dtRequestAuth(header string) *http.Request {
req, _ := http.NewRequest("GET", dtMiddlewareURL, nil)
req.Header.Add(authKey, header)
return req
}
func verifyingHandlerdt(t *testing.T, username string, userID int) http.Handler {
assert := assert.New(t)
toker := tokens.GetDeterministicToker()
dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
receivedID, _ := tokens.GetUserID(ctx)
receivedUsername, _ := tokens.GetUsername(ctx)
assert.EqualValues(userID, receivedID)
assert.Equal(username, receivedUsername)
})
return toker.Authenticator(dummyHandler)
}
func TestMiddlewareNoTokendt(t *testing.T) {
assert := assert.New(t)
req := httptest.NewRequest(http.MethodGet, dtMiddlewareURL, nil)
rr := httptest.NewRecorder()
middlewareHandler := verifyingHandlerdt(t, "", 0)
middlewareHandler.ServeHTTP(rr, req)
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestMiddlewareBadTokendt(t *testing.T) {
assert := assert.New(t)
req := mwRequestAuth("Bearer bad")
rr := httptest.NewRecorder()
middlewareHandler := verifyingHandlerdt(t, "", 0)
middlewareHandler.ServeHTTP(rr, req)
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestMiddlewareGoodTokendt(t *testing.T) {
assert := assert.New(t)
idToUse := 3
username := "username"
displayName := "display name"
user := &models.UserNoPassword{UserID: int64(idToUse), Username: username, DisplayName: displayName}
toker := tokens.GetDeterministicToker()
validToken := toker.EncodeUser(user)
log.Print(validToken)
req := mwRequestAuth("Bearer " + validToken)
rr := httptest.NewRecorder()
middlewareHandler := verifyingHandlerdt(t, username, idToUse)
middlewareHandler.ServeHTTP(rr, req)
status := rr.Code
assert.Equal(http.StatusOK, status)
}

View File

@@ -67,6 +67,11 @@ func GetUserID(ctx context.Context) (int, error) {
return int(userID), nil
}
// SetUserID sets the username field on a context, necessary because the key is an unexported custom type.
func SetUserID(ctx context.Context, id int) context.Context {
return context.WithValue(ctx, userIDCtxKey, int64(id))
}
// GetUsername does something similar to GetUserID.
func GetUsername(ctx context.Context) (string, error) {
username, ok := ctx.Value(usernameCtxKey).(string)

View File

@@ -0,0 +1,49 @@
package tokens_test
import (
"context"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"testing"
)
func TestGoodContext(t *testing.T) {
assert := assert.New(t)
idToUse := 3
username := "username"
ctx := tokens.GetContextForUserValues(idToUse, username)
receivedID, err := tokens.GetUserID(ctx)
assert.Nil(err)
assert.EqualValues(idToUse, receivedID)
receivedUsername, err := tokens.GetUsername(ctx)
assert.Nil(err)
assert.Equal(username, receivedUsername)
}
func TestBadContext(t *testing.T) {
assert := assert.New(t)
ctx := context.Background()
_, err := tokens.GetUserID(ctx)
assert.NotNil(err)
_, err = tokens.GetUsername(ctx)
assert.NotNil(err)
}
func TestSetContext(t *testing.T) {
assert := assert.New(t)
idToUse := 3
ctx := tokens.SetUserID(context.Background(), 3)
receivedID, err := tokens.GetUserID(ctx)
assert.Nil(err)
assert.EqualValues(idToUse, receivedID)
}

View File

@@ -0,0 +1,78 @@
package tokens_test
import (
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
var middlewareURL string = "/"
func mwRequestAuth(header string) *http.Request {
req, _ := http.NewRequest("GET", middlewareURL, nil)
req.Header.Add(authKey, header)
return req
}
func verifyingHandler(t *testing.T, username string, userID int) http.Handler {
assert := assert.New(t)
toker := tokens.New("secret")
dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
receivedID, _ := tokens.GetUserID(ctx)
receivedUsername, _ := tokens.GetUsername(ctx)
assert.EqualValues(userID, receivedID)
assert.Equal(username, receivedUsername)
})
return toker.Authenticator(dummyHandler)
}
func TestMiddlewareNoToken(t *testing.T) {
assert := assert.New(t)
req := httptest.NewRequest(http.MethodGet, middlewareURL, nil)
rr := httptest.NewRecorder()
middlewareHandler := verifyingHandler(t, "", 0)
middlewareHandler.ServeHTTP(rr, req)
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestMiddlewareBadToken(t *testing.T) {
assert := assert.New(t)
req := mwRequestAuth("Bearer bad")
rr := httptest.NewRecorder()
middlewareHandler := verifyingHandler(t, "", 0)
middlewareHandler.ServeHTTP(rr, req)
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestMiddlewareGoodToken(t *testing.T) {
assert := assert.New(t)
idToUse := 3
username := "username"
displayName := "display name"
user := &models.UserNoPassword{UserID: int64(idToUse), Username: username, DisplayName: displayName}
toker := tokens.New("secret")
validToken := toker.EncodeUser(user)
req := mwRequestAuth("Bearer " + validToken)
rr := httptest.NewRecorder()
middlewareHandler := verifyingHandler(t, username, idToUse)
middlewareHandler.ServeHTTP(rr, req)
status := rr.Code
assert.Equal(http.StatusOK, status)
}

View File

@@ -51,9 +51,10 @@ func (tok *jwtToker) DecodeTokenString(tokenString string) (*UserToken, error) {
return nil, fmt.Errorf("Error decoding token")
}
if token == nil {
return nil, fmt.Errorf("Token was nil")
}
// Should never happen, remove soon.
// if token == nil {
// return nil, fmt.Errorf("Token was nil")
// }
err = jwt.Validate(
token,

View File

@@ -3,22 +3,163 @@ package tokens_test
import (
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/go-chi/jwtauth"
"github.com/stretchr/testify/assert"
"testing"
"time"
)
func TestBasic(t *testing.T) {
assert := assert.New(t)
toker := tokens.New("secret")
idToUse := int64(3)
usernameToUse := "test"
usr := &models.UserNoPassword{
UserID: 3,
Username: "test",
UserID: idToUse,
Username: usernameToUse,
DisplayName: "Ted Est III",
}
token := toker.EncodeUser(usr)
_, err := toker.DecodeTokenString(token)
userToken, err := toker.DecodeTokenString(token)
assert.Nil(err)
assert.Equal(usernameToUse, userToken.Username)
assert.Equal(idToUse, userToken.ID)
_, err = tokens.New("bad secret").DecodeTokenString(token)
assert.NotNil(err)
}
func getTokenString(claims map[string]interface{}) string {
auth := jwtauth.New("HS256", []byte("secret"), nil)
jwtauth.SetIssuedNow(claims)
jwtauth.SetExpiryIn(claims, 2*time.Hour)
_, tokenString, _ := auth.Encode(claims)
return tokenString
}
func TestDecodeBadIssuer(t *testing.T) {
assert := assert.New(t)
toker := tokens.New("secret")
idToUse := 3
username := "test"
gog := "gogmagog.deepak.science"
claims := map[string]interface{}{
"user_id": int64(idToUse),
"username": username,
"display_name": "display_name",
"iss": gog,
"aud": "bad",
}
token := getTokenString(claims)
_, err := toker.DecodeTokenString(token)
assert.NotNil(err)
}
func TestDecodeBadAudience(t *testing.T) {
assert := assert.New(t)
toker := tokens.New("secret")
idToUse := 3
username := "test"
gog := "gogmagog.deepak.science"
claims := map[string]interface{}{
"user_id": int64(idToUse),
"username": username,
"display_name": "display_name",
"iss": "bad",
"aud": gog,
}
token := getTokenString(claims)
_, err := toker.DecodeTokenString(token)
assert.NotNil(err)
}
func TestDecodeMissingUserID(t *testing.T) {
assert := assert.New(t)
toker := tokens.New("secret")
username := "test"
gog := "gogmagog.deepak.science"
claims := map[string]interface{}{
"username": username,
"display_name": "display_name",
"iss": gog,
"aud": gog,
}
token := getTokenString(claims)
_, err := toker.DecodeTokenString(token)
assert.NotNil(err)
}
func TestDecodeBadUserID(t *testing.T) {
assert := assert.New(t)
toker := tokens.New("secret")
username := "test"
gog := "gogmagog.deepak.science"
claims := map[string]interface{}{
"username": username,
"user_id": "id",
"display_name": "display_name",
"iss": gog,
"aud": gog,
}
token := getTokenString(claims)
_, err := toker.DecodeTokenString(token)
assert.NotNil(err)
}
func TestDecodeMissingUsername(t *testing.T) {
assert := assert.New(t)
toker := tokens.New("secret")
idToUse := 3
gog := "gogmagog.deepak.science"
claims := map[string]interface{}{
"user_id": int64(idToUse),
"display_name": "display_name",
"iss": gog,
"aud": gog,
}
token := getTokenString(claims)
_, err := toker.DecodeTokenString(token)
assert.NotNil(err)
}
func TestDecodeBadUsername(t *testing.T) {
assert := assert.New(t)
toker := tokens.New("secret")
gog := "gogmagog.deepak.science"
claims := map[string]interface{}{
"username": 5,
"user_id": 3,
"display_name": "display_name",
"iss": gog,
"aud": gog,
}
token := getTokenString(claims)
_, err := toker.DecodeTokenString(token)
assert.NotNil(err)
}