diff options
Diffstat (limited to 'internal/auth/handlers_test.go')
| -rw-r--r-- | internal/auth/handlers_test.go | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/internal/auth/handlers_test.go b/internal/auth/handlers_test.go new file mode 100644 index 0000000..3e154ce --- /dev/null +++ b/internal/auth/handlers_test.go @@ -0,0 +1,106 @@ +package auth + +import ( + "database/sql" + "html/template" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" + "time" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/alexedwards/scs/v2" + "golang.org/x/crypto/bcrypt" +) + +func TestHandleLogin(t *testing.T) { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + defer db.Close() + + service := NewService(db) + sessionManager := scs.New() + templates := template.Must(template.New("login.html").Parse("{{.Error}}")) + + handlers := NewHandlers(service, sessionManager, templates) + + // Setup mock user + password := "password" + hash, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + rows := sqlmock.NewRows([]string{"id", "username", "password_hash", "created_at"}). + AddRow(1, "testuser", string(hash), time.Now()) + + mock.ExpectQuery("SELECT id, username, password_hash, created_at FROM users WHERE username = ?"). + WithArgs("testuser"). + WillReturnRows(rows) + + // Create request + form := url.Values{} + form.Add("username", "testuser") + form.Add("password", "password") + req := httptest.NewRequest("POST", "/login", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + // Wrap request with session middleware + ctx, _ := sessionManager.Load(req.Context(), "") + req = req.WithContext(ctx) + + rr := httptest.NewRecorder() + + handlers.HandleLogin(rr, req) + + if status := rr.Code; status != http.StatusSeeOther { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusSeeOther) + } + + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unfulfilled expectations: %s", err) + } +} + +func TestHandleLogin_InvalidCredentials(t *testing.T) { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + defer db.Close() + + service := NewService(db) + sessionManager := scs.New() + templates := template.Must(template.New("login.html").Parse("{{.Error}}")) + + handlers := NewHandlers(service, sessionManager, templates) + + mock.ExpectQuery("SELECT id, username, password_hash, created_at FROM users WHERE username = ?"). + WithArgs("testuser"). + WillReturnError(sql.ErrNoRows) + + // Create request + form := url.Values{} + form.Add("username", "testuser") + form.Add("password", "wrongpassword") + req := httptest.NewRequest("POST", "/login", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + // Wrap request with session middleware + ctx, _ := sessionManager.Load(req.Context(), "") + req = req.WithContext(ctx) + + rr := httptest.NewRecorder() + + handlers.HandleLogin(rr, req) + + if status := rr.Code; status != http.StatusUnauthorized { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusUnauthorized) + } + + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unfulfilled expectations: %s", err) + } +} |
