//go:build unit package auth import ( "context" "errors" "testing" "github.com/samber/lo" "git.sr.ht/~gabrielgio/img/pkg/components/user" "git.sr.ht/~gabrielgio/img/pkg/ext" "git.sr.ht/~gabrielgio/img/pkg/testkit" ) type ( scene struct { ctx context.Context mockRepository *MockUserRepository controller Controller } mockUser struct { id uint username string password []byte } MockUserRepository struct { index uint users []*mockUser err error } ) var ( _ Repository = &MockUserRepository{} key = []byte("6368616e676520746869732070617373") ) func setUp() *scene { mockUserRepository := &MockUserRepository{} return &scene{ ctx: context.Background(), mockRepository: mockUserRepository, controller: *NewController(mockUserRepository, nil, key), } } func TestInitialRegisterAndLogin(t *testing.T) { testCases := []struct { name string username string password []byte }{ { name: "Normal register", username: "username", password: []byte("password"), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { scene := setUp() err := scene.controller.InitialRegister(scene.ctx, []byte(tc.username), tc.password, []byte("/")) testkit.TestFatalError(t, "Register", err) userID := scene.mockRepository.GetLastId() user, err := scene.mockRepository.Get(scene.ctx, userID) testkit.TestFatalError(t, "Get", err) testkit.TestValue(t, "Register", tc.username, user.Username) auth, err := scene.controller.Login(scene.ctx, []byte(tc.username), tc.password) testkit.TestFatalError(t, "Login", err) token, err := ext.ReadToken(auth, key) testkit.TestFatalError(t, "Login", err) testkit.TestValue(t, "Login", tc.username, token.Username) testkit.TestValue(t, "Login", userID, token.UserID) }) } } func toUser(m *mockUser, _ int) *user.User { return &user.User{ ID: m.id, Username: m.username, } } func (m *MockUserRepository) GetLastId() uint { return m.index } func (m *MockUserRepository) List(ctx context.Context) ([]*user.User, error) { if m.err != nil { return nil, m.err } return lo.Map(m.users, toUser), nil } func (m *MockUserRepository) Get(ctx context.Context, id uint) (*user.User, error) { if m.err != nil { return nil, m.err } for _, m := range m.users { if m.id == id { return toUser(m, 0), nil } } return nil, errors.New("Item not found") } func (m *MockUserRepository) GetIDByUsername(ctx context.Context, username string) (uint, error) { if m.err != nil { return 0, m.err } for _, m := range m.users { if m.username == username { return m.id, nil } } return 0, errors.New("Item not found") } func (m *MockUserRepository) GetPassword(ctx context.Context, id uint) ([]byte, error) { if m.err != nil { return nil, m.err } for _, m := range m.users { if m.id == id { return m.password, nil } } return nil, errors.New("Item not found") } func (m *MockUserRepository) Create(ctx context.Context, createUser *user.CreateUser) (uint, error) { if m.err != nil { return 0, m.err } m.index++ m.users = append(m.users, &mockUser{ id: m.index, username: createUser.Username, password: createUser.Password, }) return m.index, nil } func (m *MockUserRepository) Update(ctx context.Context, id uint, update *user.UpdateUser) error { if m.err != nil { return m.err } for _, m := range m.users { if m.id == id { m.username = update.Username } } return nil } func remove[T any](slice []T, s int) []T { return append(slice[:s], slice[s+1:]...) } func (r *MockUserRepository) Delete(ctx context.Context, id uint) error { if r.err != nil { return r.err } for i, m := range r.users { if m.id == id { r.users = remove(r.users, i) } } return nil }