github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/formation/service_test.go (about)

     1  package formation_test
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/kyma-incubator/compass/components/director/internal/domain/formationassignment"
     7  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
     8  	webhookclient "github.com/kyma-incubator/compass/components/director/pkg/webhook_client"
     9  
    10  	"github.com/kyma-incubator/compass/components/director/internal/domain/labeldef"
    11  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    12  	"github.com/kyma-incubator/compass/components/director/pkg/pagination"
    13  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    14  	"github.com/pkg/errors"
    15  
    16  	"fmt"
    17  	"testing"
    18  
    19  	"github.com/kyma-incubator/compass/components/director/internal/domain/formation"
    20  	"github.com/kyma-incubator/compass/components/director/internal/domain/formation/automock"
    21  	"github.com/kyma-incubator/compass/components/director/internal/domain/tenant"
    22  	"github.com/kyma-incubator/compass/components/director/internal/model"
    23  	"github.com/stretchr/testify/assert"
    24  	"github.com/stretchr/testify/mock"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  func TestServiceList(t *testing.T) {
    29  	ctx := context.TODO()
    30  	ctx = tenant.SaveToContext(ctx, TntInternalID, TntExternalID)
    31  
    32  	pageSize := 100
    33  	cursor := "start"
    34  
    35  	expectedFormationPage := &model.FormationPage{
    36  		Data: []*model.Formation{&modelFormation},
    37  		PageInfo: &pagination.Page{
    38  			StartCursor: cursor,
    39  			EndCursor:   "",
    40  			HasNextPage: false,
    41  		},
    42  		TotalCount: 1,
    43  	}
    44  
    45  	testCases := []struct {
    46  		Name                  string
    47  		FormationRepoFn       func() *automock.FormationRepository
    48  		InputID               string
    49  		InputPageSize         int
    50  		ExpectedFormationPage *model.FormationPage
    51  		ExpectedErrMessage    string
    52  	}{
    53  		{
    54  			Name: "Success",
    55  			FormationRepoFn: func() *automock.FormationRepository {
    56  				repo := &automock.FormationRepository{}
    57  				repo.On("List", ctx, TntInternalID, pageSize, cursor).Return(expectedFormationPage, nil).Once()
    58  				return repo
    59  			},
    60  			InputID:               FormationID,
    61  			InputPageSize:         pageSize,
    62  			ExpectedFormationPage: expectedFormationPage,
    63  			ExpectedErrMessage:    "",
    64  		},
    65  		{
    66  			Name: "Returns error when can't list formations",
    67  			FormationRepoFn: func() *automock.FormationRepository {
    68  				repo := &automock.FormationRepository{}
    69  				repo.On("List", ctx, TntInternalID, pageSize, cursor).Return(nil, testErr).Once()
    70  				return repo
    71  			},
    72  			InputID:               FormationID,
    73  			InputPageSize:         pageSize,
    74  			ExpectedFormationPage: nil,
    75  			ExpectedErrMessage:    testErr.Error(),
    76  		},
    77  		{
    78  			Name:                  "Returns error when page size is not between 1 and 200",
    79  			InputID:               FormationID,
    80  			InputPageSize:         300,
    81  			ExpectedFormationPage: nil,
    82  			ExpectedErrMessage:    "page size must be between 1 and 200",
    83  		},
    84  	}
    85  
    86  	for _, testCase := range testCases {
    87  		t.Run(testCase.Name, func(t *testing.T) {
    88  			// GIVEN
    89  			formationRepo := unusedFormationRepo()
    90  			if testCase.FormationRepoFn != nil {
    91  				formationRepo = testCase.FormationRepoFn()
    92  			}
    93  
    94  			svc := formation.NewService(nil, nil, nil, nil, formationRepo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
    95  
    96  			// WHEN
    97  			actual, err := svc.List(ctx, testCase.InputPageSize, cursor)
    98  
    99  			// THEN
   100  			if testCase.ExpectedErrMessage == "" {
   101  				require.NoError(t, err)
   102  				assert.Equal(t, testCase.ExpectedFormationPage, actual)
   103  			} else {
   104  				require.Error(t, err)
   105  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   106  				require.Nil(t, actual)
   107  			}
   108  
   109  			formationRepo.AssertExpectations(t)
   110  		})
   111  	}
   112  }
   113  
   114  func TestServiceGet(t *testing.T) {
   115  	ctx := context.TODO()
   116  	ctx = tenant.SaveToContext(ctx, TntInternalID, TntExternalID)
   117  
   118  	testCases := []struct {
   119  		Name               string
   120  		FormationRepoFn    func() *automock.FormationRepository
   121  		InputID            string
   122  		ExpectedFormation  *model.Formation
   123  		ExpectedErrMessage string
   124  	}{
   125  		{
   126  			Name: "Success",
   127  			FormationRepoFn: func() *automock.FormationRepository {
   128  				repo := &automock.FormationRepository{}
   129  				repo.On("Get", ctx, FormationID, TntInternalID).Return(&modelFormation, nil).Once()
   130  				return repo
   131  			},
   132  			InputID:           FormationID,
   133  			ExpectedFormation: &modelFormation,
   134  		},
   135  		{
   136  			Name: "Returns error when can't get the formation",
   137  			FormationRepoFn: func() *automock.FormationRepository {
   138  				repo := &automock.FormationRepository{}
   139  				repo.On("Get", ctx, FormationID, TntInternalID).Return(nil, testErr).Once()
   140  				return repo
   141  			},
   142  			InputID:            FormationID,
   143  			ExpectedFormation:  nil,
   144  			ExpectedErrMessage: testErr.Error(),
   145  		},
   146  	}
   147  
   148  	for _, testCase := range testCases {
   149  		t.Run(testCase.Name, func(t *testing.T) {
   150  			// GIVEN
   151  			formationRepo := testCase.FormationRepoFn()
   152  
   153  			svc := formation.NewService(nil, nil, nil, nil, formationRepo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
   154  
   155  			// WHEN
   156  			actual, err := svc.Get(ctx, testCase.InputID)
   157  
   158  			// THEN
   159  			if testCase.ExpectedErrMessage == "" {
   160  				require.NoError(t, err)
   161  				assert.Equal(t, testCase.ExpectedFormation, actual)
   162  			} else {
   163  				require.Error(t, err)
   164  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   165  				require.Nil(t, actual)
   166  			}
   167  
   168  			formationRepo.AssertExpectations(t)
   169  		})
   170  	}
   171  }
   172  
   173  func TestService_GetFormationByName(t *testing.T) {
   174  	ctx := context.TODO()
   175  	ctx = tenant.SaveToContext(ctx, TntInternalID, TntExternalID)
   176  
   177  	testCases := []struct {
   178  		Name               string
   179  		FormationRepoFn    func() *automock.FormationRepository
   180  		Input              string
   181  		ExpectedFormation  *model.Formation
   182  		ExpectedErrMessage string
   183  	}{
   184  		{
   185  			Name: "Success",
   186  			FormationRepoFn: func() *automock.FormationRepository {
   187  				repo := &automock.FormationRepository{}
   188  				repo.On("GetByName", ctx, testFormationName, TntInternalID).Return(&modelFormation, nil).Once()
   189  				return repo
   190  			},
   191  			Input:             testFormationName,
   192  			ExpectedFormation: &modelFormation,
   193  		},
   194  		{
   195  			Name: "Returns error when can't get the formation",
   196  			FormationRepoFn: func() *automock.FormationRepository {
   197  				repo := &automock.FormationRepository{}
   198  				repo.On("GetByName", ctx, testFormationName, TntInternalID).Return(nil, testErr).Once()
   199  				return repo
   200  			},
   201  			Input:              testFormationName,
   202  			ExpectedFormation:  nil,
   203  			ExpectedErrMessage: "An error occurred while getting formation by name",
   204  		},
   205  	}
   206  
   207  	for _, testCase := range testCases {
   208  		t.Run(testCase.Name, func(t *testing.T) {
   209  			// GIVEN
   210  			formationRepo := testCase.FormationRepoFn()
   211  
   212  			svc := formation.NewService(nil, nil, nil, nil, formationRepo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
   213  
   214  			// WHEN
   215  			actual, err := svc.GetFormationByName(ctx, testCase.Input, TntInternalID)
   216  
   217  			// THEN
   218  			if testCase.ExpectedErrMessage == "" {
   219  				require.NoError(t, err)
   220  				assert.Equal(t, testCase.ExpectedFormation, actual)
   221  			} else {
   222  				require.Error(t, err)
   223  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   224  				require.Nil(t, actual)
   225  			}
   226  
   227  			formationRepo.AssertExpectations(t)
   228  		})
   229  	}
   230  }
   231  
   232  func TestService_GetGlobalByID(t *testing.T) {
   233  	ctx := context.TODO()
   234  	ctxWithTenant := tenant.SaveToContext(ctx, TntInternalID, TntExternalID)
   235  
   236  	testCases := []struct {
   237  		Name               string
   238  		FormationRepoFn    func() *automock.FormationRepository
   239  		ExpectedFormation  *model.Formation
   240  		ExpectedErrMessage string
   241  	}{
   242  		{
   243  			Name: "Success",
   244  			FormationRepoFn: func() *automock.FormationRepository {
   245  				repo := &automock.FormationRepository{}
   246  				repo.On("GetGlobalByID", ctxWithTenant, FormationID).Return(&modelFormation, nil).Once()
   247  				return repo
   248  			},
   249  			ExpectedFormation: &modelFormation,
   250  		},
   251  		{
   252  			Name: "Error when getting formation globally fails",
   253  			FormationRepoFn: func() *automock.FormationRepository {
   254  				repo := &automock.FormationRepository{}
   255  				repo.On("GetGlobalByID", ctxWithTenant, FormationID).Return(nil, testErr).Once()
   256  				return repo
   257  			},
   258  			ExpectedFormation:  nil,
   259  			ExpectedErrMessage: fmt.Sprintf("An error occurred while getting formation by ID: %q globally", FormationID),
   260  		},
   261  	}
   262  
   263  	for _, testCase := range testCases {
   264  		t.Run(testCase.Name, func(t *testing.T) {
   265  			// GIVEN
   266  			formationRepo := testCase.FormationRepoFn()
   267  			defer formationRepo.AssertExpectations(t)
   268  
   269  			svc := formation.NewService(nil, nil, nil, nil, formationRepo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
   270  
   271  			// WHEN
   272  			actual, err := svc.GetGlobalByID(ctxWithTenant, FormationID)
   273  
   274  			// THEN
   275  			if testCase.ExpectedErrMessage == "" {
   276  				require.NoError(t, err)
   277  				assert.Equal(t, testCase.ExpectedFormation, actual)
   278  			} else {
   279  				require.Error(t, err)
   280  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   281  				require.Nil(t, actual)
   282  			}
   283  		})
   284  	}
   285  }
   286  
   287  func TestService_Update(t *testing.T) {
   288  	ctx := context.TODO()
   289  	ctxWithTenant := tenant.SaveToContext(ctx, TntInternalID, TntExternalID)
   290  
   291  	testCases := []struct {
   292  		Name               string
   293  		FormationRepoFn    func() *automock.FormationRepository
   294  		ExpectedErrMessage string
   295  	}{
   296  		{
   297  			Name: "Success",
   298  			FormationRepoFn: func() *automock.FormationRepository {
   299  				repo := &automock.FormationRepository{}
   300  				repo.On("Update", ctxWithTenant, &modelFormation).Return(nil).Once()
   301  				return repo
   302  			},
   303  		},
   304  		{
   305  			Name: "Error when updating formation fails",
   306  			FormationRepoFn: func() *automock.FormationRepository {
   307  				repo := &automock.FormationRepository{}
   308  				repo.On("Update", ctxWithTenant, &modelFormation).Return(testErr).Once()
   309  				return repo
   310  			},
   311  			ExpectedErrMessage: fmt.Sprintf("An error occurred while updating formation with ID: %q", FormationID),
   312  		},
   313  	}
   314  
   315  	for _, testCase := range testCases {
   316  		t.Run(testCase.Name, func(t *testing.T) {
   317  			// GIVEN
   318  			formationRepo := testCase.FormationRepoFn()
   319  			defer formationRepo.AssertExpectations(t)
   320  
   321  			svc := formation.NewService(nil, nil, nil, nil, formationRepo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
   322  
   323  			// WHEN
   324  			err := svc.Update(ctxWithTenant, &modelFormation)
   325  
   326  			// THEN
   327  			if testCase.ExpectedErrMessage == "" {
   328  				require.NoError(t, err)
   329  			} else {
   330  				require.Error(t, err)
   331  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   332  			}
   333  		})
   334  	}
   335  }
   336  
   337  func TestServiceCreateFormation(t *testing.T) {
   338  	ctx := context.TODO()
   339  	ctx = tenant.SaveToContext(ctx, TntInternalID, TntExternalID)
   340  
   341  	in := model.Formation{
   342  		Name: testFormationName,
   343  	}
   344  
   345  	expectedFormation := fixFormationModelWithState(model.ReadyFormationState)
   346  	expectedFormationInInitialState := fixFormationModelWithState(model.InitialFormationState)
   347  
   348  	formationWithReadyState := fixFormationModelWithState(model.ReadyFormationState)
   349  	formationWithCreateErrorStateAndTechnicalAssignmentError := fixFormationModelWithStateAndAssignmentError(t, model.CreateErrorFormationState, testErr.Error(), formationassignment.TechnicalError)
   350  
   351  	testSchema, err := labeldef.NewSchemaForFormations([]string{testScenario})
   352  	assert.NoError(t, err)
   353  	testSchemaLblDef := fixScenariosLabelDefinition(TntInternalID, testSchema)
   354  
   355  	newSchema, err := labeldef.NewSchemaForFormations([]string{testScenario, testFormationName})
   356  	assert.NoError(t, err)
   357  	newSchemaLblDef := fixScenariosLabelDefinition(TntInternalID, newSchema)
   358  
   359  	emptySchemaLblDef := fixScenariosLabelDefinition(TntInternalID, testSchemaLblDef)
   360  	emptySchemaLblDef.Schema = nil
   361  
   362  	testCases := []struct {
   363  		Name                    string
   364  		FormationInput          *model.Formation
   365  		UUIDServiceFn           func() *automock.UuidService
   366  		LabelDefRepositoryFn    func() *automock.LabelDefRepository
   367  		LabelDefServiceFn       func() *automock.LabelDefService
   368  		NotificationsSvcFn      func() *automock.NotificationsService
   369  		FormationTemplateRepoFn func() *automock.FormationTemplateRepository
   370  		FormationRepoFn         func() *automock.FormationRepository
   371  		ConstraintEngineFn      func() *automock.ConstraintEngine
   372  		webhookRepoFn           func() *automock.WebhookRepository
   373  		StatusServiceFn         func() *automock.StatusService
   374  		TemplateName            string
   375  		ExpectedFormation       *model.Formation
   376  		ExpectedErrMessage      string
   377  	}{
   378  		{
   379  			Name: "success when no labeldef exists",
   380  			UUIDServiceFn: func() *automock.UuidService {
   381  				uuidService := &automock.UuidService{}
   382  				uuidService.On("Generate").Return(fixUUID())
   383  				return uuidService
   384  			},
   385  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   386  				labelDefRepo := &automock.LabelDefRepository{}
   387  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.LabelDefinition, ""))
   388  				return labelDefRepo
   389  			},
   390  			LabelDefServiceFn: func() *automock.LabelDefService {
   391  				labelDefService := &automock.LabelDefService{}
   392  				labelDefService.On("CreateWithFormations", ctx, TntInternalID, []string{testFormationName}).Return(nil)
   393  				return labelDefService
   394  			},
   395  			NotificationsSvcFn: func() *automock.NotificationsService {
   396  				notificationSvc := &automock.NotificationsService{}
   397  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(emptyFormationNotificationRequests, nil).Once()
   398  				return notificationSvc
   399  			},
   400  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   401  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   402  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   403  				return formationTemplateRepoMock
   404  			},
   405  			FormationRepoFn: func() *automock.FormationRepository {
   406  				formationRepoMock := &automock.FormationRepository{}
   407  				formationRepoMock.On("Create", ctx, formationWithReadyState).Return(nil).Once()
   408  				return formationRepoMock
   409  			},
   410  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   411  				engine := &automock.ConstraintEngine{}
   412  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   413  				engine.On("EnforceConstraints", ctx, postCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   414  				return engine
   415  			},
   416  			webhookRepoFn: func() *automock.WebhookRepository {
   417  				webhookRepo := &automock.WebhookRepository{}
   418  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
   419  				return webhookRepo
   420  			},
   421  			TemplateName:      testFormationTemplateName,
   422  			ExpectedFormation: expectedFormation,
   423  		},
   424  		{
   425  			Name: "success when labeldef exists",
   426  			UUIDServiceFn: func() *automock.UuidService {
   427  				uuidService := &automock.UuidService{}
   428  				uuidService.On("Generate").Return(fixUUID())
   429  				return uuidService
   430  			},
   431  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   432  				labelDefRepo := &automock.LabelDefRepository{}
   433  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   434  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
   435  				return labelDefRepo
   436  			},
   437  			LabelDefServiceFn: func() *automock.LabelDefService {
   438  				labelDefService := &automock.LabelDefService{}
   439  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   440  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   441  				return labelDefService
   442  			},
   443  			NotificationsSvcFn: func() *automock.NotificationsService {
   444  				notificationSvc := &automock.NotificationsService{}
   445  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(emptyFormationNotificationRequests, nil).Once()
   446  				return notificationSvc
   447  			},
   448  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   449  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   450  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   451  				return formationTemplateRepoMock
   452  			},
   453  			FormationRepoFn: func() *automock.FormationRepository {
   454  				formationRepoMock := &automock.FormationRepository{}
   455  				formationRepoMock.On("Create", ctx, formationWithReadyState).Return(nil).Once()
   456  				return formationRepoMock
   457  			},
   458  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   459  				engine := &automock.ConstraintEngine{}
   460  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   461  				engine.On("EnforceConstraints", ctx, postCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   462  				return engine
   463  			},
   464  			webhookRepoFn: func() *automock.WebhookRepository {
   465  				webhookRepo := &automock.WebhookRepository{}
   466  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
   467  				return webhookRepo
   468  			},
   469  			TemplateName:      testFormationTemplateName,
   470  			ExpectedFormation: expectedFormation,
   471  		},
   472  		{
   473  			Name: "success when state is provided externally",
   474  			UUIDServiceFn: func() *automock.UuidService {
   475  				uuidService := &automock.UuidService{}
   476  				uuidService.On("Generate").Return(fixUUID())
   477  				return uuidService
   478  			},
   479  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   480  				labelDefRepo := &automock.LabelDefRepository{}
   481  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   482  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
   483  				return labelDefRepo
   484  			},
   485  			LabelDefServiceFn: func() *automock.LabelDefService {
   486  				labelDefService := &automock.LabelDefService{}
   487  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   488  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   489  				return labelDefService
   490  			},
   491  			NotificationsSvcFn: func() *automock.NotificationsService {
   492  				notificationSvc := &automock.NotificationsService{}
   493  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithInitialState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(emptyFormationNotificationRequests, nil).Once()
   494  				return notificationSvc
   495  			},
   496  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   497  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   498  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   499  				return formationTemplateRepoMock
   500  			},
   501  			FormationRepoFn: func() *automock.FormationRepository {
   502  				formationRepoMock := &automock.FormationRepository{}
   503  				formationRepoMock.On("Create", ctx, formationWithInitialState).Return(nil).Once()
   504  				return formationRepoMock
   505  			},
   506  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   507  				engine := &automock.ConstraintEngine{}
   508  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   509  				engine.On("EnforceConstraints", ctx, postCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   510  				return engine
   511  			},
   512  			webhookRepoFn: func() *automock.WebhookRepository {
   513  				webhookRepo := &automock.WebhookRepository{}
   514  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
   515  				return webhookRepo
   516  			},
   517  			FormationInput: &model.Formation{
   518  				Name:  testFormationName,
   519  				State: model.InitialFormationState,
   520  			},
   521  			TemplateName:      testFormationTemplateName,
   522  			ExpectedFormation: expectedFormationInInitialState,
   523  		},
   524  		{
   525  			Name: "error when labeldef is missing and can not create it",
   526  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   527  				labelDefRepo := &automock.LabelDefRepository{}
   528  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.LabelDefinition, ""))
   529  				return labelDefRepo
   530  			},
   531  			LabelDefServiceFn: func() *automock.LabelDefService {
   532  				labelDefService := &automock.LabelDefService{}
   533  				labelDefService.On("CreateWithFormations", ctx, TntInternalID, []string{testFormationName}).Return(testErr)
   534  				return labelDefService
   535  			},
   536  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   537  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   538  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   539  				return formationTemplateRepoMock
   540  			},
   541  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   542  				engine := &automock.ConstraintEngine{}
   543  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   544  				return engine
   545  			},
   546  			TemplateName:       testFormationTemplateName,
   547  			ExpectedErrMessage: testErr.Error(),
   548  		},
   549  		{
   550  			Name: "error when labeldef is missing and create formation fails",
   551  			UUIDServiceFn: func() *automock.UuidService {
   552  				uuidService := &automock.UuidService{}
   553  				uuidService.On("Generate").Return(fixUUID())
   554  				return uuidService
   555  			},
   556  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   557  				labelDefRepo := &automock.LabelDefRepository{}
   558  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.LabelDefinition, ""))
   559  				return labelDefRepo
   560  			},
   561  			LabelDefServiceFn: func() *automock.LabelDefService {
   562  				labelDefService := &automock.LabelDefService{}
   563  				labelDefService.On("CreateWithFormations", ctx, TntInternalID, []string{testFormationName}).Return(nil)
   564  				return labelDefService
   565  			},
   566  			FormationRepoFn: func() *automock.FormationRepository {
   567  				formationRepoMock := &automock.FormationRepository{}
   568  				formationRepoMock.On("Create", ctx, formationWithReadyState).Return(testErr).Once()
   569  				return formationRepoMock
   570  			},
   571  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   572  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   573  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   574  				return formationTemplateRepoMock
   575  			},
   576  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   577  				engine := &automock.ConstraintEngine{}
   578  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   579  				return engine
   580  			},
   581  			webhookRepoFn: func() *automock.WebhookRepository {
   582  				webhookRepo := &automock.WebhookRepository{}
   583  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
   584  				return webhookRepo
   585  			},
   586  			TemplateName:       testFormationTemplateName,
   587  			ExpectedErrMessage: "An error occurred while creating formation with name",
   588  		},
   589  		{
   590  			Name: "error when can not get labeldef",
   591  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   592  				labelDefRepo := &automock.LabelDefRepository{}
   593  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(nil, testErr)
   594  				return labelDefRepo
   595  			},
   596  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   597  				engine := &automock.ConstraintEngine{}
   598  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   599  				return engine
   600  			},
   601  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   602  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   603  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   604  				return formationTemplateRepoMock
   605  			},
   606  			LabelDefServiceFn:  unusedLabelDefService,
   607  			TemplateName:       testFormationTemplateName,
   608  			ExpectedErrMessage: "while getting `scenarios` label definition: Test error",
   609  		},
   610  		{
   611  			Name: "error when labeldef's schema is missing",
   612  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   613  				labelDefRepo := &automock.LabelDefRepository{}
   614  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&emptySchemaLblDef, nil)
   615  				return labelDefRepo
   616  			},
   617  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   618  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   619  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   620  				return formationTemplateRepoMock
   621  			},
   622  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   623  				engine := &automock.ConstraintEngine{}
   624  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   625  				return engine
   626  			},
   627  			LabelDefServiceFn:  unusedLabelDefService,
   628  			TemplateName:       testFormationTemplateName,
   629  			ExpectedErrMessage: "missing schema",
   630  		},
   631  		{
   632  			Name: "error when validating existing labels against the schema",
   633  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   634  				labelDefRepo := &automock.LabelDefRepository{}
   635  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   636  				return labelDefRepo
   637  			},
   638  			LabelDefServiceFn: func() *automock.LabelDefService {
   639  				labelDefService := &automock.LabelDefService{}
   640  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, testSchemaLblDef.Key).Return(testErr)
   641  				return labelDefService
   642  			},
   643  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   644  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   645  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   646  				return formationTemplateRepoMock
   647  			},
   648  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   649  				engine := &automock.ConstraintEngine{}
   650  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   651  				return engine
   652  			},
   653  			TemplateName:       testFormationTemplateName,
   654  			ExpectedErrMessage: testErr.Error(),
   655  		},
   656  		{
   657  			Name: "error when validating automatic scenario assignment against the schema",
   658  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   659  				labelDefRepo := &automock.LabelDefRepository{}
   660  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   661  				return labelDefRepo
   662  			},
   663  			LabelDefServiceFn: func() *automock.LabelDefService {
   664  				labelDefService := &automock.LabelDefService{}
   665  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, testSchemaLblDef.Key).Return(nil)
   666  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, testSchemaLblDef.Key).Return(testErr)
   667  				return labelDefService
   668  			},
   669  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   670  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   671  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   672  				return formationTemplateRepoMock
   673  			},
   674  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   675  				engine := &automock.ConstraintEngine{}
   676  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   677  				return engine
   678  			},
   679  			TemplateName:       testFormationTemplateName,
   680  			ExpectedErrMessage: "while validating Scenario Assignments against a new schema",
   681  		},
   682  		{
   683  			Name: "error when update with version fails",
   684  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   685  				labelDefRepo := &automock.LabelDefRepository{}
   686  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   687  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(testErr)
   688  				return labelDefRepo
   689  			},
   690  			LabelDefServiceFn: func() *automock.LabelDefService {
   691  				labelDefService := &automock.LabelDefService{}
   692  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, testSchemaLblDef.Key).Return(nil)
   693  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, testSchemaLblDef.Key).Return(nil)
   694  				return labelDefService
   695  			},
   696  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   697  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   698  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   699  				return formationTemplateRepoMock
   700  			},
   701  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   702  				engine := &automock.ConstraintEngine{}
   703  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   704  				return engine
   705  			},
   706  			TemplateName:       testFormationTemplateName,
   707  			ExpectedErrMessage: testErr.Error(),
   708  		},
   709  		{
   710  			Name: "error when getting formation template by name fails",
   711  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   712  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   713  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(nil, testErr).Once()
   714  				return formationTemplateRepoMock
   715  			},
   716  			TemplateName:       testFormationTemplateName,
   717  			ExpectedErrMessage: "An error occurred while getting formation template by name",
   718  		},
   719  		{
   720  			Name: "error when creating formation fails",
   721  			UUIDServiceFn: func() *automock.UuidService {
   722  				uuidService := &automock.UuidService{}
   723  				uuidService.On("Generate").Return(fixUUID())
   724  				return uuidService
   725  			},
   726  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   727  				labelDefRepo := &automock.LabelDefRepository{}
   728  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   729  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
   730  				return labelDefRepo
   731  			},
   732  			LabelDefServiceFn: func() *automock.LabelDefService {
   733  				labelDefService := &automock.LabelDefService{}
   734  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   735  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   736  				return labelDefService
   737  			},
   738  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   739  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   740  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   741  				return formationTemplateRepoMock
   742  			},
   743  			FormationRepoFn: func() *automock.FormationRepository {
   744  				formationRepoMock := &automock.FormationRepository{}
   745  				formationRepoMock.On("Create", ctx, formationWithReadyState).Return(testErr).Once()
   746  				return formationRepoMock
   747  			},
   748  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   749  				engine := &automock.ConstraintEngine{}
   750  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   751  				return engine
   752  			},
   753  			webhookRepoFn: func() *automock.WebhookRepository {
   754  				webhookRepo := &automock.WebhookRepository{}
   755  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
   756  				return webhookRepo
   757  			},
   758  			TemplateName:       testFormationTemplateName,
   759  			ExpectedErrMessage: "An error occurred while creating formation with name: \"test-formation\"",
   760  		},
   761  		{
   762  			Name: "error while enforcing constraint pre operation",
   763  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   764  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   765  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   766  				return formationTemplateRepoMock
   767  			},
   768  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   769  				engine := &automock.ConstraintEngine{}
   770  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(testErr).Once()
   771  				return engine
   772  			},
   773  			TemplateName:       testFormationTemplateName,
   774  			ExpectedErrMessage: "while enforcing constraints for target operation \"CREATE_FORMATION\" and constraint type \"PRE\": Test error",
   775  		},
   776  		{
   777  			Name: "error when listing formation template's webhooks fails",
   778  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   779  				labelDefRepo := &automock.LabelDefRepository{}
   780  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   781  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
   782  				return labelDefRepo
   783  			},
   784  			LabelDefServiceFn: func() *automock.LabelDefService {
   785  				labelDefService := &automock.LabelDefService{}
   786  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   787  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   788  				return labelDefService
   789  			},
   790  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   791  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   792  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   793  				return formationTemplateRepoMock
   794  			},
   795  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   796  				engine := &automock.ConstraintEngine{}
   797  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   798  				return engine
   799  			},
   800  			webhookRepoFn: func() *automock.WebhookRepository {
   801  				webhookRepo := &automock.WebhookRepository{}
   802  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(nil, testErr).Once()
   803  				return webhookRepo
   804  			},
   805  			TemplateName:       testFormationTemplateName,
   806  			ExpectedErrMessage: "when listing formation lifecycle webhooks for formation template with ID",
   807  		},
   808  		{
   809  			Name: "error while enforcing constraints post operation",
   810  			UUIDServiceFn: func() *automock.UuidService {
   811  				uuidService := &automock.UuidService{}
   812  				uuidService.On("Generate").Return(fixUUID())
   813  				return uuidService
   814  			},
   815  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   816  				labelDefRepo := &automock.LabelDefRepository{}
   817  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.LabelDefinition, ""))
   818  				return labelDefRepo
   819  			},
   820  			LabelDefServiceFn: func() *automock.LabelDefService {
   821  				labelDefService := &automock.LabelDefService{}
   822  				labelDefService.On("CreateWithFormations", ctx, TntInternalID, []string{testFormationName}).Return(nil)
   823  				return labelDefService
   824  			},
   825  			NotificationsSvcFn: func() *automock.NotificationsService {
   826  				notificationSvc := &automock.NotificationsService{}
   827  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(emptyFormationNotificationRequests, nil).Once()
   828  				return notificationSvc
   829  			},
   830  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   831  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   832  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   833  				return formationTemplateRepoMock
   834  			},
   835  			FormationRepoFn: func() *automock.FormationRepository {
   836  				formationRepoMock := &automock.FormationRepository{}
   837  				formationRepoMock.On("Create", ctx, formationWithReadyState).Return(nil).Once()
   838  				return formationRepoMock
   839  			},
   840  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   841  				engine := &automock.ConstraintEngine{}
   842  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   843  				engine.On("EnforceConstraints", ctx, postCreateLocation, createFormationDetails, FormationTemplateID).Return(testErr).Once()
   844  				return engine
   845  			},
   846  			webhookRepoFn: func() *automock.WebhookRepository {
   847  				webhookRepo := &automock.WebhookRepository{}
   848  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
   849  				return webhookRepo
   850  			},
   851  			TemplateName:       testFormationTemplateName,
   852  			ExpectedErrMessage: "while enforcing constraints for target operation \"CREATE_FORMATION\" and constraint type \"POST\": Test error",
   853  		},
   854  		{
   855  			Name: "Success when there is formation notifications",
   856  			UUIDServiceFn: func() *automock.UuidService {
   857  				uuidService := &automock.UuidService{}
   858  				uuidService.On("Generate").Return(fixUUID())
   859  				return uuidService
   860  			},
   861  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   862  				labelDefRepo := &automock.LabelDefRepository{}
   863  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   864  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
   865  				return labelDefRepo
   866  			},
   867  			LabelDefServiceFn: func() *automock.LabelDefService {
   868  				labelDefService := &automock.LabelDefService{}
   869  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   870  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   871  				return labelDefService
   872  			},
   873  			NotificationsSvcFn: func() *automock.NotificationsService {
   874  				notificationSvc := &automock.NotificationsService{}
   875  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, formationWithInitialState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
   876  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(formationNotificationWebhookSuccessResponse, nil).Once()
   877  				return notificationSvc
   878  			},
   879  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   880  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   881  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   882  				return formationTemplateRepoMock
   883  			},
   884  			FormationRepoFn: func() *automock.FormationRepository {
   885  				formationRepoMock := &automock.FormationRepository{}
   886  				formationRepoMock.On("Create", ctx, formationWithInitialState).Return(nil).Once()
   887  				return formationRepoMock
   888  			},
   889  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   890  				engine := &automock.ConstraintEngine{}
   891  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   892  				engine.On("EnforceConstraints", ctx, postCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   893  				return engine
   894  			},
   895  			webhookRepoFn: func() *automock.WebhookRepository {
   896  				webhookRepo := &automock.WebhookRepository{}
   897  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
   898  				return webhookRepo
   899  			},
   900  			StatusServiceFn: func() *automock.StatusService {
   901  				svc := &automock.StatusService{}
   902  				svc.On("UpdateWithConstraints", ctx, formationWithReadyState, model.CreateFormation).Return(nil).Once()
   903  				return svc
   904  			},
   905  			TemplateName:      testFormationTemplateName,
   906  			ExpectedFormation: formationWithReadyState,
   907  		},
   908  		{
   909  			Name: "Success when there is formation notifications with ASYNC_CALLBACK",
   910  			UUIDServiceFn: func() *automock.UuidService {
   911  				uuidService := &automock.UuidService{}
   912  				uuidService.On("Generate").Return(fixUUID())
   913  				return uuidService
   914  			},
   915  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   916  				labelDefRepo := &automock.LabelDefRepository{}
   917  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   918  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
   919  				return labelDefRepo
   920  			},
   921  			LabelDefServiceFn: func() *automock.LabelDefService {
   922  				labelDefService := &automock.LabelDefService{}
   923  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   924  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   925  				return labelDefService
   926  			},
   927  			NotificationsSvcFn: func() *automock.NotificationsService {
   928  				notificationSvc := &automock.NotificationsService{}
   929  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleAsyncWebhooks, TntInternalID, formationWithInitialState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationAsyncCreateRequests, nil).Once()
   930  				notificationSvc.On("SendNotification", ctx, formationNotificationAsyncCreateRequest).Return(formationNotificationWebhookSuccessResponse, nil).Once()
   931  				return notificationSvc
   932  			},
   933  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   934  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   935  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   936  				return formationTemplateRepoMock
   937  			},
   938  			FormationRepoFn: func() *automock.FormationRepository {
   939  				formationRepoMock := &automock.FormationRepository{}
   940  				formationRepoMock.On("Create", ctx, formationWithInitialState).Return(nil).Once()
   941  				formationRepoMock.On("Update", ctx, formationWithInitialState).Return(nil).Once()
   942  				return formationRepoMock
   943  			},
   944  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   945  				engine := &automock.ConstraintEngine{}
   946  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   947  				engine.On("EnforceConstraints", ctx, postCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   948  				return engine
   949  			},
   950  			webhookRepoFn: func() *automock.WebhookRepository {
   951  				webhookRepo := &automock.WebhookRepository{}
   952  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleAsyncWebhooks, nil).Once()
   953  				return webhookRepo
   954  			},
   955  			TemplateName:      testFormationTemplateName,
   956  			ExpectedFormation: formationWithInitialState,
   957  		},
   958  		{
   959  			Name: "Error when there is formation notifications but webhook response status is incorrect",
   960  			UUIDServiceFn: func() *automock.UuidService {
   961  				uuidService := &automock.UuidService{}
   962  				uuidService.On("Generate").Return(fixUUID())
   963  				return uuidService
   964  			},
   965  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
   966  				labelDefRepo := &automock.LabelDefRepository{}
   967  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
   968  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
   969  				return labelDefRepo
   970  			},
   971  			LabelDefServiceFn: func() *automock.LabelDefService {
   972  				labelDefService := &automock.LabelDefService{}
   973  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   974  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
   975  				return labelDefService
   976  			},
   977  			NotificationsSvcFn: func() *automock.NotificationsService {
   978  				notificationSvc := &automock.NotificationsService{}
   979  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, formationWithInitialState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
   980  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(formationNotificationWebhookErrorResponse, nil).Once()
   981  				return notificationSvc
   982  			},
   983  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   984  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
   985  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
   986  				return formationTemplateRepoMock
   987  			},
   988  			FormationRepoFn: func() *automock.FormationRepository {
   989  				formationRepoMock := &automock.FormationRepository{}
   990  				formationRepoMock.On("Create", ctx, formationWithInitialState).Return(nil).Once()
   991  				return formationRepoMock
   992  			},
   993  			ConstraintEngineFn: func() *automock.ConstraintEngine {
   994  				engine := &automock.ConstraintEngine{}
   995  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   996  				engine.On("EnforceConstraints", ctx, postCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
   997  				return engine
   998  			},
   999  			webhookRepoFn: func() *automock.WebhookRepository {
  1000  				webhookRepo := &automock.WebhookRepository{}
  1001  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  1002  				return webhookRepo
  1003  			},
  1004  			StatusServiceFn: func() *automock.StatusService {
  1005  				svc := &automock.StatusService{}
  1006  				svc.On("SetFormationToErrorStateWithConstraints", ctx, formationWithInitialState, testErr.Error(), formationassignment.AssignmentErrorCode(formationassignment.ClientError), model.CreateErrorFormationState, model.CreateFormation).Return(nil).Once()
  1007  				return svc
  1008  			},
  1009  			TemplateName:      testFormationTemplateName,
  1010  			ExpectedFormation: formationWithInitialState,
  1011  		},
  1012  		{
  1013  			Name: "Error when generating formation notification fails",
  1014  			UUIDServiceFn: func() *automock.UuidService {
  1015  				uuidService := &automock.UuidService{}
  1016  				uuidService.On("Generate").Return(fixUUID())
  1017  				return uuidService
  1018  			},
  1019  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1020  				labelDefRepo := &automock.LabelDefRepository{}
  1021  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1022  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  1023  				return labelDefRepo
  1024  			},
  1025  			LabelDefServiceFn: func() *automock.LabelDefService {
  1026  				labelDefService := &automock.LabelDefService{}
  1027  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1028  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1029  				return labelDefService
  1030  			},
  1031  			NotificationsSvcFn: func() *automock.NotificationsService {
  1032  				notificationSvc := &automock.NotificationsService{}
  1033  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, formationWithInitialState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(nil, testErr).Once()
  1034  				return notificationSvc
  1035  			},
  1036  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1037  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
  1038  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
  1039  				return formationTemplateRepoMock
  1040  			},
  1041  			FormationRepoFn: func() *automock.FormationRepository {
  1042  				formationRepoMock := &automock.FormationRepository{}
  1043  				formationRepoMock.On("Create", ctx, formationWithInitialState).Return(nil).Once()
  1044  				return formationRepoMock
  1045  			},
  1046  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1047  				engine := &automock.ConstraintEngine{}
  1048  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
  1049  				return engine
  1050  			},
  1051  			webhookRepoFn: func() *automock.WebhookRepository {
  1052  				webhookRepo := &automock.WebhookRepository{}
  1053  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  1054  				return webhookRepo
  1055  			},
  1056  			TemplateName:       testFormationTemplateName,
  1057  			ExpectedFormation:  nil,
  1058  			ExpectedErrMessage: "while generating notifications for formation with ID",
  1059  		},
  1060  		{
  1061  			Name: "Error when sending formation notifications fails",
  1062  			UUIDServiceFn: func() *automock.UuidService {
  1063  				uuidService := &automock.UuidService{}
  1064  				uuidService.On("Generate").Return(fixUUID())
  1065  				return uuidService
  1066  			},
  1067  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1068  				labelDefRepo := &automock.LabelDefRepository{}
  1069  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1070  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  1071  				return labelDefRepo
  1072  			},
  1073  			LabelDefServiceFn: func() *automock.LabelDefService {
  1074  				labelDefService := &automock.LabelDefService{}
  1075  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1076  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1077  				return labelDefService
  1078  			},
  1079  			NotificationsSvcFn: func() *automock.NotificationsService {
  1080  				notificationSvc := &automock.NotificationsService{}
  1081  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, formationWithInitialState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
  1082  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(nil, testErr).Once()
  1083  				return notificationSvc
  1084  			},
  1085  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1086  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
  1087  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
  1088  				return formationTemplateRepoMock
  1089  			},
  1090  			FormationRepoFn: func() *automock.FormationRepository {
  1091  				formationRepoMock := &automock.FormationRepository{}
  1092  				formationRepoMock.On("Create", ctx, formationWithInitialState).Return(nil).Once()
  1093  				formationRepoMock.On("Update", ctx, formationWithCreateErrorStateAndTechnicalAssignmentError).Return(nil).Once()
  1094  				return formationRepoMock
  1095  			},
  1096  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1097  				engine := &automock.ConstraintEngine{}
  1098  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
  1099  				return engine
  1100  			},
  1101  			webhookRepoFn: func() *automock.WebhookRepository {
  1102  				webhookRepo := &automock.WebhookRepository{}
  1103  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  1104  				return webhookRepo
  1105  			},
  1106  			TemplateName:       testFormationTemplateName,
  1107  			ExpectedFormation:  nil,
  1108  			ExpectedErrMessage: "while sending notification for formation with ID",
  1109  		},
  1110  		{
  1111  			Name: "Error when sending formation notifications fails and subsequently formation update fails",
  1112  			UUIDServiceFn: func() *automock.UuidService {
  1113  				uuidService := &automock.UuidService{}
  1114  				uuidService.On("Generate").Return(fixUUID())
  1115  				return uuidService
  1116  			},
  1117  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1118  				labelDefRepo := &automock.LabelDefRepository{}
  1119  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1120  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  1121  				return labelDefRepo
  1122  			},
  1123  			LabelDefServiceFn: func() *automock.LabelDefService {
  1124  				labelDefService := &automock.LabelDefService{}
  1125  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1126  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1127  				return labelDefService
  1128  			},
  1129  			NotificationsSvcFn: func() *automock.NotificationsService {
  1130  				notificationSvc := &automock.NotificationsService{}
  1131  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, formationWithInitialState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
  1132  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(nil, testErr).Once()
  1133  				return notificationSvc
  1134  			},
  1135  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1136  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
  1137  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
  1138  				return formationTemplateRepoMock
  1139  			},
  1140  			FormationRepoFn: func() *automock.FormationRepository {
  1141  				formationRepoMock := &automock.FormationRepository{}
  1142  				formationRepoMock.On("Create", ctx, formationWithInitialState).Return(nil).Once()
  1143  				formationRepoMock.On("Update", ctx, formationWithCreateErrorStateAndTechnicalAssignmentError).Return(testErr).Once()
  1144  				return formationRepoMock
  1145  			},
  1146  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1147  				engine := &automock.ConstraintEngine{}
  1148  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
  1149  				return engine
  1150  			},
  1151  			webhookRepoFn: func() *automock.WebhookRepository {
  1152  				webhookRepo := &automock.WebhookRepository{}
  1153  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  1154  				return webhookRepo
  1155  			},
  1156  			TemplateName:       testFormationTemplateName,
  1157  			ExpectedFormation:  nil,
  1158  			ExpectedErrMessage: "while updating error state",
  1159  		},
  1160  		{
  1161  			Name: "Error when there is formation notifications, webhook response status is incorrect and setting formation to error state with constraints fails",
  1162  			UUIDServiceFn: func() *automock.UuidService {
  1163  				uuidService := &automock.UuidService{}
  1164  				uuidService.On("Generate").Return(fixUUID())
  1165  				return uuidService
  1166  			},
  1167  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1168  				labelDefRepo := &automock.LabelDefRepository{}
  1169  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1170  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  1171  				return labelDefRepo
  1172  			},
  1173  			LabelDefServiceFn: func() *automock.LabelDefService {
  1174  				labelDefService := &automock.LabelDefService{}
  1175  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1176  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1177  				return labelDefService
  1178  			},
  1179  			NotificationsSvcFn: func() *automock.NotificationsService {
  1180  				notificationSvc := &automock.NotificationsService{}
  1181  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, formationWithInitialState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
  1182  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(formationNotificationWebhookErrorResponse, nil).Once()
  1183  				return notificationSvc
  1184  			},
  1185  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1186  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
  1187  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
  1188  				return formationTemplateRepoMock
  1189  			},
  1190  			FormationRepoFn: func() *automock.FormationRepository {
  1191  				formationRepoMock := &automock.FormationRepository{}
  1192  				formationRepoMock.On("Create", ctx, formationWithInitialState).Return(nil).Once()
  1193  				return formationRepoMock
  1194  			},
  1195  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1196  				engine := &automock.ConstraintEngine{}
  1197  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
  1198  				return engine
  1199  			},
  1200  			webhookRepoFn: func() *automock.WebhookRepository {
  1201  				webhookRepo := &automock.WebhookRepository{}
  1202  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  1203  				return webhookRepo
  1204  			},
  1205  			StatusServiceFn: func() *automock.StatusService {
  1206  				svc := &automock.StatusService{}
  1207  				svc.On("SetFormationToErrorStateWithConstraints", ctx, formationWithInitialState, testErr.Error(), formationassignment.AssignmentErrorCode(formationassignment.ClientError), model.CreateErrorFormationState, model.CreateFormation).Return(testErr).Once()
  1208  				return svc
  1209  			},
  1210  			TemplateName:       testFormationTemplateName,
  1211  			ExpectedFormation:  nil,
  1212  			ExpectedErrMessage: "while updating error state for formation with ID",
  1213  		},
  1214  		{
  1215  			Name: "Error when there is formation notifications, webhook response status is correct but the formation update with constraints fails",
  1216  			UUIDServiceFn: func() *automock.UuidService {
  1217  				uuidService := &automock.UuidService{}
  1218  				uuidService.On("Generate").Return(fixUUID())
  1219  				return uuidService
  1220  			},
  1221  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1222  				labelDefRepo := &automock.LabelDefRepository{}
  1223  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1224  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  1225  				return labelDefRepo
  1226  			},
  1227  			LabelDefServiceFn: func() *automock.LabelDefService {
  1228  				labelDefService := &automock.LabelDefService{}
  1229  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1230  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1231  				return labelDefService
  1232  			},
  1233  			NotificationsSvcFn: func() *automock.NotificationsService {
  1234  				notificationSvc := &automock.NotificationsService{}
  1235  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, formationWithInitialState, testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
  1236  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(formationNotificationWebhookSuccessResponse, nil).Once()
  1237  				return notificationSvc
  1238  			},
  1239  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1240  				formationTemplateRepoMock := &automock.FormationTemplateRepository{}
  1241  				formationTemplateRepoMock.On("GetByNameAndTenant", ctx, testFormationTemplateName, TntInternalID).Return(fixFormationTemplateModel(), nil).Once()
  1242  				return formationTemplateRepoMock
  1243  			},
  1244  			FormationRepoFn: func() *automock.FormationRepository {
  1245  				formationRepoMock := &automock.FormationRepository{}
  1246  				formationRepoMock.On("Create", ctx, formationWithInitialState).Return(nil).Once()
  1247  				return formationRepoMock
  1248  			},
  1249  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1250  				engine := &automock.ConstraintEngine{}
  1251  				engine.On("EnforceConstraints", ctx, preCreateLocation, createFormationDetails, FormationTemplateID).Return(nil).Once()
  1252  				return engine
  1253  			},
  1254  			webhookRepoFn: func() *automock.WebhookRepository {
  1255  				webhookRepo := &automock.WebhookRepository{}
  1256  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  1257  				return webhookRepo
  1258  			},
  1259  			StatusServiceFn: func() *automock.StatusService {
  1260  				svc := &automock.StatusService{}
  1261  				svc.On("UpdateWithConstraints", ctx, formationWithReadyState, model.CreateFormation).Return(testErr).Once()
  1262  				return svc
  1263  			},
  1264  			TemplateName:       testFormationTemplateName,
  1265  			ExpectedErrMessage: testErr.Error(),
  1266  		},
  1267  	}
  1268  
  1269  	for _, testCase := range testCases {
  1270  		t.Run(testCase.Name, func(t *testing.T) {
  1271  			// GIVEN
  1272  			input := testCase.FormationInput
  1273  			if input == nil {
  1274  				input = &in
  1275  			}
  1276  
  1277  			uidService := unusedUUIDService()
  1278  			if testCase.UUIDServiceFn != nil {
  1279  				uidService = testCase.UUIDServiceFn()
  1280  			}
  1281  			labelDefRepo := unusedLabelDefRepository()
  1282  			if testCase.LabelDefServiceFn != nil {
  1283  				labelDefRepo = testCase.LabelDefRepositoryFn()
  1284  			}
  1285  			labelDefService := unusedLabelDefService()
  1286  			if testCase.LabelDefServiceFn != nil {
  1287  				labelDefService = testCase.LabelDefServiceFn()
  1288  			}
  1289  
  1290  			notificationsService := unusedNotificationsService()
  1291  			if testCase.NotificationsSvcFn != nil {
  1292  				notificationsService = testCase.NotificationsSvcFn()
  1293  			}
  1294  
  1295  			formationRepo := unusedFormationRepo()
  1296  			if testCase.FormationRepoFn != nil {
  1297  				formationRepo = testCase.FormationRepoFn()
  1298  			}
  1299  			formationTemplateRepo := unusedFormationTemplateRepo()
  1300  			if testCase.FormationTemplateRepoFn != nil {
  1301  				formationTemplateRepo = testCase.FormationTemplateRepoFn()
  1302  			}
  1303  			constraintEngine := unusedConstraintEngine()
  1304  			if testCase.ConstraintEngineFn != nil {
  1305  				constraintEngine = testCase.ConstraintEngineFn()
  1306  			}
  1307  			webhookRepo := unusedWebhookRepository()
  1308  			if testCase.webhookRepoFn != nil {
  1309  				webhookRepo = testCase.webhookRepoFn()
  1310  			}
  1311  
  1312  			statusSvc := &automock.StatusService{}
  1313  			if testCase.StatusServiceFn != nil {
  1314  				statusSvc = testCase.StatusServiceFn()
  1315  			}
  1316  
  1317  			svc := formation.NewService(nil, nil, labelDefRepo, nil, formationRepo, formationTemplateRepo, nil, uidService, labelDefService, nil, nil, nil, nil, nil, nil, nil, notificationsService, constraintEngine, webhookRepo, statusSvc, runtimeType, applicationType)
  1318  
  1319  			// WHEN
  1320  			actual, err := svc.CreateFormation(ctx, TntInternalID, *input, testCase.TemplateName)
  1321  
  1322  			// THEN
  1323  			if testCase.ExpectedErrMessage == "" {
  1324  				require.NoError(t, err)
  1325  				assert.Equal(t, testCase.ExpectedFormation, actual)
  1326  			} else {
  1327  				require.Error(t, err)
  1328  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  1329  				require.Nil(t, actual)
  1330  			}
  1331  
  1332  			mock.AssertExpectationsForObjects(t, uidService, labelDefRepo, labelDefService, notificationsService, formationRepo, formationTemplateRepo, constraintEngine, webhookRepo, statusSvc)
  1333  		})
  1334  	}
  1335  }
  1336  
  1337  func TestServiceDeleteFormation(t *testing.T) {
  1338  	ctx := context.TODO()
  1339  	ctx = tenant.SaveToContext(ctx, TntInternalID, TntExternalID)
  1340  
  1341  	in := model.Formation{
  1342  		Name: testFormationName,
  1343  	}
  1344  
  1345  	formationWithCreateErrorStateAndTechnicalAssignmentError := fixFormationModelWithStateAndAssignmentError(t, model.DeleteErrorFormationState, testErr.Error(), formationassignment.TechnicalError)
  1346  
  1347  	expectedFormation := fixFormationModelWithState(model.ReadyFormationState)
  1348  
  1349  	formationWithReadyState := fixFormationModelWithState(model.ReadyFormationState)
  1350  
  1351  	testSchema, err := labeldef.NewSchemaForFormations([]string{testScenario, testFormationName})
  1352  	assert.NoError(t, err)
  1353  	testSchemaLblDef := fixScenariosLabelDefinition(TntInternalID, testSchema)
  1354  
  1355  	newSchema, err := labeldef.NewSchemaForFormations([]string{testScenario})
  1356  	assert.NoError(t, err)
  1357  	newSchemaLblDef := fixScenariosLabelDefinition(TntInternalID, newSchema)
  1358  
  1359  	nilSchemaLblDef := fixScenariosLabelDefinition(TntInternalID, testSchema)
  1360  	nilSchemaLblDef.Schema = nil
  1361  
  1362  	testCases := []struct {
  1363  		Name                    string
  1364  		LabelDefRepositoryFn    func() *automock.LabelDefRepository
  1365  		LabelDefServiceFn       func() *automock.LabelDefService
  1366  		NotificationsSvcFn      func() *automock.NotificationsService
  1367  		FormationRepoFn         func() *automock.FormationRepository
  1368  		FormationTemplateRepoFn func() *automock.FormationTemplateRepository
  1369  		ConstraintEngineFn      func() *automock.ConstraintEngine
  1370  		webhookRepoFn           func() *automock.WebhookRepository
  1371  		InputFormation          model.Formation
  1372  		ExpectedFormation       *model.Formation
  1373  		ExpectedErrMessage      string
  1374  	}{
  1375  		{
  1376  			Name: "success",
  1377  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1378  				labelDefRepo := &automock.LabelDefRepository{}
  1379  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1380  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  1381  				return labelDefRepo
  1382  			},
  1383  			LabelDefServiceFn: func() *automock.LabelDefService {
  1384  				labelDefService := &automock.LabelDefService{}
  1385  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1386  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1387  				return labelDefService
  1388  			},
  1389  			NotificationsSvcFn: func() *automock.NotificationsService {
  1390  				notificationSvc := &automock.NotificationsService{}
  1391  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(emptyFormationNotificationRequests, nil).Once()
  1392  				return notificationSvc
  1393  			},
  1394  			FormationRepoFn: func() *automock.FormationRepository {
  1395  				formationRepoMock := &automock.FormationRepository{}
  1396  				formationRepoMock.On("DeleteByName", ctx, TntInternalID, testFormationName).Return(nil).Once()
  1397  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1398  				return formationRepoMock
  1399  			},
  1400  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1401  				repo := &automock.FormationTemplateRepository{}
  1402  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1403  				return repo
  1404  			},
  1405  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1406  				engine := &automock.ConstraintEngine{}
  1407  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1408  				engine.On("EnforceConstraints", ctx, postDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1409  				return engine
  1410  			},
  1411  			webhookRepoFn: func() *automock.WebhookRepository {
  1412  				webhookRepo := &automock.WebhookRepository{}
  1413  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1414  				return webhookRepo
  1415  			},
  1416  			InputFormation:    in,
  1417  			ExpectedFormation: expectedFormation,
  1418  		},
  1419  		{
  1420  			Name: "success when formation has async webhook",
  1421  			NotificationsSvcFn: func() *automock.NotificationsService {
  1422  				notificationSvc := &automock.NotificationsService{}
  1423  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleAsyncWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(formationNotificationAsyncDeleteRequests, nil).Once()
  1424  				notificationSvc.On("SendNotification", ctx, formationNotificationAsyncDeleteRequest).Return(fixFormationNotificationWebhookResponse(200, 200, nil), nil).Once()
  1425  				return notificationSvc
  1426  			},
  1427  			FormationRepoFn: func() *automock.FormationRepository {
  1428  				formationRepoMock := &automock.FormationRepository{}
  1429  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(fixFormationModelWithState(model.ReadyFormationState), nil).Once()
  1430  				formationRepoMock.On("Update", ctx, fixFormationModelWithState(model.DeletingFormationState)).Return(nil).Once()
  1431  				return formationRepoMock
  1432  			},
  1433  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1434  				repo := &automock.FormationTemplateRepository{}
  1435  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1436  				return repo
  1437  			},
  1438  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1439  				engine := &automock.ConstraintEngine{}
  1440  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1441  				return engine
  1442  			},
  1443  			webhookRepoFn: func() *automock.WebhookRepository {
  1444  				webhookRepo := &automock.WebhookRepository{}
  1445  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleAsyncWebhooks, nil).Once()
  1446  				return webhookRepo
  1447  			},
  1448  			InputFormation:    in,
  1449  			ExpectedFormation: fixFormationModelWithState(model.DeletingFormationState),
  1450  		},
  1451  		{
  1452  			Name: "error when formation has async webhook and updating to deleting state fails",
  1453  			NotificationsSvcFn: func() *automock.NotificationsService {
  1454  				notificationSvc := &automock.NotificationsService{}
  1455  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleAsyncWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(formationNotificationAsyncDeleteRequests, nil).Once()
  1456  				notificationSvc.On("SendNotification", ctx, formationNotificationAsyncDeleteRequest).Return(fixFormationNotificationWebhookResponse(200, 200, nil), nil).Once()
  1457  				return notificationSvc
  1458  			},
  1459  			FormationRepoFn: func() *automock.FormationRepository {
  1460  				formationRepoMock := &automock.FormationRepository{}
  1461  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(fixFormationModelWithState(model.ReadyFormationState), nil).Once()
  1462  				formationRepoMock.On("Update", ctx, fixFormationModelWithState(model.DeletingFormationState)).Return(testErr).Once()
  1463  				return formationRepoMock
  1464  			},
  1465  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1466  				repo := &automock.FormationTemplateRepository{}
  1467  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1468  				return repo
  1469  			},
  1470  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1471  				engine := &automock.ConstraintEngine{}
  1472  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1473  				return engine
  1474  			},
  1475  			webhookRepoFn: func() *automock.WebhookRepository {
  1476  				webhookRepo := &automock.WebhookRepository{}
  1477  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleAsyncWebhooks, nil).Once()
  1478  				return webhookRepo
  1479  			},
  1480  			InputFormation:     in,
  1481  			ExpectedErrMessage: testErr.Error(),
  1482  		},
  1483  		{
  1484  			Name: "error when can not get labeldef",
  1485  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1486  				labelDefRepo := &automock.LabelDefRepository{}
  1487  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(nil, testErr).Once()
  1488  				return labelDefRepo
  1489  			},
  1490  			NotificationsSvcFn: func() *automock.NotificationsService {
  1491  				notificationSvc := &automock.NotificationsService{}
  1492  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(emptyFormationNotificationRequests, nil).Once()
  1493  				return notificationSvc
  1494  			},
  1495  			FormationRepoFn: func() *automock.FormationRepository {
  1496  				formationRepoMock := &automock.FormationRepository{}
  1497  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1498  				return formationRepoMock
  1499  			},
  1500  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1501  				repo := &automock.FormationTemplateRepository{}
  1502  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1503  				return repo
  1504  			},
  1505  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1506  				engine := &automock.ConstraintEngine{}
  1507  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1508  				return engine
  1509  			},
  1510  			webhookRepoFn: func() *automock.WebhookRepository {
  1511  				webhookRepo := &automock.WebhookRepository{}
  1512  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1513  				return webhookRepo
  1514  			},
  1515  			InputFormation:     in,
  1516  			ExpectedErrMessage: "while getting `scenarios` label definition: Test error",
  1517  		},
  1518  		{
  1519  			Name: "error when labeldef's schema is missing",
  1520  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1521  				labelDefRepo := &automock.LabelDefRepository{}
  1522  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&nilSchemaLblDef, nil)
  1523  				return labelDefRepo
  1524  			},
  1525  			NotificationsSvcFn: func() *automock.NotificationsService {
  1526  				notificationSvc := &automock.NotificationsService{}
  1527  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(emptyFormationNotificationRequests, nil).Once()
  1528  				return notificationSvc
  1529  			},
  1530  			FormationRepoFn: func() *automock.FormationRepository {
  1531  				formationRepoMock := &automock.FormationRepository{}
  1532  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1533  				return formationRepoMock
  1534  			},
  1535  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1536  				repo := &automock.FormationTemplateRepository{}
  1537  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1538  				return repo
  1539  			},
  1540  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1541  				engine := &automock.ConstraintEngine{}
  1542  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1543  				return engine
  1544  			},
  1545  			webhookRepoFn: func() *automock.WebhookRepository {
  1546  				webhookRepo := &automock.WebhookRepository{}
  1547  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1548  				return webhookRepo
  1549  			},
  1550  			InputFormation:     in,
  1551  			ExpectedErrMessage: "missing schema",
  1552  		},
  1553  		{
  1554  			Name: "error when validating existing labels against the schema",
  1555  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1556  				labelDefRepo := &automock.LabelDefRepository{}
  1557  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1558  				return labelDefRepo
  1559  			},
  1560  			LabelDefServiceFn: func() *automock.LabelDefService {
  1561  				labelDefService := &automock.LabelDefService{}
  1562  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(testErr)
  1563  				return labelDefService
  1564  			},
  1565  			NotificationsSvcFn: func() *automock.NotificationsService {
  1566  				notificationSvc := &automock.NotificationsService{}
  1567  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(emptyFormationNotificationRequests, nil).Once()
  1568  				return notificationSvc
  1569  			},
  1570  			FormationRepoFn: func() *automock.FormationRepository {
  1571  				formationRepoMock := &automock.FormationRepository{}
  1572  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1573  				return formationRepoMock
  1574  			},
  1575  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1576  				repo := &automock.FormationTemplateRepository{}
  1577  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1578  				return repo
  1579  			},
  1580  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1581  				engine := &automock.ConstraintEngine{}
  1582  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1583  				return engine
  1584  			},
  1585  			webhookRepoFn: func() *automock.WebhookRepository {
  1586  				webhookRepo := &automock.WebhookRepository{}
  1587  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1588  				return webhookRepo
  1589  			},
  1590  			InputFormation:     in,
  1591  			ExpectedErrMessage: testErr.Error(),
  1592  		},
  1593  		{
  1594  			Name: "error when validating automatic scenario assignment against the schema",
  1595  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1596  				labelDefRepo := &automock.LabelDefRepository{}
  1597  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1598  				return labelDefRepo
  1599  			},
  1600  			LabelDefServiceFn: func() *automock.LabelDefService {
  1601  				labelDefService := &automock.LabelDefService{}
  1602  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1603  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(testErr)
  1604  				return labelDefService
  1605  			},
  1606  			NotificationsSvcFn: func() *automock.NotificationsService {
  1607  				notificationSvc := &automock.NotificationsService{}
  1608  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(emptyFormationNotificationRequests, nil).Once()
  1609  				return notificationSvc
  1610  			},
  1611  			FormationRepoFn: func() *automock.FormationRepository {
  1612  				formationRepoMock := &automock.FormationRepository{}
  1613  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1614  				return formationRepoMock
  1615  			},
  1616  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1617  				repo := &automock.FormationTemplateRepository{}
  1618  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1619  				return repo
  1620  			},
  1621  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1622  				engine := &automock.ConstraintEngine{}
  1623  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1624  				return engine
  1625  			},
  1626  			webhookRepoFn: func() *automock.WebhookRepository {
  1627  				webhookRepo := &automock.WebhookRepository{}
  1628  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1629  				return webhookRepo
  1630  			},
  1631  			InputFormation:     in,
  1632  			ExpectedErrMessage: "while validating Scenario Assignments against a new schema: Test error",
  1633  		},
  1634  		{
  1635  			Name: "error when update with version fails",
  1636  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1637  				labelDefRepo := &automock.LabelDefRepository{}
  1638  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&newSchemaLblDef, nil)
  1639  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(testErr)
  1640  				return labelDefRepo
  1641  			},
  1642  			LabelDefServiceFn: func() *automock.LabelDefService {
  1643  				labelDefService := &automock.LabelDefService{}
  1644  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, newSchemaLblDef.Key).Return(nil)
  1645  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, newSchemaLblDef.Key).Return(nil)
  1646  				return labelDefService
  1647  			},
  1648  			NotificationsSvcFn: func() *automock.NotificationsService {
  1649  				notificationSvc := &automock.NotificationsService{}
  1650  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(emptyFormationNotificationRequests, nil).Once()
  1651  				return notificationSvc
  1652  			},
  1653  			FormationRepoFn: func() *automock.FormationRepository {
  1654  				formationRepoMock := &automock.FormationRepository{}
  1655  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1656  				return formationRepoMock
  1657  			},
  1658  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1659  				repo := &automock.FormationTemplateRepository{}
  1660  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1661  				return repo
  1662  			},
  1663  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1664  				engine := &automock.ConstraintEngine{}
  1665  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1666  				return engine
  1667  			},
  1668  			webhookRepoFn: func() *automock.WebhookRepository {
  1669  				webhookRepo := &automock.WebhookRepository{}
  1670  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1671  				return webhookRepo
  1672  			},
  1673  			InputFormation:     in,
  1674  			ExpectedErrMessage: testErr.Error(),
  1675  		},
  1676  		{
  1677  			Name: "Returns error when can't get formation by name",
  1678  			FormationRepoFn: func() *automock.FormationRepository {
  1679  				formationRepoMock := &automock.FormationRepository{}
  1680  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(nil, testErr).Once()
  1681  				return formationRepoMock
  1682  			},
  1683  			InputFormation:     in,
  1684  			ExpectedFormation:  nil,
  1685  			ExpectedErrMessage: "while deleting formation: An error occurred while getting formation by name: \"test-formation\": Test error",
  1686  		},
  1687  		{
  1688  			Name: "error when deleting formation by name fails",
  1689  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1690  				labelDefRepo := &automock.LabelDefRepository{}
  1691  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1692  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  1693  				return labelDefRepo
  1694  			},
  1695  			LabelDefServiceFn: func() *automock.LabelDefService {
  1696  				labelDefService := &automock.LabelDefService{}
  1697  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1698  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1699  				return labelDefService
  1700  			},
  1701  			NotificationsSvcFn: func() *automock.NotificationsService {
  1702  				notificationSvc := &automock.NotificationsService{}
  1703  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(emptyFormationNotificationRequests, nil).Once()
  1704  				return notificationSvc
  1705  			},
  1706  			FormationRepoFn: func() *automock.FormationRepository {
  1707  				formationRepoMock := &automock.FormationRepository{}
  1708  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1709  				formationRepoMock.On("DeleteByName", ctx, TntInternalID, testFormationName).Return(testErr).Once()
  1710  				return formationRepoMock
  1711  			},
  1712  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1713  				repo := &automock.FormationTemplateRepository{}
  1714  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1715  				return repo
  1716  			},
  1717  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1718  				engine := &automock.ConstraintEngine{}
  1719  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1720  				return engine
  1721  			},
  1722  			webhookRepoFn: func() *automock.WebhookRepository {
  1723  				webhookRepo := &automock.WebhookRepository{}
  1724  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1725  				return webhookRepo
  1726  			},
  1727  			InputFormation:     in,
  1728  			ExpectedErrMessage: "An error occurred while deleting formation with name: \"test-formation\": Test error",
  1729  		},
  1730  		{
  1731  			Name: "error while enforcing constraints pre operation",
  1732  			FormationRepoFn: func() *automock.FormationRepository {
  1733  				formationRepoMock := &automock.FormationRepository{}
  1734  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1735  				return formationRepoMock
  1736  			},
  1737  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1738  				repo := &automock.FormationTemplateRepository{}
  1739  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1740  				return repo
  1741  			},
  1742  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1743  				engine := &automock.ConstraintEngine{}
  1744  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(testErr).Once()
  1745  				return engine
  1746  			},
  1747  			InputFormation:     in,
  1748  			ExpectedErrMessage: "while enforcing constraints for target operation \"DELETE_FORMATION\" and constraint type \"PRE\": Test error",
  1749  		},
  1750  		{
  1751  			Name: "error while enforcing constraint post operation",
  1752  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  1753  				labelDefRepo := &automock.LabelDefRepository{}
  1754  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  1755  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  1756  				return labelDefRepo
  1757  			},
  1758  			LabelDefServiceFn: func() *automock.LabelDefService {
  1759  				labelDefService := &automock.LabelDefService{}
  1760  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1761  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  1762  				return labelDefService
  1763  			},
  1764  			NotificationsSvcFn: func() *automock.NotificationsService {
  1765  				notificationSvc := &automock.NotificationsService{}
  1766  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(emptyFormationNotificationRequests, nil).Once()
  1767  				return notificationSvc
  1768  			},
  1769  			FormationRepoFn: func() *automock.FormationRepository {
  1770  				formationRepoMock := &automock.FormationRepository{}
  1771  				formationRepoMock.On("DeleteByName", ctx, TntInternalID, testFormationName).Return(nil).Once()
  1772  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1773  				return formationRepoMock
  1774  			},
  1775  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1776  				repo := &automock.FormationTemplateRepository{}
  1777  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1778  				return repo
  1779  			},
  1780  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1781  				engine := &automock.ConstraintEngine{}
  1782  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1783  				engine.On("EnforceConstraints", ctx, postDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(testErr).Once()
  1784  				return engine
  1785  			},
  1786  			webhookRepoFn: func() *automock.WebhookRepository {
  1787  				webhookRepo := &automock.WebhookRepository{}
  1788  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1789  				return webhookRepo
  1790  			},
  1791  			InputFormation:     in,
  1792  			ExpectedErrMessage: "while enforcing constraints for target operation \"DELETE_FORMATION\" and constraint type \"POST\": Test error",
  1793  		},
  1794  		{
  1795  			Name: "Error when listing formation template's webhooks fails",
  1796  			FormationRepoFn: func() *automock.FormationRepository {
  1797  				formationRepoMock := &automock.FormationRepository{}
  1798  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1799  				return formationRepoMock
  1800  			},
  1801  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1802  				repo := &automock.FormationTemplateRepository{}
  1803  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1804  				return repo
  1805  			},
  1806  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1807  				engine := &automock.ConstraintEngine{}
  1808  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1809  				return engine
  1810  			},
  1811  			webhookRepoFn: func() *automock.WebhookRepository {
  1812  				webhookRepo := &automock.WebhookRepository{}
  1813  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(nil, testErr).Once()
  1814  				return webhookRepo
  1815  			},
  1816  			InputFormation:     in,
  1817  			ExpectedFormation:  nil,
  1818  			ExpectedErrMessage: testErr.Error(),
  1819  		},
  1820  		{
  1821  			Name: "Error when generating formation notifications fails",
  1822  			NotificationsSvcFn: func() *automock.NotificationsService {
  1823  				notificationSvc := &automock.NotificationsService{}
  1824  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(nil, testErr).Once()
  1825  				return notificationSvc
  1826  			},
  1827  			FormationRepoFn: func() *automock.FormationRepository {
  1828  				formationRepoMock := &automock.FormationRepository{}
  1829  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1830  				return formationRepoMock
  1831  			},
  1832  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1833  				repo := &automock.FormationTemplateRepository{}
  1834  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1835  				return repo
  1836  			},
  1837  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1838  				engine := &automock.ConstraintEngine{}
  1839  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1840  				return engine
  1841  			},
  1842  			webhookRepoFn: func() *automock.WebhookRepository {
  1843  				webhookRepo := &automock.WebhookRepository{}
  1844  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1845  				return webhookRepo
  1846  			},
  1847  			InputFormation:     in,
  1848  			ExpectedFormation:  nil,
  1849  			ExpectedErrMessage: testErr.Error(),
  1850  		},
  1851  		{
  1852  			Name: "Error when processing formation notifications fails",
  1853  			NotificationsSvcFn: func() *automock.NotificationsService {
  1854  				notificationSvc := &automock.NotificationsService{}
  1855  				notificationSvc.On("GenerateFormationNotifications", ctx, emptyFormationLifecycleWebhooks, TntInternalID, formationWithReadyState, testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(formationNotificationAsyncDeleteRequests, nil).Once()
  1856  				notificationSvc.On("SendNotification", ctx, formationNotificationAsyncDeleteRequest).Return(nil, testErr).Once()
  1857  				return notificationSvc
  1858  			},
  1859  			FormationRepoFn: func() *automock.FormationRepository {
  1860  				formationRepoMock := &automock.FormationRepository{}
  1861  				formationRepoMock.On("Update", ctx, formationWithCreateErrorStateAndTechnicalAssignmentError).Return(testErr).Once()
  1862  				formationRepoMock.On("GetByName", ctx, testFormationName, TntInternalID).Return(expectedFormation, nil).Once()
  1863  				return formationRepoMock
  1864  			},
  1865  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1866  				repo := &automock.FormationTemplateRepository{}
  1867  				repo.On("Get", ctx, FormationTemplateID).Return(fixFormationTemplateModel(), nil).Once()
  1868  				return repo
  1869  			},
  1870  			ConstraintEngineFn: func() *automock.ConstraintEngine {
  1871  				engine := &automock.ConstraintEngine{}
  1872  				engine.On("EnforceConstraints", ctx, preDeleteLocation, deleteFormationDetails, FormationTemplateID).Return(nil).Once()
  1873  				return engine
  1874  			},
  1875  			webhookRepoFn: func() *automock.WebhookRepository {
  1876  				webhookRepo := &automock.WebhookRepository{}
  1877  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(emptyFormationLifecycleWebhooks, nil).Once()
  1878  				return webhookRepo
  1879  			},
  1880  			InputFormation:     in,
  1881  			ExpectedFormation:  nil,
  1882  			ExpectedErrMessage: testErr.Error(),
  1883  		},
  1884  	}
  1885  
  1886  	for _, testCase := range testCases {
  1887  		t.Run(testCase.Name, func(t *testing.T) {
  1888  			// GIVEN
  1889  			labelDefRepo := unusedLabelDefRepository()
  1890  			if testCase.LabelDefRepositoryFn != nil {
  1891  				labelDefRepo = testCase.LabelDefRepositoryFn()
  1892  			}
  1893  
  1894  			labelDefService := unusedLabelDefService()
  1895  			if testCase.LabelDefServiceFn != nil {
  1896  				labelDefService = testCase.LabelDefServiceFn()
  1897  			}
  1898  
  1899  			notificationsService := unusedNotificationsService()
  1900  			if testCase.NotificationsSvcFn != nil {
  1901  				notificationsService = testCase.NotificationsSvcFn()
  1902  			}
  1903  
  1904  			formationRepo := unusedFormationRepo()
  1905  			if testCase.FormationRepoFn != nil {
  1906  				formationRepo = testCase.FormationRepoFn()
  1907  			}
  1908  			formationTemplateRepo := unusedFormationTemplateRepo()
  1909  			if testCase.FormationTemplateRepoFn != nil {
  1910  				formationTemplateRepo = testCase.FormationTemplateRepoFn()
  1911  			}
  1912  
  1913  			constraintEngine := unusedConstraintEngine()
  1914  			if testCase.ConstraintEngineFn != nil {
  1915  				constraintEngine = testCase.ConstraintEngineFn()
  1916  			}
  1917  			webhookRepo := unusedWebhookRepository()
  1918  			if testCase.webhookRepoFn != nil {
  1919  				webhookRepo = testCase.webhookRepoFn()
  1920  			}
  1921  
  1922  			svc := formation.NewService(nil, nil, labelDefRepo, nil, formationRepo, formationTemplateRepo, nil, nil, labelDefService, nil, nil, nil, nil, nil, nil, nil, notificationsService, constraintEngine, webhookRepo, nil, runtimeType, applicationType)
  1923  
  1924  			// WHEN
  1925  			actual, err := svc.DeleteFormation(ctx, TntInternalID, testCase.InputFormation)
  1926  
  1927  			// THEN
  1928  			if testCase.ExpectedErrMessage == "" {
  1929  				require.NoError(t, err)
  1930  				assert.Equal(t, testCase.ExpectedFormation, actual)
  1931  			} else {
  1932  				require.Error(t, err)
  1933  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  1934  				require.Nil(t, actual)
  1935  			}
  1936  
  1937  			mock.AssertExpectationsForObjects(t, labelDefRepo, labelDefService, notificationsService, formationRepo, formationTemplateRepo, constraintEngine)
  1938  		})
  1939  	}
  1940  }
  1941  
  1942  func TestService_DeleteManyASAForSameTargetTenant(t *testing.T) {
  1943  	ctx := fixCtxWithTenant()
  1944  
  1945  	scenarioNameA := "scenario-A"
  1946  	scenarioNameB := "scenario-B"
  1947  	models := []*model.AutomaticScenarioAssignment{
  1948  		{
  1949  			ScenarioName:   scenarioNameA,
  1950  			TargetTenantID: TargetTenantID,
  1951  		},
  1952  		{
  1953  			ScenarioName:   scenarioNameB,
  1954  			TargetTenantID: TargetTenantID,
  1955  		},
  1956  	}
  1957  
  1958  	formations := []*model.Formation{
  1959  		{
  1960  			ID:                  FormationID,
  1961  			TenantID:            tenantID.String(),
  1962  			FormationTemplateID: FormationTemplateID,
  1963  			Name:                scenarioNameA,
  1964  		},
  1965  		{
  1966  			ID:                  FormationID,
  1967  			TenantID:            tenantID.String(),
  1968  			FormationTemplateID: FormationTemplateID,
  1969  			Name:                scenarioNameB,
  1970  		},
  1971  	}
  1972  
  1973  	t.Run("happy path", func(t *testing.T) {
  1974  		// GIVEN
  1975  		mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  1976  		mockRepo.On("DeleteForTargetTenant", ctx, tenantID.String(), TargetTenantID).Return(nil).Once()
  1977  
  1978  		runtimeRepo := &automock.RuntimeRepository{}
  1979  		runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(make([]*model.Runtime, 0), nil).Twice()
  1980  
  1981  		runtimeRepo.On("ListAllWithUnionSetCombination", ctx, TargetTenantID, runtimeLblFilters).Return(make([]*model.Runtime, 0), nil).Twice()
  1982  
  1983  		formationRepo := &automock.FormationRepository{}
  1984  		formationRepo.On("GetByName", ctx, scenarioNameA, "").Return(formations[0], nil).Once()
  1985  		formationRepo.On("GetByName", ctx, scenarioNameB, "").Return(formations[1], nil).Once()
  1986  
  1987  		formationTemplateRepo := &automock.FormationTemplateRepository{}
  1988  		formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
  1989  		formationTemplateRepo.On("Get", ctx, formations[1].FormationTemplateID).Return(&formationTemplate, nil).Once()
  1990  
  1991  		defer mock.AssertExpectationsForObjects(t, mockRepo, runtimeRepo, formationRepo, formationTemplateRepo)
  1992  
  1993  		svc := formation.NewService(nil, nil, nil, nil, formationRepo, formationTemplateRepo, nil, nil, nil, mockRepo, nil, nil, runtimeRepo, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  1994  
  1995  		// WHEN
  1996  		err := svc.DeleteManyASAForSameTargetTenant(ctx, models)
  1997  
  1998  		// THEN
  1999  		require.NoError(t, err)
  2000  	})
  2001  
  2002  	t.Run("return error when removing assigned scenarios fails", func(t *testing.T) {
  2003  		// GIVEN
  2004  		mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  2005  		mockRepo.On("DeleteForTargetTenant", ctx, tenantID.String(), TargetTenantID).Return(nil).Once()
  2006  
  2007  		runtimeRepo := &automock.RuntimeRepository{}
  2008  		runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(nil, fixError())
  2009  
  2010  		formationRepo := &automock.FormationRepository{}
  2011  
  2012  		formationRepo.On("GetByName", ctx, scenarioNameA, "").Return(formations[0], nil).Once()
  2013  
  2014  		formationTemplateRepo := &automock.FormationTemplateRepository{}
  2015  		formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
  2016  
  2017  		defer mock.AssertExpectationsForObjects(t, mockRepo, runtimeRepo, formationRepo, formationTemplateRepo)
  2018  
  2019  		svc := formation.NewService(nil, nil, nil, nil, formationRepo, formationTemplateRepo, nil, nil, nil, mockRepo, nil, nil, runtimeRepo, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2020  
  2021  		// WHEN
  2022  		err := svc.DeleteManyASAForSameTargetTenant(ctx, models)
  2023  
  2024  		// THEN
  2025  		require.Error(t, err)
  2026  		assert.Contains(t, err.Error(), fixError().Error())
  2027  	})
  2028  
  2029  	t.Run("return error when input slice is empty", func(t *testing.T) {
  2030  		// GIVEN
  2031  		svc := formation.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2032  
  2033  		// WHEN
  2034  		err := svc.DeleteManyASAForSameTargetTenant(ctx, []*model.AutomaticScenarioAssignment{})
  2035  
  2036  		// THEN
  2037  		require.Error(t, err)
  2038  		assert.Contains(t, err.Error(), "expected at least one item in Assignments slice")
  2039  	})
  2040  
  2041  	t.Run("return error when input slice contains assignments with different selectors", func(t *testing.T) {
  2042  		// GIVEN
  2043  		modelsWithDifferentSelectors := []*model.AutomaticScenarioAssignment{
  2044  			{
  2045  				ScenarioName:   scenarioNameA,
  2046  				TargetTenantID: TargetTenantID,
  2047  			},
  2048  			{
  2049  				ScenarioName:   scenarioNameB,
  2050  				TargetTenantID: "differentTargetTenantID",
  2051  			},
  2052  		}
  2053  
  2054  		svc := formation.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2055  		// WHEN
  2056  		err := svc.DeleteManyASAForSameTargetTenant(ctx, modelsWithDifferentSelectors)
  2057  
  2058  		// THEN
  2059  		require.Error(t, err)
  2060  		assert.Contains(t, err.Error(), "all input items have to have the same target tenant")
  2061  	})
  2062  
  2063  	t.Run("returns error on error from repository", func(t *testing.T) {
  2064  		// GIVEN
  2065  		mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  2066  
  2067  		mockRepo.On("DeleteForTargetTenant", ctx, tenantID.String(), TargetTenantID).Return(fixError()).Once()
  2068  
  2069  		defer mock.AssertExpectationsForObjects(t, mockRepo)
  2070  
  2071  		svc := formation.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, mockRepo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2072  		// WHEN
  2073  		err := svc.DeleteManyASAForSameTargetTenant(ctx, models)
  2074  
  2075  		// THEN
  2076  		require.EqualError(t, err, fmt.Sprintf("while deleting the Assignments: %s", ErrMsg))
  2077  	})
  2078  
  2079  	t.Run("returns error when empty tenant", func(t *testing.T) {
  2080  		svc := formation.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2081  		err := svc.DeleteManyASAForSameTargetTenant(context.TODO(), models)
  2082  		require.EqualError(t, err, "cannot read tenant from context")
  2083  	})
  2084  }
  2085  
  2086  func TestService_CreateAutomaticScenarioAssignment(t *testing.T) {
  2087  	ctx := fixCtxWithTenant()
  2088  
  2089  	testCases := []struct {
  2090  		Name               string
  2091  		LabelDefServiceFn  func() *automock.LabelDefService
  2092  		AsaRepoFn          func() *automock.AutomaticFormationAssignmentRepository
  2093  		AsaEngineFN        func() *automock.AsaEngine
  2094  		InputASA           model.AutomaticScenarioAssignment
  2095  		ExpectedASA        model.AutomaticScenarioAssignment
  2096  		ExpectedErrMessage string
  2097  	}{
  2098  		{
  2099  			Name: "happy path",
  2100  			LabelDefServiceFn: func() *automock.LabelDefService {
  2101  				return mockScenarioDefServiceThatReturns([]string{testFormationName})
  2102  			},
  2103  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2104  				mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  2105  				mockRepo.On("Create", ctx, fixModel(testFormationName)).Return(nil).Once()
  2106  				return mockRepo
  2107  			},
  2108  			AsaEngineFN: func() *automock.AsaEngine {
  2109  				engine := &automock.AsaEngine{}
  2110  				engine.On("EnsureScenarioAssigned", ctx, fixModel(testFormationName), mock.Anything).Return(nil).Once()
  2111  				return engine
  2112  			},
  2113  			InputASA:    fixModel(testFormationName),
  2114  			ExpectedASA: fixModel(testFormationName),
  2115  		},
  2116  		{
  2117  			Name: "returns error on getting available scenarios from label definition",
  2118  			LabelDefServiceFn: func() *automock.LabelDefService {
  2119  				labelDefSvc := &automock.LabelDefService{}
  2120  				labelDefSvc.On("GetAvailableScenarios", mock.Anything, tenantID.String()).Return(nil, fixError()).Once()
  2121  				return labelDefSvc
  2122  			},
  2123  			AsaRepoFn:          unusedASARepo,
  2124  			AsaEngineFN:        unusedASAEngine,
  2125  			InputASA:           fixModel(ScenarioName),
  2126  			ExpectedASA:        model.AutomaticScenarioAssignment{},
  2127  			ExpectedErrMessage: "while getting available scenarios: some error",
  2128  		},
  2129  		{
  2130  			Name: "returns error on creating asa",
  2131  			LabelDefServiceFn: func() *automock.LabelDefService {
  2132  				return mockScenarioDefServiceThatReturns([]string{testFormationName})
  2133  			},
  2134  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2135  				mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  2136  				mockRepo.On("Create", ctx, fixModel(testFormationName)).Return(fixError()).Once()
  2137  				return mockRepo
  2138  			},
  2139  			AsaEngineFN:        unusedASAEngine,
  2140  			InputASA:           fixModel(testFormationName),
  2141  			ExpectedASA:        model.AutomaticScenarioAssignment{},
  2142  			ExpectedErrMessage: "while persisting Assignment",
  2143  		},
  2144  
  2145  		{Name: "returns error on creating asa",
  2146  			LabelDefServiceFn: func() *automock.LabelDefService {
  2147  				return mockScenarioDefServiceThatReturns([]string{testFormationName})
  2148  			},
  2149  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2150  				mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  2151  				mockRepo.On("Create", ctx, fixModel(testFormationName)).Return(apperrors.NewNotUniqueError(resource.AutomaticScenarioAssigment)).Once()
  2152  				return mockRepo
  2153  			},
  2154  			AsaEngineFN:        unusedASAEngine,
  2155  			InputASA:           fixModel(testFormationName),
  2156  			ExpectedASA:        model.AutomaticScenarioAssignment{},
  2157  			ExpectedErrMessage: "a given scenario already has an assignment",
  2158  		},
  2159  		{
  2160  			Name: "returns error on ensure scenario assigned",
  2161  			LabelDefServiceFn: func() *automock.LabelDefService {
  2162  				return mockScenarioDefServiceThatReturns([]string{testFormationName})
  2163  			},
  2164  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2165  				mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  2166  				mockRepo.On("Create", ctx, fixModel(testFormationName)).Return(nil).Once()
  2167  				return mockRepo
  2168  			},
  2169  			AsaEngineFN: func() *automock.AsaEngine {
  2170  				engine := &automock.AsaEngine{}
  2171  				engine.On("EnsureScenarioAssigned", ctx, fixModel(testFormationName), mock.Anything).Return(fixError()).Once()
  2172  				return engine
  2173  			},
  2174  			InputASA:           fixModel(testFormationName),
  2175  			ExpectedASA:        model.AutomaticScenarioAssignment{},
  2176  			ExpectedErrMessage: "while assigning scenario to runtimes matching selector",
  2177  		},
  2178  	}
  2179  	for _, testCase := range testCases {
  2180  		t.Run(testCase.Name, func(t *testing.T) {
  2181  			// GIVEN
  2182  			asaRepo := testCase.AsaRepoFn()
  2183  			tenantSvc := &automock.TenantService{}
  2184  			labelDefService := testCase.LabelDefServiceFn()
  2185  			asaEngine := testCase.AsaEngineFN()
  2186  
  2187  			svc := formation.NewServiceWithAsaEngine(nil, nil, nil, nil, nil, nil, nil, nil, labelDefService, asaRepo, nil, tenantSvc, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType, asaEngine, nil)
  2188  
  2189  			// WHEN
  2190  			actual, err := svc.CreateAutomaticScenarioAssignment(ctx, testCase.InputASA)
  2191  
  2192  			// THEN
  2193  			if testCase.ExpectedErrMessage == "" {
  2194  				require.NoError(t, err)
  2195  				assert.Equal(t, testCase.ExpectedASA, actual)
  2196  			} else {
  2197  				require.Error(t, err)
  2198  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  2199  				require.Equal(t, testCase.ExpectedASA, actual)
  2200  			}
  2201  
  2202  			mock.AssertExpectationsForObjects(t, tenantSvc, asaRepo, labelDefService, asaEngine)
  2203  		})
  2204  	}
  2205  
  2206  	t.Run("returns error on missing tenant in context", func(t *testing.T) {
  2207  		// GIVEN
  2208  		svc := formation.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2209  
  2210  		// WHEN
  2211  		_, err := svc.CreateAutomaticScenarioAssignment(context.TODO(), fixModel(ScenarioName))
  2212  
  2213  		// THEN
  2214  		assert.EqualError(t, err, "cannot read tenant from context")
  2215  	})
  2216  }
  2217  
  2218  func TestService_DeleteAutomaticScenarioAssignment(t *testing.T) {
  2219  	ctx := fixCtxWithTenant()
  2220  
  2221  	testErr := errors.New("test err")
  2222  
  2223  	testCases := []struct {
  2224  		Name               string
  2225  		AsaRepoFn          func() *automock.AutomaticFormationAssignmentRepository
  2226  		AsaEngineFN        func() *automock.AsaEngine
  2227  		InputASA           model.AutomaticScenarioAssignment
  2228  		ExpectedASA        model.AutomaticScenarioAssignment
  2229  		ExpectedErrMessage string
  2230  	}{
  2231  		{
  2232  			Name: "Success",
  2233  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2234  				mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  2235  				mockRepo.On("DeleteForScenarioName", ctx, tenantID.String(), testFormationName).Return(nil).Once()
  2236  				return mockRepo
  2237  			},
  2238  			AsaEngineFN: func() *automock.AsaEngine {
  2239  				engine := &automock.AsaEngine{}
  2240  				engine.Mock.On("RemoveAssignedScenario", ctx, fixModel(testFormationName), mock.Anything).Return(nil).Once()
  2241  				return engine
  2242  			},
  2243  			InputASA:    fixModel(testFormationName),
  2244  			ExpectedASA: fixModel(testFormationName),
  2245  		},
  2246  		{
  2247  			Name: "Returns error when deleting ASA for scenario name fails",
  2248  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2249  				mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  2250  				mockRepo.On("DeleteForScenarioName", ctx, tenantID.String(), testFormationName).Return(testErr).Once()
  2251  				return mockRepo
  2252  			},
  2253  			AsaEngineFN:        unusedASAEngine,
  2254  			InputASA:           fixModel(testFormationName),
  2255  			ExpectedASA:        model.AutomaticScenarioAssignment{},
  2256  			ExpectedErrMessage: "while deleting the Assignment",
  2257  		},
  2258  		{
  2259  			Name: "Returns error when removing assigned scenario",
  2260  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2261  				mockRepo := &automock.AutomaticFormationAssignmentRepository{}
  2262  				mockRepo.On("DeleteForScenarioName", ctx, tenantID.String(), testFormationName).Return(nil).Once()
  2263  				return mockRepo
  2264  			},
  2265  			AsaEngineFN: func() *automock.AsaEngine {
  2266  				engine := &automock.AsaEngine{}
  2267  				engine.Mock.On("RemoveAssignedScenario", ctx, fixModel(testFormationName), mock.Anything).Return(testErr).Once()
  2268  				return engine
  2269  			},
  2270  			InputASA:           fixModel(testFormationName),
  2271  			ExpectedASA:        model.AutomaticScenarioAssignment{},
  2272  			ExpectedErrMessage: "while unassigning scenario from runtimes",
  2273  		},
  2274  	}
  2275  	for _, testCase := range testCases {
  2276  		t.Run(testCase.Name, func(t *testing.T) {
  2277  			// GIVEN
  2278  			asaRepo := testCase.AsaRepoFn()
  2279  			asaEngine := testCase.AsaEngineFN()
  2280  			tenantSvc := &automock.TenantService{}
  2281  
  2282  			svc := formation.NewServiceWithAsaEngine(nil, nil, nil, nil, nil, nil, nil, nil, nil, asaRepo, nil, tenantSvc, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType, asaEngine, nil)
  2283  
  2284  			// WHEN
  2285  			err := svc.DeleteAutomaticScenarioAssignment(ctx, testCase.InputASA)
  2286  
  2287  			// THEN
  2288  			if testCase.ExpectedErrMessage == "" {
  2289  				require.NoError(t, err)
  2290  			} else {
  2291  				require.Error(t, err)
  2292  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  2293  			}
  2294  
  2295  			mock.AssertExpectationsForObjects(t, tenantSvc, asaRepo, asaEngine)
  2296  		})
  2297  	}
  2298  
  2299  	t.Run("returns error on missing tenant in context", func(t *testing.T) {
  2300  		// GIVEN
  2301  		svc := formation.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2302  
  2303  		// WHEN
  2304  		err := svc.DeleteAutomaticScenarioAssignment(context.TODO(), fixModel(ScenarioName))
  2305  
  2306  		// THEN
  2307  		assert.Contains(t, err.Error(), "cannot read tenant from context")
  2308  	})
  2309  }
  2310  
  2311  func TestService_MergeScenariosFromInputLabelsAndAssignments(t *testing.T) {
  2312  	// GIVEN
  2313  	ctx := fixCtxWithTenant()
  2314  
  2315  	differentTargetTenant := "differentTargetTenant"
  2316  	runtimeID := "runtimeID"
  2317  	labelKey := "key"
  2318  	labelValue := "val"
  2319  
  2320  	scenario := "SCENARIO"
  2321  
  2322  	assignments := []*model.AutomaticScenarioAssignment{
  2323  		{
  2324  			ScenarioName:   ScenarioName,
  2325  			Tenant:         tenantID.String(),
  2326  			TargetTenantID: TargetTenantID,
  2327  		},
  2328  		{
  2329  			ScenarioName:   ScenarioName2,
  2330  			Tenant:         tenantID.String(),
  2331  			TargetTenantID: differentTargetTenant,
  2332  		},
  2333  	}
  2334  
  2335  	formations := []*model.Formation{
  2336  		{
  2337  			ID:                  FormationID,
  2338  			TenantID:            tenantID.String(),
  2339  			FormationTemplateID: FormationTemplateID,
  2340  			Name:                ScenarioName,
  2341  		},
  2342  		{
  2343  			ID:                  FormationID,
  2344  			TenantID:            tenantID.String(),
  2345  			FormationTemplateID: FormationTemplateID,
  2346  			Name:                ScenarioName2,
  2347  		},
  2348  	}
  2349  
  2350  	testCases := []struct {
  2351  		Name                    string
  2352  		AsaRepoFn               func() *automock.AutomaticFormationAssignmentRepository
  2353  		RuntimeContextRepoFn    func() *automock.RuntimeContextRepository
  2354  		RuntimeRepoFn           func() *automock.RuntimeRepository
  2355  		FormationRepoFn         func() *automock.FormationRepository
  2356  		FormationTemplateRepoFn func() *automock.FormationTemplateRepository
  2357  		InputLabels             map[string]interface{}
  2358  		ExpectedScenarios       []interface{}
  2359  		ExpectedErrMessage      string
  2360  	}{
  2361  		{
  2362  			Name: "Success",
  2363  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2364  				asaRepo := &automock.AutomaticFormationAssignmentRepository{}
  2365  				asaRepo.On("ListAll", ctx, tenantID.String()).Return(assignments, nil)
  2366  				return asaRepo
  2367  			},
  2368  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
  2369  				runtimeContextRepo := &automock.RuntimeContextRepository{}
  2370  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, runtimeID).Return(false, nil).Once()
  2371  				return runtimeContextRepo
  2372  			},
  2373  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2374  				runtimeRepo := &automock.RuntimeRepository{}
  2375  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, TargetTenantID, runtimeID, runtimeLblFilters).Return(true, nil).Once()
  2376  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, differentTargetTenant, runtimeID, runtimeLblFilters).Return(false, nil).Once()
  2377  				return runtimeRepo
  2378  			},
  2379  			FormationRepoFn: func() *automock.FormationRepository {
  2380  				formationRepo := &automock.FormationRepository{}
  2381  				formationRepo.On("GetByName", ctx, ScenarioName, tenantID.String()).Return(formations[0], nil).Once()
  2382  				formationRepo.On("GetByName", ctx, ScenarioName2, tenantID.String()).Return(formations[1], nil).Once()
  2383  				return formationRepo
  2384  			},
  2385  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  2386  				formationTemplateRepo := &automock.FormationTemplateRepository{}
  2387  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
  2388  				formationTemplateRepo.On("Get", ctx, formations[1].FormationTemplateID).Return(&formationTemplate, nil).Once()
  2389  				return formationTemplateRepo
  2390  			},
  2391  			InputLabels: map[string]interface{}{
  2392  				labelKey: labelValue,
  2393  			},
  2394  			ExpectedScenarios: []interface{}{ScenarioName},
  2395  		},
  2396  		{
  2397  			Name: "Success if scenarios label is in input",
  2398  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2399  				asaRepo := &automock.AutomaticFormationAssignmentRepository{}
  2400  				asaRepo.On("ListAll", ctx, tenantID.String()).Return(assignments, nil)
  2401  				return asaRepo
  2402  			},
  2403  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
  2404  				runtimeContextRepo := &automock.RuntimeContextRepository{}
  2405  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, runtimeID).Return(false, nil).Once()
  2406  				return runtimeContextRepo
  2407  			},
  2408  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2409  				runtimeRepo := &automock.RuntimeRepository{}
  2410  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, TargetTenantID, runtimeID, runtimeLblFilters).Return(true, nil).Once()
  2411  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, differentTargetTenant, runtimeID, runtimeLblFilters).Return(false, nil).Once()
  2412  				return runtimeRepo
  2413  			},
  2414  			FormationRepoFn: func() *automock.FormationRepository {
  2415  				formationRepo := &automock.FormationRepository{}
  2416  				formationRepo.On("GetByName", ctx, ScenarioName, tenantID.String()).Return(formations[0], nil).Once()
  2417  				formationRepo.On("GetByName", ctx, ScenarioName2, tenantID.String()).Return(formations[1], nil).Once()
  2418  				return formationRepo
  2419  			},
  2420  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  2421  				formationTemplateRepo := &automock.FormationTemplateRepository{}
  2422  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
  2423  				formationTemplateRepo.On("Get", ctx, formations[1].FormationTemplateID).Return(&formationTemplate, nil).Once()
  2424  				return formationTemplateRepo
  2425  			},
  2426  			InputLabels: map[string]interface{}{
  2427  				labelKey:           labelValue,
  2428  				model.ScenariosKey: []interface{}{scenario},
  2429  			},
  2430  			ExpectedScenarios: []interface{}{ScenarioName, scenario},
  2431  		},
  2432  		{
  2433  			Name: "Returns error when checking if ASA is matching to runtime fails",
  2434  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2435  				asaRepo := &automock.AutomaticFormationAssignmentRepository{}
  2436  				asaRepo.On("ListAll", ctx, tenantID.String()).Return(assignments, nil)
  2437  				return asaRepo
  2438  			},
  2439  			RuntimeContextRepoFn: unusedRuntimeContextRepo,
  2440  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2441  				runtimeRepo := &automock.RuntimeRepository{}
  2442  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, TargetTenantID, runtimeID, runtimeLblFilters).Return(false, testErr).Once()
  2443  				return runtimeRepo
  2444  			},
  2445  			FormationRepoFn: func() *automock.FormationRepository {
  2446  				formationRepo := &automock.FormationRepository{}
  2447  				formationRepo.On("GetByName", ctx, ScenarioName, tenantID.String()).Return(formations[0], nil).Once()
  2448  				return formationRepo
  2449  			},
  2450  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  2451  				formationTemplateRepo := &automock.FormationTemplateRepository{}
  2452  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
  2453  				return formationTemplateRepo
  2454  			},
  2455  			InputLabels: map[string]interface{}{
  2456  				labelKey: labelValue,
  2457  			},
  2458  			ExpectedScenarios:  []interface{}{},
  2459  			ExpectedErrMessage: testErr.Error(),
  2460  		},
  2461  		{
  2462  			Name: "Returns error when scenarios from input are not interface slice",
  2463  			AsaRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  2464  				asaRepo := &automock.AutomaticFormationAssignmentRepository{}
  2465  				asaRepo.On("ListAll", ctx, tenantID.String()).Return(assignments, nil)
  2466  				return asaRepo
  2467  			},
  2468  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
  2469  				runtimeContextRepo := &automock.RuntimeContextRepository{}
  2470  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, runtimeID).Return(false, nil).Once()
  2471  				return runtimeContextRepo
  2472  			},
  2473  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2474  				runtimeRepo := &automock.RuntimeRepository{}
  2475  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, TargetTenantID, runtimeID, runtimeLblFilters).Return(true, nil).Once()
  2476  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, differentTargetTenant, runtimeID, runtimeLblFilters).Return(false, nil).Once()
  2477  				return runtimeRepo
  2478  			},
  2479  			FormationRepoFn: func() *automock.FormationRepository {
  2480  				formationRepo := &automock.FormationRepository{}
  2481  				formationRepo.On("GetByName", ctx, ScenarioName, tenantID.String()).Return(formations[0], nil).Once()
  2482  				formationRepo.On("GetByName", ctx, ScenarioName2, tenantID.String()).Return(formations[1], nil).Once()
  2483  				return formationRepo
  2484  			},
  2485  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  2486  				formationTemplateRepo := &automock.FormationTemplateRepository{}
  2487  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
  2488  				formationTemplateRepo.On("Get", ctx, formations[1].FormationTemplateID).Return(&formationTemplate, nil).Once()
  2489  				return formationTemplateRepo
  2490  			},
  2491  			InputLabels: map[string]interface{}{
  2492  				labelKey:           labelValue,
  2493  				model.ScenariosKey: []string{scenario},
  2494  			},
  2495  			ExpectedScenarios:  []interface{}{},
  2496  			ExpectedErrMessage: "while converting scenarios label",
  2497  		},
  2498  	}
  2499  
  2500  	for _, testCase := range testCases {
  2501  		t.Run(testCase.Name, func(t *testing.T) {
  2502  			// GIVEN
  2503  			asaRepo := testCase.AsaRepoFn()
  2504  			runtimeRepo := testCase.RuntimeRepoFn()
  2505  			runtimeContextRepo := testCase.RuntimeContextRepoFn()
  2506  			formationRepo := testCase.FormationRepoFn()
  2507  			formationTemplateRepo := testCase.FormationTemplateRepoFn()
  2508  
  2509  			svc := formation.NewService(nil, nil, nil, nil, formationRepo, formationTemplateRepo, nil, nil, nil, asaRepo, nil, nil, runtimeRepo, runtimeContextRepo, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2510  
  2511  			// WHEN
  2512  			actualScenarios, err := svc.MergeScenariosFromInputLabelsAndAssignments(ctx, testCase.InputLabels, runtimeID)
  2513  
  2514  			// THEN
  2515  			if testCase.ExpectedErrMessage == "" {
  2516  				require.NoError(t, err)
  2517  				require.ElementsMatch(t, testCase.ExpectedScenarios, actualScenarios)
  2518  			} else {
  2519  				require.Error(t, err)
  2520  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  2521  			}
  2522  
  2523  			mock.AssertExpectationsForObjects(t, asaRepo, runtimeRepo, formationTemplateRepo, formationRepo)
  2524  		})
  2525  	}
  2526  }
  2527  
  2528  func TestService_GetFormationsForObject(t *testing.T) {
  2529  	id := "rtmID"
  2530  	testErr := "testErr"
  2531  
  2532  	scenarios := []interface{}{"scenario1", "scenario2"}
  2533  
  2534  	labelInput := &model.LabelInput{
  2535  		Key:        model.ScenariosKey,
  2536  		ObjectID:   id,
  2537  		ObjectType: model.RuntimeLabelableObject,
  2538  	}
  2539  
  2540  	label := &model.Label{
  2541  		ID:         id,
  2542  		Key:        "scenarios",
  2543  		Value:      scenarios,
  2544  		ObjectID:   id,
  2545  		ObjectType: model.RuntimeLabelableObject,
  2546  	}
  2547  
  2548  	t.Run("Success", func(t *testing.T) {
  2549  		// GIVEN
  2550  		ctx := context.TODO()
  2551  
  2552  		labelService := &automock.LabelService{}
  2553  		labelService.On("GetLabel", ctx, tenantID.String(), labelInput).Return(label, nil).Once()
  2554  
  2555  		svc := formation.NewService(nil, nil, nil, nil, nil, nil, labelService, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2556  
  2557  		// WHEN
  2558  		formations, err := svc.GetFormationsForObject(ctx, tenantID.String(), model.RuntimeLabelableObject, id)
  2559  
  2560  		// THEN
  2561  		require.NoError(t, err)
  2562  		require.ElementsMatch(t, formations, scenarios)
  2563  		mock.AssertExpectationsForObjects(t, labelService)
  2564  	})
  2565  
  2566  	t.Run("Returns error while getting label", func(t *testing.T) {
  2567  		// GIVEN
  2568  		ctx := context.TODO()
  2569  
  2570  		labelService := &automock.LabelService{}
  2571  		labelService.On("GetLabel", ctx, tenantID.String(), labelInput).Return(nil, errors.New(testErr)).Once()
  2572  
  2573  		svc := formation.NewService(nil, nil, nil, nil, nil, nil, labelService, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  2574  
  2575  		// WHEN
  2576  		formations, err := svc.GetFormationsForObject(ctx, tenantID.String(), model.RuntimeLabelableObject, id)
  2577  
  2578  		// THEN
  2579  		require.Error(t, err)
  2580  		require.Contains(t, err.Error(), "while fetching scenario label for")
  2581  		require.Nil(t, formations)
  2582  		mock.AssertExpectationsForObjects(t, labelService)
  2583  	})
  2584  }
  2585  
  2586  func TestServiceResynchronizeFormationNotifications(t *testing.T) {
  2587  	ctx := context.TODO()
  2588  	ctx = tenant.SaveToContext(ctx, TntInternalID, TntExternalID)
  2589  
  2590  	allStates := []string{string(model.InitialAssignmentState),
  2591  		string(model.DeletingAssignmentState),
  2592  		string(model.CreateErrorAssignmentState),
  2593  		string(model.DeleteErrorAssignmentState)}
  2594  
  2595  	testFormation := fixFormationModelWithState(model.ReadyFormationState)
  2596  	formationInCreateErrorState := fixFormationModelWithStateAndAssignmentError(t, model.CreateErrorFormationState, testErr.Error(), formationassignment.ClientError)
  2597  	formationInCreateErrorStateTechnicalError := fixFormationModelWithStateAndAssignmentError(t, model.CreateErrorFormationState, testErr.Error(), formationassignment.TechnicalError)
  2598  
  2599  	formationAssignments := []*model.FormationAssignment{
  2600  		fixFormationAssignmentModelWithParameters("id1", FormationID, RuntimeID, ApplicationID, model.FormationAssignmentTypeRuntime, model.FormationAssignmentTypeApplication, model.InitialFormationState),
  2601  		fixFormationAssignmentModelWithParameters("id2", FormationID, RuntimeContextID, ApplicationID, model.FormationAssignmentTypeRuntimeContext, model.FormationAssignmentTypeApplication, model.CreateErrorFormationState),
  2602  		fixFormationAssignmentModelWithParameters("id3", FormationID, RuntimeID, RuntimeContextID, model.FormationAssignmentTypeRuntime, model.FormationAssignmentTypeRuntimeContext, model.DeletingFormationState),
  2603  		fixFormationAssignmentModelWithParameters("id4", FormationID, RuntimeContextID, RuntimeContextID, model.FormationAssignmentTypeRuntimeContext, model.FormationAssignmentTypeRuntimeContext, model.DeleteErrorFormationState),
  2604  	}
  2605  	reverseAssignment := &model.FormationAssignment{
  2606  		ID:          "id1",
  2607  		FormationID: FormationID,
  2608  		Source:      ApplicationID,
  2609  		SourceType:  model.FormationAssignmentTypeApplication,
  2610  		Target:      RuntimeID,
  2611  		TargetType:  model.FormationAssignmentTypeRuntime,
  2612  		State:       string(model.ReadyAssignmentState),
  2613  	}
  2614  
  2615  	notificationsForAssignments := []*webhookclient.FormationAssignmentNotificationRequest{
  2616  		{
  2617  			Webhook: graphql.Webhook{
  2618  				ID: WebhookID,
  2619  			},
  2620  		},
  2621  		{
  2622  			Webhook: graphql.Webhook{
  2623  				ID: Webhook2ID,
  2624  			},
  2625  		},
  2626  		{
  2627  			Webhook: graphql.Webhook{
  2628  				ID: Webhook3ID,
  2629  			},
  2630  		},
  2631  		{
  2632  			Webhook: graphql.Webhook{
  2633  				ID: Webhook4ID,
  2634  			},
  2635  		},
  2636  	}
  2637  	var formationAssignmentPairs = make([]*formationassignment.AssignmentMappingPairWithOperation, 0, len(formationAssignments))
  2638  	for i := range formationAssignments {
  2639  		formationAssignmentPairs = append(formationAssignmentPairs, fixFormationAssignmentPairWithNoReverseAssignment(notificationsForAssignments[i], formationAssignments[i]))
  2640  	}
  2641  
  2642  	testSchema, err := labeldef.NewSchemaForFormations([]string{testScenario, testFormationName})
  2643  	assert.NoError(t, err)
  2644  	testSchemaLblDef := fixScenariosLabelDefinition(TntInternalID, testSchema)
  2645  
  2646  	newSchema, err := labeldef.NewSchemaForFormations([]string{testScenario})
  2647  	assert.NoError(t, err)
  2648  	newSchemaLblDef := fixScenariosLabelDefinition(TntInternalID, newSchema)
  2649  
  2650  	nilSchemaLblDef := fixScenariosLabelDefinition(TntInternalID, testSchema)
  2651  	nilSchemaLblDef.Schema = nil
  2652  
  2653  	testCases := []struct {
  2654  		Name                                     string
  2655  		LabelServiceFn                           func() *automock.LabelService
  2656  		LabelRepoFn                              func() *automock.LabelRepository
  2657  		AsaEngineFN                              func() *automock.AsaEngine
  2658  		FormationRepositoryFn                    func() *automock.FormationRepository
  2659  		FormationTemplateRepositoryFn            func() *automock.FormationTemplateRepository
  2660  		FormationAssignmentNotificationServiceFN func() *automock.FormationAssignmentNotificationsService
  2661  		NotificationServiceFN                    func() *automock.NotificationsService
  2662  		FormationAssignmentServiceFn             func() *automock.FormationAssignmentService
  2663  		WebhookRepoFn                            func() *automock.WebhookRepository
  2664  		RuntimeContextRepoFn                     func() *automock.RuntimeContextRepository
  2665  		LabelDefRepositoryFn                     func() *automock.LabelDefRepository
  2666  		LabelDefServiceFn                        func() *automock.LabelDefService
  2667  		StatusServiceFn                          func() *automock.StatusService
  2668  		ExpectedErrMessage                       string
  2669  	}{
  2670  		// Business logic tests for tenant mapping notifications only
  2671  		{
  2672  			Name: "success when resynchronization is successful and there are leftover formation assignments",
  2673  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2674  				svc := &automock.FormationAssignmentService{}
  2675  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return(formationAssignments, nil).Once()
  2676  
  2677  				for _, fa := range formationAssignments {
  2678  					svc.On("GetReverseBySourceAndTarget", ctx, FormationID, fa.Source, fa.Target).Return(nil, apperrors.NewNotFoundError(resource.FormationAssignment, "")).Once()
  2679  				}
  2680  
  2681  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[0]).Return(false, nil).Once()
  2682  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[1]).Return(false, nil).Once()
  2683  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[2]).Return(false, nil).Once()
  2684  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[3]).Return(false, nil).Once()
  2685  
  2686  				svc.On("ListFormationAssignmentsForObjectID", ctx, FormationID, formationAssignments[3].Source).Return([]*model.FormationAssignment{{ID: "id6"}}, nil).Once()
  2687  				return svc
  2688  			},
  2689  			FormationAssignmentNotificationServiceFN: func() *automock.FormationAssignmentNotificationsService {
  2690  				svc := &automock.FormationAssignmentNotificationsService{}
  2691  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[0], model.AssignFormation).Return(notificationsForAssignments[0], nil).Once()
  2692  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[1], model.AssignFormation).Return(notificationsForAssignments[1], nil).Once()
  2693  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[2], model.UnassignFormation).Return(notificationsForAssignments[2], nil).Once()
  2694  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[3], model.UnassignFormation).Return(notificationsForAssignments[3], nil).Once()
  2695  				return svc
  2696  			},
  2697  			FormationRepositoryFn: func() *automock.FormationRepository {
  2698  				repo := &automock.FormationRepository{}
  2699  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2700  				return repo
  2701  			},
  2702  		},
  2703  		{
  2704  			Name: "success when resynchronization is successful and there no left formation assignments should unassign",
  2705  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2706  				svc := &automock.FormationAssignmentService{}
  2707  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return(formationAssignments, nil).Once()
  2708  
  2709  				for _, fa := range formationAssignments {
  2710  					svc.On("GetReverseBySourceAndTarget", ctx, FormationID, fa.Source, fa.Target).Return(nil, apperrors.NewNotFoundError(resource.FormationAssignment, "")).Once()
  2711  				}
  2712  
  2713  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[0]).Return(false, nil).Once()
  2714  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[1]).Return(false, nil).Once()
  2715  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[2]).Return(false, nil).Once()
  2716  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[3]).Return(false, nil).Once()
  2717  
  2718  				svc.On("ListFormationAssignmentsForObjectID", ctx, FormationID, formationAssignments[3].Source).Return([]*model.FormationAssignment{{ID: "id6"}}, nil).Once()
  2719  				return svc
  2720  			},
  2721  			FormationAssignmentNotificationServiceFN: func() *automock.FormationAssignmentNotificationsService {
  2722  				svc := &automock.FormationAssignmentNotificationsService{}
  2723  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[0], model.AssignFormation).Return(notificationsForAssignments[0], nil).Once()
  2724  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[1], model.AssignFormation).Return(notificationsForAssignments[1], nil).Once()
  2725  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[2], model.UnassignFormation).Return(notificationsForAssignments[2], nil).Once()
  2726  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[3], model.UnassignFormation).Return(notificationsForAssignments[3], nil).Once()
  2727  				return svc
  2728  			},
  2729  			FormationRepositoryFn: func() *automock.FormationRepository {
  2730  				repo := &automock.FormationRepository{}
  2731  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2732  				return repo
  2733  			},
  2734  		},
  2735  		{
  2736  			Name: "returns error when failing to unassign from formation after resynchronizing",
  2737  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2738  				svc := &automock.FormationAssignmentService{}
  2739  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return(formationAssignments, nil).Once()
  2740  
  2741  				for _, fa := range formationAssignments {
  2742  					svc.On("GetReverseBySourceAndTarget", ctx, FormationID, fa.Source, fa.Target).Return(nil, apperrors.NewNotFoundError(resource.FormationAssignment, "")).Once()
  2743  				}
  2744  
  2745  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[0]).Return(false, nil).Once()
  2746  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[1]).Return(false, nil).Once()
  2747  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[2]).Return(false, nil).Once()
  2748  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[3]).Return(false, nil).Once()
  2749  
  2750  				svc.On("ListFormationAssignmentsForObjectID", ctx, FormationID, formationAssignments[3].Target).Return([]*model.FormationAssignment{}, nil).Once()
  2751  
  2752  				return svc
  2753  			},
  2754  			FormationAssignmentNotificationServiceFN: func() *automock.FormationAssignmentNotificationsService {
  2755  				svc := &automock.FormationAssignmentNotificationsService{}
  2756  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[0], model.AssignFormation).Return(notificationsForAssignments[0], nil).Once()
  2757  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[1], model.AssignFormation).Return(notificationsForAssignments[1], nil).Once()
  2758  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[2], model.UnassignFormation).Return(notificationsForAssignments[2], nil).Once()
  2759  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[3], model.UnassignFormation).Return(notificationsForAssignments[3], nil).Once()
  2760  				return svc
  2761  			},
  2762  			FormationRepositoryFn: func() *automock.FormationRepository {
  2763  				repo := &automock.FormationRepository{}
  2764  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2765  				return repo
  2766  			},
  2767  			AsaEngineFN: func() *automock.AsaEngine {
  2768  				engine := &automock.AsaEngine{}
  2769  				engine.On("IsFormationComingFromASA", ctx, RuntimeContextID, testFormation.Name, graphql.FormationObjectTypeRuntimeContext).Return(false, testErr).Once()
  2770  				return engine
  2771  			},
  2772  			ExpectedErrMessage: testErr.Error(),
  2773  		},
  2774  		{
  2775  			Name: "returns error when failing to list formation assignments for participant",
  2776  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2777  				svc := &automock.FormationAssignmentService{}
  2778  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return(formationAssignments, nil).Once()
  2779  
  2780  				for _, fa := range formationAssignments {
  2781  					svc.On("GetReverseBySourceAndTarget", ctx, FormationID, fa.Source, fa.Target).Return(nil, apperrors.NewNotFoundError(resource.FormationAssignment, "")).Once()
  2782  				}
  2783  
  2784  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[0]).Return(false, nil).Once()
  2785  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[1]).Return(false, nil).Once()
  2786  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[2]).Return(false, nil).Once()
  2787  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[3]).Return(false, nil).Once()
  2788  
  2789  				svc.On("ListFormationAssignmentsForObjectID", ctx, FormationID, mock.Anything).Return(nil, testErr).Once()
  2790  				return svc
  2791  			},
  2792  			FormationAssignmentNotificationServiceFN: func() *automock.FormationAssignmentNotificationsService {
  2793  				svc := &automock.FormationAssignmentNotificationsService{}
  2794  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[0], model.AssignFormation).Return(notificationsForAssignments[0], nil).Once()
  2795  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[1], model.AssignFormation).Return(notificationsForAssignments[1], nil).Once()
  2796  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[2], model.UnassignFormation).Return(notificationsForAssignments[2], nil).Once()
  2797  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[3], model.UnassignFormation).Return(notificationsForAssignments[3], nil).Once()
  2798  				return svc
  2799  			},
  2800  			FormationRepositoryFn: func() *automock.FormationRepository {
  2801  				repo := &automock.FormationRepository{}
  2802  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2803  				return repo
  2804  			},
  2805  			ExpectedErrMessage: testErr.Error(),
  2806  		},
  2807  		{
  2808  			Name: "returns error when failing to get formation",
  2809  			FormationRepositoryFn: func() *automock.FormationRepository {
  2810  				repo := &automock.FormationRepository{}
  2811  				repo.On("Get", ctx, FormationID, TntInternalID).Return(nil, testErr).Once()
  2812  				return repo
  2813  			},
  2814  			ExpectedErrMessage: testErr.Error(),
  2815  		},
  2816  		{
  2817  			Name: "returns error when failing processing formation assignments fails",
  2818  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2819  				svc := &automock.FormationAssignmentService{}
  2820  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return(formationAssignments, nil).Once()
  2821  
  2822  				for _, fa := range formationAssignments {
  2823  					svc.On("GetReverseBySourceAndTarget", ctx, FormationID, fa.Source, fa.Target).Return(nil, apperrors.NewNotFoundError(resource.FormationAssignment, "")).Once()
  2824  				}
  2825  
  2826  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[0]).Return(false, testErr).Once()
  2827  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[1]).Return(false, testErr).Once()
  2828  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[2]).Return(false, testErr).Once()
  2829  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[3]).Return(false, testErr).Once()
  2830  
  2831  				svc.On("ListFormationAssignmentsForObjectID", ctx, FormationID, formationAssignments[3].Source).Return([]*model.FormationAssignment{{ID: "id6"}}, nil).Once()
  2832  				return svc
  2833  			},
  2834  			FormationAssignmentNotificationServiceFN: func() *automock.FormationAssignmentNotificationsService {
  2835  				svc := &automock.FormationAssignmentNotificationsService{}
  2836  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[0], model.AssignFormation).Return(notificationsForAssignments[0], nil).Once()
  2837  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[1], model.AssignFormation).Return(notificationsForAssignments[1], nil).Once()
  2838  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[2], model.UnassignFormation).Return(notificationsForAssignments[2], nil).Once()
  2839  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[3], model.UnassignFormation).Return(notificationsForAssignments[3], nil).Once()
  2840  				return svc
  2841  			},
  2842  			FormationRepositoryFn: func() *automock.FormationRepository {
  2843  				repo := &automock.FormationRepository{}
  2844  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2845  				return repo
  2846  			},
  2847  			ExpectedErrMessage: testErr.Error(),
  2848  		},
  2849  		{
  2850  			Name: "returns error when getting reverse formation assignment",
  2851  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2852  				svc := &automock.FormationAssignmentService{}
  2853  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return([]*model.FormationAssignment{formationAssignments[0]}, nil).Once()
  2854  
  2855  				svc.On("GetReverseBySourceAndTarget", ctx, FormationID, formationAssignments[0].Source, formationAssignments[0].Target).Return(nil, testErr).Once()
  2856  
  2857  				return svc
  2858  			},
  2859  			FormationAssignmentNotificationServiceFN: func() *automock.FormationAssignmentNotificationsService {
  2860  				svc := &automock.FormationAssignmentNotificationsService{}
  2861  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[0], model.AssignFormation).Return(notificationsForAssignments[0], nil).Once()
  2862  				return svc
  2863  			},
  2864  			FormationRepositoryFn: func() *automock.FormationRepository {
  2865  				repo := &automock.FormationRepository{}
  2866  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2867  				return repo
  2868  			},
  2869  			ExpectedErrMessage: testErr.Error(),
  2870  		},
  2871  		{
  2872  			Name: "returns error when generating reverse formation assignment notification",
  2873  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2874  				svc := &automock.FormationAssignmentService{}
  2875  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return([]*model.FormationAssignment{formationAssignments[0]}, nil)
  2876  
  2877  				svc.On("GetReverseBySourceAndTarget", ctx, FormationID, formationAssignments[0].Source, formationAssignments[0].Target).Return(reverseAssignment, nil)
  2878  
  2879  				return svc
  2880  			},
  2881  			FormationAssignmentNotificationServiceFN: func() *automock.FormationAssignmentNotificationsService {
  2882  				svc := &automock.FormationAssignmentNotificationsService{}
  2883  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[0], model.AssignFormation).Return(notificationsForAssignments[0], nil)
  2884  				svc.On("GenerateFormationAssignmentNotification", ctx, reverseAssignment, model.AssignFormation).Return(nil, testErr)
  2885  				return svc
  2886  			},
  2887  			FormationRepositoryFn: func() *automock.FormationRepository {
  2888  				repo := &automock.FormationRepository{}
  2889  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2890  				return repo
  2891  			},
  2892  			ExpectedErrMessage: testErr.Error(),
  2893  		},
  2894  		{
  2895  			Name: "returns error when generating formation assignment notification",
  2896  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2897  				svc := &automock.FormationAssignmentService{}
  2898  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return([]*model.FormationAssignment{formationAssignments[0]}, nil).Once()
  2899  
  2900  				return svc
  2901  			},
  2902  			FormationAssignmentNotificationServiceFN: func() *automock.FormationAssignmentNotificationsService {
  2903  				svc := &automock.FormationAssignmentNotificationsService{}
  2904  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[0], model.AssignFormation).Return(nil, testErr).Once()
  2905  				return svc
  2906  			},
  2907  			FormationRepositoryFn: func() *automock.FormationRepository {
  2908  				repo := &automock.FormationRepository{}
  2909  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2910  				return repo
  2911  			},
  2912  			ExpectedErrMessage: testErr.Error(),
  2913  		},
  2914  		{
  2915  			Name: "returns error when listing formation assignments with states",
  2916  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2917  				svc := &automock.FormationAssignmentService{}
  2918  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return(nil, testErr).Once()
  2919  
  2920  				return svc
  2921  			},
  2922  			FormationRepositoryFn: func() *automock.FormationRepository {
  2923  				repo := &automock.FormationRepository{}
  2924  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2925  				return repo
  2926  			},
  2927  			ExpectedErrMessage: testErr.Error(),
  2928  		},
  2929  		// Business logic tests for formation and tenant mapping notifications
  2930  		{
  2931  			Name: "success when both formation and formation assignment resynchronization are successful and there no left formation assignments should unassign",
  2932  			FormationAssignmentServiceFn: func() *automock.FormationAssignmentService {
  2933  				svc := &automock.FormationAssignmentService{}
  2934  				svc.On("GetAssignmentsForFormationWithStates", ctx, TntInternalID, FormationID, allStates).Return(formationAssignments, nil).Once()
  2935  
  2936  				for _, fa := range formationAssignments {
  2937  					svc.On("GetReverseBySourceAndTarget", ctx, FormationID, fa.Source, fa.Target).Return(nil, apperrors.NewNotFoundError(resource.FormationAssignment, "")).Once()
  2938  				}
  2939  
  2940  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[0]).Return(false, nil).Once()
  2941  				svc.On("ProcessFormationAssignmentPair", ctx, formationAssignmentPairs[1]).Return(false, nil).Once()
  2942  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[2]).Return(false, nil).Once()
  2943  				svc.On("CleanupFormationAssignment", ctx, formationAssignmentPairs[3]).Return(false, nil).Once()
  2944  
  2945  				svc.On("ListFormationAssignmentsForObjectID", ctx, FormationID, formationAssignments[3].Source).Return([]*model.FormationAssignment{{ID: "id6"}}, nil).Once()
  2946  				return svc
  2947  			},
  2948  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
  2949  				repo := &automock.FormationTemplateRepository{}
  2950  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil)
  2951  				return repo
  2952  			},
  2953  			NotificationServiceFN: func() *automock.NotificationsService {
  2954  				notificationSvc := &automock.NotificationsService{}
  2955  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, fixFormationModelWithState(model.InitialFormationState), testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
  2956  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(formationNotificationWebhookSuccessResponse, nil).Once()
  2957  				return notificationSvc
  2958  			},
  2959  			FormationAssignmentNotificationServiceFN: func() *automock.FormationAssignmentNotificationsService {
  2960  				svc := &automock.FormationAssignmentNotificationsService{}
  2961  
  2962  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[0], model.AssignFormation).Return(notificationsForAssignments[0], nil).Once()
  2963  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[1], model.AssignFormation).Return(notificationsForAssignments[1], nil).Once()
  2964  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[2], model.UnassignFormation).Return(notificationsForAssignments[2], nil).Once()
  2965  				svc.On("GenerateFormationAssignmentNotification", ctx, formationAssignments[3], model.UnassignFormation).Return(notificationsForAssignments[3], nil).Once()
  2966  				return svc
  2967  			},
  2968  			WebhookRepoFn: func() *automock.WebhookRepository {
  2969  				webhookRepo := &automock.WebhookRepository{}
  2970  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  2971  				return webhookRepo
  2972  			},
  2973  			FormationRepositoryFn: func() *automock.FormationRepository {
  2974  				repo := &automock.FormationRepository{}
  2975  				repo.On("Get", ctx, FormationID, TntInternalID).Return(fixFormationModelWithState(model.InitialFormationState), nil).Once()
  2976  				repo.On("Get", ctx, FormationID, TntInternalID).Return(testFormation, nil).Once()
  2977  				return repo
  2978  			},
  2979  			StatusServiceFn: func() *automock.StatusService {
  2980  				svc := &automock.StatusService{}
  2981  				svc.On("UpdateWithConstraints", ctx, fixFormationModelWithState(model.ReadyFormationState), model.CreateFormation).Return(nil).Once()
  2982  				return svc
  2983  			},
  2984  		},
  2985  		// Business logic tests for formation notifications only
  2986  		{
  2987  			Name: "success when resynchronization is successful for formation notifications",
  2988  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
  2989  				repo := &automock.FormationTemplateRepository{}
  2990  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil)
  2991  				return repo
  2992  			},
  2993  			NotificationServiceFN: func() *automock.NotificationsService {
  2994  				notificationSvc := &automock.NotificationsService{}
  2995  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, fixFormationModelWithState(model.InitialFormationState), testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
  2996  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(formationNotificationWebhookErrorResponse, nil).Once()
  2997  				return notificationSvc
  2998  			},
  2999  			WebhookRepoFn: func() *automock.WebhookRepository {
  3000  				webhookRepo := &automock.WebhookRepository{}
  3001  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  3002  				return webhookRepo
  3003  			},
  3004  			FormationRepositoryFn: func() *automock.FormationRepository {
  3005  				repo := &automock.FormationRepository{}
  3006  				repo.On("Get", ctx, FormationID, TntInternalID).Return(fixFormationModelWithState(model.InitialFormationState), nil).Once()
  3007  				repo.On("Get", ctx, FormationID, TntInternalID).Return(formationInCreateErrorState, nil).Once()
  3008  				return repo
  3009  			},
  3010  			StatusServiceFn: func() *automock.StatusService {
  3011  				svc := &automock.StatusService{}
  3012  				svc.On("SetFormationToErrorStateWithConstraints", ctx, formationWithInitialState, testErr.Error(), formationassignment.AssignmentErrorCode(formationassignment.ClientError), model.CreateErrorFormationState, model.CreateFormation).Return(nil).Once()
  3013  				return svc
  3014  			},
  3015  		},
  3016  		{
  3017  			Name: "error when resynchronization is successful for formation notifications but fails while getting formation",
  3018  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
  3019  				repo := &automock.FormationTemplateRepository{}
  3020  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil)
  3021  				return repo
  3022  			},
  3023  			NotificationServiceFN: func() *automock.NotificationsService {
  3024  				notificationSvc := &automock.NotificationsService{}
  3025  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, fixFormationModelWithState(model.InitialFormationState), testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
  3026  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(formationNotificationWebhookErrorResponse, nil).Once()
  3027  				return notificationSvc
  3028  			},
  3029  			WebhookRepoFn: func() *automock.WebhookRepository {
  3030  				webhookRepo := &automock.WebhookRepository{}
  3031  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  3032  				return webhookRepo
  3033  			},
  3034  			FormationRepositoryFn: func() *automock.FormationRepository {
  3035  				repo := &automock.FormationRepository{}
  3036  				repo.On("Get", ctx, FormationID, TntInternalID).Return(fixFormationModelWithState(model.InitialFormationState), nil).Once()
  3037  				repo.On("Get", ctx, FormationID, TntInternalID).Return(nil, testErr).Once()
  3038  				return repo
  3039  			},
  3040  			StatusServiceFn: func() *automock.StatusService {
  3041  				svc := &automock.StatusService{}
  3042  				svc.On("SetFormationToErrorStateWithConstraints", ctx, formationWithInitialState, testErr.Error(), formationassignment.AssignmentErrorCode(formationassignment.ClientError), model.CreateErrorFormationState, model.CreateFormation).Return(nil).Once()
  3043  				return svc
  3044  			},
  3045  			ExpectedErrMessage: testErr.Error(),
  3046  		},
  3047  		{
  3048  			Name: "error when resynchronization is unsuccessful for formation notifications due to technical error",
  3049  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
  3050  				repo := &automock.FormationTemplateRepository{}
  3051  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil)
  3052  				return repo
  3053  			},
  3054  			NotificationServiceFN: func() *automock.NotificationsService {
  3055  				notificationSvc := &automock.NotificationsService{}
  3056  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, fixFormationModelWithState(model.InitialFormationState), testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(formationNotificationSyncCreateRequests, nil).Once()
  3057  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncCreateRequest).Return(nil, testErr).Once()
  3058  				return notificationSvc
  3059  			},
  3060  			WebhookRepoFn: func() *automock.WebhookRepository {
  3061  				webhookRepo := &automock.WebhookRepository{}
  3062  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  3063  				return webhookRepo
  3064  			},
  3065  			FormationRepositoryFn: func() *automock.FormationRepository {
  3066  				repo := &automock.FormationRepository{}
  3067  				repo.On("Get", ctx, FormationID, TntInternalID).Return(fixFormationModelWithState(model.InitialFormationState), nil).Once()
  3068  				repo.On("Update", ctx, formationInCreateErrorStateTechnicalError).Return(nil).Once()
  3069  				return repo
  3070  			},
  3071  			ExpectedErrMessage: testErr.Error(),
  3072  		},
  3073  		{
  3074  			Name: "error when resynchronization is unsuccessful for formation notifications during generating notifications",
  3075  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
  3076  				repo := &automock.FormationTemplateRepository{}
  3077  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil)
  3078  				return repo
  3079  			},
  3080  			NotificationServiceFN: func() *automock.NotificationsService {
  3081  				notificationSvc := &automock.NotificationsService{}
  3082  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, fixFormationModelWithState(model.InitialFormationState), testFormationTemplateName, FormationTemplateID, model.CreateFormation).Return(nil, testErr).Once()
  3083  				return notificationSvc
  3084  			},
  3085  			WebhookRepoFn: func() *automock.WebhookRepository {
  3086  				webhookRepo := &automock.WebhookRepository{}
  3087  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  3088  				return webhookRepo
  3089  			},
  3090  			FormationRepositoryFn: func() *automock.FormationRepository {
  3091  				repo := &automock.FormationRepository{}
  3092  				repo.On("Get", ctx, FormationID, TntInternalID).Return(fixFormationModelWithState(model.InitialFormationState), nil).Once()
  3093  				return repo
  3094  			},
  3095  			ExpectedErrMessage: testErr.Error(),
  3096  		},
  3097  		{
  3098  			Name: "error when resynchronization is unsuccessful for formation notifications during getting webhooks",
  3099  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
  3100  				repo := &automock.FormationTemplateRepository{}
  3101  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil)
  3102  				return repo
  3103  			},
  3104  			WebhookRepoFn: func() *automock.WebhookRepository {
  3105  				webhookRepo := &automock.WebhookRepository{}
  3106  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(nil, testErr).Once()
  3107  				return webhookRepo
  3108  			},
  3109  			FormationRepositoryFn: func() *automock.FormationRepository {
  3110  				repo := &automock.FormationRepository{}
  3111  				repo.On("Get", ctx, FormationID, TntInternalID).Return(fixFormationModelWithState(model.InitialFormationState), nil).Once()
  3112  				return repo
  3113  			},
  3114  			ExpectedErrMessage: testErr.Error(),
  3115  		},
  3116  		{
  3117  			Name: "error when resynchronization is unsuccessful for formation notifications during getting formation template",
  3118  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
  3119  				repo := &automock.FormationTemplateRepository{}
  3120  				repo.On("Get", ctx, FormationTemplateID).Return(nil, testErr)
  3121  				return repo
  3122  			},
  3123  			FormationRepositoryFn: func() *automock.FormationRepository {
  3124  				repo := &automock.FormationRepository{}
  3125  				repo.On("Get", ctx, FormationID, TntInternalID).Return(fixFormationModelWithState(model.InitialFormationState), nil).Once()
  3126  				return repo
  3127  			},
  3128  			ExpectedErrMessage: testErr.Error(),
  3129  		},
  3130  		{
  3131  			Name: "success when resynchronization is successful for formation notifications with DELETE_ERROR state",
  3132  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
  3133  				repo := &automock.FormationTemplateRepository{}
  3134  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil)
  3135  				return repo
  3136  			},
  3137  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  3138  				labelDefRepo := &automock.LabelDefRepository{}
  3139  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  3140  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  3141  				return labelDefRepo
  3142  			},
  3143  			LabelDefServiceFn: func() *automock.LabelDefService {
  3144  				labelDefService := &automock.LabelDefService{}
  3145  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  3146  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  3147  				return labelDefService
  3148  			},
  3149  			NotificationServiceFN: func() *automock.NotificationsService {
  3150  				notificationSvc := &automock.NotificationsService{}
  3151  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, fixFormationModelWithStateAndAssignmentError(t, model.DeleteErrorFormationState, testErr.Error(), formationassignment.ClientError), testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(formationNotificationSyncDeleteRequests, nil).Once()
  3152  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncDeleteRequest).Return(formationNotificationWebhookSuccessResponse, nil).Once()
  3153  				return notificationSvc
  3154  			},
  3155  			WebhookRepoFn: func() *automock.WebhookRepository {
  3156  				webhookRepo := &automock.WebhookRepository{}
  3157  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  3158  				return webhookRepo
  3159  			},
  3160  			FormationRepositoryFn: func() *automock.FormationRepository {
  3161  				repo := &automock.FormationRepository{}
  3162  				repo.On("Get", ctx, FormationID, TntInternalID).Return(fixFormationModelWithStateAndAssignmentError(t, model.DeleteErrorFormationState, testErr.Error(), formationassignment.ClientError), nil).Once()
  3163  				repo.On("DeleteByName", ctx, TntInternalID, testFormationName).Return(nil).Once()
  3164  				return repo
  3165  			},
  3166  			StatusServiceFn: func() *automock.StatusService {
  3167  				svc := &automock.StatusService{}
  3168  				svc.On("UpdateWithConstraints", ctx, fixFormationModelWithState(model.ReadyFormationState), model.DeleteFormation).Return(nil).Once()
  3169  				return svc
  3170  			},
  3171  		},
  3172  		{
  3173  			Name: "error when resynchronization is successful for formation notifications with DELETE_ERROR during deletion of formation",
  3174  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
  3175  				repo := &automock.FormationTemplateRepository{}
  3176  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil)
  3177  				return repo
  3178  			},
  3179  			LabelDefRepositoryFn: func() *automock.LabelDefRepository {
  3180  				labelDefRepo := &automock.LabelDefRepository{}
  3181  				labelDefRepo.On("GetByKey", ctx, TntInternalID, model.ScenariosKey).Return(&testSchemaLblDef, nil)
  3182  				labelDefRepo.On("UpdateWithVersion", ctx, newSchemaLblDef).Return(nil)
  3183  				return labelDefRepo
  3184  			},
  3185  			LabelDefServiceFn: func() *automock.LabelDefService {
  3186  				labelDefService := &automock.LabelDefService{}
  3187  				labelDefService.On("ValidateExistingLabelsAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  3188  				labelDefService.On("ValidateAutomaticScenarioAssignmentAgainstSchema", ctx, newSchema, TntInternalID, model.ScenariosKey).Return(nil)
  3189  				return labelDefService
  3190  			},
  3191  			NotificationServiceFN: func() *automock.NotificationsService {
  3192  				notificationSvc := &automock.NotificationsService{}
  3193  				notificationSvc.On("GenerateFormationNotifications", ctx, formationLifecycleSyncWebhooks, TntInternalID, fixFormationModelWithStateAndAssignmentError(t, model.DeleteErrorFormationState, testErr.Error(), formationassignment.ClientError), testFormationTemplateName, FormationTemplateID, model.DeleteFormation).Return(formationNotificationSyncDeleteRequests, nil).Once()
  3194  				notificationSvc.On("SendNotification", ctx, formationNotificationSyncDeleteRequest).Return(formationNotificationWebhookSuccessResponse, nil).Once()
  3195  				return notificationSvc
  3196  			},
  3197  			WebhookRepoFn: func() *automock.WebhookRepository {
  3198  				webhookRepo := &automock.WebhookRepository{}
  3199  				webhookRepo.On("ListByReferenceObjectIDGlobal", ctx, FormationTemplateID, model.FormationTemplateWebhookReference).Return(formationLifecycleSyncWebhooks, nil).Once()
  3200  				return webhookRepo
  3201  			},
  3202  			FormationRepositoryFn: func() *automock.FormationRepository {
  3203  				repo := &automock.FormationRepository{}
  3204  				repo.On("Get", ctx, FormationID, TntInternalID).Return(fixFormationModelWithStateAndAssignmentError(t, model.DeleteErrorFormationState, testErr.Error(), formationassignment.ClientError), nil).Once()
  3205  				repo.On("DeleteByName", ctx, TntInternalID, testFormationName).Return(testErr).Once()
  3206  				return repo
  3207  			},
  3208  			StatusServiceFn: func() *automock.StatusService {
  3209  				svc := &automock.StatusService{}
  3210  				svc.On("UpdateWithConstraints", ctx, fixFormationModelWithState(model.ReadyFormationState), model.DeleteFormation).Return(nil).Once()
  3211  				return svc
  3212  			},
  3213  			ExpectedErrMessage: testErr.Error(),
  3214  		},
  3215  	}
  3216  
  3217  	for _, testCase := range testCases {
  3218  		t.Run(testCase.Name, func(t *testing.T) {
  3219  			// GIVEN
  3220  			labelService := unusedLabelService()
  3221  			if testCase.LabelServiceFn != nil {
  3222  				labelService = testCase.LabelServiceFn()
  3223  			}
  3224  			runtimeContextRepo := unusedRuntimeContextRepo()
  3225  			if testCase.RuntimeContextRepoFn != nil {
  3226  				runtimeContextRepo = testCase.RuntimeContextRepoFn()
  3227  			}
  3228  			formationRepo := unusedFormationRepo()
  3229  			if testCase.FormationRepositoryFn != nil {
  3230  				formationRepo = testCase.FormationRepositoryFn()
  3231  			}
  3232  			formationTemplateRepo := unusedFormationTemplateRepo()
  3233  			if testCase.FormationTemplateRepositoryFn != nil {
  3234  				formationTemplateRepo = testCase.FormationTemplateRepositoryFn()
  3235  			}
  3236  			labelRepo := unusedLabelRepo()
  3237  			if testCase.LabelRepoFn != nil {
  3238  				labelRepo = testCase.LabelRepoFn()
  3239  			}
  3240  			notificationsSvc := unusedNotificationsService()
  3241  			if testCase.NotificationServiceFN != nil {
  3242  				notificationsSvc = testCase.NotificationServiceFN()
  3243  			}
  3244  			formationAssignmentSvc := unusedFormationAssignmentService()
  3245  			if testCase.FormationAssignmentServiceFn != nil {
  3246  				formationAssignmentSvc = testCase.FormationAssignmentServiceFn()
  3247  			}
  3248  			asaEngine := unusedASAEngine()
  3249  			if testCase.AsaEngineFN != nil {
  3250  				asaEngine = testCase.AsaEngineFN()
  3251  			}
  3252  			formationAssignmentNotificationService := unusedFormationAssignmentNotificationService()
  3253  			if testCase.FormationAssignmentNotificationServiceFN != nil {
  3254  				formationAssignmentNotificationService = testCase.FormationAssignmentNotificationServiceFN()
  3255  			}
  3256  			webhookRepo := unusedWebhookRepository()
  3257  			if testCase.WebhookRepoFn != nil {
  3258  				webhookRepo = testCase.WebhookRepoFn()
  3259  			}
  3260  			labelDefRepo := unusedLabelDefRepository()
  3261  			if testCase.LabelDefRepositoryFn != nil {
  3262  				labelDefRepo = testCase.LabelDefRepositoryFn()
  3263  			}
  3264  			labelDefSvc := unusedLabelDefService()
  3265  			if testCase.LabelDefServiceFn != nil {
  3266  				labelDefSvc = testCase.LabelDefServiceFn()
  3267  			}
  3268  			statusService := &automock.StatusService{}
  3269  			if testCase.StatusServiceFn != nil {
  3270  				statusService = testCase.StatusServiceFn()
  3271  			}
  3272  
  3273  			svc := formation.NewServiceWithAsaEngine(nil, nil, labelDefRepo, labelRepo, formationRepo, formationTemplateRepo, labelService, nil, labelDefSvc, nil, nil, nil, nil, runtimeContextRepo, formationAssignmentSvc, webhookRepo, formationAssignmentNotificationService, notificationsSvc, nil, runtimeType, applicationType, asaEngine, statusService)
  3274  
  3275  			// WHEN
  3276  			_, err := svc.ResynchronizeFormationNotifications(ctx, FormationID)
  3277  
  3278  			// THEN
  3279  			if testCase.ExpectedErrMessage == "" {
  3280  				require.NoError(t, err)
  3281  			} else {
  3282  				require.Error(t, err)
  3283  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  3284  			}
  3285  			mock.AssertExpectationsForObjects(t, labelService, runtimeContextRepo, asaEngine, formationRepo, labelRepo, notificationsSvc, formationAssignmentSvc, formationAssignmentNotificationService, formationTemplateRepo, webhookRepo, statusService)
  3286  		})
  3287  	}
  3288  	t.Run("returns error when empty tenant", func(t *testing.T) {
  3289  		svc := formation.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, runtimeType, applicationType)
  3290  		_, err := svc.ResynchronizeFormationNotifications(context.TODO(), FormationID)
  3291  		require.Contains(t, err.Error(), "cannot read tenant from context")
  3292  	})
  3293  }