~evanj/cms

cb201a12310a2a3e77dfeb72cb8336800f470544 — Evan M Jones 4 months ago 9d9f1d5
Feat(c/user): Adding testing for user controller.
M internal/c/space/space_test.go => internal/c/space/space_test.go +1 -0
@@ 223,6 223,7 @@ func TestAll(t *testing.T) {

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()

			var (
				ctrl = gomock.NewController(t)

A internal/c/user/mock/mock_user.go => internal/c/user/mock/mock_user.go +96 -0
@@ 0,0 1,96 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: user.go

// Package mock_user is a generated GoMock package.
package mock_user

import (
	reflect "reflect"

	space "git.sr.ht/~evanj/cms/internal/m/space"
	user "git.sr.ht/~evanj/cms/internal/m/user"
	gomock "github.com/golang/mock/gomock"
)

// Mockdber is a mock of dber interface
type Mockdber struct {
	ctrl     *gomock.Controller
	recorder *MockdberMockRecorder
}

// MockdberMockRecorder is the mock recorder for Mockdber
type MockdberMockRecorder struct {
	mock *Mockdber
}

// NewMockdber creates a new mock instance
func NewMockdber(ctrl *gomock.Controller) *Mockdber {
	mock := &Mockdber{ctrl: ctrl}
	mock.recorder = &MockdberMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use
func (m *Mockdber) EXPECT() *MockdberMockRecorder {
	return m.recorder
}

// UserNew mocks base method
func (m *Mockdber) UserNew(username, password, verifyPassword string) (user.User, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "UserNew", username, password, verifyPassword)
	ret0, _ := ret[0].(user.User)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// UserNew indicates an expected call of UserNew
func (mr *MockdberMockRecorder) UserNew(username, password, verifyPassword interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserNew", reflect.TypeOf((*Mockdber)(nil).UserNew), username, password, verifyPassword)
}

// UserGet mocks base method
func (m *Mockdber) UserGet(username, password string) (user.User, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "UserGet", username, password)
	ret0, _ := ret[0].(user.User)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// UserGet indicates an expected call of UserGet
func (mr *MockdberMockRecorder) UserGet(username, password interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserGet", reflect.TypeOf((*Mockdber)(nil).UserGet), username, password)
}

// UserGetFromToken mocks base method
func (m *Mockdber) UserGetFromToken(token string) (user.User, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "UserGetFromToken", token)
	ret0, _ := ret[0].(user.User)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// UserGetFromToken indicates an expected call of UserGetFromToken
func (mr *MockdberMockRecorder) UserGetFromToken(token interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserGetFromToken", reflect.TypeOf((*Mockdber)(nil).UserGetFromToken), token)
}

// SpacesPerUser mocks base method
func (m *Mockdber) SpacesPerUser(user user.User, before int) (space.SpaceList, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "SpacesPerUser", user, before)
	ret0, _ := ret[0].(space.SpaceList)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// SpacesPerUser indicates an expected call of SpacesPerUser
func (mr *MockdberMockRecorder) SpacesPerUser(user, before interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpacesPerUser", reflect.TypeOf((*Mockdber)(nil).SpacesPerUser), user, before)
}

M internal/c/user/user.go => internal/c/user/user.go +9 -6
@@ 1,6 1,7 @@
package user

import (
	"errors"
	"log"
	"net/http"
	"strconv"


@@ 12,7 13,9 @@ import (
)

var (
	indexHTML = tmpl.MustParse("html/index.html")
	indexHTML   = tmpl.MustParse("html/index.html")
	ErrNoUser   = errors.New("incorrect user credentials")
	ErrNoSignup = errors.New("signups are forbidden at this time")
)

type User struct {


@@ 40,7 43,7 @@ func New(log *log.Logger, db dber, signupEnabled bool) *User {

func (l *User) logout(w http.ResponseWriter, r *http.Request) {
	l.SetCookieUser(w, r, nil)
	http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
	l.Redirect(w, r, "/")
}

func (l *User) login(w http.ResponseWriter, r *http.Request) {


@@ 49,17 52,17 @@ func (l *User) login(w http.ResponseWriter, r *http.Request) {

	user, err := l.db.UserGet(username, password)
	if err != nil {
		l.Error(w, r, http.StatusBadRequest, "incorrect user credentials")
		l.Error2(w, r, http.StatusBadRequest, ErrNoUser)
		return
	}

	l.SetCookieUser(w, r, user)
	http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
	l.Redirect(w, r, "/")
}

func (l *User) signup(w http.ResponseWriter, r *http.Request) {
	if !l.signupEnabled {
		l.Error(w, r, http.StatusForbidden, "signups are forbidden at this time")
		l.Error2(w, r, http.StatusForbidden, ErrNoSignup)
		return
	}



@@ 75,7 78,7 @@ func (l *User) signup(w http.ResponseWriter, r *http.Request) {
	}

	l.SetCookieUser(w, r, user)
	http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
	l.Redirect(w, r, "/")
}

func (l *User) home(w http.ResponseWriter, r *http.Request) {

M internal/c/user/user_test.go => internal/c/user/user_test.go +184 -0
@@ 1,1 1,185 @@
package user_test

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"

	"git.sr.ht/~evanj/cms/internal/c/user"
	mock_user "git.sr.ht/~evanj/cms/internal/c/user/mock"
	spaceType "git.sr.ht/~evanj/cms/internal/m/space"
	"github.com/bmizerany/assert"
	"github.com/golang/mock/gomock"
	"github.com/google/uuid"
)

type FakeUser struct{ u, p string }

func (u FakeUser) ID() string    { return fmt.Sprintf("id-%s-%s", u.u, u.p) }
func (u FakeUser) Name() string  { return u.u }
func (u FakeUser) Token() string { return fmt.Sprintf("token-%s-%s", u.u, u.p) }

type FakeSpaceList struct{}

func (_ FakeSpaceList) List() (r []spaceType.Space) { return }
func (_ FakeSpaceList) More() (r bool)              { return }
func (_ FakeSpaceList) Before() (r int)             { return }

func TestCreate(t *testing.T) {
	t.Parallel()

	var (
		ctrl = gomock.NewController(t)
		db   = mock_user.NewMockdber(ctrl)
		l    *log.Logger
		s    = user.New(l, db, true)
		ts   = httptest.NewServer(s)

		uname = uuid.New().String()
		upass = uuid.New().String()
		u     = FakeUser{uname, upass}

		form = url.Values{
			"username": {uname},
			"password": {upass},
			"verify":   {upass},
		}
	)

	db.EXPECT().UserNew(uname, upass, upass).Return(u, nil).AnyTimes()

	res, _ := http.PostForm(ts.URL+"/user/signup", form)
	assert.Equal(t, res.StatusCode, http.StatusOK)
}

func TestLogin(t *testing.T) {
	t.Parallel()

	var (
		ctrl = gomock.NewController(t)
		db   = mock_user.NewMockdber(ctrl)
		l    *log.Logger
		s    = user.New(l, db, true)
		ts   = httptest.NewServer(s)

		uname = uuid.New().String()
		upass = uuid.New().String()
		u     = FakeUser{uname, upass}

		form = url.Values{
			"username": {uname},
			"password": {upass},
		}
	)

	db.EXPECT().UserGet(uname, upass).Return(u, nil).AnyTimes()

	res, _ := http.PostForm(ts.URL+"/user/login", form)
	assert.Equal(t, res.StatusCode, http.StatusOK)
}

func TestLogout(t *testing.T) {
	t.Parallel()

	var (
		ctrl = gomock.NewController(t)
		db   = mock_user.NewMockdber(ctrl)
		l    *log.Logger
		s    = user.New(l, db, true)
		ts   = httptest.NewServer(s)
	)

	res, _ := http.PostForm(ts.URL+"/user/logout", url.Values{})
	assert.Equal(t, res.StatusCode, http.StatusOK)
}

func TestHome(t *testing.T) {
	t.Parallel()

	var (
		ctrl = gomock.NewController(t)
		db   = mock_user.NewMockdber(ctrl)
		l    *log.Logger
		s    = user.New(l, db, true)
		ts   = httptest.NewServer(s)

		uname = uuid.New().String()
		upass = uuid.New().String()
		u     = FakeUser{uname, upass}

		form = url.Values{
			"username": {uname},
			"password": {upass},
			"verify":   {upass},
		}

		sl = FakeSpaceList{}
	)

	db.EXPECT().UserNew(uname, upass, upass).Return(u, nil).AnyTimes()
	db.EXPECT().UserGet(uname, upass).Return(u, nil).AnyTimes()
	db.EXPECT().SpacesPerUser(u, 0).Return(sl, nil).AnyTimes()

	res, _ := http.PostForm(ts.URL+"/user/signup", form)
	assert.Equal(t, res.StatusCode, http.StatusOK)

	req, _ := http.NewRequest("POST", ts.URL, nil)
	req.SetBasicAuth(uname, upass)
	req.Header.Set("Accept", "text/html")
	res, _ = http.DefaultClient.Do(req)
	assert.Equal(t, res.StatusCode, http.StatusOK)
}

func TestBadLogin(t *testing.T) {
	t.Parallel()

	var (
		ctrl = gomock.NewController(t)
		db   = mock_user.NewMockdber(ctrl)
		l    *log.Logger
		s    = user.New(l, db, true)
		ts   = httptest.NewServer(s)

		uname = uuid.New().String()
		upass = uuid.New().String()

		form = url.Values{
			"username": {uname},
			"password": {upass},
		}
	)

	db.EXPECT().UserGet(uname, upass).Return(nil, user.ErrNoUser).AnyTimes()

	res, _ := http.PostForm(ts.URL+"/user/login", form)
	assert.Equal(t, res.StatusCode, http.StatusBadRequest)
}

func TestNoSignups(t *testing.T) {
	t.Parallel()

	var (
		ctrl = gomock.NewController(t)
		db   = mock_user.NewMockdber(ctrl)
		l    *log.Logger
		s    = user.New(l, db, false)
		ts   = httptest.NewServer(s)

		uname = uuid.New().String()
		upass = uuid.New().String()

		form = url.Values{
			"username": {uname},
			"password": {upass},
			"verify":   {upass},
		}
	)

	db.EXPECT().UserNew(uname, upass, upass).Return(nil, user.ErrNoSignup).AnyTimes()

	res, _ := http.PostForm(ts.URL+"/user/signup", form)
	assert.Equal(t, res.StatusCode, http.StatusForbidden)
}