diff options
Diffstat (limited to 'backend/auth/auth_test.go')
| -rw-r--r-- | backend/auth/auth_test.go | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/backend/auth/auth_test.go b/backend/auth/auth_test.go new file mode 100644 index 0000000..00d4527 --- /dev/null +++ b/backend/auth/auth_test.go @@ -0,0 +1,125 @@ +package auth + +import ( + "context" + "errors" + "testing" + + "github.com/jackc/pgx/v5" + "golang.org/x/crypto/bcrypt" + + "albatross-2026-backend/db" +) + +type mockQuerier struct { + db.Querier + getUserAuthByUsernameFunc func(ctx context.Context, username string) (db.GetUserAuthByUsernameRow, error) +} + +func (m *mockQuerier) GetUserAuthByUsername(ctx context.Context, username string) (db.GetUserAuthByUsernameRow, error) { + if m.getUserAuthByUsernameFunc != nil { + return m.getUserAuthByUsernameFunc(ctx, username) + } + return db.GetUserAuthByUsernameRow{}, pgx.ErrNoRows +} + +type mockTxManager struct{} + +func (m *mockTxManager) RunInTx(_ context.Context, fn func(q db.Querier) error) error { + return fn(&mockQuerier{}) +} + +func TestLogin_PasswordAuth_Success(t *testing.T) { + hash, err := bcrypt.GenerateFromPassword([]byte("correct-password"), bcrypt.MinCost) + if err != nil { + t.Fatalf("failed to generate hash: %v", err) + } + hashStr := string(hash) + + a := NewAuthenticator( + &mockQuerier{ + getUserAuthByUsernameFunc: func(_ context.Context, _ string) (db.GetUserAuthByUsernameRow, error) { + return db.GetUserAuthByUsernameRow{ + UserID: 42, + AuthType: "password", + PasswordHash: &hashStr, + }, nil + }, + }, + &mockTxManager{}, + ) + + userID, err := a.Login(context.Background(), "testuser", "correct-password") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if userID != 42 { + t.Errorf("expected userID 42, got %d", userID) + } +} + +func TestLogin_PasswordAuth_WrongPassword(t *testing.T) { + hash, err := bcrypt.GenerateFromPassword([]byte("correct-password"), bcrypt.MinCost) + if err != nil { + t.Fatalf("failed to generate hash: %v", err) + } + hashStr := string(hash) + + a := NewAuthenticator( + &mockQuerier{ + getUserAuthByUsernameFunc: func(_ context.Context, _ string) (db.GetUserAuthByUsernameRow, error) { + return db.GetUserAuthByUsernameRow{ + UserID: 42, + AuthType: "password", + PasswordHash: &hashStr, + }, nil + }, + }, + &mockTxManager{}, + ) + + _, err = a.Login(context.Background(), "testuser", "wrong-password") + if err == nil { + t.Fatal("expected error for wrong password, got nil") + } +} + +func TestLogin_PasswordAuth_NilHash(t *testing.T) { + a := NewAuthenticator( + &mockQuerier{ + getUserAuthByUsernameFunc: func(_ context.Context, _ string) (db.GetUserAuthByUsernameRow, error) { + return db.GetUserAuthByUsernameRow{ + UserID: 42, + AuthType: "password", + PasswordHash: nil, + }, nil + }, + }, + &mockTxManager{}, + ) + + _, err := a.Login(context.Background(), "testuser", "any") + if err == nil { + t.Fatal("expected error for nil password hash, got nil") + } + if err.Error() != "inconsistent data: password auth type but no password hash" { + t.Errorf("unexpected error message: %s", err.Error()) + } +} + +func TestLogin_DBError(t *testing.T) { + dbErr := errors.New("database connection failed") + a := NewAuthenticator( + &mockQuerier{ + getUserAuthByUsernameFunc: func(_ context.Context, _ string) (db.GetUserAuthByUsernameRow, error) { + return db.GetUserAuthByUsernameRow{}, dbErr + }, + }, + &mockTxManager{}, + ) + + _, err := a.Login(context.Background(), "testuser", "any") + if !errors.Is(err, dbErr) { + t.Errorf("expected db error, got: %v", err) + } +} |
