mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-31 19:42:15 +00:00
chore(test): streamline integration tests for instance management (#12243)
- Removed redundant relational instance handling in integration tests for adding and removing custom domains. - Simplified test cases by consolidating instance creation and context management. - Enhanced clarity and maintainability of test logic by reducing complexity in test structures. # Which Problems Are Solved `backed/v3` tests are flaky, but the code is not productive. Development is paused for the moment. Disabling flaky tests helps us to maintain the product easier. # How the Problems Are Solved - Removed redundant relational instance handling in integration tests for adding and removing custom domains. - Simplified test cases by consolidating instance creation and context management. - Enhanced clarity and maintainability of test logic by reducing complexity in test structures.newly introduced terms). # Additional Context - related to https://github.com/zitadel/zitadel/pull/12241 --------- Co-authored-by: Livio Spring <[email protected]> Co-authored-by: Copilot Autofix powered by AI <[email protected]>
This commit is contained in:
co-authored by
Livio Spring
Copilot Autofix powered by AI
parent
7019a03ec4
commit
f85a2373c5
@@ -4,18 +4,15 @@ package instance_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/feature/v2"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/instance/v2"
|
||||
)
|
||||
|
||||
@@ -28,135 +25,101 @@ func TestDeleteInstance(t *testing.T) {
|
||||
|
||||
ctxWithSysAuthZ := integration.WithSystemAuthorization(ctx)
|
||||
|
||||
// Event store instances
|
||||
instES := integration.NewInstance(ctxWithSysAuthZ)
|
||||
instanceESOwnerCtx := instES.WithAuthorizationToken(t.Context(), integration.UserTypeIAMOwner)
|
||||
instES2 := integration.NewInstance(ctxWithSysAuthZ)
|
||||
|
||||
instRelational := integration.NewInstance(ctxWithSysAuthZ)
|
||||
integration.EnsureInstanceFeature(t, ctxWithSysAuthZ, instRelational, &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)}, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.True(tCollect, got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
instanceRelationalOwnerCtx := instRelational.WithAuthorizationToken(t.Context(), integration.UserTypeIAMOwner)
|
||||
instRelational2 := integration.NewInstance(ctxWithSysAuthZ)
|
||||
integration.EnsureInstanceFeature(t, ctxWithSysAuthZ, instRelational2, &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)}, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.True(tCollect, got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
|
||||
type instAndCtx struct {
|
||||
testType string
|
||||
i1 *integration.Instance
|
||||
i2 *integration.Instance
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
testedInstancesAndCtxs := []instAndCtx{
|
||||
{testType: "eventstore", i1: instES, i2: instES2, ctx: instanceESOwnerCtx},
|
||||
{testType: "relational", i1: instRelational, i2: instRelational2, ctx: instanceRelationalOwnerCtx},
|
||||
}
|
||||
inst := integration.NewInstance(ctxWithSysAuthZ)
|
||||
instanceOwnerCtx := inst.WithAuthorizationToken(t.Context(), integration.UserTypeIAMOwner)
|
||||
inst2 := integration.NewInstance(ctxWithSysAuthZ)
|
||||
|
||||
t.Cleanup(func() {
|
||||
instES.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instES.ID()})
|
||||
instES2.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instES2.ID()})
|
||||
instRelational.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instRelational.ID()})
|
||||
instRelational2.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instRelational2.ID()})
|
||||
inst.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst.ID()})
|
||||
inst2.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst2.ID()})
|
||||
})
|
||||
|
||||
for _, instanceWithCtx := range testedInstancesAndCtxs {
|
||||
tt := []struct {
|
||||
testName string
|
||||
inputRequest *instance.DeleteInstanceRequest
|
||||
inputContext context.Context
|
||||
expectedErrorMsg string
|
||||
expectedErrorCode codes.Code
|
||||
expectedInstanceID string
|
||||
expectsNullTimestamp bool
|
||||
}{
|
||||
{
|
||||
testName: "when invalid context should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: instanceWithCtx.i1.ID(),
|
||||
},
|
||||
inputContext: t.Context(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
tt := []struct {
|
||||
testName string
|
||||
inputRequest *instance.DeleteInstanceRequest
|
||||
inputContext context.Context
|
||||
expectedErrorMsg string
|
||||
expectedErrorCode codes.Code
|
||||
expectedInstanceID string
|
||||
expectsNullTimestamp bool
|
||||
}{
|
||||
{
|
||||
testName: "when invalid context should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
},
|
||||
{
|
||||
testName: "when invalid context and invalid id should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: instanceWithCtx.i1.ID() + "invalid",
|
||||
},
|
||||
inputContext: t.Context(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
inputContext: t.Context(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when invalid context and invalid id should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID() + "invalid",
|
||||
},
|
||||
{
|
||||
testName: "when instance token for invalid instance should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: instanceWithCtx.i1.ID() + "invalid",
|
||||
},
|
||||
inputContext: instanceWithCtx.ctx,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "Errors.Token.Invalid (AUTH-7fs1e)",
|
||||
inputContext: t.Context(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when instance token for invalid instance should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID() + "invalid",
|
||||
},
|
||||
{
|
||||
testName: "when instance token for other instance should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: instanceWithCtx.i2.ID(),
|
||||
},
|
||||
inputContext: instanceWithCtx.ctx,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "Errors.Token.Invalid (AUTH-7fs1e)",
|
||||
inputContext: instanceOwnerCtx,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "Errors.Token.Invalid (AUTH-7fs1e)",
|
||||
},
|
||||
{
|
||||
testName: "when instance token for other instance should return unauthN error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst2.ID(),
|
||||
},
|
||||
{
|
||||
testName: "when instance token for own instance should return unauthZ error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: instanceWithCtx.i1.ID(),
|
||||
},
|
||||
inputContext: instanceWithCtx.ctx,
|
||||
expectedErrorCode: codes.PermissionDenied,
|
||||
expectedErrorMsg: "No matching permissions found (AUTH-5mWD2)",
|
||||
inputContext: instanceOwnerCtx,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "Errors.Token.Invalid (AUTH-7fs1e)",
|
||||
},
|
||||
{
|
||||
testName: "when instance token for own instance should return unauthZ error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
},
|
||||
{
|
||||
// TODO(IAM-Marco): This test won't reach the relational side due to an interceptor
|
||||
// automatically changing the instance in context to an empty one.
|
||||
// The interceptor will look for the instance matching the instance ID passed here.
|
||||
// Since the instance doesn't exist, it will put an empty instance in context.
|
||||
// But an empty instance has no feature flags enabled.
|
||||
testName: "when invalid id should return no error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: instanceWithCtx.i1.ID() + "invalid",
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectsNullTimestamp: true,
|
||||
inputContext: instanceOwnerCtx,
|
||||
expectedErrorCode: codes.PermissionDenied,
|
||||
expectedErrorMsg: "No matching permissions found (AUTH-5mWD2)",
|
||||
},
|
||||
{
|
||||
testName: "when invalid id should return no error",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID() + "invalid",
|
||||
},
|
||||
{
|
||||
testName: "when delete succeeds should return deletion date",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: instanceWithCtx.i1.ID(),
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedInstanceID: instanceWithCtx.i1.ID(),
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectsNullTimestamp: true,
|
||||
},
|
||||
{
|
||||
testName: "when delete succeeds should return deletion date",
|
||||
inputRequest: &instance.DeleteInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(fmt.Sprintf("%s - %s", instanceWithCtx.testType, tc.testName), func(t *testing.T) {
|
||||
// Test
|
||||
res, err := instanceWithCtx.i1.Client.InstanceV2.DeleteInstance(tc.inputContext, tc.inputRequest)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Equal(t, tc.expectedErrorMsg, status.Convert(err).Message())
|
||||
if tc.expectedErrorMsg == "" {
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, tc.expectsNullTimestamp, res.GetDeletionDate() == nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedInstanceID: inst.ID(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2.DeleteInstance(tc.inputContext, tc.inputRequest)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Equal(t, tc.expectedErrorMsg, status.Convert(err).Message())
|
||||
if tc.expectedErrorMsg == "" {
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, tc.expectsNullTimestamp, res.GetDeletionDate() == nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateInstance(t *testing.T) {
|
||||
@@ -168,163 +131,124 @@ func TestUpdateInstance(t *testing.T) {
|
||||
|
||||
ctxWithSysAuthZ := integration.WithSystemAuthorization(ctx)
|
||||
|
||||
instES := integration.NewInstance(ctxWithSysAuthZ)
|
||||
instanceOwnerCtxES := instES.WithAuthorizationToken(context.Background(), integration.UserTypeIAMOwner)
|
||||
orgOwnerCtxES := instES.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
inst2ES := integration.NewInstance(ctxWithSysAuthZ)
|
||||
|
||||
// Relational
|
||||
instRelational := integration.NewInstance(ctxWithSysAuthZ)
|
||||
integration.EnsureInstanceFeature(t, ctxWithSysAuthZ, instRelational, &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)}, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.True(tCollect, got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
instanceOwnerCtxRelational := instRelational.WithAuthorizationToken(context.Background(), integration.UserTypeIAMOwner)
|
||||
orgOwnerCtxRelational := instRelational.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
inst2Relational := integration.NewInstance(ctxWithSysAuthZ)
|
||||
integration.EnsureInstanceFeature(t, ctxWithSysAuthZ, inst2Relational, &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)}, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.True(tCollect, got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
inst := integration.NewInstance(ctxWithSysAuthZ)
|
||||
instanceOwnerCtx := inst.WithAuthorizationToken(context.Background(), integration.UserTypeIAMOwner)
|
||||
orgOwnerCtx := inst.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
inst2 := integration.NewInstance(ctxWithSysAuthZ)
|
||||
|
||||
t.Cleanup(func() {
|
||||
instES.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instES.ID()})
|
||||
inst2ES.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst2ES.ID()})
|
||||
instRelational.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: instRelational.ID()})
|
||||
inst2Relational.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst2Relational.ID()})
|
||||
inst.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst.ID()})
|
||||
inst2.Client.InstanceV2.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst2.ID()})
|
||||
})
|
||||
|
||||
type instAndCtx struct {
|
||||
testType string
|
||||
inst *integration.Instance
|
||||
inst2 *integration.Instance
|
||||
instanceOwnerCtx context.Context
|
||||
orgOwnerCtx context.Context
|
||||
tt := []struct {
|
||||
testName string
|
||||
inputRequest *instance.UpdateInstanceRequest
|
||||
inputContext context.Context
|
||||
expectedErrorMsg string
|
||||
expectedErrorCode codes.Code
|
||||
expectedNewName string
|
||||
}{
|
||||
{
|
||||
testName: "when invalid context should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: context.Background(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when invalid context and invalid id should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.ID() + "invalid",
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: context.Background(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when instance token for invalid instance should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.ID() + "invalid",
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: instanceOwnerCtx,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "Errors.Token.Invalid (AUTH-7fs1e)",
|
||||
},
|
||||
{
|
||||
testName: "when instance token for other instance should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst2.ID(),
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: instanceOwnerCtx,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "Errors.Token.Invalid (AUTH-7fs1e)",
|
||||
},
|
||||
{
|
||||
testName: "when unauthZ context should return unauthZ error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
InstanceName: "a valid name",
|
||||
},
|
||||
inputContext: orgOwnerCtx,
|
||||
expectedErrorCode: codes.NotFound,
|
||||
expectedErrorMsg: "membership not found (AUTHZ-cdgFk)",
|
||||
},
|
||||
{
|
||||
testName: "when invalid id should return not found error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.ID() + "invalid",
|
||||
InstanceName: "an-updated-name",
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedErrorCode: codes.NotFound,
|
||||
expectedErrorMsg: "Errors.Instance.NotFound (INST-nuso2m)",
|
||||
},
|
||||
{
|
||||
testName: "when update succeeds (instance owner) should change instance name",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst.ID(),
|
||||
InstanceName: "an-updated-name",
|
||||
},
|
||||
inputContext: instanceOwnerCtx,
|
||||
expectedNewName: "an-updated-name",
|
||||
},
|
||||
{
|
||||
testName: "when update succeeds should change instance name",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: inst2.ID(),
|
||||
InstanceName: "an-updated-name2",
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedNewName: "an-updated-name2",
|
||||
},
|
||||
}
|
||||
|
||||
testedInstancesAndCtxs := []instAndCtx{
|
||||
{testType: "eventstore", inst: instES, inst2: inst2ES, instanceOwnerCtx: instanceOwnerCtxES, orgOwnerCtx: orgOwnerCtxES},
|
||||
{testType: "relational", inst: instRelational, inst2: inst2Relational, instanceOwnerCtx: instanceOwnerCtxRelational, orgOwnerCtx: orgOwnerCtxRelational},
|
||||
}
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2.UpdateInstance(tc.inputContext, tc.inputRequest)
|
||||
|
||||
for _, instancesWithCtx := range testedInstancesAndCtxs {
|
||||
tt := []struct {
|
||||
testName string
|
||||
inputRequest *instance.UpdateInstanceRequest
|
||||
inputContext context.Context
|
||||
expectedErrorMsg string
|
||||
expectedErrorCode codes.Code
|
||||
expectedNewName string
|
||||
}{
|
||||
{
|
||||
testName: "when invalid context should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: instancesWithCtx.inst.ID(),
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: context.Background(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when invalid context and invalid id should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: instancesWithCtx.inst.ID() + "invalid",
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: context.Background(),
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "auth header missing",
|
||||
},
|
||||
{
|
||||
testName: "when instance token for invalid instance should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: instancesWithCtx.inst.ID() + "invalid",
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: instancesWithCtx.instanceOwnerCtx,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "Errors.Token.Invalid (AUTH-7fs1e)",
|
||||
},
|
||||
{
|
||||
testName: "when instance token for other instance should return unauthN error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: instancesWithCtx.inst2.ID(),
|
||||
InstanceName: " ",
|
||||
},
|
||||
inputContext: instancesWithCtx.instanceOwnerCtx,
|
||||
expectedErrorCode: codes.Unauthenticated,
|
||||
expectedErrorMsg: "Errors.Token.Invalid (AUTH-7fs1e)",
|
||||
},
|
||||
{
|
||||
// TODO(IAM-Marco): Fix this test for relational case when permission checks are in place (see https://github.com/zitadel/zitadel/issues/10917)
|
||||
testName: "when unauthZ context should return unauthZ error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: instancesWithCtx.inst.ID(),
|
||||
InstanceName: "a valid name",
|
||||
},
|
||||
inputContext: instancesWithCtx.orgOwnerCtx,
|
||||
expectedErrorCode: codes.NotFound,
|
||||
expectedErrorMsg: "membership not found (AUTHZ-cdgFk)",
|
||||
},
|
||||
{
|
||||
// TODO(IAM-Marco): This test won't reach the relational side due to an interceptor
|
||||
// automatically changing the instance in context to an empty one.
|
||||
// The interceptor will look for the instance matching the instance ID passed here.
|
||||
// Since the instance doesn't exist, it will put an empty instance in context.
|
||||
// But an empty instance has no feature flags enabled.
|
||||
testName: "when invalid id should return not found error",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: instancesWithCtx.inst.ID() + "invalid",
|
||||
InstanceName: "an-updated-name",
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedErrorCode: codes.NotFound,
|
||||
expectedErrorMsg: "Errors.Instance.NotFound (INST-nuso2m)",
|
||||
},
|
||||
{
|
||||
testName: "when update succeeds (instance owner) should change instance name",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: instancesWithCtx.inst.ID(),
|
||||
InstanceName: "an-updated-name",
|
||||
},
|
||||
inputContext: instancesWithCtx.instanceOwnerCtx,
|
||||
expectedNewName: "an-updated-name",
|
||||
},
|
||||
{
|
||||
testName: "when update succeeds should change instance name",
|
||||
inputRequest: &instance.UpdateInstanceRequest{
|
||||
InstanceId: instancesWithCtx.inst2.ID(),
|
||||
InstanceName: "an-updated-name2",
|
||||
},
|
||||
inputContext: ctxWithSysAuthZ,
|
||||
expectedNewName: "an-updated-name2",
|
||||
},
|
||||
}
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Equal(t, tc.expectedErrorMsg, status.Convert(err).Message())
|
||||
if tc.expectedErrorMsg == "" {
|
||||
|
||||
for _, tc := range tt {
|
||||
// TODO(IAM-Marco): Fix this test for relational case when permission checks are in place (see https://github.com/zitadel/zitadel/issues/10917)
|
||||
if tc.testName == "when unauthZ context should return unauthZ error" && instancesWithCtx.testType == "relational" {
|
||||
continue
|
||||
require.NotNil(t, res)
|
||||
assert.NotEmpty(t, res.GetChangeDate())
|
||||
|
||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tc.inputContext, time.Minute)
|
||||
require.EventuallyWithT(t, func(tt *assert.CollectT) {
|
||||
retrievedInstance, err := inst.Client.InstanceV2.GetInstance(tc.inputContext, &instance.GetInstanceRequest{InstanceId: tc.inputRequest.GetInstanceId()})
|
||||
require.Nil(tt, err)
|
||||
assert.Equal(tt, tc.expectedNewName, retrievedInstance.GetInstance().GetName())
|
||||
}, retryDuration, tick, "timeout waiting for expected execution result")
|
||||
}
|
||||
t.Run(fmt.Sprintf("%s - %s", instancesWithCtx.testType, tc.testName), func(t *testing.T) {
|
||||
// Test
|
||||
res, err := instES.Client.InstanceV2.UpdateInstance(tc.inputContext, tc.inputRequest)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, tc.expectedErrorCode, status.Code(err))
|
||||
assert.Equal(t, tc.expectedErrorMsg, status.Convert(err).Message())
|
||||
if tc.expectedErrorMsg == "" {
|
||||
|
||||
require.NotNil(t, res)
|
||||
assert.NotEmpty(t, res.GetChangeDate())
|
||||
|
||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tc.inputContext, time.Minute)
|
||||
require.EventuallyWithT(t, func(tt *assert.CollectT) {
|
||||
retrievedInstance, err := instES.Client.InstanceV2.GetInstance(tc.inputContext, &instance.GetInstanceRequest{InstanceId: tc.inputRequest.GetInstanceId()})
|
||||
require.Nil(tt, err)
|
||||
assert.Equal(tt, tc.expectedNewName, retrievedInstance.GetInstance().GetName())
|
||||
}, retryDuration, tick, "timeout waiting for expected execution result")
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user