forked from baron/baron-sso
테넌트 목록 조회 cursor기반으로 재구성. 사용자 metadata 미사용 필드 제거
This commit is contained in:
@@ -130,10 +130,10 @@ func (m *MockUserRepoForHandler) ListByTenant(ctx context.Context, tenantID stri
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockUserRepoForHandler) List(ctx context.Context, offset, limit int, search string, companyCode string) ([]domain.User, int64, error) {
|
||||
func (m *MockUserRepoForHandler) List(ctx context.Context, offset, limit int, search string, tenantSlug string) ([]domain.User, int64, error) {
|
||||
for _, call := range m.ExpectedCalls {
|
||||
if call.Method == "List" {
|
||||
args := m.Called(ctx, offset, limit, search, companyCode)
|
||||
args := m.Called(ctx, offset, limit, search, tenantSlug)
|
||||
return args.Get(0).([]domain.User), args.Get(1).(int64), args.Error(2)
|
||||
}
|
||||
}
|
||||
@@ -368,6 +368,205 @@ func TestTenantHandler_ListTenants(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTenantHandler_ListTenantsReturnsNextCursorWhenMoreRowsExist(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
mockProjection := new(MockUserProjectionRepoForHandler)
|
||||
|
||||
h := &TenantHandler{
|
||||
Service: mockSvc,
|
||||
UserProjectionRepo: mockProjection,
|
||||
}
|
||||
|
||||
app.Use(func(c *fiber.Ctx) error {
|
||||
c.Locals("user_profile", &domain.UserProfileResponse{
|
||||
Role: "super_admin",
|
||||
})
|
||||
return c.Next()
|
||||
})
|
||||
app.Get("/tenants", h.ListTenants)
|
||||
|
||||
createdAt := time.Date(2026, 5, 13, 8, 0, 0, 0, time.UTC)
|
||||
tenants := []domain.Tenant{
|
||||
{ID: "00000000-0000-0000-0000-000000000002", Name: "Tenant B", Slug: "slug-b", CreatedAt: createdAt},
|
||||
{ID: "00000000-0000-0000-0000-000000000001", Name: "Tenant A", Slug: "slug-a", CreatedAt: createdAt.Add(-time.Minute)},
|
||||
}
|
||||
|
||||
mockSvc.On("ListTenants", mock.Anything, 2, 0, "").Return(tenants, int64(3), nil).Once()
|
||||
mockProjection.On("IsReady", mock.Anything).Return(true, nil).Once()
|
||||
mockProjection.On("CountTenantMembers", mock.Anything, tenants).Return(map[string]int64{}, nil).Once()
|
||||
|
||||
req := httptest.NewRequest("GET", "/tenants?limit=2&offset=0", nil)
|
||||
resp, _ := app.Test(req)
|
||||
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var res tenantListResponse
|
||||
require.NoError(t, json.NewDecoder(resp.Body).Decode(&res))
|
||||
require.Len(t, res.Items, 2)
|
||||
require.NotEmpty(t, res.NextCursor)
|
||||
}
|
||||
|
||||
func TestPageTenantsByCursorUsesStableCreatedAtAndIDOrder(t *testing.T) {
|
||||
createdAt := time.Date(2026, 5, 13, 8, 0, 0, 0, time.UTC)
|
||||
tenants := []domain.Tenant{
|
||||
{ID: "00000000-0000-0000-0000-000000000001", Name: "Tenant A", Slug: "slug-a", CreatedAt: createdAt},
|
||||
{ID: "00000000-0000-0000-0000-000000000003", Name: "Tenant C", Slug: "slug-c", CreatedAt: createdAt},
|
||||
{ID: "00000000-0000-0000-0000-000000000002", Name: "Tenant B", Slug: "slug-b", CreatedAt: createdAt},
|
||||
}
|
||||
|
||||
page, nextCursor, err := pageTenantsByCursor(tenants, 2, "")
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, nextCursor)
|
||||
require.Equal(t, []string{
|
||||
"00000000-0000-0000-0000-000000000003",
|
||||
"00000000-0000-0000-0000-000000000002",
|
||||
}, []string{page[0].ID, page[1].ID})
|
||||
|
||||
nextPage, _, err := pageTenantsByCursor(tenants, 2, nextCursor)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []string{"00000000-0000-0000-0000-000000000001"}, []string{nextPage[0].ID})
|
||||
}
|
||||
|
||||
func TestTenantHandler_ListTenantsHidesPrivateSubtreeForUnauthorizedUser(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
mockProjection := new(MockUserProjectionRepoForHandler)
|
||||
|
||||
h := &TenantHandler{
|
||||
Service: mockSvc,
|
||||
UserProjectionRepo: mockProjection,
|
||||
}
|
||||
|
||||
parent := func(id string) *string { return &id }
|
||||
tenants := []domain.Tenant{
|
||||
{ID: "family", Type: domain.TenantTypeCompanyGroup, Name: "한맥가족", Slug: "hanmac-family"},
|
||||
{ID: "company", Type: domain.TenantTypeCompany, ParentID: parent("family"), Name: "한맥", Slug: "hanmac"},
|
||||
{ID: "public-team", Type: domain.TenantTypeUserGroup, ParentID: parent("company"), Name: "공개팀", Slug: "public-team"},
|
||||
{ID: "private-team", Type: domain.TenantTypeUserGroup, ParentID: parent("company"), Name: "비공개팀", Slug: "private-team", Config: domain.JSONMap{"visibility": "private"}},
|
||||
{ID: "private-child", Type: domain.TenantTypeUserGroup, ParentID: parent("private-team"), Name: "비공개하위", Slug: "private-child"},
|
||||
}
|
||||
|
||||
app.Use(func(c *fiber.Ctx) error {
|
||||
c.Locals("user_profile", &domain.UserProfileResponse{
|
||||
ID: "user-1",
|
||||
Role: domain.RoleTenantAdmin,
|
||||
TenantID: parent("company"),
|
||||
})
|
||||
return c.Next()
|
||||
})
|
||||
app.Get("/tenants", h.ListTenants)
|
||||
|
||||
mockSvc.On("ListTenants", mock.Anything, 10000, 0, "").Return(tenants, int64(len(tenants)), nil).Once()
|
||||
mockProjection.On("IsReady", mock.Anything).Return(true, nil).Once()
|
||||
mockProjection.On("CountTenantMembers", mock.Anything, mock.MatchedBy(func(got []domain.Tenant) bool {
|
||||
return tenantSlugsMatch(got, "hanmac-family", "hanmac", "public-team")
|
||||
})).Return(map[string]int64{}, nil).Once()
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/tenants?limit=100&offset=0", nil)
|
||||
resp, err := app.Test(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var res tenantListResponse
|
||||
require.NoError(t, json.NewDecoder(resp.Body).Decode(&res))
|
||||
require.Equal(t, int64(3), res.Total)
|
||||
require.NotContains(t, toJSONString(t, res), "private-team")
|
||||
require.NotContains(t, toJSONString(t, res), "private-child")
|
||||
}
|
||||
|
||||
func TestTenantHandler_ListTenantsShowsPrivateSubtreeForManageableTenant(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
mockProjection := new(MockUserProjectionRepoForHandler)
|
||||
|
||||
h := &TenantHandler{
|
||||
Service: mockSvc,
|
||||
UserProjectionRepo: mockProjection,
|
||||
}
|
||||
|
||||
parent := func(id string) *string { return &id }
|
||||
tenants := []domain.Tenant{
|
||||
{ID: "family", Type: domain.TenantTypeCompanyGroup, Name: "한맥가족", Slug: "hanmac-family"},
|
||||
{ID: "company", Type: domain.TenantTypeCompany, ParentID: parent("family"), Name: "한맥", Slug: "hanmac"},
|
||||
{ID: "private-team", Type: domain.TenantTypeUserGroup, ParentID: parent("company"), Name: "비공개팀", Slug: "private-team", Config: domain.JSONMap{"visibility": "private"}},
|
||||
{ID: "private-child", Type: domain.TenantTypeUserGroup, ParentID: parent("private-team"), Name: "비공개하위", Slug: "private-child"},
|
||||
}
|
||||
|
||||
app.Use(func(c *fiber.Ctx) error {
|
||||
c.Locals("user_profile", &domain.UserProfileResponse{
|
||||
ID: "user-1",
|
||||
Role: domain.RoleTenantAdmin,
|
||||
TenantID: parent("company"),
|
||||
ManageableTenants: []domain.Tenant{
|
||||
{ID: "private-team", Slug: "private-team"},
|
||||
},
|
||||
})
|
||||
return c.Next()
|
||||
})
|
||||
app.Get("/tenants", h.ListTenants)
|
||||
|
||||
mockSvc.On("ListTenants", mock.Anything, 10000, 0, "").Return(tenants, int64(len(tenants)), nil).Once()
|
||||
mockProjection.On("IsReady", mock.Anything).Return(true, nil).Once()
|
||||
mockProjection.On("CountTenantMembers", mock.Anything, mock.MatchedBy(func(got []domain.Tenant) bool {
|
||||
return tenantSlugsMatch(got, "hanmac-family", "hanmac", "private-team", "private-child")
|
||||
})).Return(map[string]int64{}, nil).Once()
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/tenants?limit=100&offset=0", nil)
|
||||
resp, err := app.Test(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var res tenantListResponse
|
||||
require.NoError(t, json.NewDecoder(resp.Body).Decode(&res))
|
||||
require.Equal(t, int64(4), res.Total)
|
||||
require.Contains(t, toJSONString(t, res), "private-team")
|
||||
require.Contains(t, toJSONString(t, res), "private-child")
|
||||
}
|
||||
|
||||
func TestTenantHandler_FilterPrivateTenantsAllowsExplicitPrivatePermission(t *testing.T) {
|
||||
parent := func(id string) *string { return &id }
|
||||
tenants := []domain.Tenant{
|
||||
{ID: "family", Type: domain.TenantTypeCompanyGroup, Name: "한맥가족", Slug: "hanmac-family"},
|
||||
{ID: "company", Type: domain.TenantTypeCompany, ParentID: parent("family"), Name: "한맥", Slug: "hanmac"},
|
||||
{ID: "private-team", Type: domain.TenantTypeUserGroup, ParentID: parent("company"), Name: "비공개팀", Slug: "private-team", Config: domain.JSONMap{"visibility": "private"}},
|
||||
{ID: "private-child", Type: domain.TenantTypeUserGroup, ParentID: parent("private-team"), Name: "비공개하위", Slug: "private-child"},
|
||||
}
|
||||
mockKeto := new(devMockKetoService)
|
||||
h := &TenantHandler{Keto: mockKeto}
|
||||
|
||||
mockKeto.On("CheckPermission", mock.Anything, "User:user-1", "Tenant", "private-team", "view_private").Return(true, nil).Once()
|
||||
|
||||
filtered, err := h.filterPrivateTenantsForProfile(context.Background(), tenants, &domain.UserProfileResponse{
|
||||
ID: "user-1",
|
||||
Role: domain.RoleTenantAdmin,
|
||||
TenantID: parent("company"),
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.True(t, tenantSlugsMatch(filtered, "hanmac-family", "hanmac", "private-team", "private-child"))
|
||||
mockKeto.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func tenantSlugsMatch(got []domain.Tenant, want ...string) bool {
|
||||
if len(got) != len(want) {
|
||||
return false
|
||||
}
|
||||
counts := make(map[string]int, len(want))
|
||||
for _, slug := range want {
|
||||
counts[slug]++
|
||||
}
|
||||
for _, tenant := range got {
|
||||
counts[tenant.Slug]--
|
||||
if counts[tenant.Slug] < 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func TestTenantHandler_GetOrgContextJSONDefaultsToHanmacFamilyForApiKey(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
@@ -391,15 +590,60 @@ func TestTenantHandler_GetOrgContextJSONDefaultsToHanmacFamilyForApiKey(t *testi
|
||||
{ID: "private-team", Type: domain.TenantTypeUserGroup, ParentID: parent("company-hanmac"), Name: "비공개", Slug: "private-team", Status: domain.TenantStatusActive, Config: domain.JSONMap{"visibility": "private"}, CreatedAt: now, UpdatedAt: now},
|
||||
}
|
||||
usersByTenantID := []domain.User{
|
||||
{ID: "user-platform-lead", Email: "lead@example.com", Name: "플랫폼 리드", Status: domain.UserStatusActive, TenantID: parent("dept-platform"), CompanyCode: "platform", Grade: "책임", Position: "실장", CreatedAt: now, UpdatedAt: now},
|
||||
{
|
||||
ID: "user-platform-lead",
|
||||
Email: "lead@example.com",
|
||||
Name: "플랫폼 리드",
|
||||
Phone: "010-1111-2222",
|
||||
Status: domain.UserStatusActive,
|
||||
TenantID: parent("dept-platform"),
|
||||
CompanyCode: "platform",
|
||||
Grade: "책임",
|
||||
Position: "실장",
|
||||
JobTitle: "Backend Engineer",
|
||||
Metadata: domain.JSONMap{
|
||||
"additionalAppointments": []any{
|
||||
map[string]any{
|
||||
"tenantId": "dept-platform",
|
||||
"isPrimary": true,
|
||||
"isOwner": true,
|
||||
"grade": "수석",
|
||||
"position": "실장",
|
||||
"jobTitle": "기술기획",
|
||||
},
|
||||
},
|
||||
},
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
},
|
||||
}
|
||||
usersBySlug := []domain.User{
|
||||
{ID: "user-sso-member", Email: "member@example.com", Name: "SSO 구성원", Status: domain.UserStatusActive, CompanyCode: "sso", Grade: "선임", CreatedAt: now, UpdatedAt: now},
|
||||
}
|
||||
usersByList := []domain.User{
|
||||
{
|
||||
ID: "user-appointment-only",
|
||||
Email: "appointment@example.com",
|
||||
Name: "겸직 사용자",
|
||||
Status: domain.UserStatusActive,
|
||||
Metadata: domain.JSONMap{
|
||||
"additionalAppointments": []any{
|
||||
map[string]any{
|
||||
"tenantSlug": "sso",
|
||||
"lead": true,
|
||||
"position": "파트장",
|
||||
},
|
||||
},
|
||||
},
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
},
|
||||
}
|
||||
|
||||
mockSvc.On("ListTenants", mock.Anything, 10000, 0, "").Return(tenants, int64(len(tenants)), nil)
|
||||
mockUsers.On("FindByTenantIDs", mock.Anything, []string{"group-hanmac-family", "company-hanmac", "dept-platform", "team-sso"}).Return(usersByTenantID, nil)
|
||||
mockUsers.On("FindByCompanyCodes", mock.Anything, []string{"hanmac-family", "hanmac", "platform", "sso"}).Return(usersBySlug, nil)
|
||||
mockUsers.On("List", mock.Anything, 0, 10000, "", "").Return(usersByList, int64(len(usersByList)), nil)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/org-context", nil)
|
||||
resp, err := app.Test(req)
|
||||
@@ -421,18 +665,96 @@ func TestTenantHandler_GetOrgContextJSONDefaultsToHanmacFamilyForApiKey(t *testi
|
||||
require.Equal(t, "dept-platform", tenantsPayload[2].(map[string]any)["id"])
|
||||
require.Equal(t, "team-sso", tenantsPayload[3].(map[string]any)["id"])
|
||||
|
||||
usersPayload := got["users"].([]any)
|
||||
require.Len(t, usersPayload, 2)
|
||||
require.Equal(t, "user-platform-lead", usersPayload[0].(map[string]any)["id"])
|
||||
require.Equal(t, []any{"dept-platform"}, usersPayload[0].(map[string]any)["tenantIds"])
|
||||
require.Equal(t, "user-sso-member", usersPayload[1].(map[string]any)["id"])
|
||||
require.NotContains(t, got, "users")
|
||||
deptPlatform := tenantsPayload[2].(map[string]any)
|
||||
platformMembers := deptPlatform["members"].([]any)
|
||||
require.Len(t, platformMembers, 1)
|
||||
firstUser := platformMembers[0].(map[string]any)
|
||||
require.NotContains(t, firstUser, "id")
|
||||
require.NotContains(t, firstUser, "phone")
|
||||
require.NotContains(t, firstUser, "tenantIds")
|
||||
require.NotContains(t, firstUser, "tenantSlugs")
|
||||
require.NotContains(t, firstUser, "memberships")
|
||||
require.NotContains(t, firstUser, "role")
|
||||
require.NotContains(t, firstUser, "status")
|
||||
require.NotContains(t, firstUser, "metadata")
|
||||
require.NotContains(t, firstUser, "createdAt")
|
||||
require.NotContains(t, firstUser, "updatedAt")
|
||||
require.Equal(t, "lead@example.com", firstUser["email"])
|
||||
require.Equal(t, "플랫폼 리드", firstUser["name"])
|
||||
require.Equal(t, true, firstUser["isOwner"])
|
||||
require.Equal(t, true, firstUser["isLeader"])
|
||||
require.Equal(t, true, firstUser["isPrimary"])
|
||||
require.Equal(t, "수석", firstUser["grade"])
|
||||
require.Equal(t, "실장", firstUser["position"])
|
||||
require.Equal(t, "기술기획", firstUser["jobTitle"])
|
||||
teamSSO := tenantsPayload[3].(map[string]any)
|
||||
ssoMembers := teamSSO["members"].([]any)
|
||||
require.Len(t, ssoMembers, 2)
|
||||
appointmentOnly := ssoMembers[1].(map[string]any)
|
||||
require.Equal(t, "appointment@example.com", appointmentOnly["email"])
|
||||
require.Equal(t, false, appointmentOnly["isOwner"])
|
||||
require.Equal(t, true, appointmentOnly["isLeader"])
|
||||
|
||||
tree := got["tree"].(map[string]any)
|
||||
require.Equal(t, "group-hanmac-family", tree["id"])
|
||||
require.NotContains(t, tree, "directUserIds")
|
||||
require.Contains(t, tree, "members")
|
||||
require.NotContains(t, toJSONString(t, got), "directUserIds")
|
||||
require.NotContains(t, toJSONString(t, got), "private-team")
|
||||
require.NotContains(t, toJSONString(t, got), "root-other")
|
||||
}
|
||||
|
||||
func TestTenantHandler_GetOrgContextJSONIncludesUserIDsOnlyWhenRequested(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
mockUsers := new(MockUserRepoForHandler)
|
||||
h := &TenantHandler{Service: mockSvc, UserRepo: mockUsers}
|
||||
|
||||
app.Use(func(c *fiber.Ctx) error {
|
||||
c.Locals("apiKeyName", "orgfront-ssot-client")
|
||||
return c.Next()
|
||||
})
|
||||
app.Get("/org-context", h.GetOrgContext)
|
||||
|
||||
now := time.Date(2026, 5, 13, 12, 0, 0, 0, time.UTC)
|
||||
parent := func(id string) *string { return &id }
|
||||
tenants := []domain.Tenant{
|
||||
{ID: "company-hanmac", Type: domain.TenantTypeCompany, Name: "한맥기술", Slug: "hanmac", Status: domain.TenantStatusActive, CreatedAt: now, UpdatedAt: now},
|
||||
}
|
||||
users := []domain.User{
|
||||
{ID: "user-1", Email: "user@example.com", Name: "사용자", Phone: "010-1234-5678", Status: domain.UserStatusActive, TenantID: parent("company-hanmac"), CompanyCode: "hanmac", CreatedAt: now, UpdatedAt: now},
|
||||
}
|
||||
|
||||
mockSvc.On("ListTenants", mock.Anything, 10000, 0, "").Return(tenants, int64(len(tenants)), nil)
|
||||
mockUsers.On("FindByTenantIDs", mock.Anything, []string{"company-hanmac"}).Return(users, nil)
|
||||
mockUsers.On("FindByCompanyCodes", mock.Anything, []string{"hanmac"}).Return([]domain.User{}, nil)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/org-context?tenantSlug=hanmac&includeUserIds=true", nil)
|
||||
resp, err := app.Test(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var got map[string]any
|
||||
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
|
||||
require.NotContains(t, got, "users")
|
||||
tenantsPayload := got["tenants"].([]any)
|
||||
members := tenantsPayload[0].(map[string]any)["members"].([]any)
|
||||
require.Len(t, members, 1)
|
||||
member := members[0].(map[string]any)
|
||||
require.Equal(t, "user-1", member["id"])
|
||||
require.Equal(t, "010-1234-5678", member["phone"])
|
||||
require.NotContains(t, member, "tenantIds")
|
||||
require.NotContains(t, member, "tenantSlugs")
|
||||
require.NotContains(t, member, "memberships")
|
||||
tree := got["tree"].(map[string]any)
|
||||
treeMembers := tree["members"].([]any)
|
||||
require.Len(t, treeMembers, 1)
|
||||
require.Equal(t, "user-1", treeMembers[0].(map[string]any)["id"])
|
||||
require.Equal(t, "010-1234-5678", treeMembers[0].(map[string]any)["phone"])
|
||||
require.NotContains(t, tree, "directUserIds")
|
||||
}
|
||||
|
||||
func TestTenantHandler_GetOrgContextJSONScopesByTenantSlug(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
@@ -697,6 +1019,44 @@ func TestTenantHandler_ExportTenantsCSV_FiltersDescendantsByParentIDWithIDs(t *t
|
||||
mockSvc.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestTenantHandler_ExportTenantsCSV_HidesPrivateSubtreeForUnauthorizedUser(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
h := &TenantHandler{Service: mockSvc}
|
||||
|
||||
parent := func(id string) *string { return &id }
|
||||
tenants := []domain.Tenant{
|
||||
{ID: "family", Type: domain.TenantTypeCompanyGroup, Name: "한맥가족", Slug: "hanmac-family"},
|
||||
{ID: "company", Type: domain.TenantTypeCompany, ParentID: parent("family"), Name: "한맥", Slug: "hanmac"},
|
||||
{ID: "public-team", Type: domain.TenantTypeUserGroup, ParentID: parent("company"), Name: "공개팀", Slug: "public-team"},
|
||||
{ID: "private-team", Type: domain.TenantTypeUserGroup, ParentID: parent("company"), Name: "비공개팀", Slug: "private-team", Config: domain.JSONMap{"visibility": "private"}},
|
||||
{ID: "private-child", Type: domain.TenantTypeUserGroup, ParentID: parent("private-team"), Name: "비공개하위", Slug: "private-child"},
|
||||
}
|
||||
|
||||
app.Use(func(c *fiber.Ctx) error {
|
||||
c.Locals("user_profile", &domain.UserProfileResponse{
|
||||
ID: "user-1",
|
||||
Role: domain.RoleTenantAdmin,
|
||||
TenantID: parent("company"),
|
||||
})
|
||||
return c.Next()
|
||||
})
|
||||
app.Get("/tenants/export", h.ExportTenantsCSV)
|
||||
|
||||
mockSvc.On("ListTenants", mock.Anything, 10000, 0, "").Return(tenants, int64(len(tenants)), nil).Once()
|
||||
|
||||
req := httptest.NewRequest("GET", "/tenants/export?includeIds=true", nil)
|
||||
resp, _ := app.Test(req)
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
text := string(body)
|
||||
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
assert.Contains(t, text, "public-team")
|
||||
assert.NotContains(t, text, "private-team")
|
||||
assert.NotContains(t, text, "private-child")
|
||||
mockSvc.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestTenantHandler_ImportTenantsCSVCreatesTenant(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
|
||||
Reference in New Issue
Block a user