hub/internal/org/manager_test.go

518 lines
13 KiB
Go

package org
import (
"context"
"errors"
"fmt"
"testing"
"github.com/artifacthub/hub/internal/email"
"github.com/artifacthub/hub/internal/hub"
"github.com/artifacthub/hub/internal/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestAdd(t *testing.T) {
dbQuery := `select add_organization($1::uuid, $2::jsonb)`
ctx := context.WithValue(context.Background(), hub.UserIDKey, "userID")
t.Run("user id not found in ctx", func(t *testing.T) {
m := NewManager(nil, nil)
assert.Panics(t, func() {
_ = m.Add(context.Background(), &hub.Organization{})
})
})
t.Run("invalid input", func(t *testing.T) {
testCases := []struct {
errMsg string
org *hub.Organization
}{
{
"name not provided",
&hub.Organization{
Name: "",
},
},
{
"invalid name",
&hub.Organization{
Name: "_org1",
},
},
{
"invalid name",
&hub.Organization{
Name: "UPPERCASE",
},
},
{
"invalid logo image id",
&hub.Organization{
Name: "org1",
LogoImageID: "invalid",
},
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.errMsg, func(t *testing.T) {
m := NewManager(nil, nil)
err := m.Add(ctx, tc.org)
assert.True(t, errors.Is(err, ErrInvalidInput))
assert.Contains(t, err.Error(), tc.errMsg)
})
}
})
t.Run("database query succeeded", func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQuery, "userID", mock.Anything).Return(nil)
m := NewManager(db, nil)
err := m.Add(ctx, &hub.Organization{Name: "org1"})
assert.NoError(t, err)
db.AssertExpectations(t)
})
t.Run("database error", func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQuery, "userID", mock.Anything).Return(tests.ErrFakeDatabaseFailure)
m := NewManager(db, nil)
err := m.Add(ctx, &hub.Organization{Name: "org1"})
assert.Equal(t, tests.ErrFakeDatabaseFailure, err)
db.AssertExpectations(t)
})
}
func TestAddMember(t *testing.T) {
dbQueryAddMember := `select add_organization_member($1::uuid, $2::text, $3::text)`
dbQueryGetUserEmail := `select email from "user" where alias = $1`
ctx := context.WithValue(context.Background(), hub.UserIDKey, "userID")
t.Run("user id not found in ctx", func(t *testing.T) {
m := NewManager(nil, nil)
assert.Panics(t, func() {
_ = m.AddMember(context.Background(), "orgName", "userAlias", "")
})
})
t.Run("invalid input", func(t *testing.T) {
testCases := []struct {
errMsg string
orgName string
userAlias string
baseURL string
}{
{
"organization name not provided",
"",
"user1",
"https://baseurl.com",
},
{
"user alias not provided",
"org1",
"",
"https://baseurl.com",
},
{
"base url not provided",
"org1",
"user1",
"",
},
{
"invalid base url",
"org1",
"user1",
"/invalid",
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.errMsg, func(t *testing.T) {
m := NewManager(nil, nil)
err := m.AddMember(ctx, tc.orgName, tc.userAlias, tc.baseURL)
assert.True(t, errors.Is(err, ErrInvalidInput))
assert.Contains(t, err.Error(), tc.errMsg)
})
}
})
t.Run("database query succeeded", func(t *testing.T) {
testCases := []struct {
description string
emailSenderResponse error
}{
{
"organization invitation email sent successfully",
nil,
},
{
"error sending organization invitation email",
email.ErrFakeSenderFailure,
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.description, func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQueryAddMember, "userID", "orgName", "userAlias").Return(nil)
db.On("QueryRow", dbQueryGetUserEmail, mock.Anything).Return("email", nil)
es := &email.SenderMock{}
es.On("SendEmail", mock.Anything).Return(tc.emailSenderResponse)
m := NewManager(db, es)
err := m.AddMember(ctx, "orgName", "userAlias", "http://baseurl.com")
assert.Equal(t, tc.emailSenderResponse, err)
db.AssertExpectations(t)
es.AssertExpectations(t)
})
}
})
t.Run("database error", func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQueryAddMember, "userID", "orgName", "userAlias").
Return(tests.ErrFakeDatabaseFailure)
m := NewManager(db, nil)
err := m.AddMember(ctx, "orgName", "userAlias", "http://baseurl.com")
assert.Equal(t, tests.ErrFakeDatabaseFailure, err)
db.AssertExpectations(t)
})
}
func TestCheckAvailability(t *testing.T) {
t.Run("invalid input", func(t *testing.T) {
testCases := []struct {
errMsg string
resourceKind string
value string
}{
{
"invalid resource kind",
"invalid",
"value",
},
{
"invalid value",
"organizationName",
"",
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.errMsg, func(t *testing.T) {
m := NewManager(nil, nil)
_, err := m.CheckAvailability(context.Background(), tc.resourceKind, tc.value)
assert.True(t, errors.Is(err, ErrInvalidInput))
assert.Contains(t, err.Error(), tc.errMsg)
})
}
})
t.Run("database query succeeded", func(t *testing.T) {
testCases := []struct {
resourceKind string
dbQuery string
available bool
}{
{
"organizationName",
`select organization_id from organization where name = $1`,
true,
},
}
for _, tc := range testCases {
tc := tc
t.Run(fmt.Sprintf("resource kind: %s", tc.resourceKind), func(t *testing.T) {
tc.dbQuery = fmt.Sprintf("select not exists (%s)", tc.dbQuery)
db := &tests.DBMock{}
db.On("QueryRow", tc.dbQuery, "value").Return(tc.available, nil)
m := NewManager(db, nil)
available, err := m.CheckAvailability(context.Background(), tc.resourceKind, "value")
assert.NoError(t, err)
assert.Equal(t, tc.available, available)
db.AssertExpectations(t)
})
}
})
t.Run("database error", func(t *testing.T) {
db := &tests.DBMock{}
dbQuery := `select not exists (select organization_id from organization where name = $1)`
db.On("QueryRow", dbQuery, "value").Return(false, tests.ErrFakeDatabaseFailure)
m := NewManager(db, nil)
available, err := m.CheckAvailability(context.Background(), "organizationName", "value")
assert.Equal(t, tests.ErrFakeDatabaseFailure, err)
assert.False(t, available)
db.AssertExpectations(t)
})
}
func TestConfirmMembership(t *testing.T) {
dbQuery := `select confirm_organization_membership($1::uuid, $2::text)`
ctx := context.WithValue(context.Background(), hub.UserIDKey, "userID")
t.Run("user id not found in ctx", func(t *testing.T) {
m := NewManager(nil, nil)
assert.Panics(t, func() {
_ = m.ConfirmMembership(context.Background(), "orgName")
})
})
t.Run("invalid input", func(t *testing.T) {
m := NewManager(nil, nil)
err := m.ConfirmMembership(ctx, "")
assert.True(t, errors.Is(err, ErrInvalidInput))
})
t.Run("database query succeeded", func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQuery, "userID", "orgName").Return(nil)
m := NewManager(db, nil)
err := m.ConfirmMembership(ctx, "orgName")
assert.NoError(t, err)
db.AssertExpectations(t)
})
t.Run("database error", func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQuery, "userID", "orgName").Return(tests.ErrFakeDatabaseFailure)
m := NewManager(db, nil)
err := m.ConfirmMembership(ctx, "orgName")
assert.Equal(t, tests.ErrFakeDatabaseFailure, err)
db.AssertExpectations(t)
})
}
func TestDeleteMember(t *testing.T) {
dbQuery := `select delete_organization_member($1::uuid, $2::text, $3::text)`
ctx := context.WithValue(context.Background(), hub.UserIDKey, "userID")
t.Run("user id not found in ctx", func(t *testing.T) {
m := NewManager(nil, nil)
assert.Panics(t, func() {
_ = m.DeleteMember(context.Background(), "orgName", "userAlias")
})
})
t.Run("invalid input", func(t *testing.T) {
testCases := []struct {
errMsg string
orgName string
userAlias string
}{
{
"organization name not provided",
"",
"user1",
},
{
"user alias not provided",
"org1",
"",
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.errMsg, func(t *testing.T) {
m := NewManager(nil, nil)
err := m.DeleteMember(ctx, tc.orgName, tc.userAlias)
assert.True(t, errors.Is(err, ErrInvalidInput))
assert.Contains(t, err.Error(), tc.errMsg)
})
}
})
t.Run("database query succeeded", func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQuery, "userID", "orgName", "userAlias").Return(nil)
m := NewManager(db, nil)
err := m.DeleteMember(ctx, "orgName", "userAlias")
assert.NoError(t, err)
db.AssertExpectations(t)
})
t.Run("database error", func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQuery, "userID", "orgName", "userAlias").Return(tests.ErrFakeDatabaseFailure)
m := NewManager(db, nil)
err := m.DeleteMember(ctx, "orgName", "userAlias")
assert.Equal(t, tests.ErrFakeDatabaseFailure, err)
db.AssertExpectations(t)
})
}
func TestGetByUserJSON(t *testing.T) {
dbQuery := `select get_user_organizations($1::uuid)`
ctx := context.WithValue(context.Background(), hub.UserIDKey, "userID")
t.Run("user id not found in ctx", func(t *testing.T) {
m := NewManager(nil, nil)
assert.Panics(t, func() {
_, _ = m.GetByUserJSON(context.Background())
})
})
t.Run("database query succeeded", func(t *testing.T) {
db := &tests.DBMock{}
db.On("QueryRow", dbQuery, "userID").Return([]byte("dataJSON"), nil)
m := NewManager(db, nil)
dataJSON, err := m.GetByUserJSON(ctx)
assert.NoError(t, err)
assert.Equal(t, []byte("dataJSON"), dataJSON)
db.AssertExpectations(t)
})
t.Run("database error", func(t *testing.T) {
db := &tests.DBMock{}
db.On("QueryRow", dbQuery, "userID").Return(nil, tests.ErrFakeDatabaseFailure)
m := NewManager(db, nil)
dataJSON, err := m.GetByUserJSON(ctx)
assert.Equal(t, tests.ErrFakeDatabaseFailure, err)
assert.Nil(t, dataJSON)
db.AssertExpectations(t)
})
}
func TestGetJSON(t *testing.T) {
dbQuery := `select get_organization($1::text)`
t.Run("invalid input", func(t *testing.T) {
m := NewManager(nil, nil)
_, err := m.GetJSON(context.Background(), "")
assert.True(t, errors.Is(err, ErrInvalidInput))
})
t.Run("database query succeeded", func(t *testing.T) {
db := &tests.DBMock{}
db.On("QueryRow", dbQuery, "orgName").Return([]byte("dataJSON"), nil)
m := NewManager(db, nil)
dataJSON, err := m.GetJSON(context.Background(), "orgName")
assert.NoError(t, err)
assert.Equal(t, []byte("dataJSON"), dataJSON)
db.AssertExpectations(t)
})
t.Run("database error", func(t *testing.T) {
db := &tests.DBMock{}
db.On("QueryRow", dbQuery, "orgName").Return(nil, tests.ErrFakeDatabaseFailure)
m := NewManager(db, nil)
dataJSON, err := m.GetJSON(context.Background(), "orgName")
assert.Equal(t, tests.ErrFakeDatabaseFailure, err)
assert.Nil(t, dataJSON)
db.AssertExpectations(t)
})
}
func TestGetMembersJSON(t *testing.T) {
dbQuery := `select get_organization_members($1::uuid, $2::text)`
ctx := context.WithValue(context.Background(), hub.UserIDKey, "userID")
t.Run("user id not found in ctx", func(t *testing.T) {
m := NewManager(nil, nil)
assert.Panics(t, func() {
_, _ = m.GetMembersJSON(context.Background(), "orgName")
})
})
t.Run("invalid input", func(t *testing.T) {
m := NewManager(nil, nil)
_, err := m.GetMembersJSON(ctx, "")
assert.True(t, errors.Is(err, ErrInvalidInput))
})
t.Run("database query succeeded", func(t *testing.T) {
db := &tests.DBMock{}
db.On("QueryRow", dbQuery, "userID", "orgName").Return([]byte("dataJSON"), nil)
m := NewManager(db, nil)
dataJSON, err := m.GetMembersJSON(ctx, "orgName")
assert.NoError(t, err)
assert.Equal(t, []byte("dataJSON"), dataJSON)
db.AssertExpectations(t)
})
t.Run("database error", func(t *testing.T) {
db := &tests.DBMock{}
db.On("QueryRow", dbQuery, "userID", "orgName").Return(nil, tests.ErrFakeDatabaseFailure)
m := NewManager(db, nil)
dataJSON, err := m.GetMembersJSON(ctx, "orgName")
assert.Equal(t, tests.ErrFakeDatabaseFailure, err)
assert.Nil(t, dataJSON)
db.AssertExpectations(t)
})
}
func TestUpdate(t *testing.T) {
dbQuery := `select update_organization($1::uuid, $2::jsonb)`
ctx := context.WithValue(context.Background(), hub.UserIDKey, "userID")
t.Run("user id not found in ctx", func(t *testing.T) {
m := NewManager(nil, nil)
assert.Panics(t, func() {
_ = m.Update(context.Background(), &hub.Organization{})
})
})
t.Run("invalid input", func(t *testing.T) {
testCases := []struct {
errMsg string
org *hub.Organization
}{
{
"invalid logo image id",
&hub.Organization{
Name: "org1",
LogoImageID: "invalid",
},
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.errMsg, func(t *testing.T) {
m := NewManager(nil, nil)
err := m.Update(ctx, tc.org)
assert.True(t, errors.Is(err, ErrInvalidInput))
assert.Contains(t, err.Error(), tc.errMsg)
})
}
})
t.Run("database query succeeded", func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQuery, "userID", mock.Anything).Return(nil)
m := NewManager(db, nil)
err := m.Update(ctx, &hub.Organization{})
assert.NoError(t, err)
db.AssertExpectations(t)
})
t.Run("database error", func(t *testing.T) {
db := &tests.DBMock{}
db.On("Exec", dbQuery, "userID", mock.Anything).Return(tests.ErrFakeDatabaseFailure)
m := NewManager(db, nil)
err := m.Update(ctx, &hub.Organization{})
assert.Equal(t, tests.ErrFakeDatabaseFailure, err)
db.AssertExpectations(t)
})
}