Files
tapir/internal/adapters/store/identity_test.go
T
mathiasandClaude Sonnet 4.6 38f222c931
CI / Lint / Test / Vet (push) Successful in 11s
CI / Build & Import (push) Successful in 12s
chore: rename Go module path gitea.d-ma.be → git.d-ma.be
Infra ADR-0004 renamed the Gitea host. Bulk replace across go.mod and
all .go import paths. Build and tests pass unchanged.

Closes #20

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dt6aHEDWRjkK14Voi6HnGh
2026-07-02 14:37:33 +02:00

137 lines
3.5 KiB
Go

package store_test
import (
"context"
"errors"
"testing"
"github.com/stretchr/testify/require"
"git.d-ma.be/mathias/tapir/internal/adapters/store"
)
const (
subjectA = "dex|alice-123"
subjectB = "dex|bob-456"
)
func TestUserBySubjectUnknownReturnsNotFound(t *testing.T) {
ctx := context.Background()
s := newStore(t)
resetDB(t, rawPool(t))
id, found, err := s.UserBySubject(ctx, subjectA)
require.NoError(t, err)
require.False(t, found)
require.Empty(t, id)
}
func TestRegisterUserCreatesUserAndIdentity(t *testing.T) {
ctx := context.Background()
s := newStore(t)
p := rawPool(t)
resetDB(t, p)
id, err := s.RegisterUser(ctx, subjectA, "Alice")
require.NoError(t, err)
require.NotEmpty(t, id)
// Exactly one users row with the returned id and the given display name.
var users int
var name string
require.NoError(t, p.QueryRow(ctx,
`SELECT count(*), coalesce(max(display_name), '') FROM users WHERE id = $1`, id).
Scan(&users, &name))
require.Equal(t, 1, users)
require.Equal(t, "Alice", name)
// Exactly one identity row mapping the subject to that id.
var idents int
require.NoError(t, p.QueryRow(ctx,
`SELECT count(*) FROM user_identities WHERE dex_subject = $1 AND user_id = $2`,
subjectA, id).Scan(&idents))
require.Equal(t, 1, idents)
// And it now resolves straight through.
got, found, err := s.UserBySubject(ctx, subjectA)
require.NoError(t, err)
require.True(t, found)
require.Equal(t, id, got)
}
func TestRegisterUserRejectsDuplicateSubject(t *testing.T) {
ctx := context.Background()
s := newStore(t)
p := rawPool(t)
resetDB(t, p)
first, err := s.RegisterUser(ctx, subjectA, "Alice")
require.NoError(t, err)
_, err = s.RegisterUser(ctx, subjectA, "Alice Again")
require.Error(t, err)
require.True(t, errors.Is(err, store.ErrSubjectRegistered))
// No second user was created; the original mapping is intact.
var users, idents int
require.NoError(t, p.QueryRow(ctx, `SELECT count(*) FROM users`).Scan(&users))
require.NoError(t, p.QueryRow(ctx, `SELECT count(*) FROM user_identities`).Scan(&idents))
require.Equal(t, 1, users)
require.Equal(t, 1, idents)
got, found, err := s.UserBySubject(ctx, subjectA)
require.NoError(t, err)
require.True(t, found)
require.Equal(t, first, got)
}
func TestListAllUsersReturnsEveryIdentity(t *testing.T) {
ctx := context.Background()
s := newStore(t)
resetDB(t, rawPool(t))
empty, err := s.ListAllUsers(ctx)
require.NoError(t, err)
require.Empty(t, empty, "no registrations yet → empty slice")
const subjectC = "dex|carol-789"
idA, err := s.RegisterUser(ctx, subjectA, "Alice")
require.NoError(t, err)
idB, err := s.RegisterUser(ctx, subjectB, "Bob")
require.NoError(t, err)
idC, err := s.RegisterUser(ctx, subjectC, "Carol")
require.NoError(t, err)
users, err := s.ListAllUsers(ctx)
require.NoError(t, err)
require.Len(t, users, 3)
// Order is unspecified; compare as a set of (userID, subject) pairs.
got := make(map[string]string, len(users))
for _, u := range users {
got[u.DexSubject] = u.UserID
}
require.Equal(t, map[string]string{
subjectA: idA,
subjectB: idB,
subjectC: idC,
}, got)
}
func TestRegisterUserDistinctSubjectsGetDistinctUsers(t *testing.T) {
ctx := context.Background()
s := newStore(t)
p := rawPool(t)
resetDB(t, p)
idA, err := s.RegisterUser(ctx, subjectA, "Alice")
require.NoError(t, err)
idB, err := s.RegisterUser(ctx, subjectB, "Bob")
require.NoError(t, err)
require.NotEqual(t, idA, idB)
var users int
require.NoError(t, p.QueryRow(ctx, `SELECT count(*) FROM users`).Scan(&users))
require.Equal(t, 2, users)
}