implement tests

This commit is contained in:
2025-04-17 18:31:43 +02:00
parent 29f8f539c8
commit 9db46a759d
4 changed files with 290 additions and 5 deletions

View File

@@ -0,0 +1,172 @@
package api
import (
"errors"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
memgraphMock "github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/internal/memgraph/mock"
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api"
)
func TestCreateAdminRelationship(t *testing.T) {
gin.SetMode(gin.TestMode)
t.Run("Successful case", func(t *testing.T) {
mockSession := new(memgraphMock.SessionWithContext)
mockDriver := new(memgraphMock.DriverWithContext)
mockDriver.On("NewSession", mock.Anything, mock.Anything).Return(mockSession)
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
mockSession.On("ExecuteWrite", mock.Anything, mock.Anything, mock.Anything).Return(map[string]any{"result": "success"}, nil)
mockSession.On("Close", mock.Anything).Return(nil)
srv := &server{
db: mockDriver,
dbOpTimeout: 5 * time.Second,
}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodPost, "/admin", nil)
params := api.CreateAdminRelationshipParams{XUserID: *api.IntPtr(1)}
srv.CreateAdminRelationship(c, 1, 2, params)
assert.Equal(t, http.StatusOK, w.Code)
assert.Contains(t, w.Body.String(), "success")
})
t.Run("Unauthorized case", func(t *testing.T) {
mockSession := new(memgraphMock.SessionWithContext)
mockDriver := new(memgraphMock.DriverWithContext)
mockDriver.On("NewSession", mock.Anything, mock.Anything).Return(mockSession)
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("unauthorized"))
mockSession.On("Close", mock.Anything).Return(nil)
srv := &server{
db: mockDriver,
dbOpTimeout: 5 * time.Second,
}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodPost, "/admin", nil)
params := api.CreateAdminRelationshipParams{XUserID: *api.IntPtr(3)}
srv.CreateAdminRelationship(c, 1, 2, params)
assert.Equal(t, http.StatusUnauthorized, w.Code)
assert.Contains(t, w.Body.String(), "unauthorized")
})
t.Run("Internal server error case", func(t *testing.T) {
mockSession := new(memgraphMock.SessionWithContext)
mockDriver := new(memgraphMock.DriverWithContext)
mockDriver.On("NewSession", mock.Anything, mock.Anything).Return(mockSession)
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
mockSession.On("ExecuteWrite", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("db error"))
mockSession.On("Close", mock.Anything).Return(nil)
srv := &server{
db: mockDriver,
dbOpTimeout: 5 * time.Second,
}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodPost, "/admin", nil)
params := api.CreateAdminRelationshipParams{XUserID: 1}
srv.CreateAdminRelationship(c, 1, 2, params)
assert.Equal(t, http.StatusInternalServerError, w.Code)
assert.Contains(t, w.Body.String(), "db error")
})
}
func TestDeleteAdminRelationship(t *testing.T) {
gin.SetMode(gin.TestMode)
t.Run("Successful case", func(t *testing.T) {
mockSession := new(memgraphMock.SessionWithContext)
mockDriver := new(memgraphMock.DriverWithContext)
mockDriver.On("NewSession", mock.Anything, mock.Anything).Return(mockSession)
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
mockSession.On("ExecuteWrite", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
mockSession.On("Close", mock.Anything).Return(nil)
srv := &server{
db: mockDriver,
dbOpTimeout: 5 * time.Second,
}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodDelete, "/admin", nil)
params := api.DeleteAdminRelationshipParams{XUserID: 2}
srv.DeleteAdminRelationship(c, 1, 2, params)
assert.Equal(t, http.StatusOK, w.Code)
assert.Contains(t, w.Body.String(), "admin relationship was deleted")
})
t.Run("Unauthorized case", func(t *testing.T) {
mockSession := new(memgraphMock.SessionWithContext)
mockDriver := new(memgraphMock.DriverWithContext)
mockDriver.On("NewSession", mock.Anything, mock.Anything).Return(mockSession)
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("unauthorized"))
mockSession.On("Close", mock.Anything).Return(nil)
srv := &server{
db: mockDriver,
dbOpTimeout: 5 * time.Second,
}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodDelete, "/admin", nil)
params := api.DeleteAdminRelationshipParams{XUserID: 3}
srv.DeleteAdminRelationship(c, 1, 2, params)
assert.Equal(t, http.StatusUnauthorized, w.Code)
assert.Contains(t, w.Body.String(), "unauthorized")
})
t.Run("Internal server error case", func(t *testing.T) {
mockSession := new(memgraphMock.SessionWithContext)
mockDriver := new(memgraphMock.DriverWithContext)
mockDriver.On("NewSession", mock.Anything, mock.Anything).Return(mockSession)
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
mockSession.On("ExecuteWrite", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("db error"))
mockSession.On("Close", mock.Anything).Return(nil)
srv := &server{
db: mockDriver,
dbOpTimeout: 5 * time.Second,
}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodDelete, "/admin", nil)
params := api.DeleteAdminRelationshipParams{XUserID: 2}
srv.DeleteAdminRelationship(c, 1, 2, params)
assert.Equal(t, http.StatusInternalServerError, w.Code)
assert.Contains(t, w.Body.String(), "db error")
})
}

View File

@@ -22,6 +22,6 @@ func CouldManagePersonUnknownAdmin(ctx context.Context, session neo4j.SessionWit
return nil
}
_, err := session.ExecuteRead(ctx, memgraph.GetAdminRelationship(ctx, userId, XUserID), nil)
_, err := session.ExecuteRead(ctx, memgraph.GetAdminRelationship(ctx, userId, XUserID))
return err
}

View File

@@ -0,0 +1,97 @@
package auth
import (
"fmt"
"sync"
"testing"
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
memgraphMock "github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/internal/memgraph/mock"
"github.com/vcscsvcscs/GenerationsHeritage/apps/db-adapter/pkg/api"
)
func TestCouldSeePersonsProfile(t *testing.T) {
ctx := t.Context()
t.Run("User can manage person", func(t *testing.T) {
mockResult := new(memgraphMock.Result)
mockResult.On("Single", mock.Anything).Return(&neo4j.Record{}, nil)
mockSession := new(memgraphMock.SessionWithContext)
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(mockResult, nil).Once()
err := CouldSeePersonsProfile(ctx, mockSession, 1, 2)
require.NoError(t, err)
})
t.Run("User cannot manage person but is in family tree", func(t *testing.T) {
mockResult := new(memgraphMock.Result)
mockResult.On("Single", mock.Anything).Return(nil, fmt.Errorf("no permission"))
mockSession := &memgraphMock.SessionWithContext{
ReturnOnce: &sync.Once{},
}
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(mockResult, nil, map[string]any{
"people": []api.OptimizedPersonNode{
{Id: api.IntPtr(1)},
},
}, nil)
err := CouldSeePersonsProfile(ctx, mockSession, 1, 3)
require.NoError(t, err)
mockSession.AssertExpectations(t)
})
t.Run("User not in family tree", func(t *testing.T) {
mockSession := memgraphMock.SessionWithContext{
ReturnOnce: &sync.Once{},
}
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("no permission"), map[string]any{
"people": []api.OptimizedPersonNode{
{Id: api.IntPtr(4)},
},
}, nil)
err := CouldSeePersonsProfile(ctx, &mockSession, 1, 3)
require.Error(t, err)
require.EqualError(t, err, "user 3 does not have permission to see user 1")
mockSession.AssertExpectations(t)
})
t.Run("Error during ExecuteRead", func(t *testing.T) {
mockSession := &memgraphMock.SessionWithContext{
ReturnOnce: &sync.Once{},
}
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("read error"), nil, fmt.Errorf("read error"))
err := CouldSeePersonsProfile(ctx, mockSession, 1, 3)
require.Error(t, err)
require.EqualError(t, err, "read error")
mockSession.AssertExpectations(t)
})
t.Run("Invalid result format from ExecuteRead", func(t *testing.T) {
mockSession := &memgraphMock.SessionWithContext{
ReturnOnce: &sync.Once{},
}
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("invalid"), "invalid", nil).Once()
err := CouldSeePersonsProfile(ctx, mockSession, 1, 3)
require.Error(t, err)
require.EqualError(t, err, "could not convert result to map[string]any")
mockSession.AssertExpectations(t)
})
t.Run("Invalid people format in result", func(t *testing.T) {
mockSession := &memgraphMock.SessionWithContext{
ReturnOnce: &sync.Once{},
}
mockSession.On("ExecuteRead", mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("invalid"), map[string]any{
"people": "invalid",
}, nil)
err := CouldSeePersonsProfile(ctx, mockSession, 1, 3)
require.Error(t, err)
require.EqualError(t, err, "could not convert people to []api.PersonProperties")
mockSession.AssertExpectations(t)
})
}

View File

@@ -2,6 +2,7 @@ package mock
import (
"context"
"sync"
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
"github.com/stretchr/testify/mock"
@@ -9,6 +10,7 @@ import (
type SessionWithContext struct {
neo4j.SessionWithContext
ReturnOnce *sync.Once
mock.Mock
}
@@ -43,11 +45,25 @@ func (m *SessionWithContext) BeginTransaction(ctx context.Context, configurers .
func (m *SessionWithContext) ExecuteRead(ctx context.Context, work neo4j.ManagedTransactionWork, configurers ...func(*neo4j.TransactionConfig)) (any, error) {
args := m.Called(ctx, work, configurers)
if args.Get(0) != nil {
return args.Get(0), args.Error(1)
}
if len(args) > 2 && args.Get(2) != nil {
returnValue1, returnValue2 := args.Get(2), args.Error(3)
return nil, args.Error(1)
m.ReturnOnce.Do(func() {
if args.Get(0) != nil {
returnValue1, returnValue2 = args.Get(0), args.Error(1)
}
returnValue1, returnValue2 = nil, args.Error(1)
})
return returnValue1, returnValue2
} else {
if args.Get(0) != nil {
return args.Get(0), args.Error(1)
}
return nil, args.Error(1)
}
}
func (m *SessionWithContext) ExecuteWrite(ctx context.Context, work neo4j.ManagedTransactionWork, configurers ...func(*neo4j.TransactionConfig)) (any, error) {